diff options
author | aa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-26 21:50:23 +0000 |
---|---|---|
committer | aa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-26 21:50:23 +0000 |
commit | bb461530cb42d050c91bacc9ec1a6a48100c6be7 (patch) | |
tree | 8b88b90958fdd1d2dcdc666b4414a93ca833c97e /chrome/browser | |
parent | 11740d25bd6ac9c9da9ceb99ba1ba59d3caabeeb (diff) | |
download | chromium_src-bb461530cb42d050c91bacc9ec1a6a48100c6be7.zip chromium_src-bb461530cb42d050c91bacc9ec1a6a48100c6be7.tar.gz chromium_src-bb461530cb42d050c91bacc9ec1a6a48100c6be7.tar.bz2 |
Revert "Revert "Finish wiring up chrome.app.install().""
This reverts commit 89f4de523e9c916950f72c264cdefed662849124.
TBR=aa@chromium.org
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@67474 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
22 files changed, 181 insertions, 41 deletions
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index bb52310..5f24585 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc @@ -154,6 +154,13 @@ const Experiment kExperiments[] = { switches::kEnableCloudPrintProxy }, { + "crxless-web-apps", + IDS_FLAGS_CRXLESS_WEB_APPS_NAME, + IDS_FLAGS_CRXLESS_WEB_APPS_DESCRIPTION, + kOsAll, + switches::kEnableCrxlessWebApps + }, + { "match-preview", // FLAGS:RECORD_UMA IDS_FLAGS_PREDICTIVE_INSTANT_NAME, IDS_FLAGS_PREDICTIVE_INSTANT_DESCRIPTION, diff --git a/chrome/browser/automation/automation_provider.cc b/chrome/browser/automation/automation_provider.cc index 65dc5a3..bbfb3c5c 100644 --- a/chrome/browser/automation/automation_provider.cc +++ b/chrome/browser/automation/automation_provider.cc @@ -797,11 +797,8 @@ void AutomationProvider::InstallExtension(const FilePath& crx_path, AutomationMsg_InstallExtension::ID, reply_message); - const FilePath& install_dir = service->install_directory(); scoped_refptr<CrxInstaller> installer( - new CrxInstaller(install_dir, - service, - NULL)); // silent install, no UI + new CrxInstaller(service, NULL)); // silent install, no UI installer->set_allow_privilege_increase(true); installer->InstallCrx(crx_path); } else { @@ -870,10 +867,7 @@ void AutomationProvider::InstallExtensionAndGetHandle( ExtensionInstallUI* client = (with_ui ? new ExtensionInstallUI(profile_) : NULL); - scoped_refptr<CrxInstaller> installer( - new CrxInstaller(service->install_directory(), - service, - client)); + scoped_refptr<CrxInstaller> installer(new CrxInstaller(service, client)); installer->set_allow_privilege_increase(true); installer->InstallCrx(crx_path); } else { diff --git a/chrome/browser/download/download_util.cc b/chrome/browser/download/download_util.cc index 2c856be..dd4a34c 100644 --- a/chrome/browser/download/download_util.cc +++ b/chrome/browser/download/download_util.cc @@ -239,9 +239,7 @@ void OpenChromeExtension(Profile* profile, Details<GURL>(&nonconst_download_url)); scoped_refptr<CrxInstaller> installer( - new CrxInstaller(service->install_directory(), - service, - new ExtensionInstallUI(profile))); + new CrxInstaller(service, new ExtensionInstallUI(profile))); installer->set_delete_source(true); if (UserScript::HasUserScriptFileExtension(download_item.url())) { diff --git a/chrome/browser/extensions/convert_web_app.cc b/chrome/browser/extensions/convert_web_app.cc index 47a9143..11303ff 100644 --- a/chrome/browser/extensions/convert_web_app.cc +++ b/chrome/browser/extensions/convert_web_app.cc @@ -34,7 +34,7 @@ using base::Time; namespace { -const char kIconsDirName[] = "_icons"; +const char kIconsDirName[] = "icons"; // Create the public key for the converted web app. // diff --git a/chrome/browser/extensions/convert_web_app_browsertest.cc b/chrome/browser/extensions/convert_web_app_browsertest.cc new file mode 100644 index 0000000..a6cdb19 --- /dev/null +++ b/chrome/browser/extensions/convert_web_app_browsertest.cc @@ -0,0 +1,68 @@ +// Copyright (c) 2010 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 <string> + +#include "chrome/browser/profile.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/extensions/extensions_service.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/extensions/extension.h" +#include "chrome/common/notification_details.h" +#include "chrome/common/notification_observer.h" +#include "chrome/common/notification_registrar.h" +#include "chrome/common/notification_type.h" +#include "chrome/test/in_process_browser_test.h" +#include "chrome/test/ui_test_utils.h" + +class ExtensionFromWebAppTest + : public InProcessBrowserTest, public NotificationObserver { + protected: + ExtensionFromWebAppTest() : installed_extension_(NULL) { + } + + std::string expected_extension_id_; + const Extension* installed_extension_; + + private: + // InProcessBrowserTest + virtual void SetUpCommandLine(CommandLine* command_line) { + command_line->AppendSwitch(switches::kEnableCrxlessWebApps); + } + + // NotificationObserver + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + if (type == NotificationType::EXTENSION_INSTALLED) { + const Extension* extension = Details<const Extension>(details).ptr(); + if (extension->id() == expected_extension_id_) { + installed_extension_ = extension; + MessageLoopForUI::current()->Quit(); + } + } + } +}; + +IN_PROC_BROWSER_TEST_F(ExtensionFromWebAppTest, Basic) { + ASSERT_TRUE(test_server()->Start()); + browser()->profile()->GetExtensionsService()->set_show_extensions_prompts( + false); + + NotificationRegistrar registrar; + registrar.Add(this, NotificationType::EXTENSION_INSTALLED, + NotificationService::AllSources()); + + expected_extension_id_ = "fnpgoaochgbdfjndakichfafiocjjpmm"; + ui_test_utils::NavigateToURL( + browser(), + test_server()->GetURL( + "files/extensions/convert_web_app/application.html")); + + if (!installed_extension_) + ui_test_utils::RunMessageLoop(); + + EXPECT_TRUE(installed_extension_); + EXPECT_TRUE(installed_extension_->is_hosted_app()); +} diff --git a/chrome/browser/extensions/convert_web_app_unittest.cc b/chrome/browser/extensions/convert_web_app_unittest.cc index fc10347..eab9b8f 100644 --- a/chrome/browser/extensions/convert_web_app_unittest.cc +++ b/chrome/browser/extensions/convert_web_app_unittest.cc @@ -132,7 +132,7 @@ TEST(ExtensionFromWebApp, Basic) { EXPECT_EQ(web_app.icons.size(), extension->icons().map().size()); for (size_t i = 0; i < web_app.icons.size(); ++i) { - EXPECT_EQ(StringPrintf("_icons/%i.png", web_app.icons[i].width), + EXPECT_EQ(StringPrintf("icons/%i.png", web_app.icons[i].width), extension->icons().Get(web_app.icons[i].width, ExtensionIconSet::MATCH_EXACTLY)); ExtensionResource resource = extension->GetIconResource( diff --git a/chrome/browser/extensions/crx_installer.cc b/chrome/browser/extensions/crx_installer.cc index d90bbbd..3a9a3df 100644 --- a/chrome/browser/extensions/crx_installer.cc +++ b/chrome/browser/extensions/crx_installer.cc @@ -14,6 +14,7 @@ #include "base/singleton.h" #include "base/stl_util-inl.h" #include "base/stringprintf.h" +#include "base/time.h" #include "base/task.h" #include "base/thread_restrictions.h" #include "base/utf_string_conversions.h" @@ -21,6 +22,7 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_thread.h" #include "chrome/browser/extensions/convert_user_script.h" +#include "chrome/browser/extensions/convert_web_app.h" #include "chrome/browser/extensions/extensions_service.h" #include "chrome/browser/extensions/extension_error_reporter.h" #include "chrome/browser/profile.h" @@ -75,11 +77,11 @@ bool CrxInstaller::ClearWhitelistedInstallId(const std::string& id) { return false; } -CrxInstaller::CrxInstaller(const FilePath& install_directory, - ExtensionsService* frontend, +CrxInstaller::CrxInstaller(ExtensionsService* frontend, ExtensionInstallUI* client) - : install_directory_(install_directory), + : install_directory_(frontend->install_directory()), install_source_(Extension::INTERNAL), + extensions_enabled_(frontend->extensions_enabled()), delete_source_(false), allow_privilege_increase_(false), is_gallery_install_(false), @@ -88,7 +90,6 @@ CrxInstaller::CrxInstaller(const FilePath& install_directory, client_(client), apps_require_extension_mime_type_(false), allow_silent_install_(false) { - extensions_enabled_ = frontend_->extensions_enabled(); } CrxInstaller::~CrxInstaller() { @@ -160,6 +161,29 @@ void CrxInstaller::ConvertUserScriptOnFileThread() { OnUnpackSuccess(extension->path(), extension->path(), extension); } +void CrxInstaller::InstallWebApp(const WebApplicationInfo& web_app) { + BrowserThread::PostTask( + BrowserThread::FILE, FROM_HERE, + NewRunnableMethod(this, &CrxInstaller::ConvertWebAppOnFileThread, + web_app)); +} + +void CrxInstaller::ConvertWebAppOnFileThread( + const WebApplicationInfo& web_app) { + std::string error; + scoped_refptr<Extension> extension( + ConvertWebAppToExtension(web_app, base::Time::Now())); + if (!extension) { + // Validation should have stopped any potential errors before getting here. + NOTREACHED() << "Could not convert web app to extension."; + return; + } + + // TODO(aa): conversion data gets lost here :( + + OnUnpackSuccess(extension->path(), extension->path(), extension); +} + bool CrxInstaller::AllowInstall(const Extension* extension, std::string* error) { DCHECK(error); @@ -362,7 +386,7 @@ void CrxInstaller::CompleteInstall() { std::string error; extension_ = extension_file_util::LoadExtension( version_dir, install_source_, true, &error); - DCHECK(error.empty()); + CHECK(error.empty()) << error; ReportSuccessFromFileThread(); } diff --git a/chrome/browser/extensions/crx_installer.h b/chrome/browser/extensions/crx_installer.h index 5426b1a..26bbbd8 100644 --- a/chrome/browser/extensions/crx_installer.h +++ b/chrome/browser/extensions/crx_installer.h @@ -13,6 +13,7 @@ #include "chrome/browser/extensions/extension_install_ui.h" #include "chrome/browser/extensions/sandboxed_extension_unpacker.h" #include "chrome/common/extensions/extension.h" +#include "chrome/common/web_apps.h" class ExtensionsService; class SkBitmap; @@ -60,22 +61,23 @@ class CrxInstaller // only be called on the UI thread. static bool ClearWhitelistedInstallId(const std::string& id); - // Constructor. Extensions will be unpacked to |install_directory|. - // Extension objects will be sent to |frontend|, and any UI will be shown - // via |client|. For silent install, pass NULL for |client|. - CrxInstaller(const FilePath& install_directory, - ExtensionsService* frontend, + // Constructor. Extensions will be installed into + // frontend->install_directory() then registered with |frontend|. Any install + // UI will be displayed using |client|. Pass NULL for |client| for silent + // install. + CrxInstaller(ExtensionsService* frontend, ExtensionInstallUI* client); - // Install the crx in |source_file|. Note that this will most likely - // complete asynchronously. + // Install the crx in |source_file|. void InstallCrx(const FilePath& source_file); - // Install the user script in |source_file|. Note that this will most likely - // complete asynchronously. + // Convert the specified user script into an extension and install it. void InstallUserScript(const FilePath& source_file, const GURL& original_url); + // Convert the specified web app into an extension and install it. + void InstallWebApp(const WebApplicationInfo& web_app); + // Overridden from ExtensionInstallUI::Delegate: virtual void InstallUIProceed(); virtual void InstallUIAbort(); @@ -122,6 +124,9 @@ class CrxInstaller // Converts the source user script to an extension. void ConvertUserScriptOnFileThread(); + // Converts the source web app to an extension. + void ConvertWebAppOnFileThread(const WebApplicationInfo& web_app); + // Called after OnUnpackSuccess as a last check to see whether the install // should complete. bool AllowInstall(const Extension* extension, std::string* error); diff --git a/chrome/browser/extensions/crx_installer_browsertest.cc b/chrome/browser/extensions/crx_installer_browsertest.cc index c4adb21..64fee97 100644 --- a/chrome/browser/extensions/crx_installer_browsertest.cc +++ b/chrome/browser/extensions/crx_installer_browsertest.cc @@ -50,9 +50,7 @@ class ExtensionCrxInstallerTest : public ExtensionBrowserTest { MockInstallUI* mock_install_ui = new MockInstallUI(browser()->profile()); scoped_refptr<CrxInstaller> installer( - new CrxInstaller(service->install_directory(), - service, - mock_install_ui /* ownership transferred */)); + new CrxInstaller(service, mock_install_ui /* ownership transferred */)); installer->set_allow_silent_install(true); installer->set_is_gallery_install(true); diff --git a/chrome/browser/extensions/extension_browsertest.cc b/chrome/browser/extensions/extension_browsertest.cc index bea1c5e..ae90a66 100644 --- a/chrome/browser/extensions/extension_browsertest.cc +++ b/chrome/browser/extensions/extension_browsertest.cc @@ -144,7 +144,7 @@ bool ExtensionBrowserTest::InstallOrUpdateExtension(const std::string& id, install_ui = new ExtensionInstallUI(browser()->profile()); scoped_refptr<CrxInstaller> installer( - new CrxInstaller(service->install_directory(), service, install_ui)); + new CrxInstaller(service, install_ui)); installer->set_expected_id(id); installer->InstallCrx(path); diff --git a/chrome/browser/extensions/extensions_service.cc b/chrome/browser/extensions/extensions_service.cc index 3357e45..627fe39 100644 --- a/chrome/browser/extensions/extensions_service.cc +++ b/chrome/browser/extensions/extensions_service.cc @@ -642,8 +642,7 @@ void ExtensionsService::Init() { void ExtensionsService::InstallExtension(const FilePath& extension_path) { scoped_refptr<CrxInstaller> installer( - new CrxInstaller(install_directory_, - this, // frontend + new CrxInstaller(this, // frontend NULL)); // no client (silent install) installer->set_allow_privilege_increase(true); installer->InstallCrx(extension_path); @@ -685,8 +684,7 @@ void ExtensionsService::UpdateExtension(const std::string& id, NULL : new ExtensionInstallUI(profile_); scoped_refptr<CrxInstaller> installer( - new CrxInstaller(install_directory_, - this, // frontend + new CrxInstaller(this, // frontend client)); installer->set_expected_id(id); if (is_pending_extension) @@ -1879,8 +1877,7 @@ void ExtensionsService::OnExternalExtensionFileFound( } scoped_refptr<CrxInstaller> installer( - new CrxInstaller(install_directory_, - this, // frontend + new CrxInstaller(this, // frontend NULL)); // no client (silent install) installer->set_install_source(location); installer->set_expected_id(id); diff --git a/chrome/browser/extensions/extensions_service_unittest.cc b/chrome/browser/extensions/extensions_service_unittest.cc index 54aaf78..e222c27 100644 --- a/chrome/browser/extensions/extensions_service_unittest.cc +++ b/chrome/browser/extensions/extensions_service_unittest.cc @@ -988,9 +988,7 @@ TEST_F(ExtensionsServiceTest, InstallUserScript) { ASSERT_TRUE(file_util::PathExists(path)); scoped_refptr<CrxInstaller> installer( - new CrxInstaller(service_->install_directory(), - service_, - NULL)); // silent install + new CrxInstaller(service_, NULL)); // silent install installer->InstallUserScript( path, GURL("http://www.aaronboodman.com/scripts/user_script_basic.user.js")); diff --git a/chrome/browser/renderer_host/browser_render_process_host.cc b/chrome/browser/renderer_host/browser_render_process_host.cc index ed68d1e..07391cb 100644 --- a/chrome/browser/renderer_host/browser_render_process_host.cc +++ b/chrome/browser/renderer_host/browser_render_process_host.cc @@ -629,7 +629,8 @@ void BrowserRenderProcessHost::PropagateBrowserCommandLineToRenderer( switches::kDisableFileSystem, switches::kPpapiOutOfProcess, switches::kEnablePrintPreview, - switches::kEnableClientSidePhishingDetection + switches::kEnableClientSidePhishingDetection, + switches::kEnableCrxlessWebApps }; renderer_cmd->CopySwitchesFrom(browser_cmd, kSwitchNames, arraysize(kSwitchNames)); diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc index 9d701fc..9c1757d 100644 --- a/chrome/browser/renderer_host/render_view_host.cc +++ b/chrome/browser/renderer_host/render_view_host.cc @@ -852,6 +852,8 @@ void RenderViewHost::OnMessageReceived(const IPC::Message& msg) { OnReceivedSerializedHtmlData); IPC_MESSAGE_HANDLER(ViewHostMsg_DidGetApplicationInfo, OnDidGetApplicationInfo); + IPC_MESSAGE_HANDLER(ViewHostMsg_InstallApplication, + OnInstallApplication); IPC_MESSAGE_FORWARD(ViewHostMsg_JSOutOfMemory, delegate_, RenderViewHostDelegate::OnJSOutOfMemory); IPC_MESSAGE_HANDLER(ViewHostMsg_ShouldClose_ACK, OnMsgShouldCloseACK); @@ -1656,6 +1658,14 @@ void RenderViewHost::OnDidGetApplicationInfo( integration_delegate->OnDidGetApplicationInfo(page_id, info); } +void RenderViewHost::OnInstallApplication( + const WebApplicationInfo& info) { + RenderViewHostDelegate::BrowserIntegration* integration_delegate = + delegate_->GetBrowserIntegrationDelegate(); + if (integration_delegate) + integration_delegate->OnInstallApplication(info); +} + void RenderViewHost::GetSerializedHtmlDataForCurrentPageWithLocalLinks( const std::vector<GURL>& links, const std::vector<FilePath>& local_paths, diff --git a/chrome/browser/renderer_host/render_view_host.h b/chrome/browser/renderer_host/render_view_host.h index 077f7ea..19b2b17 100644 --- a/chrome/browser/renderer_host/render_view_host.h +++ b/chrome/browser/renderer_host/render_view_host.h @@ -670,6 +670,7 @@ class RenderViewHost : public RenderWidgetHost { int32 status); void OnDidGetApplicationInfo(int32 page_id, const WebApplicationInfo& info); + void OnInstallApplication(const WebApplicationInfo& info); void OnMsgShouldCloseACK(bool proceed); void OnQueryFormFieldAutoFill(int request_id, bool form_autofilled, diff --git a/chrome/browser/renderer_host/render_view_host_delegate.h b/chrome/browser/renderer_host/render_view_host_delegate.h index 9bde9cd..a569480 100644 --- a/chrome/browser/renderer_host/render_view_host_delegate.h +++ b/chrome/browser/renderer_host/render_view_host_delegate.h @@ -290,6 +290,10 @@ class RenderViewHostDelegate { int32 page_id, const WebApplicationInfo& app_info) = 0; + // Notification when an application programmatically requests installation. + virtual void OnInstallApplication( + const WebApplicationInfo& app_info) = 0; + // Notification that the contents of the page has been loaded. virtual void OnPageContents(const GURL& url, int renderer_process_id, diff --git a/chrome/browser/tab_contents/tab_contents.cc b/chrome/browser/tab_contents/tab_contents.cc index 3631575..c846d62 100644 --- a/chrome/browser/tab_contents/tab_contents.cc +++ b/chrome/browser/tab_contents/tab_contents.cc @@ -2061,6 +2061,11 @@ void TabContents::OnDidGetApplicationInfo(int32 page_id, delegate()->OnDidGetApplicationInfo(this, page_id); } +void TabContents::OnInstallApplication(const WebApplicationInfo& info) { + if (delegate()) + delegate()->OnInstallApplication(this, info); +} + void TabContents::OnDisabledOutdatedPlugin(const string16& name, const GURL& update_url) { new DisabledPluginInfoBar(this, name, update_url); diff --git a/chrome/browser/tab_contents/tab_contents.h b/chrome/browser/tab_contents/tab_contents.h index 4d54db5..19a61a8 100644 --- a/chrome/browser/tab_contents/tab_contents.h +++ b/chrome/browser/tab_contents/tab_contents.h @@ -868,6 +868,7 @@ class TabContents : public PageNavigator, virtual void OnCrashedWorker(); virtual void OnDidGetApplicationInfo(int32 page_id, const WebApplicationInfo& info); + virtual void OnInstallApplication(const WebApplicationInfo& info); virtual void OnDisabledOutdatedPlugin(const string16& name, const GURL& update_url); virtual void OnPageContents(const GURL& url, diff --git a/chrome/browser/tab_contents/tab_contents_delegate.cc b/chrome/browser/tab_contents/tab_contents_delegate.cc index 89eef5c..6c54933 100644 --- a/chrome/browser/tab_contents/tab_contents_delegate.cc +++ b/chrome/browser/tab_contents/tab_contents_delegate.cc @@ -162,6 +162,12 @@ void TabContentsDelegate::OnDidGetApplicationInfo(TabContents* tab_contents, int32 page_id) { } +// Notification when an application programmatically requests installation. +void TabContentsDelegate::OnInstallApplication( + TabContents* tab_contents, + const WebApplicationInfo& app_info) { +} + gfx::NativeWindow TabContentsDelegate::GetFrameNativeWindow() { return NULL; } diff --git a/chrome/browser/tab_contents/tab_contents_delegate.h b/chrome/browser/tab_contents/tab_contents_delegate.h index 5d9ee37..e748229 100644 --- a/chrome/browser/tab_contents/tab_contents_delegate.h +++ b/chrome/browser/tab_contents/tab_contents_delegate.h @@ -38,6 +38,7 @@ class RenderViewHost; class TabContents; class TemplateURL; class TemplateURLModel; +struct WebApplicationInfo; // Objects implement this interface to get notified about changes in the // TabContents and to provide necessary functionality. @@ -274,6 +275,10 @@ class TabContentsDelegate : public AutomationResourceRoutingDelegate { virtual void OnDidGetApplicationInfo(TabContents* tab_contents, int32 page_id); + // Notification when an application programmatically requests installation. + virtual void OnInstallApplication(TabContents* tab_contents, + const WebApplicationInfo& app_info); + // Returns the native window framing the view containing the tab contents. virtual gfx::NativeWindow GetFrameNativeWindow(); diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index b113408..24f7c6f 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc @@ -46,6 +46,7 @@ #include "chrome/browser/download/download_shelf.h" #include "chrome/browser/download/download_started_animation.h" #include "chrome/browser/extensions/crashed_extension_infobar.h" +#include "chrome/browser/extensions/crx_installer.h" #include "chrome/browser/extensions/extension_browser_event_router.h" #include "chrome/browser/extensions/extension_disabled_infobar_delegate.h" #include "chrome/browser/extensions/extension_host.h" @@ -97,6 +98,7 @@ #include "chrome/common/page_transition_types.h" #include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" +#include "chrome/common/web_apps.h" #include "grit/chromium_strings.h" #include "grit/generated_resources.h" #include "grit/locale_settings.h" @@ -3143,6 +3145,19 @@ void Browser::OnDidGetApplicationInfo(TabContents* tab_contents, pending_web_app_action_ = NONE; } +void Browser::OnInstallApplication(TabContents* source, + const WebApplicationInfo& web_app) { + ExtensionsService* extensions_service = profile()->GetExtensionsService(); + if (!extensions_service) + return; + + scoped_refptr<CrxInstaller> installer( + new CrxInstaller(extensions_service, + extensions_service->show_extensions_prompts() ? + new ExtensionInstallUI(profile()) : NULL)); + installer->InstallWebApp(web_app); +} + void Browser::ContentRestrictionsChanged(TabContents* source) { UpdateCommandsForContentRestrictionState(); } diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h index 79bde6d..faa316c 100644 --- a/chrome/browser/ui/browser.h +++ b/chrome/browser/ui/browser.h @@ -47,6 +47,7 @@ class SkBitmap; class StatusBubble; class TabNavigation; class TabStripModel; +struct WebApplicationInfo; namespace gfx { class Point; } @@ -776,6 +777,8 @@ class Browser : public TabHandlerDelegate, NavigationType::Type navigation_type); virtual void OnDidGetApplicationInfo(TabContents* tab_contents, int32 page_id); + virtual void OnInstallApplication(TabContents* tab_contents, + const WebApplicationInfo& app_info); virtual void ContentRestrictionsChanged(TabContents* source); // Overridden from SelectFileDialog::Listener: |