summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authorlevin@chromium.org <levin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-16 04:10:38 +0000
committerlevin@chromium.org <levin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-16 04:10:38 +0000
commit0688d8dc3ed88977a92675dac4d03520d71afc24 (patch)
tree24bb368a1554ccb90194db42fc39c8f7246b32ad /chrome/browser
parentb225e9557f5bca7253d131a9913da4af9cd204e5 (diff)
downloadchromium_src-0688d8dc3ed88977a92675dac4d03520d71afc24.zip
chromium_src-0688d8dc3ed88977a92675dac4d03520d71afc24.tar.gz
chromium_src-0688d8dc3ed88977a92675dac4d03520d71afc24.tar.bz2
Add a limited install extension from webstore command.
chrome/browser/extensions/startup_helper.*: Added a method which does an asynchronous install of an extension. It only handles fixed inputs to limit the surface area of the feature. The callback for LimitedInstallFromWebstore and the "2" are there to help with testing. The core was formed by pulling out common code from InstallFromWebstore. InstallFromWebstore doesn't meet the needs because this command is used for apps (not extensions). chrome/browser/extensions/webstore_standalone_install_browsertest.cc: Made CommandLineWebstoreInstall slightly more general so that it could be used to test the limited install scenario as well. chrome/browser/ui/startup/startup_browser_creator.cc: Handle the command line flag. This location handles flags passed cross-process when a browser instance is already running and another instance is started with the flag. chrome/installer/setup/install_worker.cc: Added the app command to the registry to allow using the limited install switch. This re-uses much of the same code as AddInstallAppCommandWorkItems. chrome/installer/util/installation_validator.* The verification for the new registry entry. chrome/installer/util/installation_validator_unittest.cc: Testing the verification. chrome/common/chrome_switches.*: The command line flag to do the limited install. chrome/installer/util/util_constants.*: The registry key value for the app command. Review URL: https://chromiumcodereview.appspot.com/12226105 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@182914 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/extensions/startup_helper.cc105
-rw-r--r--chrome/browser/extensions/startup_helper.h12
-rw-r--r--chrome/browser/extensions/webstore_standalone_install_browsertest.cc53
-rw-r--r--chrome/browser/extensions/webstore_standalone_installer.cc4
-rw-r--r--chrome/browser/ui/startup/startup_browser_creator.cc6
5 files changed, 155 insertions, 25 deletions
diff --git a/chrome/browser/extensions/startup_helper.cc b/chrome/browser/extensions/startup_helper.cc
index fefd492..3df2360 100644
--- a/chrome/browser/extensions/startup_helper.cc
+++ b/chrome/browser/extensions/startup_helper.cc
@@ -5,6 +5,7 @@
#include "chrome/browser/extensions/startup_helper.h"
#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/message_loop.h"
#include "base/string_util.h"
@@ -93,18 +94,30 @@ namespace {
class AppInstallHelper {
public:
+ // A callback for when the install process is done.
+ typedef base::Callback<void()> DoneCallback;
+
AppInstallHelper();
virtual ~AppInstallHelper();
bool success() { return success_; }
const std::string& error() { return error_; }
+ void BeginInstall(Profile* profile,
+ const std::string& id,
+ WebstoreStandaloneInstaller::PromptType prompt_type,
+ DoneCallback callback);
+ private:
WebstoreStandaloneInstaller::Callback Callback();
void OnAppInstallComplete(bool success, const std::string& error);
- private:
+ DoneCallback done_callback_;
+
// These hold on to the result of the app install when it is complete.
bool success_;
std::string error_;
+
+ scoped_ptr<content::WebContents> web_contents_;
+ scoped_refptr<WebstoreStandaloneInstaller> installer_;
};
AppInstallHelper::AppInstallHelper() : success_(false) {}
@@ -115,11 +128,44 @@ WebstoreStandaloneInstaller::Callback AppInstallHelper::Callback() {
return base::Bind(&AppInstallHelper::OnAppInstallComplete,
base::Unretained(this));
}
+
+void AppInstallHelper::BeginInstall(
+ Profile* profile,
+ const std::string& id,
+ WebstoreStandaloneInstaller::PromptType prompt_type,
+ DoneCallback done_callback) {
+ done_callback_ = done_callback;
+
+ // TODO(asargent) - it would be nice not to need a WebContents just to
+ // use the standalone installer. (crbug.com/149039)
+ web_contents_.reset(content::WebContents::Create(
+ content::WebContents::CreateParams(profile)));
+
+ WebstoreStandaloneInstaller::Callback callback =
+ base::Bind(&AppInstallHelper::OnAppInstallComplete,
+ base::Unretained(this));
+ installer_ = new WebstoreStandaloneInstaller(
+ web_contents_.get(),
+ id,
+ WebstoreStandaloneInstaller::DO_NOT_REQUIRE_VERIFIED_SITE,
+ prompt_type,
+ GURL(),
+ callback);
+ installer_->set_skip_post_install_ui(true);
+ installer_->BeginInstall();
+}
+
void AppInstallHelper::OnAppInstallComplete(bool success,
const std::string& error) {
success_ = success;
error_= error;
- MessageLoop::current()->Quit();
+ done_callback_.Run();
+}
+
+void DeleteHelperAndRunCallback(AppInstallHelper* helper,
+ base::Callback<void()> callback) {
+ delete helper;
+ callback.Run();
}
} // namespace
@@ -133,27 +179,12 @@ bool StartupHelper::InstallFromWebstore(const CommandLine& cmd_line,
return false;
}
- // TODO(asargent) - it would be nice not to need a WebContents just to
- // use the standalone installer. (crbug.com/149039)
- scoped_ptr<content::WebContents> web_contents(content::WebContents::Create(
- content::WebContents::CreateParams(profile)));
-
AppInstallHelper helper;
- WebstoreStandaloneInstaller::Callback callback =
- base::Bind(&AppInstallHelper::OnAppInstallComplete,
- base::Unretained(&helper));
- scoped_refptr<WebstoreStandaloneInstaller> installer(
- new WebstoreStandaloneInstaller(
- web_contents.get(),
- id,
- WebstoreStandaloneInstaller::DO_NOT_REQUIRE_VERIFIED_SITE,
- cmd_line.HasSwitch(switches::kForceAppMode) ?
- WebstoreStandaloneInstaller::SKIP_PROMPT :
- WebstoreStandaloneInstaller::STANDARD_PROMPT ,
- GURL(),
- callback));
- installer->set_skip_post_install_ui(true);
- installer->BeginInstall();
+ helper.BeginInstall(profile, id,
+ cmd_line.HasSwitch(switches::kForceAppMode) ?
+ WebstoreStandaloneInstaller::SKIP_PROMPT :
+ WebstoreStandaloneInstaller::STANDARD_PROMPT,
+ MessageLoop::QuitWhenIdleClosure());
MessageLoop::current()->Run();
if (!helper.success())
@@ -161,6 +192,36 @@ bool StartupHelper::InstallFromWebstore(const CommandLine& cmd_line,
return helper.success();
}
+void StartupHelper::LimitedInstallFromWebstore(
+ const CommandLine& cmd_line,
+ Profile* profile,
+ base::Callback<void()> done_callback) {
+ std::string id = WebStoreIdFromLimitedInstallCmdLine(cmd_line);
+ if (!Extension::IdIsValid(id)) {
+ LOG(ERROR) << "Invalid index for " << switches::kLimitedInstallFromWebstore;
+ done_callback.Run();
+ return;
+ }
+
+ AppInstallHelper* helper = new AppInstallHelper();
+ helper->BeginInstall(profile, id,
+ WebstoreStandaloneInstaller::STANDARD_PROMPT,
+ base::Bind(&DeleteHelperAndRunCallback, helper, done_callback));
+}
+
+std::string StartupHelper::WebStoreIdFromLimitedInstallCmdLine(
+ const CommandLine& cmd_line) {
+ std::string index = cmd_line.GetSwitchValueASCII(
+ switches::kLimitedInstallFromWebstore);
+ std::string id;
+ if (index == "1") {
+ id = "nckgahadagoaajjgafhacjanaoiihapd";
+ } else if (index == "2") {
+ id = "ecglahbcnmdpdciemllbhojghbkagdje";
+ }
+ return id;
+}
+
StartupHelper::~StartupHelper() {
if (pack_job_.get())
pack_job_->ClearClient();
diff --git a/chrome/browser/extensions/startup_helper.h b/chrome/browser/extensions/startup_helper.h
index dc54491..01ccfa6 100644
--- a/chrome/browser/extensions/startup_helper.h
+++ b/chrome/browser/extensions/startup_helper.h
@@ -39,6 +39,18 @@ class StartupHelper : public PackExtensionJob::Client {
// confirm, and then downloading the crx and installing it.
bool InstallFromWebstore(const CommandLine& cmd_line, Profile* profile);
+ // Handle --limited-install-from-webstore flag from |cmd_line| by downloading
+ // metadata from the webstore for the given id, prompting the user to
+ // confirm, and then downloading the crx and installing it.
+ // This whole process is only kicked off by this function and completed
+ // asynchronously unlike InstallFromWebstore which finishes everything before
+ // returning.
+ void LimitedInstallFromWebstore(const CommandLine& cmd_line, Profile* profile,
+ base::Callback<void()> done_callback);
+
+ // Maps the command line argument to the extension id. Returns an empty string
+ // in the case when there is no mapping.
+ std::string WebStoreIdFromLimitedInstallCmdLine(const CommandLine& cmd_line);
private:
scoped_refptr<PackExtensionJob> pack_job_;
bool pack_job_succeeded_;
diff --git a/chrome/browser/extensions/webstore_standalone_install_browsertest.cc b/chrome/browser/extensions/webstore_standalone_install_browsertest.cc
index d07d545..b56c0b3e 100644
--- a/chrome/browser/extensions/webstore_standalone_install_browsertest.cc
+++ b/chrome/browser/extensions/webstore_standalone_install_browsertest.cc
@@ -232,8 +232,6 @@ class CommandLineWebstoreInstall : public WebstoreStandaloneInstallTest,
content::NotificationService::AllSources());
registrar_.Add(this, chrome::NOTIFICATION_BROWSER_OPENED,
content::NotificationService::AllSources());
- CommandLine::ForCurrentProcess()->AppendSwitchASCII(
- switches::kInstallFromWebstore, kTestExtensionId);
}
bool saw_install() { return saw_install_; }
@@ -243,7 +241,7 @@ class CommandLineWebstoreInstall : public WebstoreStandaloneInstallTest,
// NotificationObserver interface.
virtual void Observe(int type,
const content::NotificationSource& source,
- const content::NotificationDetails& details) OVERRIDE {
+ const content::NotificationDetails& details) OVERRIDE {
if (type == chrome::NOTIFICATION_EXTENSION_INSTALLED) {
const Extension* extension = content::Details<Extension>(details).ptr();
ASSERT_TRUE(extension != NULL);
@@ -268,6 +266,8 @@ class CommandLineWebstoreInstall : public WebstoreStandaloneInstallTest,
IN_PROC_BROWSER_TEST_F(CommandLineWebstoreInstall, Accept) {
CommandLine* command_line = CommandLine::ForCurrentProcess();
command_line->AppendSwitchASCII(
+ switches::kInstallFromWebstore, kTestExtensionId);
+ command_line->AppendSwitchASCII(
switches::kAppsGalleryInstallAutoConfirmForTests, "accept");
extensions::StartupHelper helper;
EXPECT_TRUE(helper.InstallFromWebstore(*command_line, browser()->profile()));
@@ -278,9 +278,56 @@ IN_PROC_BROWSER_TEST_F(CommandLineWebstoreInstall, Accept) {
IN_PROC_BROWSER_TEST_F(CommandLineWebstoreInstall, Cancel) {
CommandLine* command_line = CommandLine::ForCurrentProcess();
command_line->AppendSwitchASCII(
+ switches::kInstallFromWebstore, kTestExtensionId);
+ command_line->AppendSwitchASCII(
switches::kAppsGalleryInstallAutoConfirmForTests, "cancel");
extensions::StartupHelper helper;
EXPECT_FALSE(helper.InstallFromWebstore(*command_line, browser()->profile()));
EXPECT_FALSE(saw_install());
EXPECT_EQ(0, browser_open_count());
}
+
+IN_PROC_BROWSER_TEST_F(CommandLineWebstoreInstall, LimitedAccept) {
+ extensions::StartupHelper helper;
+
+ // Small test of "WebStoreIdFromLimitedInstallCmdLine" which made more
+ // sense together with the rest of the test for "LimitedInstallFromWebstore".
+ CommandLine command_line_test1(CommandLine::NO_PROGRAM);
+ command_line_test1.AppendSwitchASCII(switches::kLimitedInstallFromWebstore,
+ "1");
+ EXPECT_EQ("nckgahadagoaajjgafhacjanaoiihapd",
+ helper.WebStoreIdFromLimitedInstallCmdLine(command_line_test1));
+
+ CommandLine command_line_test2(CommandLine::NO_PROGRAM);
+ command_line_test1.AppendSwitchASCII(switches::kLimitedInstallFromWebstore,
+ "2");
+ EXPECT_EQ(kTestExtensionId,
+ helper.WebStoreIdFromLimitedInstallCmdLine(command_line_test1));
+
+ // Now, on to the real test for LimitedInstallFromWebstore.
+ CommandLine* command_line = CommandLine::ForCurrentProcess();
+ command_line->AppendSwitchASCII(
+ switches::kLimitedInstallFromWebstore, "2");
+ command_line->AppendSwitchASCII(
+ switches::kAppsGalleryInstallAutoConfirmForTests, "accept");
+ helper.LimitedInstallFromWebstore(*command_line, browser()->profile(),
+ MessageLoop::QuitWhenIdleClosure());
+ MessageLoop::current()->Run();
+
+ EXPECT_TRUE(saw_install());
+ EXPECT_EQ(0, browser_open_count());
+}
+
+IN_PROC_BROWSER_TEST_F(CommandLineWebstoreInstall, LimitedCancel) {
+ CommandLine* command_line = CommandLine::ForCurrentProcess();
+ command_line->AppendSwitchASCII(
+ switches::kLimitedInstallFromWebstore, "2");
+ command_line->AppendSwitchASCII(
+ switches::kAppsGalleryInstallAutoConfirmForTests, "cancel");
+ extensions::StartupHelper helper;
+ helper.LimitedInstallFromWebstore(*command_line, browser()->profile(),
+ MessageLoop::QuitWhenIdleClosure());
+ MessageLoop::current()->Run();
+ EXPECT_FALSE(saw_install());
+ EXPECT_EQ(0, browser_open_count());
+}
diff --git a/chrome/browser/extensions/webstore_standalone_installer.cc b/chrome/browser/extensions/webstore_standalone_installer.cc
index 792be92..19316fa 100644
--- a/chrome/browser/extensions/webstore_standalone_installer.cc
+++ b/chrome/browser/extensions/webstore_standalone_installer.cc
@@ -324,6 +324,10 @@ void WebstoreStandaloneInstaller::OnExtensionInstallFailure(
}
void WebstoreStandaloneInstaller::CompleteInstall(const std::string& error) {
+ // Clear webstore_data_fetcher_ so that WebContentsDestroyed will no longer
+ // call Release in case the WebContents is destroyed before this object.
+ scoped_ptr<WebstoreDataFetcher> webstore_data_fetcher(
+ webstore_data_fetcher_.Pass());
if (!callback_.is_null())
callback_.Run(error.empty(), error);
diff --git a/chrome/browser/ui/startup/startup_browser_creator.cc b/chrome/browser/ui/startup/startup_browser_creator.cc
index bdd7284..207f9e0 100644
--- a/chrome/browser/ui/startup/startup_browser_creator.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator.cc
@@ -550,6 +550,12 @@ bool StartupBrowserCreator::ProcessCmdLineImpl(
}
}
+ if (command_line.HasSwitch(switches::kLimitedInstallFromWebstore)) {
+ extensions::StartupHelper helper;
+ helper.LimitedInstallFromWebstore(command_line, last_used_profile,
+ base::Bind(&base::DoNothing));
+ }
+
#if defined(OS_CHROMEOS)
// The browser will be launched after the user logs in.
if (command_line.HasSwitch(switches::kLoginManager) ||