blob: 7dacb13ca8c1eaf09458e66e4b9fcb411b27c0d4 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/ash/chrome_shell_delegate.h"
#include "ash/launcher/launcher_types.h"
#include "ash/system/tray/system_tray_delegate.h"
#include "ash/wm/window_util.h"
#include "base/command_line.h"
#include "chrome/browser/chromeos/login/screen_locker.h"
#include "chrome/browser/extensions/api/terminal/terminal_extension_helper.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/sessions/tab_restore_service.h"
#include "chrome/browser/sessions/tab_restore_service_factory.h"
#include "chrome/browser/ui/app_list/app_list_view_delegate.h"
#include "chrome/browser/ui/ash/app_list/app_list_controller_ash.h"
#include "chrome/browser/ui/ash/caps_lock_handler.h"
#include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h"
#include "chrome/browser/ui/ash/user_action_handler.h"
#include "chrome/browser/ui/ash/window_positioner.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/webui/chrome_web_contents_handler.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/time_format.h"
#include "chrome/common/url_constants.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/browser/web_contents.h"
#include "grit/generated_resources.h"
#include "ui/aura/client/user_action_client.h"
#include "ui/aura/window.h"
#if defined(OS_CHROMEOS)
#include "ash/keyboard_overlay/keyboard_overlay_view.h"
#include "base/chromeos/chromeos_version.h"
#include "chrome/browser/chromeos/accessibility/accessibility_util.h"
#include "chrome/browser/chromeos/background/ash_user_wallpaper_delegate.h"
#include "chrome/browser/chromeos/extensions/file_manager_util.h"
#include "chrome/browser/chromeos/extensions/media_player_event_router.h"
#include "chrome/browser/chromeos/input_method/input_method_manager.h"
#include "chrome/browser/chromeos/kiosk_mode/kiosk_mode_settings.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/chromeos/login/webui_login_display_host.h"
#include "chrome/browser/chromeos/system/ash_system_tray_delegate.h"
#include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
#include "chrome/browser/ui/webui/chromeos/mobile_setup_dialog.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/power_manager_client.h"
#include "chromeos/dbus/session_manager_client.h"
#endif
namespace {
// Returns the browser that should handle accelerators.
Browser* GetTargetBrowser() {
Browser* browser = browser::FindBrowserWithWindow(ash::wm::GetActiveWindow());
if (browser)
return browser;
return browser::FindOrCreateTabbedBrowser(
ProfileManager::GetDefaultProfileOrOffTheRecord());
}
} // namespace
// static
ChromeShellDelegate* ChromeShellDelegate::instance_ = NULL;
ChromeShellDelegate::ChromeShellDelegate()
: window_positioner_(new ash::WindowPositioner()),
ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
instance_ = this;
#if defined(OS_CHROMEOS)
registrar_.Add(
this,
chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED,
content::NotificationService::AllSources());
registrar_.Add(
this,
chrome::NOTIFICATION_SESSION_STARTED,
content::NotificationService::AllSources());
#endif
}
ChromeShellDelegate::~ChromeShellDelegate() {
if (instance_ == this)
instance_ = NULL;
}
bool ChromeShellDelegate::IsUserLoggedIn() {
#if defined(OS_CHROMEOS)
// When running a Chrome OS build outside of a device (i.e. on a developer's
// workstation) and not running as login-manager, pretend like we're always
// logged in.
if (!base::chromeos::IsRunningOnChromeOS() &&
!CommandLine::ForCurrentProcess()->HasSwitch(switches::kLoginManager)) {
return true;
}
return chromeos::UserManager::Get()->IsUserLoggedIn();
#else
return true;
#endif
}
// Returns true if we're logged in and browser has been started
bool ChromeShellDelegate::IsSessionStarted() {
#if defined(OS_CHROMEOS)
return chromeos::UserManager::Get()->IsSessionStarted();
#else
return true;
#endif
}
void ChromeShellDelegate::LockScreen() {
#if defined(OS_CHROMEOS)
if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kGuestSession) &&
!chromeos::KioskModeSettings::Get()->IsKioskModeEnabled()) {
chromeos::DBusThreadManager::Get()->GetSessionManagerClient()->
RequestLockScreen();
}
#endif
}
void ChromeShellDelegate::UnlockScreen() {
// This is used only for testing thus far.
NOTIMPLEMENTED();
}
bool ChromeShellDelegate::IsScreenLocked() const {
#if defined(OS_CHROMEOS)
if (!chromeos::ScreenLocker::default_screen_locker())
return false;
return chromeos::ScreenLocker::default_screen_locker()->locked();
#else
return false;
#endif
}
void ChromeShellDelegate::Shutdown() {
#if defined(OS_CHROMEOS)
content::RecordAction(content::UserMetricsAction("Shutdown"));
chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
RequestShutdown();
#endif
}
void ChromeShellDelegate::Exit() {
browser::AttemptUserExit();
}
void ChromeShellDelegate::NewTab() {
Browser* browser = GetTargetBrowser();
// If the browser was not active, we call BrowserWindow::Show to make it
// visible. Otherwise, we let Browser::NewTab handle the active window change.
const bool was_active = browser->window()->IsActive();
chrome::NewTab(browser);
if (!was_active)
browser->window()->Show();
}
void ChromeShellDelegate::NewWindow(bool is_incognito) {
Profile* profile = ProfileManager::GetDefaultProfileOrOffTheRecord();
chrome::NewEmptyWindow(
is_incognito ? profile->GetOffTheRecordProfile() : profile);
}
void ChromeShellDelegate::OpenFileManager(bool as_dialog) {
#if defined(OS_CHROMEOS)
if (as_dialog) {
Browser* browser =
browser::FindBrowserWithWindow(ash::wm::GetActiveWindow());
// Open the select file dialog only if there is an active browser where the
// selected file is displayed. Otherwise open a file manager in a tab.
if (browser) {
browser->OpenFile();
return;
}
}
file_manager_util::OpenApplication();
#endif
}
void ChromeShellDelegate::OpenCrosh() {
#if defined(OS_CHROMEOS)
Browser* browser = GetTargetBrowser();
GURL crosh_url = TerminalExtensionHelper::GetCroshExtensionURL(
browser->profile());
if (!crosh_url.is_valid())
return;
content::WebContents* page = browser->OpenURL(
content::OpenURLParams(crosh_url,
content::Referrer(),
NEW_FOREGROUND_TAB,
content::PAGE_TRANSITION_GENERATED,
false));
browser->window()->Show();
browser->window()->Activate();
page->Focus();
#endif
}
void ChromeShellDelegate::OpenMobileSetup(const std::string& service_path) {
#if defined(OS_CHROMEOS)
MobileSetupDialog::Show(service_path);
#endif
}
void ChromeShellDelegate::RestoreTab() {
Browser* browser = GetTargetBrowser();
// Do not restore tabs while in the incognito mode.
if (browser->profile()->IsOffTheRecord())
return;
TabRestoreService* service =
TabRestoreServiceFactory::GetForProfile(browser->profile());
if (!service)
return;
if (service->IsLoaded()) {
chrome::RestoreTab(browser);
} else {
service->LoadTabsFromLastSession();
// LoadTabsFromLastSession is asynchronous, so TabRestoreService has not
// finished loading the entries at this point. Wait for next event cycle
// which loads the restored tab entries.
MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(&ChromeShellDelegate::RestoreTab,
weak_factory_.GetWeakPtr()));
}
}
bool ChromeShellDelegate::RotatePaneFocus(ash::Shell::Direction direction) {
aura::Window* window = ash::wm::GetActiveWindow();
if (!window)
return false;
Browser* browser = browser::FindBrowserWithWindow(window);
if (!browser)
return false;
switch (direction) {
case ash::Shell::FORWARD:
chrome::FocusNextPane(browser);
break;
case ash::Shell::BACKWARD:
chrome::FocusPreviousPane(browser);
break;
}
return true;
}
void ChromeShellDelegate::ShowKeyboardOverlay() {
#if defined(OS_CHROMEOS)
// TODO(mazda): Move the show logic to ash (http://crbug.com/124222).
Profile* profile = ProfileManager::GetDefaultProfileOrOffTheRecord();
std::string url(chrome::kChromeUIKeyboardOverlayURL);
KeyboardOverlayView::ShowDialog(profile,
new ChromeWebContentsHandler,
GURL(url));
#endif
}
void ChromeShellDelegate::ShowTaskManager() {
Browser* browser = browser::FindOrCreateTabbedBrowser(
ProfileManager::GetDefaultProfileOrOffTheRecord());
chrome::OpenTaskManager(browser, false);
}
content::BrowserContext* ChromeShellDelegate::GetCurrentBrowserContext() {
return ProfileManager::GetDefaultProfile();
}
void ChromeShellDelegate::ToggleSpokenFeedback() {
#if defined(OS_CHROMEOS)
content::WebUI* login_screen_web_ui = NULL;
chromeos::WebUILoginDisplayHost* host =
static_cast<chromeos::WebUILoginDisplayHost*>(
chromeos::BaseLoginDisplayHost::default_host());
if (host && host->GetOobeUI())
login_screen_web_ui = host->GetOobeUI()->web_ui();
chromeos::accessibility::ToggleSpokenFeedback(login_screen_web_ui);
#endif
}
bool ChromeShellDelegate::IsSpokenFeedbackEnabled() const {
#if defined(OS_CHROMEOS)
return chromeos::accessibility::IsSpokenFeedbackEnabled();
#else
return false;
#endif
}
app_list::AppListViewDelegate*
ChromeShellDelegate::CreateAppListViewDelegate() {
DCHECK(ash::Shell::HasInstance());
// Shell will own the created delegate, and the delegate will own
// the controller.
return new AppListViewDelegate(new AppListControllerAsh());
}
ash::LauncherDelegate* ChromeShellDelegate::CreateLauncherDelegate(
ash::LauncherModel* model) {
ChromeLauncherController* controller =
new ChromeLauncherController(NULL, model);
controller->Init();
return controller;
}
ash::SystemTrayDelegate* ChromeShellDelegate::CreateSystemTrayDelegate(
ash::SystemTray* tray) {
#if defined(OS_CHROMEOS)
return chromeos::CreateSystemTrayDelegate(tray);
#else
return NULL;
#endif
}
ash::UserWallpaperDelegate* ChromeShellDelegate::CreateUserWallpaperDelegate() {
#if defined(OS_CHROMEOS)
return chromeos::CreateUserWallpaperDelegate();
#else
return NULL;
#endif
}
ash::CapsLockDelegate* ChromeShellDelegate::CreateCapsLockDelegate() {
#if defined(OS_CHROMEOS)
chromeos::input_method::XKeyboard* xkeyboard =
chromeos::input_method::InputMethodManager::GetInstance()->GetXKeyboard();
return new CapsLockHandler(xkeyboard);
#else
return new CapsLockHandler;
#endif
}
aura::client::UserActionClient* ChromeShellDelegate::CreateUserActionClient() {
return new UserActionHandler;
}
void ChromeShellDelegate::OpenFeedbackPage() {
chrome::OpenFeedbackDialog(GetTargetBrowser());
}
void ChromeShellDelegate::RecordUserMetricsAction(
ash::UserMetricsAction action) {
switch (action) {
case ash::UMA_ACCEL_MAXIMIZE_RESTORE_F4:
content::RecordAction(
content::UserMetricsAction("Accel_Maximize_Restore_F4"));
break;
case ash::UMA_ACCEL_PREVWINDOW_TAB:
content::RecordAction(content::UserMetricsAction("Accel_PrevWindow_Tab"));
break;
case ash::UMA_ACCEL_NEXTWINDOW_TAB:
content::RecordAction(content::UserMetricsAction("Accel_NextWindow_Tab"));
break;
case ash::UMA_ACCEL_PREVWINDOW_F5:
content::RecordAction(content::UserMetricsAction("Accel_PrevWindow_F5"));
break;
case ash::UMA_ACCEL_NEXTWINDOW_F5:
content::RecordAction(content::UserMetricsAction("Accel_NextWindow_F5"));
break;
case ash::UMA_ACCEL_NEWTAB_T:
content::RecordAction(content::UserMetricsAction("Accel_NewTab_T"));
break;
case ash::UMA_ACCEL_SEARCH_LWIN:
content::RecordAction(content::UserMetricsAction("Accel_Search_LWin"));
break;
case ash::UMA_MOUSE_DOWN:
content::RecordAction(content::UserMetricsAction("Mouse_Down"));
break;
case ash::UMA_TOUCHSCREEN_TAP_DOWN:
content::RecordAction(content::UserMetricsAction("Touchscreen_Down"));
break;
case ash::UMA_LAUNCHER_CLICK_ON_APPLIST_BUTTON:
content::RecordAction(
content::UserMetricsAction("Launcher_ClickOnApplistButton"));
break;
case ash::UMA_LAUNCHER_CLICK_ON_APP:
content::RecordAction(content::UserMetricsAction("Launcher_ClickOnApp"));
break;
}
}
void ChromeShellDelegate::HandleMediaNextTrack() {
#if defined(OS_CHROMEOS)
ExtensionMediaPlayerEventRouter::GetInstance()->NotifyNextTrack();
#endif
}
void ChromeShellDelegate::HandleMediaPlayPause() {
#if defined(OS_CHROMEOS)
ExtensionMediaPlayerEventRouter::GetInstance()->NotifyTogglePlayState();
#endif
}
void ChromeShellDelegate::HandleMediaPrevTrack() {
#if defined(OS_CHROMEOS)
ExtensionMediaPlayerEventRouter::GetInstance()->NotifyPrevTrack();
#endif
}
string16 ChromeShellDelegate::GetTimeRemainingString(base::TimeDelta delta) {
return TimeFormat::TimeRemaining(delta);
}
void ChromeShellDelegate::Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
#if defined(OS_CHROMEOS)
switch (type) {
case chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED:
ash::Shell::GetInstance()->CreateLauncher();
break;
case chrome::NOTIFICATION_SESSION_STARTED:
ash::Shell::GetInstance()->ShowLauncher();
break;
default:
NOTREACHED() << "Unexpected notification " << type;
}
#else
// MSVC++ warns about switch statements without any cases.
NOTREACHED() << "Unexpected notification " << type;
#endif
}