summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/about_flags.cc7
-rw-r--r--chrome/browser/automation/automation_provider.cc10
-rw-r--r--chrome/browser/download/download_util.cc4
-rw-r--r--chrome/browser/extensions/convert_web_app.cc2
-rw-r--r--chrome/browser/extensions/convert_web_app_browsertest.cc68
-rw-r--r--chrome/browser/extensions/convert_web_app_unittest.cc2
-rw-r--r--chrome/browser/extensions/crx_installer.cc34
-rw-r--r--chrome/browser/extensions/crx_installer.h23
-rw-r--r--chrome/browser/extensions/crx_installer_browsertest.cc4
-rw-r--r--chrome/browser/extensions/extension_browsertest.cc2
-rw-r--r--chrome/browser/extensions/extensions_service.cc9
-rw-r--r--chrome/browser/extensions/extensions_service_unittest.cc4
-rw-r--r--chrome/browser/renderer_host/browser_render_process_host.cc3
-rw-r--r--chrome/browser/renderer_host/render_view_host.cc10
-rw-r--r--chrome/browser/renderer_host/render_view_host.h1
-rw-r--r--chrome/browser/renderer_host/render_view_host_delegate.h4
-rw-r--r--chrome/browser/tab_contents/tab_contents.cc5
-rw-r--r--chrome/browser/tab_contents/tab_contents.h1
-rw-r--r--chrome/browser/tab_contents/tab_contents_delegate.cc6
-rw-r--r--chrome/browser/tab_contents/tab_contents_delegate.h5
-rw-r--r--chrome/browser/ui/browser.cc15
-rw-r--r--chrome/browser/ui/browser.h3
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: