diff options
author | skerner@google.com <skerner@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-30 03:17:11 +0000 |
---|---|---|
committer | skerner@google.com <skerner@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-30 03:17:11 +0000 |
commit | a3b734b1277c1cd57819f4f0f754ad880cd32f3d (patch) | |
tree | 0796ef9750bea984bd1c44168eccd75f5fbe93cd | |
parent | 381bc458bfc58a239f3dfe69b008c6d3522869a2 (diff) | |
download | chromium_src-a3b734b1277c1cd57819f4f0f754ad880cd32f3d.zip chromium_src-a3b734b1277c1cd57819f4f0f754ad880cd32f3d.tar.gz chromium_src-a3b734b1277c1cd57819f4f0f754ad880cd32f3d.tar.bz2 |
Add "create Application Shortcut" to the app menu on NTP.
BUG=52451
TEST=Manually create app shortcuts for urls and apps.
Review URL: http://codereview.chromium.org/5273004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@67664 0039d316-1c4b-4281-b951-d872f2087c98
26 files changed, 509 insertions, 148 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 87c6a8f..e61f3ec 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd @@ -7517,6 +7517,10 @@ Keep your key file in a safe place. You will need it to create new versions of y desc="Text for the button that takes the user to the options of an app."> Options </message> + <message name="IDS_NEW_TAB_APP_CREATE_SHORTCUT" + desc="Text for the button that creates an app shortcut."> + Create shortcut + </message> <message name="IDS_APP_CONTEXT_MENU_OPEN_PINNED" desc="Text for the button that opens the app in a pinned tab."> Open as pinned tab diff --git a/chrome/browser/browser_main.cc b/chrome/browser/browser_main.cc index 1e57561..0d3ddb3 100644 --- a/chrome/browser/browser_main.cc +++ b/chrome/browser/browser_main.cc @@ -1177,6 +1177,7 @@ int BrowserMain(const MainFunctionParams& parameters) { // (first run) UI. if (!first_run_ui_bypass && (parsed_command_line.HasSwitch(switches::kApp) || + parsed_command_line.HasSwitch(switches::kAppId) || parsed_command_line.HasSwitch(switches::kNoFirstRun))) first_run_ui_bypass = true; } diff --git a/chrome/browser/cocoa/browser_window_cocoa.h b/chrome/browser/cocoa/browser_window_cocoa.h index 1e9cf22..97038cd 100644 --- a/chrome/browser/cocoa/browser_window_cocoa.h +++ b/chrome/browser/cocoa/browser_window_cocoa.h @@ -100,7 +100,9 @@ class BrowserWindowCocoa : public BrowserWindow, virtual bool PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event, bool* is_keyboard_shortcut); virtual void HandleKeyboardEvent(const NativeWebKeyboardEvent& event); - virtual void ShowCreateShortcutsDialog(TabContents* tab_contents); + virtual void ShowCreateWebAppShortcutsDialog(TabContents* tab_contents); + virtual void ShowCreateChromeAppShortcutsDialog(Profile* profile, + const Extension* app); virtual void Cut(); virtual void Copy(); virtual void Paste(); diff --git a/chrome/browser/cocoa/browser_window_cocoa.mm b/chrome/browser/cocoa/browser_window_cocoa.mm index 63cb997..57dc7a2 100644 --- a/chrome/browser/cocoa/browser_window_cocoa.mm +++ b/chrome/browser/cocoa/browser_window_cocoa.mm @@ -549,7 +549,13 @@ bool BrowserWindowCocoa::HandleKeyboardEventInternal(NSEvent* event) { return [event_window redispatchKeyEvent:event]; } -void BrowserWindowCocoa::ShowCreateShortcutsDialog(TabContents* tab_contents) { +void BrowserWindowCocoa::ShowCreateWebAppShortcutsDialog( + TabContents* tab_contents) { + NOTIMPLEMENTED(); +} + +void BrowserWindowCocoa::ShowCreateChromeAppShortcutsDialog( + Profile* profile, const Extension* app) { NOTIMPLEMENTED(); } diff --git a/chrome/browser/dom_ui/app_launcher_handler.cc b/chrome/browser/dom_ui/app_launcher_handler.cc index e57dfdc..74bea4b 100644 --- a/chrome/browser/dom_ui/app_launcher_handler.cc +++ b/chrome/browser/dom_ui/app_launcher_handler.cc @@ -20,6 +20,7 @@ #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_list.h" +#include "chrome/browser/ui/browser_window.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/extension_constants.h" @@ -97,7 +98,8 @@ void AppLauncherHandler::CreateAppInfo(const Extension* extension, std::string("chrome://favicon/") + extension->GetFullLaunchURL().spec())); value->SetInteger("launch_container", extension->launch_container()); value->SetInteger("launch_type", - extension_prefs->GetLaunchType(extension->id())); + extension_prefs->GetLaunchType(extension->id(), + ExtensionPrefs::LAUNCH_REGULAR)); int app_launch_index = extension_prefs->GetAppLaunchIndex(extension->id()); if (app_launch_index == -1) { @@ -137,6 +139,8 @@ void AppLauncherHandler::RegisterMessages() { NewCallback(this, &AppLauncherHandler::HandleUninstallApp)); dom_ui_->RegisterMessageCallback("hideAppsPromo", NewCallback(this, &AppLauncherHandler::HandleHideAppsPromo)); + dom_ui_->RegisterMessageCallback("createAppShortcut", + NewCallback(this, &AppLauncherHandler::HandleCreateAppShortcut)); } void AppLauncherHandler::Observe(NotificationType type, @@ -193,11 +197,9 @@ void AppLauncherHandler::FillAppDictionary(DictionaryValue* dictionary) { #if defined(OS_MACOSX) // App windows are not yet implemented on mac. - bool disable_app_window_launch = true; -#else - bool disable_app_window_launch = false; + dictionary->SetBoolean("disableAppWindowLaunch", true); + dictionary->SetBoolean("disableCreateAppShortcut", true); #endif - dictionary->SetBoolean("disableAppWindowLaunch", disable_app_window_launch); } void AppLauncherHandler::HandleGetApps(const ListValue* args) { @@ -257,14 +259,11 @@ void AppLauncherHandler::HandleLaunchApp(const ListValue* args) { AnimateAppIcon(extension, rect); + // Look at preference to find the right launch container. If no preference + // is set, launch as a regular tab. extension_misc::LaunchContainer launch_container = - extension->launch_container(); - ExtensionPrefs::LaunchType prefs_launch_type = - extensions_service_->extension_prefs()->GetLaunchType(extension_id); - - // If the user chose to open in a window, change the container type. - if (prefs_launch_type == ExtensionPrefs::LAUNCH_WINDOW) - launch_container = extension_misc::LAUNCH_WINDOW; + extensions_service_->extension_prefs()->GetLaunchContainer( + extension, ExtensionPrefs::LAUNCH_REGULAR); TabContents* new_contents = Browser::OpenApplication( profile, extension, launch_container, old_contents); @@ -328,6 +327,24 @@ void AppLauncherHandler::HandleHideAppsPromo(const ListValue* args) { extensions_service_->default_apps()->SetPromoHidden(); } +void AppLauncherHandler::HandleCreateAppShortcut(const ListValue* args) { + std::string extension_id; + if (!args->GetString(0, &extension_id)) { + NOTREACHED(); + return; + } + + const Extension* extension = + extensions_service_->GetExtensionById(extension_id, false); + CHECK(extension); + + Browser* browser = BrowserList::GetLastActive(); + if (!browser) + return; + browser->window()->ShowCreateChromeAppShortcutsDialog( + browser->profile(), extension); +} + // static void AppLauncherHandler::RecordWebStoreLaunch(bool promo_active) { if (!promo_active) return; diff --git a/chrome/browser/dom_ui/app_launcher_handler.h b/chrome/browser/dom_ui/app_launcher_handler.h index 1ebeaf7..2f93c9b 100644 --- a/chrome/browser/dom_ui/app_launcher_handler.h +++ b/chrome/browser/dom_ui/app_launcher_handler.h @@ -67,6 +67,9 @@ class AppLauncherHandler // Callback for the "hideAppPromo" message. void HandleHideAppsPromo(const ListValue* args); + // Callback for the "createAppShortcut" message. + void HandleCreateAppShortcut(const ListValue* args); + private: // Records a web store launch in the appropriate histograms. |promo_active| // specifies if the web store promotion was active. diff --git a/chrome/browser/dom_ui/ntp_resource_cache.cc b/chrome/browser/dom_ui/ntp_resource_cache.cc index 9f25058..5770e4d 100644 --- a/chrome/browser/dom_ui/ntp_resource_cache.cc +++ b/chrome/browser/dom_ui/ntp_resource_cache.cc @@ -314,6 +314,8 @@ void NTPResourceCache::CreateNewTabHTML() { l10n_util::GetStringUTF16(IDS_NEW_TAB_APP_UNINSTALL)); localized_strings.SetString("appoptions", l10n_util::GetStringUTF16(IDS_NEW_TAB_APP_OPTIONS)); + localized_strings.SetString("appcreateshortcut", + l10n_util::GetStringUTF16(IDS_NEW_TAB_APP_CREATE_SHORTCUT)); localized_strings.SetString("applaunchtypepinned", l10n_util::GetStringUTF16(IDS_APP_CONTEXT_MENU_OPEN_PINNED)); localized_strings.SetString("applaunchtyperegular", diff --git a/chrome/browser/extensions/extension_prefs.cc b/chrome/browser/extensions/extension_prefs.cc index b4e706d..96e497f 100644 --- a/chrome/browser/extensions/extension_prefs.cc +++ b/chrome/browser/extensions/extension_prefs.cc @@ -564,25 +564,46 @@ void ExtensionPrefs::SetAllowFileAccess(const std::string& extension_id, } ExtensionPrefs::LaunchType ExtensionPrefs::GetLaunchType( - const std::string& extension_id) { - int value; + const std::string& extension_id, + ExtensionPrefs::LaunchType default_pref_value) { + int value = -1; + LaunchType result = LAUNCH_REGULAR; + if (ReadExtensionPrefInteger(extension_id, kPrefLaunchType, &value) && (value == LAUNCH_PINNED || value == LAUNCH_REGULAR || value == LAUNCH_FULLSCREEN || value == LAUNCH_WINDOW)) { - -#if defined(OS_MACOSX) + result = static_cast<LaunchType>(value); + } else { + result = default_pref_value; + } + #if defined(OS_MACOSX) // App windows are not yet supported on mac. Pref sync could make // the launch type LAUNCH_WINDOW, even if there is no UI to set it // on mac. - if (value == LAUNCH_WINDOW) - return LAUNCH_REGULAR; -#endif - return static_cast<LaunchType>(value); - } + if (result == LAUNCH_WINDOW) + result = LAUNCH_REGULAR; + #endif + + return result; +} + +extension_misc::LaunchContainer ExtensionPrefs::GetLaunchContainer( + const Extension* extension, + ExtensionPrefs::LaunchType default_pref_value) { + extension_misc::LaunchContainer launch_container = + extension->launch_container(); + + ExtensionPrefs::LaunchType prefs_launch_type = + GetLaunchType(extension->id(), default_pref_value); + + // If the user chose to open in a window, then launch in one. + if (prefs_launch_type == ExtensionPrefs::LAUNCH_WINDOW) + return extension_misc::LAUNCH_WINDOW; - return LAUNCH_REGULAR; + // Otherwise, use the container the extension chose. + return launch_container; } void ExtensionPrefs::SetLaunchType(const std::string& extension_id, diff --git a/chrome/browser/extensions/extension_prefs.h b/chrome/browser/extensions/extension_prefs.h index 26e4327..6245eda 100644 --- a/chrome/browser/extensions/extension_prefs.h +++ b/chrome/browser/extensions/extension_prefs.h @@ -158,9 +158,21 @@ class ExtensionPrefs { bool AllowFileAccess(const std::string& extension_id); void SetAllowFileAccess(const std::string& extension_id, bool allow); - ExtensionPrefs::LaunchType GetLaunchType(const std::string& extension_id); + // Get the launch type preference. If no preference is set, return + // |default_pref_value|. + LaunchType GetLaunchType(const std::string& extension_id, + LaunchType default_pref_value); + void SetLaunchType(const std::string& extension_id, LaunchType launch_type); + // Find the right launch container based on the launch type. + // If |extension|'s prefs do not have a launch type set, then + // use |default_pref_value|. + extension_misc::LaunchContainer GetLaunchContainer( + const Extension* extension, + LaunchType default_pref_value); + + // Saves ExtensionInfo for each installed extension with the path to the // version directory and the location. Blacklisted extensions won't be saved // and neither will external extensions the user has explicitly uninstalled. diff --git a/chrome/browser/gtk/browser_window_gtk.cc b/chrome/browser/gtk/browser_window_gtk.cc index f175e71..06dac0d 100644 --- a/chrome/browser/gtk/browser_window_gtk.cc +++ b/chrome/browser/gtk/browser_window_gtk.cc @@ -1085,8 +1085,14 @@ void BrowserWindowGtk::HandleKeyboardEvent( gtk_window_activate_key(window_, os_event); } -void BrowserWindowGtk::ShowCreateShortcutsDialog(TabContents* tab_contents) { - CreateApplicationShortcutsDialogGtk::Show(window_, tab_contents); +void BrowserWindowGtk::ShowCreateWebAppShortcutsDialog( + TabContents* tab_contents) { + CreateWebApplicationShortcutsDialogGtk::Show(window_, tab_contents); +} + +void BrowserWindowGtk::ShowCreateChromeAppShortcutsDialog( + Profile* profile, const Extension* app) { + CreateChromeApplicationShortcutsDialogGtk::Show(window_, app); } void BrowserWindowGtk::Cut() { diff --git a/chrome/browser/gtk/browser_window_gtk.h b/chrome/browser/gtk/browser_window_gtk.h index 1a73b0f..a00cf4b 100644 --- a/chrome/browser/gtk/browser_window_gtk.h +++ b/chrome/browser/gtk/browser_window_gtk.h @@ -119,7 +119,9 @@ class BrowserWindowGtk : public BrowserWindow, virtual bool PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event, bool* is_keyboard_shortcut); virtual void HandleKeyboardEvent(const NativeWebKeyboardEvent& event); - virtual void ShowCreateShortcutsDialog(TabContents* tab_contents); + virtual void ShowCreateWebAppShortcutsDialog(TabContents* tab_contents); + virtual void ShowCreateChromeAppShortcutsDialog(Profile* profile, + const Extension* app); virtual void Cut(); virtual void Copy(); virtual void Paste(); diff --git a/chrome/browser/gtk/create_application_shortcuts_dialog_gtk.cc b/chrome/browser/gtk/create_application_shortcuts_dialog_gtk.cc index d748622..34ee5a7 100644 --- a/chrome/browser/gtk/create_application_shortcuts_dialog_gtk.cc +++ b/chrome/browser/gtk/create_application_shortcuts_dialog_gtk.cc @@ -15,6 +15,8 @@ #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tab_contents/tab_contents_delegate.h" #include "chrome/browser/web_applications/web_app.h" +#include "chrome/common/extensions/extension.h" +#include "chrome/common/extensions/extension_resource.h" #include "gfx/gtk_util.h" #include "grit/chromium_strings.h" #include "grit/generated_resources.h" @@ -31,24 +33,29 @@ const int kDescriptionLabelHeightLines = 3; } // namespace // static -void CreateApplicationShortcutsDialogGtk::Show(GtkWindow* parent, - TabContents* tab_contents) { - new CreateApplicationShortcutsDialogGtk(parent, tab_contents); +void CreateWebApplicationShortcutsDialogGtk::Show(GtkWindow* parent, + TabContents* tab_contents) { + new CreateWebApplicationShortcutsDialogGtk(parent, tab_contents); } +void CreateChromeApplicationShortcutsDialogGtk::Show(GtkWindow* parent, + const Extension* app) { + new CreateChromeApplicationShortcutsDialogGtk(parent, app); +} + + CreateApplicationShortcutsDialogGtk::CreateApplicationShortcutsDialogGtk( - GtkWindow* parent, - TabContents* tab_contents) - : tab_contents_(tab_contents), - error_dialog_(NULL) { + GtkWindow* parent) + : parent_(parent), + error_dialog_(NULL) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); // Will be balanced by Release later. AddRef(); +} - // Get shortcut information now, it's needed for our UI. - web_app::GetShortcutInfoForTab(tab_contents_, &shortcut_info_); - +void CreateApplicationShortcutsDialogGtk::CreateIconPixBuf( + const SkBitmap& bitmap) { // Prepare the icon. Try to scale it if it's too small, otherwise it would // look weird. GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&shortcut_info_.favicon); @@ -56,7 +63,7 @@ CreateApplicationShortcutsDialogGtk::CreateApplicationShortcutsDialogGtk( int pixbuf_height = gdk_pixbuf_get_height(pixbuf); if (pixbuf_width == pixbuf_height && pixbuf_width < kIconPreviewSizePixels) { // Only scale the pixbuf if it's a square (for simplicity). - // Generally it should be square, if it's a favicon. + // Generally it should be square, if it's a favicon or app icon. // Use the highest quality interpolation. The scaling is // going to have low quality anyway, because the initial image // is likely small. @@ -68,7 +75,9 @@ CreateApplicationShortcutsDialogGtk::CreateApplicationShortcutsDialogGtk( } else { favicon_pixbuf_ = pixbuf; } +} +void CreateApplicationShortcutsDialogGtk::CreateDialogBox(GtkWindow* parent) { // Build the dialog. create_dialog_ = gtk_dialog_new_with_buttons( l10n_util::GetStringUTF8(IDS_CREATE_SHORTCUTS_TITLE).c_str(), @@ -171,8 +180,7 @@ void CreateApplicationShortcutsDialogGtk::OnCreateDialogResponse( &CreateApplicationShortcutsDialogGtk::CreateDesktopShortcut, shortcut_info_)); - if (tab_contents_->delegate()) - tab_contents_->delegate()->ConvertContentsToApplication(tab_contents_); + OnCreatedShortcut(); } else { Release(); } @@ -253,3 +261,65 @@ void CreateApplicationShortcutsDialogGtk::OnToggleCheckbox(GtkWidget* sender) { GTK_RESPONSE_ACCEPT, can_accept); } + +CreateWebApplicationShortcutsDialogGtk::CreateWebApplicationShortcutsDialogGtk( + GtkWindow* parent, + TabContents* tab_contents) + : CreateApplicationShortcutsDialogGtk(parent), + tab_contents_(tab_contents) { + + // Get shortcut information now, it's needed for our UI. + web_app::GetShortcutInfoForTab(tab_contents_, &shortcut_info_); + CreateIconPixBuf(shortcut_info_.favicon); + + CreateDialogBox(parent); +} + +void CreateWebApplicationShortcutsDialogGtk::OnCreatedShortcut() { + if (tab_contents_->delegate()) + tab_contents_->delegate()->ConvertContentsToApplication(tab_contents_); +} + +CreateChromeApplicationShortcutsDialogGtk:: + CreateChromeApplicationShortcutsDialogGtk( + GtkWindow* parent, + const Extension* app) + : CreateApplicationShortcutsDialogGtk(parent), + app_(app), + ALLOW_THIS_IN_INITIALIZER_LIST(tracker_(this)) { + + // Get shortcut information now, it's needed for our UI. + shortcut_info_.extension_id = UTF8ToUTF16(app_->id()); + shortcut_info_.url = GURL(app_->launch_web_url()); + shortcut_info_.title = UTF8ToUTF16(app_->name()); + shortcut_info_.description = UTF8ToUTF16(app_->description()); + + // Get the icon. + const gfx::Size max_size(kIconPreviewSizePixels, kIconPreviewSizePixels); + ExtensionResource icon_resource = app_->GetIconResource( + kIconPreviewSizePixels, ExtensionIconSet::MATCH_BIGGER); + + // If no icon exists that is the desired size or larger, get the + // largest icon available: + if (icon_resource.empty()) + icon_resource = app_->GetIconResource( + kIconPreviewSizePixels, ExtensionIconSet::MATCH_SMALLER); + + tracker_.LoadImage(app_, + icon_resource, + max_size, + ImageLoadingTracker::DONT_CACHE); +} + +// Called by tracker_ when the app's icon is loaded. +void CreateChromeApplicationShortcutsDialogGtk::OnImageLoaded( + SkBitmap* image, ExtensionResource resource, int index) { + if (image->isNull()) { + NOTREACHED() << "Corrupt image in profile?"; + return; + } + shortcut_info_.favicon = *image; + + CreateIconPixBuf(*image); + CreateDialogBox(parent_); +} diff --git a/chrome/browser/gtk/create_application_shortcuts_dialog_gtk.h b/chrome/browser/gtk/create_application_shortcuts_dialog_gtk.h index 054a0bd..5570e0c 100644 --- a/chrome/browser/gtk/create_application_shortcuts_dialog_gtk.h +++ b/chrome/browser/gtk/create_application_shortcuts_dialog_gtk.h @@ -10,6 +10,7 @@ #include "base/basictypes.h" #include "base/ref_counted.h" #include "chrome/browser/browser_thread.h" +#include "chrome/browser/extensions/image_loading_tracker.h" #include "chrome/browser/shell_integration.h" #include "googleurl/src/gurl.h" @@ -17,21 +18,14 @@ typedef struct _GdkPixbuf GdkPixbuf; typedef struct _GtkWidget GtkWidget; typedef struct _GtkWindow GtkWindow; +class Extension; class TabContents; class CreateApplicationShortcutsDialogGtk : public base::RefCountedThreadSafe<CreateApplicationShortcutsDialogGtk, BrowserThread::DeleteOnUIThread> { - public: - // Displays the dialog box to create application shortcuts for |tab_contents|. - static void Show(GtkWindow* parent, TabContents* tab_contents); - - private: - friend class BrowserThread; - friend class DeleteTask<CreateApplicationShortcutsDialogGtk>; - - CreateApplicationShortcutsDialogGtk(GtkWindow* parent, - TabContents* tab_contents); + protected: + explicit CreateApplicationShortcutsDialogGtk(GtkWindow* parent); virtual ~CreateApplicationShortcutsDialogGtk(); CHROMEGTK_CALLBACK_1(CreateApplicationShortcutsDialogGtk, void, @@ -43,17 +37,23 @@ class CreateApplicationShortcutsDialogGtk CHROMEGTK_CALLBACK_0(CreateApplicationShortcutsDialogGtk, void, OnToggleCheckbox); + virtual void CreateDialogBox(GtkWindow* parent); + virtual void CreateIconPixBuf(const SkBitmap& bitmap); + + // This method is called after a shortcut is created. + // Subclasses can override it to take some action at that time. + virtual void OnCreatedShortcut(void) {} + void CreateDesktopShortcut( const ShellIntegration::ShortcutInfo& shortcut_info); void ShowErrorDialog(); + GtkWindow* parent_; + // UI elements. GtkWidget* desktop_checkbox_; GtkWidget* menu_checkbox_; - // TabContents for which the shortcut will be created. - TabContents* tab_contents_; - // ShortcutInfo for the new shortcut. ShellIntegration::ShortcutInfo shortcut_info_; @@ -66,7 +66,54 @@ class CreateApplicationShortcutsDialogGtk // Dialog box that shows the error message. GtkWidget* error_dialog_; + private: + friend class BrowserThread; + friend class DeleteTask<CreateApplicationShortcutsDialogGtk>; DISALLOW_COPY_AND_ASSIGN(CreateApplicationShortcutsDialogGtk); }; +class CreateWebApplicationShortcutsDialogGtk + : public CreateApplicationShortcutsDialogGtk { + public: + // Displays the dialog box to create application shortcuts for |tab_contents|. + static void Show(GtkWindow* parent, TabContents* tab_contents); + + explicit CreateWebApplicationShortcutsDialogGtk(GtkWindow* parent, + TabContents* tab_contents); + virtual ~CreateWebApplicationShortcutsDialogGtk() {} + + virtual void OnCreatedShortcut(void); + + private: + + // TabContents for which the shortcut will be created. + TabContents* tab_contents_; + + DISALLOW_COPY_AND_ASSIGN(CreateWebApplicationShortcutsDialogGtk); +}; + +class CreateChromeApplicationShortcutsDialogGtk + : public CreateApplicationShortcutsDialogGtk, + public ImageLoadingTracker::Observer { + public: + // Displays the dialog box to create application shortcuts for |app|. + static void Show(GtkWindow* parent, const Extension* app); + + explicit CreateChromeApplicationShortcutsDialogGtk(GtkWindow* parent, + const Extension* app); + virtual ~CreateChromeApplicationShortcutsDialogGtk() {} + + // Implement ImageLoadingTracker::Observer. |tracker_| is used to + // load the app's icon. This method recieves the icon, and adds + // it to the "Create Shortcut" dailog box. + virtual void OnImageLoaded(SkBitmap* image, + ExtensionResource resource, + int index); + + private: + const Extension* app_; + ImageLoadingTracker tracker_; + DISALLOW_COPY_AND_ASSIGN(CreateChromeApplicationShortcutsDialogGtk); +}; + #endif // CHROME_BROWSER_GTK_CREATE_APPLICATION_SHORTCUTS_DIALOG_GTK_H_ diff --git a/chrome/browser/resources/new_new_tab.html b/chrome/browser/resources/new_new_tab.html index cd2613c..2eeccca 100644 --- a/chrome/browser/resources/new_new_tab.html +++ b/chrome/browser/resources/new_new_tab.html @@ -232,6 +232,8 @@ if ('mode' in hashParams) { <command id="apps-launch-command"> <command id="apps-options-command" i18n-values=".label:appoptions"> <command id="apps-uninstall-command" i18n-values=".label:appuninstall"> +<command id="apps-create-shortcut-command" + i18n-values=".label:appcreateshortcut"> <command id="apps-launch-type-pinned" i18n-values=".label:applaunchtypepinned" launch-type="0"> <command id="apps-launch-type-regular" i18n-values=".label:applaunchtyperegular" @@ -257,6 +259,8 @@ if ('mode' in hashParams) { <hr> <button command="#apps-options-command"></button> <button command="#apps-uninstall-command"></button> + <button id="apps-create-shortcut-command-menu-item" + command="#apps-create-shortcut-command"></button> </menu> </body> diff --git a/chrome/browser/resources/ntp/apps.js b/chrome/browser/resources/ntp/apps.js index 3cbfc9e..9c032fe 100644 --- a/chrome/browser/resources/ntp/apps.js +++ b/chrome/browser/resources/ntp/apps.js @@ -21,10 +21,16 @@ function getAppsCallback(data) { var appsPromoPing = PING_WEBSTORE_LAUNCH_PREFIX + '+' + data.showPromo; var webStoreEntry; - // Hide the app window menu option on platforms that do not support it. + // Hide menu options that are not supported on the OS or windowing system. + + // The "Launch as Window" menu option. $('apps-launch-type-window-menu-item').style.display = (data.disableAppWindowLaunch ? 'none' : 'inline'); + // The "Create App Shortcut" menu option. + $('apps-create-shortcut-command-menu-item').style.display = + (data.disableCreateAppShortcut ? 'none' : 'inline'); + appsMiniview.textContent = ''; appsSectionContent.textContent = ''; @@ -218,6 +224,9 @@ var apps = (function() { case 'apps-uninstall-command': chrome.send('uninstallApp', [currentApp['id']]); break; + case 'apps-create-shortcut-command': + chrome.send('createAppShortcut', [currentApp['id']]); + break; case 'apps-launch-type-pinned': case 'apps-launch-type-regular': case 'apps-launch-type-fullscreen': diff --git a/chrome/browser/shell_integration.cc b/chrome/browser/shell_integration.cc index 13782d8..4b6b2a5d 100644 --- a/chrome/browser/shell_integration.cc +++ b/chrome/browser/shell_integration.cc @@ -52,7 +52,7 @@ std::string ShellIntegration::GetCommandLineArgumentsCommon(const GURL& url, // during launch. if (!extension_app_id.empty()) { arguments_w += std::wstring(L"--") + ASCIIToWide(switches::kAppId) + - L"=\"" + ASCIIToWide(UTF16ToASCII(extension_app_id)); + L"=\"" + ASCIIToWide(UTF16ToASCII(extension_app_id)) + L"\""; } else { // Use '--app=url' instead of just 'url' to launch the browser with minimal // chrome. diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index 24f7c6f..e91f4c7 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc @@ -610,7 +610,8 @@ TabContents* Browser::OpenApplicationTab(Profile* profile, DCHECK(extensions_service); ExtensionPrefs::LaunchType launch_type = - extensions_service->extension_prefs()->GetLaunchType(extension->id()); + extensions_service->extension_prefs()->GetLaunchType( + extension->id(), ExtensionPrefs::LAUNCH_REGULAR); UMA_HISTOGRAM_ENUMERATION("Extensions.AppTabLaunchType", launch_type, 100); int add_type = TabStripModel::ADD_SELECTED; if (launch_type == ExtensionPrefs::LAUNCH_PINNED) @@ -3130,7 +3131,7 @@ void Browser::OnDidGetApplicationInfo(TabContents* tab_contents, switch (pending_web_app_action_) { case CREATE_SHORTCUT: { - window()->ShowCreateShortcutsDialog(current_tab); + window()->ShowCreateWebAppShortcutsDialog(current_tab); break; } case UPDATE_SHORTCUT: { diff --git a/chrome/browser/ui/browser_init.cc b/chrome/browser/ui/browser_init.cc index e0a7ff5..cc26ca6 100644 --- a/chrome/browser/ui/browser_init.cc +++ b/chrome/browser/ui/browser_init.cc @@ -620,8 +620,25 @@ bool BrowserInit::LaunchWithProfile::OpenApplicationWindow(Profile* profile) { // extension is external, and has not yet been installed. // TODO(skerner): Do something reasonable here. Pop up a warning panel? // Open an URL to the gallery page of the extension id? - if (!app_id.empty()) - return Browser::OpenApplication(profile, app_id, NULL) != NULL; + if (!app_id.empty()) { + ExtensionsService* extensions_service = profile->GetExtensionsService(); + const Extension* extension = + extensions_service->GetExtensionById(app_id, false); + + // The extension with |app_id| may have been uninstalled. + if (!extension) + return false; + + // Look at prefs to find the container in which an app should launch. + // If no preference is set, launch in a window. + extension_misc::LaunchContainer launch_container = + extensions_service->extension_prefs()->GetLaunchContainer( + extension, ExtensionPrefs::LAUNCH_WINDOW); + + TabContents* app_window = Browser::OpenApplication( + profile, extension, launch_container, NULL); + return (app_window != NULL); + } if (url_string.empty()) return false; diff --git a/chrome/browser/ui/browser_window.h b/chrome/browser/ui/browser_window.h index 6780411..810bf92 100644 --- a/chrome/browser/ui/browser_window.h +++ b/chrome/browser/ui/browser_window.h @@ -36,6 +36,8 @@ namespace views { class Window; } +class Extension; + //////////////////////////////////////////////////////////////////////////////// // BrowserWindow interface // An interface implemented by the "view" of the Browser window. @@ -295,7 +297,11 @@ class BrowserWindow { virtual void HandleKeyboardEvent(const NativeWebKeyboardEvent& event) = 0; // Shows the create web app shortcut dialog box. - virtual void ShowCreateShortcutsDialog(TabContents* tab_contents) = 0; + virtual void ShowCreateWebAppShortcutsDialog(TabContents* tab_contents) = 0; + + // Shows the create chrome app shortcut dialog box. + virtual void ShowCreateChromeAppShortcutsDialog(Profile* profile, + const Extension* app) = 0; // Clipboard commands applied to the whole browser window. virtual void Cut() = 0; diff --git a/chrome/browser/ui/views/browser_dialogs.h b/chrome/browser/ui/views/browser_dialogs.h index 66d7d8f..f49cc2a 100644 --- a/chrome/browser/ui/views/browser_dialogs.h +++ b/chrome/browser/ui/views/browser_dialogs.h @@ -19,6 +19,7 @@ class Browser; class BrowserView; class EditSearchEngineControllerDelegate; +class Extension; class FilePath; class FindBar; class GURL; @@ -121,9 +122,15 @@ void ShowContentSettingsWindow(gfx::NativeWindow parent_window, void ShowCollectedCookiesDialog(gfx::NativeWindow parent_window, TabContents* tab_contents); + // Shows the create web app shortcut dialog box. -void ShowCreateShortcutsDialog(gfx::NativeWindow parent_window, - TabContents* tab_contents); +void ShowCreateWebAppShortcutsDialog(gfx::NativeWindow parent_window, + TabContents* tab_contents); + +// Shows the create chrome app shortcut dialog box. +void ShowCreateChromeAppShortcutsDialog(gfx::NativeWindow parent_window, + Profile* profile, + const Extension* app); } // namespace browser diff --git a/chrome/browser/ui/views/create_application_shortcut_view.cc b/chrome/browser/ui/views/create_application_shortcut_view.cc index f0ec8ee..2867c9a 100644 --- a/chrome/browser/ui/views/create_application_shortcut_view.cc +++ b/chrome/browser/ui/views/create_application_shortcut_view.cc @@ -14,6 +14,8 @@ #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tab_contents/tab_contents_delegate.h" #include "chrome/common/chrome_constants.h" +#include "chrome/common/extensions/extension.h" +#include "chrome/common/extensions/extension_resource.h" #include "chrome/common/pref_names.h" #include "gfx/canvas_skia.h" #include "gfx/codec/png_codec.h" @@ -30,6 +32,7 @@ #include "views/standard_layout.h" #include "views/window/window.h" + #if defined(OS_WIN) #include "base/win_util.h" #endif // defined(OS_WIN) @@ -188,21 +191,28 @@ void AppInfoView::Paint(gfx::Canvas* canvas) { inner_rect, SkIntToScalar(1.5), SkIntToScalar(1.5), inner_paint); } -}; // namespace +} // namespace namespace browser { -void ShowCreateShortcutsDialog(gfx::NativeWindow parent_window, - TabContents* tab_contents) { +void ShowCreateWebAppShortcutsDialog(gfx::NativeWindow parent_window, + TabContents* tab_contents) { + views::Window::CreateChromeWindow(parent_window, gfx::Rect(), + new CreateUrlApplicationShortcutView(tab_contents))->Show(); +} + +void ShowCreateChromeAppShortcutsDialog(gfx::NativeWindow parent_window, + Profile* profile, + const Extension* app) { views::Window::CreateChromeWindow(parent_window, gfx::Rect(), - new CreateApplicationShortcutView(tab_contents))->Show(); + new CreateChromeApplicationShortcutView(profile, app))->Show(); } -}; // namespace browser +} // namespace browser -class CreateApplicationShortcutView::IconDownloadCallbackFunctor { +class CreateUrlApplicationShortcutView::IconDownloadCallbackFunctor { public: - explicit IconDownloadCallbackFunctor(CreateApplicationShortcutView* owner) + explicit IconDownloadCallbackFunctor(CreateUrlApplicationShortcutView* owner) : owner_(owner) { } @@ -217,31 +227,15 @@ class CreateApplicationShortcutView::IconDownloadCallbackFunctor { } private: - CreateApplicationShortcutView* owner_; + CreateUrlApplicationShortcutView* owner_; }; -CreateApplicationShortcutView::CreateApplicationShortcutView( - TabContents* tab_contents) - : tab_contents_(tab_contents), - pending_download_(NULL) { - Init(); -} - -CreateApplicationShortcutView::~CreateApplicationShortcutView() { - if (pending_download_) - pending_download_->Cancel(); -} - -void CreateApplicationShortcutView::Init() { - // Prepare data - web_app::GetShortcutInfoForTab(tab_contents_, &shortcut_info_); +CreateApplicationShortcutView::CreateApplicationShortcutView(Profile* profile) + : profile_(profile) {} - const WebApplicationInfo& app_info = tab_contents_->web_app_info(); - if (!app_info.icons.empty()) { - web_app::GetIconsInfo(app_info, &unprocessed_icons_); - FetchIcon(); - } +CreateApplicationShortcutView::~CreateApplicationShortcutView() {} +void CreateApplicationShortcutView::InitControls() { // Create controls app_info_ = new AppInfoView(shortcut_info_.title, shortcut_info_.description, shortcut_info_.favicon); @@ -249,11 +243,9 @@ void CreateApplicationShortcutView::Init() { l10n_util::GetString(IDS_CREATE_SHORTCUTS_LABEL)); create_shortcuts_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); - Profile* profile = tab_contents_->profile(); - desktop_check_box_ = AddCheckbox( l10n_util::GetString(IDS_CREATE_SHORTCUTS_DESKTOP_CHKBOX), - profile->GetPrefs()->GetBoolean(prefs::kWebAppCreateOnDesktop)); + profile_->GetPrefs()->GetBoolean(prefs::kWebAppCreateOnDesktop)); menu_check_box_ = NULL; quick_launch_check_box_ = NULL; @@ -261,17 +253,17 @@ void CreateApplicationShortcutView::Init() { #if defined(OS_WIN) menu_check_box_ = AddCheckbox( l10n_util::GetString(IDS_CREATE_SHORTCUTS_START_MENU_CHKBOX), - profile->GetPrefs()->GetBoolean(prefs::kWebAppCreateInAppsMenu)); + profile_->GetPrefs()->GetBoolean(prefs::kWebAppCreateInAppsMenu)); quick_launch_check_box_ = AddCheckbox( (base::win::GetVersion() >= base::win::VERSION_WIN7) ? l10n_util::GetString(IDS_PIN_TO_TASKBAR_CHKBOX) : l10n_util::GetString(IDS_CREATE_SHORTCUTS_QUICK_LAUNCH_BAR_CHKBOX), - profile->GetPrefs()->GetBoolean(prefs::kWebAppCreateInQuickLaunchBar)); + profile_->GetPrefs()->GetBoolean(prefs::kWebAppCreateInQuickLaunchBar)); #elif defined(OS_LINUX) menu_check_box_ = AddCheckbox( l10n_util::GetString(IDS_CREATE_SHORTCUTS_MENU_CHKBOX), - profile->GetPrefs()->GetBoolean(prefs::kWebAppCreateInAppsMenu)); + profile_->GetPrefs()->GetBoolean(prefs::kWebAppCreateInAppsMenu)); #endif // Layout controls @@ -367,9 +359,8 @@ std::wstring CreateApplicationShortcutView::GetWindowTitle() const { } bool CreateApplicationShortcutView::Accept() { - if (!IsDialogButtonEnabled(MessageBoxFlags::DIALOGBUTTON_OK)) { + if (!IsDialogButtonEnabled(MessageBoxFlags::DIALOGBUTTON_OK)) return false; - } shortcut_info_.create_on_desktop = desktop_check_box_->checked(); shortcut_info_.create_in_applications_menu = menu_check_box_ == NULL ? false : @@ -384,16 +375,13 @@ bool CreateApplicationShortcutView::Accept() { shortcut_info_.create_in_quick_launch_bar = false; #endif - web_app::CreateShortcut(tab_contents_->profile()->GetPath(), + web_app::CreateShortcut(profile_->GetPath(), shortcut_info_, NULL); - - tab_contents_->SetAppIcon(shortcut_info_.favicon); - if (tab_contents_->delegate()) - tab_contents_->delegate()->ConvertContentsToApplication(tab_contents_); return true; } + views::View* CreateApplicationShortcutView::GetContentsView() { return this; } @@ -406,14 +394,59 @@ views::Checkbox* CreateApplicationShortcutView::AddCheckbox( return checkbox; } -void CreateApplicationShortcutView::FetchIcon() { +void CreateApplicationShortcutView::ButtonPressed(views::Button* sender, + const views::Event& event) { + if (sender == desktop_check_box_) + profile_->GetPrefs()->SetBoolean(prefs::kWebAppCreateOnDesktop, + desktop_check_box_->checked() ? true : false); + else if (sender == menu_check_box_) + profile_->GetPrefs()->SetBoolean(prefs::kWebAppCreateInAppsMenu, + menu_check_box_->checked() ? true : false); + else if (sender == quick_launch_check_box_) + profile_->GetPrefs()->SetBoolean(prefs::kWebAppCreateInQuickLaunchBar, + quick_launch_check_box_->checked() ? true : false); + + // When no checkbox is checked we should not have the action button enabled. + GetDialogClientView()->UpdateDialogButtons(); +} + +CreateUrlApplicationShortcutView::CreateUrlApplicationShortcutView( + TabContents* tab_contents) + : CreateApplicationShortcutView(tab_contents->profile()), + tab_contents_(tab_contents), + pending_download_(NULL) { + + web_app::GetShortcutInfoForTab(tab_contents_, &shortcut_info_); + const WebApplicationInfo& app_info = tab_contents_->web_app_info(); + if (!app_info.icons.empty()) { + web_app::GetIconsInfo(app_info, &unprocessed_icons_); + FetchIcon(); + } + + InitControls(); +} + +CreateUrlApplicationShortcutView::~CreateUrlApplicationShortcutView() { + if (pending_download_) + pending_download_->Cancel(); +} + +bool CreateUrlApplicationShortcutView::Accept() { + if (!CreateApplicationShortcutView::Accept()) + return false; + + tab_contents_->SetAppIcon(shortcut_info_.favicon); + if (tab_contents_->delegate()) + tab_contents_->delegate()->ConvertContentsToApplication(tab_contents_); + return true; +} + +void CreateUrlApplicationShortcutView::FetchIcon() { // There should only be fetch job at a time. DCHECK(pending_download_ == NULL); - if (unprocessed_icons_.empty()) { - // No icons to fetch. + if (unprocessed_icons_.empty()) // No icons to fetch. return; - } pending_download_ = new IconDownloadCallbackFunctor(this); DCHECK(pending_download_); @@ -427,25 +460,8 @@ void CreateApplicationShortcutView::FetchIcon() { unprocessed_icons_.pop_back(); } -void CreateApplicationShortcutView::ButtonPressed(views::Button* sender, - const views::Event& event) { - Profile* profile = tab_contents_->profile(); - if (sender == desktop_check_box_) - profile->GetPrefs()->SetBoolean(prefs::kWebAppCreateOnDesktop, - desktop_check_box_->checked() ? true : false); - else if (sender == menu_check_box_) - profile->GetPrefs()->SetBoolean(prefs::kWebAppCreateInAppsMenu, - menu_check_box_->checked() ? true : false); - else if (sender == quick_launch_check_box_) - profile->GetPrefs()->SetBoolean(prefs::kWebAppCreateInQuickLaunchBar, - quick_launch_check_box_->checked() ? true : false); - - // When no checkbox is checked we should not have the action button enabled. - GetDialogClientView()->UpdateDialogButtons(); -} - -void CreateApplicationShortcutView::OnIconDownloaded(bool errored, - const SkBitmap& image) { +void CreateUrlApplicationShortcutView::OnIconDownloaded(bool errored, + const SkBitmap& image) { pending_download_ = NULL; if (!errored && !image.isNull()) { @@ -455,3 +471,56 @@ void CreateApplicationShortcutView::OnIconDownloaded(bool errored, FetchIcon(); } } + +CreateChromeApplicationShortcutView::CreateChromeApplicationShortcutView( + Profile* profile, + const Extension* app) : + CreateApplicationShortcutView(profile), + app_(app), + ALLOW_THIS_IN_INITIALIZER_LIST(tracker_(this)) { + + shortcut_info_.extension_id = UTF8ToUTF16(app_->id()); + shortcut_info_.url = GURL(app_->launch_web_url()); + shortcut_info_.title = UTF8ToUTF16(app_->name()); + shortcut_info_.description = UTF8ToUTF16(app_->description()); + + // The icon will be resized to |max_size|. + const gfx::Size max_size(kAppIconSize, kAppIconSize); + + // Look for an icon. If there is no icon at the ideal size, + // we will resize whatever we can get. Making a large icon smaller + // is prefered to making a small icon larger, so look for a larger + // icon first: + ExtensionResource icon_resource = app_->GetIconResource( + kAppIconSize, + ExtensionIconSet::MATCH_BIGGER); + + // If no icon exists that is the desired size or larger, get the + // largest icon available: + if (icon_resource.empty()) { + icon_resource = app_->GetIconResource( + kAppIconSize, + ExtensionIconSet::MATCH_SMALLER); + } + + tracker_.LoadImage(app_, + icon_resource, + max_size, + ImageLoadingTracker::DONT_CACHE); + + InitControls(); +} + +CreateChromeApplicationShortcutView::~CreateChromeApplicationShortcutView() {} + +// Called by tracker_ when the app's icon is loaded. +void CreateChromeApplicationShortcutView::OnImageLoaded( + SkBitmap* image, ExtensionResource resource, int index) { + if (image->isNull()) { + NOTREACHED() << "Corrupt image in profile?"; + return; + } + shortcut_info_.favicon = *image; + static_cast<AppInfoView*>(app_info_)->UpdateIcon(shortcut_info_.favicon); +} + diff --git a/chrome/browser/ui/views/create_application_shortcut_view.h b/chrome/browser/ui/views/create_application_shortcut_view.h index f1cd707..e94bea2 100644 --- a/chrome/browser/ui/views/create_application_shortcut_view.h +++ b/chrome/browser/ui/views/create_application_shortcut_view.h @@ -8,6 +8,7 @@ #include <string> +#include "chrome/browser/extensions/image_loading_tracker.h" #include "chrome/browser/web_applications/web_app.h" #include "views/controls/label.h" #include "views/view.h" @@ -20,21 +21,25 @@ class Label; class Window; }; // namespace views +class Extension; class MessageLoop; class Profile; class TabContents; -// CreateShortcutView implements a dialog that asks user where to create -// the shortcut for given web app. +// CreateShortcutViewCommon implements a dialog that asks user where to create +// the shortcut for given web app. There are two variants of this dialog: +// Shortcuts that load a URL in an app-like window, and shortcuts that load +// a chrome app (the kind you see under "apps" on the new tabs page) in an app +// window. These are implemented as subclasses of CreateShortcutViewCommon. class CreateApplicationShortcutView : public views::View, public views::DialogDelegate, public views::ButtonListener { public: - explicit CreateApplicationShortcutView(TabContents* tab_contents); + explicit CreateApplicationShortcutView(Profile* profile); virtual ~CreateApplicationShortcutView(); // Initialize the controls on the dialog. - void Init(); + void InitControls(); // Overridden from views::View: virtual gfx::Size GetPreferredSize(); @@ -56,19 +61,12 @@ class CreateApplicationShortcutView : public views::View, // Overridden from views::ButtonListener: virtual void ButtonPressed(views::Button* sender, const views::Event& event); - private: + protected: // Adds a new check-box as a child to the view. views::Checkbox* AddCheckbox(const std::wstring& text, bool checked); - // Fetch the largest unprocessed icon. - // The first largest icon downloaded and decoded successfully will be used. - void FetchIcon(); - - // Callback of icon download. - void OnIconDownloaded(bool errored, const SkBitmap& image); - - // TabContents of the page that we want to create shortcut. - TabContents* tab_contents_; + // Profile in which the shortcuts will be created. + Profile* profile_; // UI elements on the dialog. views::View* app_info_; @@ -80,14 +78,60 @@ class CreateApplicationShortcutView : public views::View, // Target shortcut info. ShellIntegration::ShortcutInfo shortcut_info_; - // Unprocessed icons from the WebApplicationInfo passed in. - web_app::IconInfoList unprocessed_icons_; + DISALLOW_COPY_AND_ASSIGN(CreateApplicationShortcutView); +}; + +// Create an application shortcut pointing to a URL. +class CreateUrlApplicationShortcutView : public CreateApplicationShortcutView { + public: + explicit CreateUrlApplicationShortcutView(TabContents* tab_contents); + virtual ~CreateUrlApplicationShortcutView(); + + virtual bool Accept(); + + private: + // Fetch the largest unprocessed icon. + // The first largest icon downloaded and decoded successfully will be used. + void FetchIcon(); + + // Callback of icon download. + void OnIconDownloaded(bool errored, const SkBitmap& image); + + // The tab whose URL is being turned into an app. + TabContents* tab_contents_; // Pending app icon download tracked by us. class IconDownloadCallbackFunctor; IconDownloadCallbackFunctor* pending_download_; - DISALLOW_COPY_AND_ASSIGN(CreateApplicationShortcutView); + // Unprocessed icons from the WebApplicationInfo passed in. + web_app::IconInfoList unprocessed_icons_; + + DISALLOW_COPY_AND_ASSIGN(CreateUrlApplicationShortcutView); }; +// Create an application shortcut pointing to a chrome application. +class CreateChromeApplicationShortcutView + : public CreateApplicationShortcutView, + public ImageLoadingTracker::Observer { + public: + explicit CreateChromeApplicationShortcutView(Profile* profile, + const Extension* app); + virtual ~CreateChromeApplicationShortcutView(); + + // Implement ImageLoadingTracker::Observer. |tracker_| is used to + // load the app's icon. This method recieves the icon, and adds + // it to the "Create Shortcut" dailog box. + virtual void OnImageLoaded(SkBitmap* image, + ExtensionResource resource, + int index); + + private: + const Extension* app_; + ImageLoadingTracker tracker_; + + DISALLOW_COPY_AND_ASSIGN(CreateChromeApplicationShortcutView); +}; + + #endif // CHROME_BROWSER_UI_VIEWS_CREATE_APPLICATION_SHORTCUT_VIEW_H_ diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index f8bba33..a9186e8 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc @@ -1167,8 +1167,13 @@ void BrowserView::ShowHTMLDialog(HtmlDialogUIDelegate* delegate, browser::ShowHtmlDialogView(parent, browser_.get()->profile(), delegate); } -void BrowserView::ShowCreateShortcutsDialog(TabContents* tab_contents) { - browser::ShowCreateShortcutsDialog(GetNativeHandle(), tab_contents); +void BrowserView::ShowCreateWebAppShortcutsDialog(TabContents* tab_contents) { + browser::ShowCreateWebAppShortcutsDialog(GetNativeHandle(), tab_contents); +} + +void BrowserView::ShowCreateChromeAppShortcutsDialog(Profile* profile, + const Extension* app) { + browser::ShowCreateChromeAppShortcutsDialog(GetNativeHandle(), profile, app); } void BrowserView::UserChangedTheme() { diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h index 380ee8b..c0464d4 100644 --- a/chrome/browser/ui/views/frame/browser_view.h +++ b/chrome/browser/ui/views/frame/browser_view.h @@ -56,6 +56,7 @@ class StatusBubbleViews; class TabStripModel; class ToolbarView; class ZoomMenuModel; +class Extension; #if defined(OS_WIN) class AeroPeekManager; @@ -315,7 +316,9 @@ class BrowserView : public BrowserBubbleHost, virtual bool PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event, bool* is_keyboard_shortcut); virtual void HandleKeyboardEvent(const NativeWebKeyboardEvent& event); - virtual void ShowCreateShortcutsDialog(TabContents* tab_contents); + virtual void ShowCreateWebAppShortcutsDialog(TabContents* tab_contents); + virtual void ShowCreateChromeAppShortcutsDialog(Profile*, + const Extension* app); virtual void Cut(); virtual void Copy(); virtual void Paste(); diff --git a/chrome/common/switch_utils.cc b/chrome/common/switch_utils.cc index d202bcb..b6acf643 100644 --- a/chrome/common/switch_utils.cc +++ b/chrome/common/switch_utils.cc @@ -14,6 +14,7 @@ namespace switches { // pick up an automatic update, be sure to add it to this list. const char* const kSwitchesToRemoveOnAutorestart[] = { switches::kApp, + switches::kAppId, switches::kFirstRun, switches::kImport, switches::kImportFromFile, diff --git a/chrome/test/test_browser_window.h b/chrome/test/test_browser_window.h index 71a15e4..b051dfb 100644 --- a/chrome/test/test_browser_window.h +++ b/chrome/test/test_browser_window.h @@ -58,7 +58,9 @@ class TestBrowserWindow : public BrowserWindow { return false; } virtual void HandleKeyboardEvent(const NativeWebKeyboardEvent& event) {} - virtual void ShowCreateShortcutsDialog(TabContents* tab_contents) {} + virtual void ShowCreateWebAppShortcutsDialog(TabContents* tab_contents) {} + virtual void ShowCreateChromeAppShortcutsDialog(Profile* profile, + const Extension* app) {} #if defined(TOOLKIT_VIEWS) virtual void ToggleCompactNavigationBar() {} #endif // defined(TOOLKIT_VIEWS) |