diff options
author | tapted@chromium.org <tapted@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-04 08:32:39 +0000 |
---|---|---|
committer | tapted@chromium.org <tapted@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-04 08:32:39 +0000 |
commit | 24ced7dc02d290de10b00379c485584ccc896ec3 (patch) | |
tree | 8ddefb277c4a67ba2449c973b668868e503ced96 | |
parent | bda506cad679d2a9800f5a8eb41da9fb676ee1b9 (diff) | |
download | chromium_src-24ced7dc02d290de10b00379c485584ccc896ec3.zip chromium_src-24ced7dc02d290de10b00379c485584ccc896ec3.tar.gz chromium_src-24ced7dc02d290de10b00379c485584ccc896ec3.tar.bz2 |
[win8] Show a prompt before relaunching Chrome in Windows 8 mode while packaged apps are running.
Introduces ShellWindowRegistry::IsShellWindowRegisteredInAnyProfile to
help determine if packaged apps are currently running. Intercepts the
IDC_WIN8_METRO_RESTART command and shows a modal dialog box if packaged
apps are running to confirm that the user is OK with their packaged
apps closing. Ensures apps with a relaunch handler are not relaunched
when restarting in metro mode.
BUG=222297
TEST=Launch a packaged app in desktop mode and select 'Relaunch Chrome
in Windows 8 mode' from the hotdog menu. A prompt should appear
confirming that your Chrome apps will close if you continue. If no
packaged apps are running, no prompt should appear.
Review URL: https://chromiumcodereview.appspot.com/12566039
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@192240 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | apps/app_restore_service.cc | 18 | ||||
-rw-r--r-- | apps/app_restore_service.h | 4 | ||||
-rw-r--r-- | chrome/app/generated_resources.grd | 4 | ||||
-rw-r--r-- | chrome/browser/extensions/shell_window_registry.cc | 47 | ||||
-rw-r--r-- | chrome/browser/extensions/shell_window_registry.h | 7 | ||||
-rw-r--r-- | chrome/browser/ui/browser_command_controller.cc | 15 | ||||
-rw-r--r-- | chrome/browser/ui/cocoa/simple_message_box_mac.mm | 3 | ||||
-rw-r--r-- | chrome/browser/ui/extensions/apps_metro_handler_win.cc | 31 | ||||
-rw-r--r-- | chrome/browser/ui/extensions/apps_metro_handler_win.h | 20 | ||||
-rw-r--r-- | chrome/browser/ui/extensions/shell_window.h | 7 | ||||
-rw-r--r-- | chrome/browser/ui/gtk/simple_message_box_gtk.cc | 3 | ||||
-rw-r--r-- | chrome/browser/ui/simple_message_box.h | 14 | ||||
-rw-r--r-- | chrome/browser/ui/startup/startup_browser_creator_impl.cc | 13 | ||||
-rw-r--r-- | chrome/browser/ui/views/simple_message_box_views.cc | 11 | ||||
-rw-r--r-- | chrome/browser/ui/views/simple_message_box_win.cc | 13 | ||||
-rw-r--r-- | chrome/chrome_browser_ui.gypi | 2 |
16 files changed, 176 insertions, 36 deletions
diff --git a/apps/app_restore_service.cc b/apps/app_restore_service.cc index 683718a..66f2a73 100644 --- a/apps/app_restore_service.cc +++ b/apps/app_restore_service.cc @@ -18,6 +18,10 @@ #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_types.h" +#if defined(OS_WIN) +#include "win8/util/win8_util.h" +#endif + using extensions::AppEventRouter; using extensions::Extension; using extensions::ExtensionHost; @@ -26,6 +30,20 @@ using extensions::ExtensionSystem; namespace apps { +// static +bool AppRestoreService::ShouldRestoreApps(bool is_browser_restart) { + bool should_restore_apps = is_browser_restart; +#if defined(OS_CHROMEOS) + // Chromeos always restarts apps, even if it was a regular shutdown. + should_restore_apps = true; +#elif defined(OS_WIN) + // Packaged apps are not supported in Metro mode, so don't try to start them. + if (win8::IsSingleWindowMetroMode()) + should_restore_apps = false; +#endif + return should_restore_apps; +} + AppRestoreService::AppRestoreService(Profile* profile) : profile_(profile) { registrar_.Add( diff --git a/apps/app_restore_service.h b/apps/app_restore_service.h index a308c31..f27c83c 100644 --- a/apps/app_restore_service.h +++ b/apps/app_restore_service.h @@ -31,6 +31,10 @@ namespace apps { class AppRestoreService : public ProfileKeyedService, public content::NotificationObserver { public: + // Returns true if apps should be restored on the current platform, given + // whether this new browser process launched due to a restart. + static bool ShouldRestoreApps(bool is_browser_restart); + explicit AppRestoreService(Profile* profile); // Restart apps that need to be restarted and clear the "running" preference diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 2ebccb8..b4ac7f5 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd @@ -14920,6 +14920,10 @@ Some features may be unavailable. Please check that the profile exists and you desc="Infobar button 'no' text to cancel prompt to relaunch in deskop mode to use Chrome Apps"> No, stay in Windows 8 mode </message> + <message name="IDS_WIN8_PROMPT_TO_CLOSE_APPS_FOR_METRO" + desc="Modal message box prompt shown to the user after requesting to relaunch in Windows 8 mode while packaged apps are running, which will require all packaged apps to be closed. Dialog is shown with choices: OK, Cancel."> + Relaunching in Windows 8 mode will close your Chrome apps. + </message> <!-- Media Galleries. --> <message name="IDS_MEDIA_GALLERIES_DIALOG_HEADER" desc="Header for media gallery permissions dialog."> diff --git a/chrome/browser/extensions/shell_window_registry.cc b/chrome/browser/extensions/shell_window_registry.cc index f7495f8..2b5d3b0 100644 --- a/chrome/browser/extensions/shell_window_registry.cc +++ b/chrome/browser/extensions/shell_window_registry.cc @@ -52,7 +52,7 @@ ShellWindowRegistry::~ShellWindowRegistry() {} // static ShellWindowRegistry* ShellWindowRegistry::Get(Profile* profile) { - return Factory::GetForProfile(profile); + return Factory::GetForProfile(profile, true /* create */); } void ShellWindowRegistry::AddShellWindow(ShellWindow* shell_window) { @@ -153,11 +153,13 @@ ShellWindow* ShellWindowRegistry::GetShellWindowForNativeWindowAnyProfile( gfx::NativeWindow window) { std::vector<Profile*> profiles = g_browser_process->profile_manager()->GetLoadedProfiles(); - for (std::vector<Profile*>::const_iterator i(profiles.begin()); - i < profiles.end(); ++i) { - extensions::ShellWindowRegistry* registry = - extensions::ShellWindowRegistry::Get(*i); - DCHECK(registry); + for (std::vector<Profile*>::const_iterator i = profiles.begin(); + i != profiles.end(); ++i) { + ShellWindowRegistry* registry = Factory::GetForProfile(*i, + false /* create */); + if (!registry) + continue; + ShellWindow* shell_window = registry->GetShellWindowForNativeWindow(window); if (shell_window) return shell_window; @@ -166,6 +168,35 @@ ShellWindow* ShellWindowRegistry::GetShellWindowForNativeWindowAnyProfile( return NULL; } +// static +bool ShellWindowRegistry::IsShellWindowRegisteredInAnyProfile( + int window_type_mask) { + std::vector<Profile*> profiles = + g_browser_process->profile_manager()->GetLoadedProfiles(); + for (std::vector<Profile*>::const_iterator i = profiles.begin(); + i != profiles.end(); ++i) { + ShellWindowRegistry* registry = Factory::GetForProfile(*i, + false /* create */); + if (!registry) + continue; + + const ShellWindowSet& shell_windows = registry->shell_windows(); + if (shell_windows.empty()) + continue; + + if (window_type_mask == 0) + return true; + + for (const_iterator j = shell_windows.begin(); j != shell_windows.end(); + ++j) { + if ((*j)->window_type() & window_type_mask) + return true; + } + } + + return false; +} + void ShellWindowRegistry::Observe(int type, const content::NotificationSource& source, const content::NotificationDetails& details) { @@ -192,9 +223,9 @@ void ShellWindowRegistry::Observe(int type, // static ShellWindowRegistry* ShellWindowRegistry::Factory::GetForProfile( - Profile* profile) { + Profile* profile, bool create) { return static_cast<ShellWindowRegistry*>( - GetInstance()->GetServiceForProfile(profile, true)); + GetInstance()->GetServiceForProfile(profile, create)); } ShellWindowRegistry::Factory* ShellWindowRegistry::Factory::GetInstance() { diff --git a/chrome/browser/extensions/shell_window_registry.h b/chrome/browser/extensions/shell_window_registry.h index 265ceea..113a156 100644 --- a/chrome/browser/extensions/shell_window_registry.h +++ b/chrome/browser/extensions/shell_window_registry.h @@ -94,6 +94,11 @@ class ShellWindowRegistry : public ProfileKeyedService, static ShellWindow* GetShellWindowForNativeWindowAnyProfile( gfx::NativeWindow window); + // Returns true if the number of shell windows registered across all profiles + // is non-zero. |window_type_mask| is a bitwise OR filter of + // ShellWindow::WindowType, or 0 for any window type. + static bool IsShellWindowRegisteredInAnyProfile(int window_type_mask); + protected: // content::NotificationObserver: virtual void Observe(int type, @@ -103,7 +108,7 @@ class ShellWindowRegistry : public ProfileKeyedService, private: class Factory : public ProfileKeyedServiceFactory { public: - static ShellWindowRegistry* GetForProfile(Profile* profile); + static ShellWindowRegistry* GetForProfile(Profile* profile, bool create); static Factory* GetInstance(); private: diff --git a/chrome/browser/ui/browser_command_controller.cc b/chrome/browser/ui/browser_command_controller.cc index 87a53d3..3ba5797 100644 --- a/chrome/browser/ui/browser_command_controller.cc +++ b/chrome/browser/ui/browser_command_controller.cc @@ -46,6 +46,7 @@ #if defined(OS_WIN) #include "base/win/metro.h" #include "base/win/windows_version.h" +#include "chrome/browser/ui/extensions/apps_metro_handler_win.h" #endif #if defined(USE_ASH) @@ -87,17 +88,17 @@ bool HasInternalURL(const NavigationEntry* entry) { // 6- If we are not the default exit. // // Note: this class deletes itself. -class SwichToMetroUIHandler +class SwitchToMetroUIHandler : public ShellIntegration::DefaultWebClientObserver { public: - SwichToMetroUIHandler() + SwitchToMetroUIHandler() : ALLOW_THIS_IN_INITIALIZER_LIST(default_browser_worker_( new ShellIntegration::DefaultBrowserWorker(this))), first_check_(true) { default_browser_worker_->StartCheckIsDefault(); } - virtual ~SwichToMetroUIHandler() { + virtual ~SwitchToMetroUIHandler() { default_browser_worker_->ObserverDestroyed(); } @@ -140,7 +141,7 @@ class SwichToMetroUIHandler scoped_refptr<ShellIntegration::DefaultBrowserWorker> default_browser_worker_; bool first_check_; - DISALLOW_COPY_AND_ASSIGN(SwichToMetroUIHandler); + DISALLOW_COPY_AND_ASSIGN(SwitchToMetroUIHandler); }; #endif // defined(OS_WIN) @@ -447,7 +448,11 @@ void BrowserCommandController::ExecuteCommandWithDisposition( content::RecordAction(content::UserMetricsAction("Win8DesktopRestart")); break; case IDC_WIN8_METRO_RESTART: - new SwichToMetroUIHandler; + if (!chrome::VerifySwitchToMetroForApps(window()->GetNativeWindow())) + break; + + // SwitchToMetroUIHandler deletes itself. + new SwitchToMetroUIHandler; content::RecordAction(content::UserMetricsAction("Win8MetroRestart")); break; #endif diff --git a/chrome/browser/ui/cocoa/simple_message_box_mac.mm b/chrome/browser/ui/cocoa/simple_message_box_mac.mm index a81d106..088e493 100644 --- a/chrome/browser/ui/cocoa/simple_message_box_mac.mm +++ b/chrome/browser/ui/cocoa/simple_message_box_mac.mm @@ -17,6 +17,9 @@ MessageBoxResult ShowMessageBox(gfx::NativeWindow parent, const string16& title, const string16& message, MessageBoxType type) { + if (type == MESSAGE_BOX_TYPE_OK_CANCEL) + NOTIMPLEMENTED(); + startup_metric_utils::SetNonBrowserUIDisplayed(); // Ignore the title; it's the window title on other platforms and ignorable. diff --git a/chrome/browser/ui/extensions/apps_metro_handler_win.cc b/chrome/browser/ui/extensions/apps_metro_handler_win.cc new file mode 100644 index 0000000..125c8bf --- /dev/null +++ b/chrome/browser/ui/extensions/apps_metro_handler_win.cc @@ -0,0 +1,31 @@ +// Copyright 2013 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/extensions/apps_metro_handler_win.h" + +#include "chrome/browser/extensions/shell_window_registry.h" +#include "chrome/browser/ui/extensions/shell_window.h" +#include "chrome/browser/ui/simple_message_box.h" +#include "grit/chromium_strings.h" +#include "grit/generated_resources.h" +#include "ui/base/l10n/l10n_util.h" + +namespace chrome { + +bool VerifySwitchToMetroForApps(gfx::NativeWindow parent_window) { + if (!extensions::ShellWindowRegistry::IsShellWindowRegisteredInAnyProfile( + ShellWindow::WINDOW_TYPE_DEFAULT)) { + return true; + } + + MessageBoxResult result = ShowMessageBox( + parent_window, + l10n_util::GetStringUTF16(IDS_PRODUCT_NAME), + l10n_util::GetStringUTF16(IDS_WIN8_PROMPT_TO_CLOSE_APPS_FOR_METRO), + MESSAGE_BOX_TYPE_OK_CANCEL); + + return result == MESSAGE_BOX_RESULT_YES; +} + +} // namespace chrome diff --git a/chrome/browser/ui/extensions/apps_metro_handler_win.h b/chrome/browser/ui/extensions/apps_metro_handler_win.h new file mode 100644 index 0000000..f1a79de --- /dev/null +++ b/chrome/browser/ui/extensions/apps_metro_handler_win.h @@ -0,0 +1,20 @@ +// Copyright 2013 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. + +#ifndef CHROME_BROWSER_UI_EXTENSIONS_APPS_METRO_HANDLER_WIN_H_ +#define CHROME_BROWSER_UI_EXTENSIONS_APPS_METRO_HANDLER_WIN_H_ + +#include "ui/gfx/native_widget_types.h" + +namespace chrome { + +// Check if there are apps running and if not, return true. Otherwise, Show a +// modal dialog on |parent| asking whether the user is OK with their packaged +// apps closing, in order to relaunch to metro mode. Returns true if the user +// clicks OK. +bool VerifySwitchToMetroForApps(gfx::NativeWindow parent); + +} // namespace chrome + +#endif // CHROME_BROWSER_UI_EXTENSIONS_APPS_METRO_HANDLER_WIN_H_ diff --git a/chrome/browser/ui/extensions/shell_window.h b/chrome/browser/ui/extensions/shell_window.h index 932f673..1654d54 100644 --- a/chrome/browser/ui/extensions/shell_window.h +++ b/chrome/browser/ui/extensions/shell_window.h @@ -67,9 +67,10 @@ class ShellWindow : public content::NotificationObserver, public extensions::ExtensionKeybindingRegistry::Delegate { public: enum WindowType { - WINDOW_TYPE_DEFAULT, // Default shell window - WINDOW_TYPE_PANEL, // OS controlled panel window (Ash only) - WINDOW_TYPE_V1_PANEL, // For apps v1 support in Ash; deprecate with v1 apps + WINDOW_TYPE_DEFAULT = 1 << 0, // Default shell window. + WINDOW_TYPE_PANEL = 1 << 1, // OS controlled panel window (Ash only). + WINDOW_TYPE_V1_PANEL = 1 << 2, // For apps v1 support in Ash; deprecate + // with v1 apps. }; enum Frame { diff --git a/chrome/browser/ui/gtk/simple_message_box_gtk.cc b/chrome/browser/ui/gtk/simple_message_box_gtk.cc index 703ab89..3ce0150 100644 --- a/chrome/browser/ui/gtk/simple_message_box_gtk.cc +++ b/chrome/browser/ui/gtk/simple_message_box_gtk.cc @@ -47,6 +47,9 @@ MessageBoxResult ShowMessageBox(gfx::NativeWindow parent, const string16& title, const string16& message, MessageBoxType type) { + if (type == MESSAGE_BOX_TYPE_OK_CANCEL) + NOTIMPLEMENTED(); + GtkMessageType gtk_message_type = GTK_MESSAGE_OTHER; GtkButtonsType gtk_buttons_type = GTK_BUTTONS_OK; if (type == MESSAGE_BOX_TYPE_QUESTION) { diff --git a/chrome/browser/ui/simple_message_box.h b/chrome/browser/ui/simple_message_box.h index 9169066..46cea98 100644 --- a/chrome/browser/ui/simple_message_box.h +++ b/chrome/browser/ui/simple_message_box.h @@ -11,20 +11,20 @@ namespace chrome { enum MessageBoxResult { - MESSAGE_BOX_RESULT_NO = 0, - MESSAGE_BOX_RESULT_YES = 1, + MESSAGE_BOX_RESULT_NO = 0, // User chose NO or CANCEL. + MESSAGE_BOX_RESULT_YES = 1, // User chose YES or OK. }; enum MessageBoxType { - MESSAGE_BOX_TYPE_INFORMATION, - MESSAGE_BOX_TYPE_WARNING, - MESSAGE_BOX_TYPE_QUESTION, + MESSAGE_BOX_TYPE_INFORMATION, // Shows an OK button. + MESSAGE_BOX_TYPE_WARNING, // Shows an OK button. + MESSAGE_BOX_TYPE_QUESTION, // Shows YES and NO buttons. + MESSAGE_BOX_TYPE_OK_CANCEL, // Shows OK and CANCEL buttons (Windows only). }; // Shows a dialog box with the given |title| and |message|. If |parent| is // non-NULL, the box will be made modal to the |parent|, except on Mac, where it -// is always app-modal. If |type| is MESSAGE_BOX_TYPE_QUESTION, the box will -// have YES and NO buttons; otherwise it will have an OK button. +// is always app-modal. // // NOTE: In general, you should avoid this since it's usually poor UI. // We have a variety of other surfaces such as wrench menu notifications and diff --git a/chrome/browser/ui/startup/startup_browser_creator_impl.cc b/chrome/browser/ui/startup/startup_browser_creator_impl.cc index b03cc55..4eec6c8 100644 --- a/chrome/browser/ui/startup/startup_browser_creator_impl.cc +++ b/chrome/browser/ui/startup/startup_browser_creator_impl.cc @@ -647,17 +647,14 @@ bool StartupBrowserCreatorImpl::ProcessStartupURLs( else if (pref.type == SessionStartupPref::DEFAULT) VLOG(1) << "Pref: default"; - apps::AppRestoreService* service = + apps::AppRestoreService* restore_service = apps::AppRestoreServiceFactory::GetForProfile(profile_); // NULL in incognito mode. - if (service) { - bool should_restore_apps = StartupBrowserCreator::WasRestarted(); -#if defined(OS_CHROMEOS) - // Chromeos always restarts apps, even if it was a regular shutdown. - should_restore_apps = true; -#endif - service->HandleStartup(should_restore_apps); + if (restore_service) { + restore_service->HandleStartup(apps::AppRestoreService::ShouldRestoreApps( + StartupBrowserCreator::WasRestarted())); } + if (pref.type == SessionStartupPref::LAST) { if (profile_->GetLastSessionExitType() == Profile::EXIT_CRASHED && !command_line_.HasSwitch(switches::kRestoreLastSession)) { diff --git a/chrome/browser/ui/views/simple_message_box_views.cc b/chrome/browser/ui/views/simple_message_box_views.cc index 2faa66f..fcda39e 100644 --- a/chrome/browser/ui/views/simple_message_box_views.cc +++ b/chrome/browser/ui/views/simple_message_box_views.cc @@ -91,8 +91,11 @@ SimpleMessageBoxViews::SimpleMessageBoxViews(const string16& title, } int SimpleMessageBoxViews::GetDialogButtons() const { - if (type_ == MESSAGE_BOX_TYPE_QUESTION) + if (type_ == MESSAGE_BOX_TYPE_QUESTION || + type_ == MESSAGE_BOX_TYPE_OK_CANCEL) { return ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL; + } + return ui::DIALOG_BUTTON_OK; } @@ -103,6 +106,12 @@ string16 SimpleMessageBoxViews::GetDialogButtonLabel( IDS_CONFIRM_MESSAGEBOX_YES_BUTTON_LABEL : IDS_CONFIRM_MESSAGEBOX_NO_BUTTON_LABEL); } + + if (type_ == MESSAGE_BOX_TYPE_OK_CANCEL) { + return l10n_util::GetStringUTF16((button == ui::DIALOG_BUTTON_OK) ? + IDS_OK : IDS_CANCEL); + } + return l10n_util::GetStringUTF16(IDS_OK); } diff --git a/chrome/browser/ui/views/simple_message_box_win.cc b/chrome/browser/ui/views/simple_message_box_win.cc index 861384e..167600c 100644 --- a/chrome/browser/ui/views/simple_message_box_win.cc +++ b/chrome/browser/ui/views/simple_message_box_win.cc @@ -20,11 +20,18 @@ MessageBoxResult ShowMessageBox(gfx::NativeWindow parent, parent = ui::GetWindowToParentTo(true); UINT flags = MB_SETFOREGROUND; - flags |= ((type == MESSAGE_BOX_TYPE_QUESTION) ? MB_YESNO : MB_OK); + if (type == MESSAGE_BOX_TYPE_QUESTION) { + flags |= MB_YESNO; + } else if (type == MESSAGE_BOX_TYPE_OK_CANCEL) { + flags |= MB_OKCANCEL; + } else { + flags |= MB_OK; + } flags |= ((type == MESSAGE_BOX_TYPE_INFORMATION) ? MB_ICONINFORMATION : MB_ICONWARNING); - return (ui::MessageBox(parent, message, title, flags) == IDNO) ? - MESSAGE_BOX_RESULT_NO : MESSAGE_BOX_RESULT_YES; + int result = ui::MessageBox(parent, message, title, flags); + return (result == IDYES || result == IDOK) ? + MESSAGE_BOX_RESULT_YES : MESSAGE_BOX_RESULT_NO; } } // namespace chrome diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi index bc3b67a..29d9558 100644 --- a/chrome/chrome_browser_ui.gypi +++ b/chrome/chrome_browser_ui.gypi @@ -868,6 +868,8 @@ 'browser/ui/extensions/app_metro_infobar_delegate_win.h', 'browser/ui/extensions/application_launch.cc', 'browser/ui/extensions/application_launch.h', + 'browser/ui/extensions/apps_metro_handler_win.cc', + 'browser/ui/extensions/apps_metro_handler_win.h', 'browser/ui/extensions/extension_install_ui_default.cc', 'browser/ui/extensions/extension_install_ui_default.h', 'browser/ui/extensions/extension_enable_flow.cc', |