summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/app/generated_resources.grd9
-rw-r--r--chrome/browser/extensions/tab_helper.cc51
-rw-r--r--chrome/browser/ui/browser_window.h11
-rw-r--r--chrome/browser/ui/cocoa/browser_window_cocoa.h3
-rw-r--r--chrome/browser/ui/cocoa/browser_window_cocoa.mm6
-rw-r--r--chrome/browser/ui/gtk/browser_window_gtk.cc6
-rw-r--r--chrome/browser/ui/gtk/browser_window_gtk.h3
-rw-r--r--chrome/browser/ui/views/extensions/bookmark_app_bubble_view.cc224
-rw-r--r--chrome/browser/ui/views/extensions/bookmark_app_bubble_view.h95
-rw-r--r--chrome/browser/ui/views/frame/browser_view.cc10
-rw-r--r--chrome/browser/ui/views/frame/browser_view.h3
-rw-r--r--chrome/chrome_browser_ui.gypi2
-rw-r--r--chrome/test/base/test_browser_window.h3
-rw-r--r--extensions/common/extension.h5
14 files changed, 398 insertions, 33 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index a930513..1221b56 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -2152,6 +2152,15 @@ Even if you have downloaded files from this website before, the website might ha
No
</message>
+ <!-- Bookmark app bubble -->
+ <message name="IDS_BOOKMARK_APP_BUBBLE_TITLE" desc="Title of the bubble to add a bookmark app.">
+ Add shortcut?
+ </message>
+
+ <message name="IDS_BOOKMARK_APP_BUBBLE_OPEN_AS_TAB" desc="Checkbox text for opening the bookmark app as a tab.">
+ Open as tab
+ </message>
+
<!-- "Create application shortcuts" menu item -->
<if expr="not pp_ifdef('use_titlecase')">
<message name="IDS_CREATE_SHORTCUTS" desc="Default installation menu label">
diff --git a/chrome/browser/extensions/tab_helper.cc b/chrome/browser/extensions/tab_helper.cc
index ffe9606..1638928 100644
--- a/chrome/browser/extensions/tab_helper.cc
+++ b/chrome/browser/extensions/tab_helper.cc
@@ -27,11 +27,10 @@
#include "chrome/browser/sessions/session_id.h"
#include "chrome/browser/sessions/session_tab_helper.h"
#include "chrome/browser/shell_integration.h"
-#include "chrome/browser/ui/app_list/app_list_service.h"
-#include "chrome/browser/ui/app_list/app_list_util.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_dialogs.h"
#include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/host_desktop.h"
#include "chrome/browser/ui/web_applications/web_app_ui.h"
#include "chrome/browser/web_applications/web_app.h"
@@ -66,6 +65,10 @@
#include "ui/gfx/color_analysis.h"
#include "ui/gfx/image/image.h"
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h"
+#endif
+
using content::NavigationController;
using content::NavigationEntry;
using content::RenderViewHost;
@@ -413,14 +416,13 @@ void TabHelper::FinishCreateHostedApp(
return;
}
- WebApplicationInfo install_info(web_app_info_);
- if (install_info.app_url.is_empty())
- install_info.app_url = web_contents()->GetURL();
+ if (web_app_info_.app_url.is_empty())
+ web_app_info_.app_url = web_contents()->GetURL();
- if (install_info.title.empty())
- install_info.title = web_contents()->GetTitle();
- if (install_info.title.empty())
- install_info.title = base::UTF8ToUTF16(install_info.app_url.spec());
+ if (web_app_info_.title.empty())
+ web_app_info_.title = web_contents()->GetTitle();
+ if (web_app_info_.title.empty())
+ web_app_info_.title = base::UTF8ToUTF16(web_app_info_.app_url.spec());
// Add the downloaded icons. Extensions only allow certain icon sizes. First
// populate icons that match the allowed sizes exactly and then downscale
@@ -481,7 +483,7 @@ void TabHelper::FinishCreateHostedApp(
icon_info.data = resized_bitmaps_it->second;
icon_info.width = icon_info.data.width();
icon_info.height = icon_info.data.height();
- install_info.icons.push_back(icon_info);
+ web_app_info_.icons.push_back(icon_info);
}
// Install the app.
@@ -490,7 +492,7 @@ void TabHelper::FinishCreateHostedApp(
scoped_refptr<extensions::CrxInstaller> installer(
extensions::CrxInstaller::CreateSilent(profile->GetExtensionService()));
installer->set_error_on_unsupported_requirements(true);
- installer->InstallWebApp(install_info);
+ installer->InstallWebApp(web_app_info_);
favicon_downloader_.reset();
}
@@ -734,34 +736,21 @@ void TabHelper::Observe(int type,
const Extension* extension =
content::Details<const Extension>(details).ptr();
- if (!extension || !extension->from_bookmark())
+ if (!extension ||
+ AppLaunchInfo::GetLaunchWebURL(extension) != web_app_info_.app_url)
return;
- // If enabled, launch the app launcher and highlight the new app.
- // Otherwise, open the chrome://apps page in a new foreground tab.
- if (IsAppLauncherEnabled()) {
- AppListService::Get(chrome::GetHostDesktopTypeForNativeView(
- web_contents()->GetView()->GetNativeView()))->
- ShowForProfile(profile_);
-
- content::NotificationService::current()->Notify(
- chrome::NOTIFICATION_APP_INSTALLED_TO_APPLIST,
- content::Source<Profile>(profile_),
- content::Details<const std::string>(&extension->id()));
- return;
- }
+#if defined(OS_CHROMEOS)
+ ChromeLauncherController::instance()->PinAppWithID(extension->id());
+#endif
// Android does not implement browser_finder.cc.
#if !defined(OS_ANDROID)
Browser* browser =
chrome::FindBrowserWithWebContents(web_contents());
if (browser) {
- browser->OpenURL(
- content::OpenURLParams(GURL(chrome::kChromeUIAppsURL),
- content::Referrer(),
- NEW_FOREGROUND_TAB,
- content::PAGE_TRANSITION_LINK,
- false));
+ browser->window()->ShowBookmarkAppBubble(web_app_info_,
+ extension->id());
}
#endif
}
diff --git a/chrome/browser/ui/browser_window.h b/chrome/browser/ui/browser_window.h
index be23fd4..6a23b11 100644
--- a/chrome/browser/ui/browser_window.h
+++ b/chrome/browser/ui/browser_window.h
@@ -32,6 +32,8 @@ class TemplateURL;
class ToolbarView;
#endif
+struct WebApplicationInfo;
+
namespace autofill {
class PasswordGenerator;
struct PasswordForm;
@@ -214,6 +216,15 @@ class BrowserWindow : public ui::BaseWindow {
// |already_bookmarked| is true if the url is already bookmarked.
virtual void ShowBookmarkBubble(const GURL& url, bool already_bookmarked) = 0;
+ // Shows the Bookmark App bubble.
+ // See Extension::InitFromValueFlags::FROM_BOOKMARK for a description of
+ // bookmark apps.
+ //
+ // |web_app_info| is the WebApplicationInfo being converted into an app.
+ // |extension_id| is the id of the bookmark app.
+ virtual void ShowBookmarkAppBubble(const WebApplicationInfo& web_app_info,
+ const std::string& extension_id) = 0;
+
// Shows the bookmark prompt.
// TODO(yosin): Make ShowBookmarkPrompt pure virtual.
virtual void ShowBookmarkPrompt() {}
diff --git a/chrome/browser/ui/cocoa/browser_window_cocoa.h b/chrome/browser/ui/cocoa/browser_window_cocoa.h
index 4091953..24c7bbc 100644
--- a/chrome/browser/ui/cocoa/browser_window_cocoa.h
+++ b/chrome/browser/ui/cocoa/browser_window_cocoa.h
@@ -101,6 +101,9 @@ class BrowserWindowCocoa :
virtual void ShowUpdateChromeDialog() OVERRIDE;
virtual void ShowBookmarkBubble(const GURL& url,
bool already_bookmarked) OVERRIDE;
+ virtual void ShowBookmarkAppBubble(
+ const WebApplicationInfo& web_app_info,
+ const std::string& extension_id) OVERRIDE;
virtual void ShowTranslateBubble(
content::WebContents* contents,
TranslateBubbleModel::ViewState view_state,
diff --git a/chrome/browser/ui/cocoa/browser_window_cocoa.mm b/chrome/browser/ui/cocoa/browser_window_cocoa.mm
index 4287c00..439a15e 100644
--- a/chrome/browser/ui/cocoa/browser_window_cocoa.mm
+++ b/chrome/browser/ui/cocoa/browser_window_cocoa.mm
@@ -478,6 +478,12 @@ void BrowserWindowCocoa::ShowBookmarkBubble(const GURL& url,
alreadyBookmarked:(already_bookmarked ? YES : NO)];
}
+void BrowserWindowCocoa::ShowBookmarkAppBubble(
+ const WebApplicationInfo& web_app_info,
+ const std::string& extension_id) {
+ NOTIMPLEMENTED();
+}
+
void BrowserWindowCocoa::ShowTranslateBubble(
content::WebContents* contents,
TranslateBubbleModel::ViewState view_state,
diff --git a/chrome/browser/ui/gtk/browser_window_gtk.cc b/chrome/browser/ui/gtk/browser_window_gtk.cc
index c038e11..7130452 100644
--- a/chrome/browser/ui/gtk/browser_window_gtk.cc
+++ b/chrome/browser/ui/gtk/browser_window_gtk.cc
@@ -1027,6 +1027,12 @@ void BrowserWindowGtk::ShowBookmarkBubble(const GURL& url,
toolbar_->GetLocationBarView()->ShowStarBubble(url, !already_bookmarked);
}
+void BrowserWindowGtk::ShowBookmarkAppBubble(
+ const WebApplicationInfo& web_app_info,
+ const std::string& extension_id) {
+ NOTIMPLEMENTED();
+}
+
void BrowserWindowGtk::ShowTranslateBubble(
content::WebContents* contents,
TranslateBubbleModel::ViewState view_state,
diff --git a/chrome/browser/ui/gtk/browser_window_gtk.h b/chrome/browser/ui/gtk/browser_window_gtk.h
index 6185654..fe5382a4 100644
--- a/chrome/browser/ui/gtk/browser_window_gtk.h
+++ b/chrome/browser/ui/gtk/browser_window_gtk.h
@@ -137,6 +137,9 @@ class BrowserWindowGtk
virtual void ShowUpdateChromeDialog() OVERRIDE;
virtual void ShowBookmarkBubble(const GURL& url,
bool already_bookmarked) OVERRIDE;
+ virtual void ShowBookmarkAppBubble(
+ const WebApplicationInfo& web_app_info,
+ const std::string& extension_id) OVERRIDE;
virtual void ShowTranslateBubble(
content::WebContents* contents,
TranslateBubbleModel::ViewState view_state,
diff --git a/chrome/browser/ui/views/extensions/bookmark_app_bubble_view.cc b/chrome/browser/ui/views/extensions/bookmark_app_bubble_view.cc
new file mode 100644
index 0000000..013dec4
--- /dev/null
+++ b/chrome/browser/ui/views/extensions/bookmark_app_bubble_view.cc
@@ -0,0 +1,224 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/extensions/bookmark_app_bubble_view.h"
+
+#include "base/strings/string16.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/extensions/crx_installer.h"
+#include "chrome/browser/extensions/launch_util.h"
+#include "chrome/browser/profiles/profile.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/events/keycodes/keyboard_codes.h"
+#include "ui/views/controls/button/checkbox.h"
+#include "ui/views/controls/button/label_button.h"
+#include "ui/views/controls/label.h"
+#include "ui/views/controls/textfield/textfield.h"
+#include "ui/views/layout/grid_layout.h"
+#include "ui/views/layout/layout_constants.h"
+#include "ui/views/widget/widget.h"
+
+using views::ColumnSet;
+using views::GridLayout;
+
+namespace {
+
+// Minimum width of the the bubble.
+const int kMinBubbleWidth = 300;
+
+} // namespace
+
+BookmarkAppBubbleView* BookmarkAppBubbleView::bookmark_app_bubble_ = NULL;
+
+BookmarkAppBubbleView::~BookmarkAppBubbleView() {
+}
+
+// static
+void BookmarkAppBubbleView::ShowBubble(views::View* anchor_view,
+ Profile* profile,
+ const WebApplicationInfo& web_app_info,
+ const std::string& extension_id) {
+ if (bookmark_app_bubble_ != NULL)
+ return;
+
+ bookmark_app_bubble_ = new BookmarkAppBubbleView(
+ anchor_view, profile, web_app_info, extension_id);
+ views::BubbleDelegateView::CreateBubble(bookmark_app_bubble_)->Show();
+ // Select the entire title textfield contents when the bubble is first shown.
+ bookmark_app_bubble_->title_tf_->SelectAll(true);
+ bookmark_app_bubble_->SetArrowPaintType(views::BubbleBorder::PAINT_NONE);
+}
+
+BookmarkAppBubbleView::BookmarkAppBubbleView(
+ views::View* anchor_view,
+ Profile* profile,
+ const WebApplicationInfo& web_app_info,
+ const std::string& extension_id)
+ : BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_RIGHT),
+ profile_(profile),
+ web_app_info_(web_app_info),
+ extension_id_(extension_id),
+ add_button_(NULL),
+ cancel_button_(NULL),
+ open_as_tab_checkbox_(NULL),
+ title_tf_(NULL),
+ remove_app_(true) {
+ const SkColor background_color = GetNativeTheme()->GetSystemColor(
+ ui::NativeTheme::kColorId_DialogBackground);
+ set_color(background_color);
+ set_background(views::Background::CreateSolidBackground(background_color));
+ set_margins(gfx::Insets(views::kPanelVertMargin, 0, 0, 0));
+}
+
+void BookmarkAppBubbleView::Init() {
+ views::Label* title_label = new views::Label(
+ l10n_util::GetStringUTF16(IDS_BOOKMARK_APP_BUBBLE_TITLE));
+ ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
+ title_label->SetFontList(rb->GetFontList(ui::ResourceBundle::MediumFont));
+ title_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+
+ add_button_ =
+ new views::LabelButton(this, l10n_util::GetStringUTF16(IDS_ADD));
+ add_button_->SetStyle(views::Button::STYLE_BUTTON);
+ add_button_->SetIsDefault(true);
+
+ cancel_button_ =
+ new views::LabelButton(this, l10n_util::GetStringUTF16(IDS_CANCEL));
+ cancel_button_->SetStyle(views::Button::STYLE_BUTTON);
+
+ GridLayout* layout = new GridLayout(this);
+ SetLayoutManager(layout);
+
+ // Column sets used in the layout of the bubble.
+ enum ColumnSetID {
+ TITLE_COLUMN_SET_ID,
+ TITLE_TEXT_COLUMN_SET_ID,
+ CONTENT_COLUMN_SET_ID
+ };
+
+ // The column layout used for the title and checkbox.
+ ColumnSet* cs = layout->AddColumnSet(TITLE_COLUMN_SET_ID);
+ cs->AddPaddingColumn(0, views::kButtonHEdgeMarginNew);
+ cs->AddColumn(
+ GridLayout::LEADING, GridLayout::CENTER, 0, GridLayout::USE_PREF, 0, 0);
+ cs->AddPaddingColumn(0, views::kButtonHEdgeMarginNew);
+
+ // The column layout used for the text box.
+ cs = layout->AddColumnSet(TITLE_TEXT_COLUMN_SET_ID);
+ cs->AddPaddingColumn(0, views::kButtonHEdgeMarginNew);
+ cs->AddColumn(
+ GridLayout::FILL, GridLayout::FILL, 1, GridLayout::USE_PREF, 0, 0);
+ cs->AddPaddingColumn(0, views::kButtonHEdgeMarginNew);
+
+ // The column layout used for the row with buttons.
+ cs = layout->AddColumnSet(CONTENT_COLUMN_SET_ID);
+ cs->AddPaddingColumn(1, views::kButtonHEdgeMarginNew);
+
+ cs->AddColumn(
+ GridLayout::LEADING, GridLayout::TRAILING, 0, GridLayout::USE_PREF, 0, 0);
+ cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
+ cs->AddColumn(
+ GridLayout::LEADING, GridLayout::TRAILING, 0, GridLayout::USE_PREF, 0, 0);
+ cs->AddPaddingColumn(0, views::kButtonHEdgeMarginNew);
+
+ layout->StartRow(0, TITLE_COLUMN_SET_ID);
+ layout->AddView(title_label);
+ layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
+
+ layout->StartRow(0, TITLE_TEXT_COLUMN_SET_ID);
+ title_tf_ = new views::Textfield();
+ const extensions::Extension* extension =
+ profile_->GetExtensionService()->GetInstalledExtension(extension_id_);
+ title_tf_->SetText(extension ? base::UTF8ToUTF16(extension->name())
+ : web_app_info_.title);
+ layout->AddView(title_tf_);
+ layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
+
+ layout->StartRow(0, TITLE_COLUMN_SET_ID);
+ open_as_tab_checkbox_ = new views::Checkbox(
+ l10n_util::GetStringUTF16(IDS_BOOKMARK_APP_BUBBLE_OPEN_AS_TAB));
+ layout->AddView(open_as_tab_checkbox_);
+ layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
+
+ layout->StartRow(0, CONTENT_COLUMN_SET_ID);
+ layout->AddView(add_button_);
+ layout->AddView(cancel_button_);
+ layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
+
+ AddAccelerator(ui::Accelerator(ui::VKEY_RETURN, ui::EF_NONE));
+}
+
+views::View* BookmarkAppBubbleView::GetInitiallyFocusedView() {
+ return title_tf_;
+}
+
+void BookmarkAppBubbleView::WindowClosing() {
+ // We have to reset |bookmark_app_bubble_| here, not in our destructor,
+ // because we'll be destroyed asynchronously and the shown state will be
+ // checked before then.
+ DCHECK_EQ(bookmark_app_bubble_, this);
+ bookmark_app_bubble_ = NULL;
+
+ if (remove_app_) {
+ profile_->GetExtensionService()->UninstallExtension(
+ extension_id_, false, NULL);
+ } else {
+ ApplyEdits();
+ }
+}
+
+bool BookmarkAppBubbleView::AcceleratorPressed(
+ const ui::Accelerator& accelerator) {
+ if (accelerator.key_code() == ui::VKEY_RETURN) {
+ HandleButtonPressed(add_button_);
+ }
+
+ return BubbleDelegateView::AcceleratorPressed(accelerator);
+}
+
+gfx::Size BookmarkAppBubbleView::GetMinimumSize() {
+ gfx::Size size(views::BubbleDelegateView::GetPreferredSize());
+ size.SetToMax(gfx::Size(kMinBubbleWidth, 0));
+ return size;
+}
+
+void BookmarkAppBubbleView::ButtonPressed(views::Button* sender,
+ const ui::Event& event) {
+ HandleButtonPressed(sender);
+}
+
+void BookmarkAppBubbleView::HandleButtonPressed(views::Button* sender) {
+ // Unset |remove_app_| so we don't delete the bookmark after the window
+ // closes.
+ if (sender == add_button_)
+ remove_app_ = false;
+
+ StartFade(false);
+}
+
+void BookmarkAppBubbleView::ApplyEdits() {
+ // Set the launch type based on the checkbox.
+ extensions::SetLaunchType(profile_->GetExtensionService(),
+ extension_id_,
+ open_as_tab_checkbox_->checked()
+ ? extensions::LAUNCH_TYPE_REGULAR
+ : extensions::LAUNCH_TYPE_WINDOW);
+
+ const extensions::Extension* extension =
+ profile_->GetExtensionService()->GetInstalledExtension(extension_id_);
+ if (extension && base::UTF8ToUTF16(extension->name()) == title_tf_->text())
+ return;
+
+ // Reinstall the app with an updated name.
+ WebApplicationInfo install_info(web_app_info_);
+ install_info.title = title_tf_->text();
+
+ scoped_refptr<extensions::CrxInstaller> installer(
+ extensions::CrxInstaller::CreateSilent(profile_->GetExtensionService()));
+ installer->set_error_on_unsupported_requirements(true);
+ installer->InstallWebApp(install_info);
+}
diff --git a/chrome/browser/ui/views/extensions/bookmark_app_bubble_view.h b/chrome/browser/ui/views/extensions/bookmark_app_bubble_view.h
new file mode 100644
index 0000000..0a07228
--- /dev/null
+++ b/chrome/browser/ui/views/extensions/bookmark_app_bubble_view.h
@@ -0,0 +1,95 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_VIEWS_EXTENSIONS_BOOKMARK_APP_BUBBLE_VIEW_H_
+#define CHROME_BROWSER_UI_VIEWS_EXTENSIONS_BOOKMARK_APP_BUBBLE_VIEW_H_
+
+#include "base/basictypes.h"
+#include "base/strings/string16.h"
+#include "chrome/common/web_application_info.h"
+#include "ui/views/bubble/bubble_delegate.h"
+#include "ui/views/controls/button/button.h"
+
+class Profile;
+
+namespace views {
+class Checkbox;
+class LabelButton;
+class Textfield;
+}
+
+// BookmarkAppBubbleView is a view intended to be used as the content of a
+// Bubble. BookmarkAppBubbleView provides views for editing the bookmark app it
+// is created with. Don't create a BookmarkAppBubbleView directly, instead use
+// the static ShowBubble method.
+class BookmarkAppBubbleView : public views::BubbleDelegateView,
+ public views::ButtonListener {
+ public:
+ virtual ~BookmarkAppBubbleView();
+
+ static void ShowBubble(views::View* anchor_view,
+ Profile* profile,
+ const WebApplicationInfo& web_app_info,
+ const std::string& extension_id);
+
+ private:
+ // Creates a BookmarkAppBubbleView.
+ BookmarkAppBubbleView(views::View* anchor_view,
+ Profile* profile,
+ const WebApplicationInfo& web_app_info,
+ const std::string& extension_id);
+
+ // Overriden from views::BubbleDelegateView:
+ virtual void Init() OVERRIDE;
+ virtual views::View* GetInitiallyFocusedView() OVERRIDE;
+
+ // Overridden from views::WidgetDelegate:
+ virtual void WindowClosing() OVERRIDE;
+
+ // Overridden from views::View:
+ virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE;
+ virtual gfx::Size GetMinimumSize() OVERRIDE;
+
+ // Overridden from views::ButtonListener:
+ // Closes the bubble or opens the edit dialog.
+ virtual void ButtonPressed(views::Button* sender,
+ const ui::Event& event) OVERRIDE;
+
+ // Handle the message when the user presses a button.
+ void HandleButtonPressed(views::Button* sender);
+
+ // Sets the title and launch type of the app.
+ void ApplyEdits();
+
+ // The bookmark app bubble, if we're showing one.
+ static BookmarkAppBubbleView* bookmark_app_bubble_;
+
+ // The profile.
+ Profile* profile_;
+
+ // The WebApplicationInfo being used to create the app.
+ const WebApplicationInfo web_app_info_;
+
+ // The extension id of the bookmark app.
+ const std::string extension_id_;
+
+ // Button for removing the bookmark.
+ views::LabelButton* add_button_;
+
+ // Button to close the window.
+ views::LabelButton* cancel_button_;
+
+ // Checkbox to launch as a tab.
+ views::Checkbox* open_as_tab_checkbox_;
+
+ // Textfield showing the title of the app.
+ views::Textfield* title_tf_;
+
+ // When the destructor is invoked should the app be removed?
+ bool remove_app_;
+
+ DISALLOW_COPY_AND_ASSIGN(BookmarkAppBubbleView);
+};
+
+#endif // CHROME_BROWSER_UI_VIEWS_EXTENSIONS_BOOKMARK_APP_BUBBLE_VIEW_H_
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index b86e848..655d51a 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -66,6 +66,7 @@
#include "chrome/browser/ui/views/browser_dialogs.h"
#include "chrome/browser/ui/views/download/download_in_progress_dialog_view.h"
#include "chrome/browser/ui/views/download/download_shelf_view.h"
+#include "chrome/browser/ui/views/extensions/bookmark_app_bubble_view.h"
#include "chrome/browser/ui/views/frame/browser_view_layout.h"
#include "chrome/browser/ui/views/frame/browser_view_layout_delegate.h"
#include "chrome/browser/ui/views/frame/contents_layout_manager.h"
@@ -1196,6 +1197,15 @@ void BrowserView::ShowBookmarkBubble(const GURL& url, bool already_bookmarked) {
!already_bookmarked);
}
+void BrowserView::ShowBookmarkAppBubble(
+ const WebApplicationInfo& web_app_info,
+ const std::string& extension_id) {
+ BookmarkAppBubbleView::ShowBubble(GetToolbarView(),
+ browser_->profile(),
+ web_app_info,
+ extension_id);
+}
+
void BrowserView::ShowBookmarkPrompt() {
GetLocationBarView()->ShowBookmarkPrompt();
}
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h
index 06fcb0a..6a8c617 100644
--- a/chrome/browser/ui/views/frame/browser_view.h
+++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -323,6 +323,9 @@ class BrowserView : public BrowserWindow,
virtual void ShowUpdateChromeDialog() OVERRIDE;
virtual void ShowBookmarkBubble(const GURL& url,
bool already_bookmarked) OVERRIDE;
+ virtual void ShowBookmarkAppBubble(
+ const WebApplicationInfo& web_app_info,
+ const std::string& extension_id) OVERRIDE;
virtual void ShowBookmarkPrompt() OVERRIDE;
virtual void ShowTranslateBubble(
content::WebContents* contents,
diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi
index d0a8a5f..6ef0aa7 100644
--- a/chrome/chrome_browser_ui.gypi
+++ b/chrome/chrome_browser_ui.gypi
@@ -1819,6 +1819,8 @@
'browser/ui/views/dropdown_bar_view.h',
'browser/ui/views/edit_search_engine_dialog.cc',
'browser/ui/views/edit_search_engine_dialog.h',
+ 'browser/ui/views/extensions/bookmark_app_bubble_view.cc',
+ 'browser/ui/views/extensions/bookmark_app_bubble_view.h',
'browser/ui/views/extensions/browser_action_drag_data.cc',
'browser/ui/views/extensions/browser_action_drag_data.h',
'browser/ui/views/extensions/browser_action_overflow_menu_controller.cc',
diff --git a/chrome/test/base/test_browser_window.h b/chrome/test/base/test_browser_window.h
index 6a462a4..3a5072c 100644
--- a/chrome/test/base/test_browser_window.h
+++ b/chrome/test/base/test_browser_window.h
@@ -102,6 +102,9 @@ class TestBrowserWindow : public BrowserWindow {
virtual void ShowUpdateChromeDialog() OVERRIDE {}
virtual void ShowBookmarkBubble(const GURL& url,
bool already_bookmarked) OVERRIDE {}
+ virtual void ShowBookmarkAppBubble(
+ const WebApplicationInfo& web_app_info,
+ const std::string& extension_id) OVERRIDE {}
virtual void ShowTranslateBubble(
content::WebContents* contents,
TranslateBubbleModel::ViewState view_state,
diff --git a/extensions/common/extension.h b/extensions/common/extension.h
index ead3dd0..4ea11b4 100644
--- a/extensions/common/extension.h
+++ b/extensions/common/extension.h
@@ -133,8 +133,9 @@ class Extension : public base::RefCountedThreadSafe<Extension> {
// Chrome Web Store.
FROM_WEBSTORE = 1 << 3,
- // |FROM_BOOKMARK| indicates the extension was created using a mock App
- // created from a bookmark.
+ // |FROM_BOOKMARK| indicates the extension is a bookmark app which has been
+ // generated from a web page. Bookmark apps have no permissions or extent
+ // and launch the web page they are created from when run.
FROM_BOOKMARK = 1 << 4,
// |FOLLOW_SYMLINKS_ANYWHERE| means that resources can be symlinks to