summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorskerner@google.com <skerner@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-30 03:17:11 +0000
committerskerner@google.com <skerner@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-30 03:17:11 +0000
commita3b734b1277c1cd57819f4f0f754ad880cd32f3d (patch)
tree0796ef9750bea984bd1c44168eccd75f5fbe93cd
parent381bc458bfc58a239f3dfe69b008c6d3522869a2 (diff)
downloadchromium_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
-rw-r--r--chrome/app/generated_resources.grd4
-rw-r--r--chrome/browser/browser_main.cc1
-rw-r--r--chrome/browser/cocoa/browser_window_cocoa.h4
-rw-r--r--chrome/browser/cocoa/browser_window_cocoa.mm8
-rw-r--r--chrome/browser/dom_ui/app_launcher_handler.cc41
-rw-r--r--chrome/browser/dom_ui/app_launcher_handler.h3
-rw-r--r--chrome/browser/dom_ui/ntp_resource_cache.cc2
-rw-r--r--chrome/browser/extensions/extension_prefs.cc41
-rw-r--r--chrome/browser/extensions/extension_prefs.h14
-rw-r--r--chrome/browser/gtk/browser_window_gtk.cc10
-rw-r--r--chrome/browser/gtk/browser_window_gtk.h4
-rw-r--r--chrome/browser/gtk/create_application_shortcuts_dialog_gtk.cc96
-rw-r--r--chrome/browser/gtk/create_application_shortcuts_dialog_gtk.h73
-rw-r--r--chrome/browser/resources/new_new_tab.html4
-rw-r--r--chrome/browser/resources/ntp/apps.js11
-rw-r--r--chrome/browser/shell_integration.cc2
-rw-r--r--chrome/browser/ui/browser.cc5
-rw-r--r--chrome/browser/ui/browser_init.cc21
-rw-r--r--chrome/browser/ui/browser_window.h8
-rw-r--r--chrome/browser/ui/views/browser_dialogs.h11
-rw-r--r--chrome/browser/ui/views/create_application_shortcut_view.cc197
-rw-r--r--chrome/browser/ui/views/create_application_shortcut_view.h78
-rw-r--r--chrome/browser/ui/views/frame/browser_view.cc9
-rw-r--r--chrome/browser/ui/views/frame/browser_view.h5
-rw-r--r--chrome/common/switch_utils.cc1
-rw-r--r--chrome/test/test_browser_window.h4
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)