summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/browser_init.cc76
-rw-r--r--chrome/browser/browser_main.cc20
-rw-r--r--chrome/browser/extensions/extensions_service.cc19
-rw-r--r--chrome/browser/extensions/extensions_service.h5
-rw-r--r--chrome/browser/extensions/extensions_service_unittest.cc41
-rw-r--r--chrome/browser/extensions/extensions_startup.cc123
-rw-r--r--chrome/browser/extensions/extensions_startup.h24
-rw-r--r--chrome/browser/process_singleton_win.cc11
-rw-r--r--chrome/chrome_browser.gypi2
-rw-r--r--chrome/common/chrome_switches.cc3
-rw-r--r--chrome/common/chrome_switches.h1
-rw-r--r--chrome/common/result_codes.h2
12 files changed, 251 insertions, 76 deletions
diff --git a/chrome/browser/browser_init.cc b/chrome/browser/browser_init.cc
index f7f01a4..3e7e440 100644
--- a/chrome/browser/browser_init.cc
+++ b/chrome/browser/browser_init.cc
@@ -909,54 +909,6 @@ void BrowserInit::LaunchWithProfile::CheckDefaultBrowser(Profile* profile) {
ChromeThread::FILE, FROM_HERE, new CheckDefaultBrowserTask());
}
-class PackExtensionLogger : public PackExtensionJob::Client {
- public:
- PackExtensionLogger() {}
- virtual void OnPackSuccess(const FilePath& crx_path,
- const FilePath& output_private_key_path);
- virtual void OnPackFailure(const std::string& error_message);
-
- private:
- void ShowPackExtensionMessage(const std::wstring& caption,
- const std::wstring& message);
-
- DISALLOW_COPY_AND_ASSIGN(PackExtensionLogger);
-};
-
-void PackExtensionLogger::OnPackSuccess(const FilePath& crx_path,
- const FilePath& output_private_key_path)
-{
- ShowPackExtensionMessage(L"Extension Packaging Success",
- PackExtensionJob::StandardSuccessMessage(
- crx_path, output_private_key_path));
-}
-
-void PackExtensionLogger::OnPackFailure(const std::string& error_message) {
- ShowPackExtensionMessage(L"Extension Packaging Error",
- UTF8ToWide(error_message));
-}
-
-void PackExtensionLogger::ShowPackExtensionMessage(const std::wstring& caption,
- const std::wstring& message)
-{
-#if defined(OS_WIN)
- win_util::MessageBox(NULL, message, caption, MB_OK | MB_SETFOREGROUND);
-#else
- // Just send caption & text to stdout on mac & linux.
- std::string out_text = WideToASCII(caption);
- out_text.append("\n\n");
- out_text.append(WideToASCII(message));
- out_text.append("\n");
- printf("%s", out_text.c_str());
-#endif
-
- // We got the notification and processed it; we don't expect any further tasks
- // to be posted to the current thread, so we should stop blocking and exit.
- // This call to |Quit()| matches the call to |Run()| in
- // |ProcessCmdLineImpl()|.
- MessageLoop::current()->Quit();
-}
-
bool BrowserInit::ProcessCmdLineImpl(const CommandLine& command_line,
const FilePath& cur_dir,
bool process_startup,
@@ -992,34 +944,6 @@ bool BrowserInit::ProcessCmdLineImpl(const CommandLine& command_line,
profile,
static_cast<size_t>(expected_tab_count));
}
-
- if (command_line.HasSwitch(switches::kPackExtension)) {
- // Input Paths.
- FilePath src_dir = command_line.GetSwitchValuePath(
- switches::kPackExtension);
- FilePath private_key_path;
- if (command_line.HasSwitch(switches::kPackExtensionKey)) {
- private_key_path = command_line.GetSwitchValuePath(
- switches::kPackExtensionKey);
- }
-
- // Launch a job to perform the packing on the file thread.
- PackExtensionLogger pack_client;
- scoped_refptr<PackExtensionJob> pack_job =
- new PackExtensionJob(&pack_client, src_dir, private_key_path);
- pack_job->Start();
-
- // The job will post a notification task to the current thread's message
- // loop when it is finished. We manually run the loop here so that we
- // block and catch the notification. Otherwise, the process would exit;
- // in particular, this would mean that |pack_client| would be destroyed
- // and we wouldn't be able to report success or failure back to the user.
- // This call to |Run()| is matched by a call to |Quit()| in the
- // |PackExtensionLogger|'s notification handling code.
- MessageLoop::current()->Run();
-
- return false;
- }
}
bool silent_launch = false;
diff --git a/chrome/browser/browser_main.cc b/chrome/browser/browser_main.cc
index d711778..4b3c4c1 100644
--- a/chrome/browser/browser_main.cc
+++ b/chrome/browser/browser_main.cc
@@ -43,6 +43,7 @@
#include "chrome/browser/dom_ui/chrome_url_data_manager.h"
#include "chrome/browser/extensions/extension_protocols.h"
#include "chrome/browser/extensions/extensions_service.h"
+#include "chrome/browser/extensions/extensions_startup.h"
#include "chrome/browser/first_run/first_run.h"
#include "chrome/browser/jankometer.h"
#include "chrome/browser/labs.h"
@@ -1095,6 +1096,13 @@ int BrowserMain(const MainFunctionParams& parameters) {
ResultCodes::NORMAL_EXIT : ResultCodes::SHELL_INTEGRATION_FAILED;
}
+ // If the command line specifies --pack-extension, attempt the pack extension
+ // startup action and exit.
+ if (parsed_command_line.HasSwitch(switches::kPackExtension)) {
+ extensions_startup::HandlePackExtension(parsed_command_line);
+ return ResultCodes::NORMAL_EXIT;
+ }
+
#if !defined(OS_MACOSX)
// In environments other than Mac OS X we support import of settings
// from other browsers. In case this process is a short-lived "import"
@@ -1384,6 +1392,18 @@ int BrowserMain(const MainFunctionParams& parameters) {
profile->GetExtensionsService()->InitEventRouters();
}
+ // The extension service may be available at this point. If the command line
+ // specifies --uninstall-extension, attempt the uninstall extension startup
+ // action.
+ if (parsed_command_line.HasSwitch(switches::kUninstallExtension)) {
+ if (extensions_startup::HandleUninstallExtension(parsed_command_line,
+ profile)) {
+ return ResultCodes::NORMAL_EXIT;
+ } else {
+ return ResultCodes::UNINSTALL_EXTENSION_ERROR;
+ }
+ }
+
#if defined(OS_WIN)
// We check this here because if the profile is OTR (chromeos possibility)
// it won't still be accessible after browser is destroyed.
diff --git a/chrome/browser/extensions/extensions_service.cc b/chrome/browser/extensions/extensions_service.cc
index 0a0b980..bffb732 100644
--- a/chrome/browser/extensions/extensions_service.cc
+++ b/chrome/browser/extensions/extensions_service.cc
@@ -532,6 +532,25 @@ bool ExtensionsService::IsDownloadFromMiniGallery(const GURL& download_url) {
false); // case_sensitive
}
+// static
+bool ExtensionsService::UninstallExtensionHelper(
+ ExtensionsService* extensions_service,
+ const std::string& extension_id) {
+ DCHECK(extensions_service);
+
+ // We can't call UninstallExtension with an invalid extension ID, so check it
+ // first.
+ if (extensions_service->GetExtensionById(extension_id, true)) {
+ extensions_service->UninstallExtension(extension_id, false);
+ } else {
+ LOG(WARNING) << "Attempted uninstallation of non-existent extension with "
+ << "extension with id: " << extension_id;
+ return false;
+ }
+
+ return true;
+}
+
ExtensionsService::ExtensionsService(Profile* profile,
const CommandLine* command_line,
const FilePath& install_directory,
diff --git a/chrome/browser/extensions/extensions_service.h b/chrome/browser/extensions/extensions_service.h
index 7d5ad97..18ef1f3 100644
--- a/chrome/browser/extensions/extensions_service.h
+++ b/chrome/browser/extensions/extensions_service.h
@@ -139,6 +139,11 @@ class ExtensionsService
// Used to test if we need to show the "Loading" dialog for themes.
static bool IsDownloadFromMiniGallery(const GURL& download_url);
+ // Attempts to uninstall an extension from a given ExtensionService. Returns
+ // true iff the target extension exists.
+ static bool UninstallExtensionHelper(ExtensionsService* extensions_service,
+ const std::string& extension_id);
+
ExtensionsService(Profile* profile,
const CommandLine* command_line,
const FilePath& install_directory,
diff --git a/chrome/browser/extensions/extensions_service_unittest.cc b/chrome/browser/extensions/extensions_service_unittest.cc
index 3240287..7d6733d 100644
--- a/chrome/browser/extensions/extensions_service_unittest.cc
+++ b/chrome/browser/extensions/extensions_service_unittest.cc
@@ -2034,6 +2034,47 @@ TEST_F(ExtensionsServiceTest, UninstallExtension) {
EXPECT_FALSE(file_util::PathExists(extension_path));
}
+// Tests the uninstaller helper.
+TEST_F(ExtensionsServiceTest, UninstallExtensionHelper) {
+ InitializeEmptyExtensionsService();
+ FilePath extensions_path;
+ ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path));
+ extensions_path = extensions_path.AppendASCII("extensions");
+
+ // A simple extension that should install without error.
+ FilePath path = extensions_path.AppendASCII("good.crx");
+ InstallExtension(path, true);
+
+ // The directory should be there now.
+ const char* extension_id = good_crx;
+ FilePath extension_path = extensions_install_dir_.AppendASCII(extension_id);
+ EXPECT_TRUE(file_util::PathExists(extension_path));
+
+ bool result = ExtensionsService::UninstallExtensionHelper(service_,
+ extension_id);
+ total_successes_ = 0;
+
+ EXPECT_TRUE(result);
+
+ // We should get an unload notification.
+ ASSERT_TRUE(unloaded_id_.length());
+ EXPECT_EQ(extension_id, unloaded_id_);
+
+ ValidatePrefKeyCount(0);
+
+ // The extension should not be in the service anymore.
+ ASSERT_FALSE(service_->GetExtensionById(extension_id, false));
+ loop_.RunAllPending();
+
+ // The directory should be gone.
+ EXPECT_FALSE(file_util::PathExists(extension_path));
+
+ // Attempt to uninstall again. This should fail as we just removed the
+ // extension.
+ result = ExtensionsService::UninstallExtensionHelper(service_, extension_id);
+ EXPECT_FALSE(result);
+}
+
// Verifies extension state is removed upon uninstall
TEST_F(ExtensionsServiceTest, ClearExtensionData) {
InitializeEmptyExtensionsService();
diff --git a/chrome/browser/extensions/extensions_startup.cc b/chrome/browser/extensions/extensions_startup.cc
new file mode 100644
index 0000000..90b0372
--- /dev/null
+++ b/chrome/browser/extensions/extensions_startup.cc
@@ -0,0 +1,123 @@
+// 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 "chrome/browser/extensions/extensions_startup.h"
+
+#include "base/string_util.h"
+#include "base/stringprintf.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/extensions/extensions_service.h"
+#include "chrome/browser/extensions/pack_extension_job.h"
+#include "chrome/browser/profile.h"
+#include "chrome/common/chrome_switches.h"
+
+#if defined(OS_WIN)
+#include "app/win_util.h"
+#endif
+
+namespace extensions_startup {
+
+class PackExtensionLogger : public PackExtensionJob::Client {
+ public:
+ PackExtensionLogger() {}
+ virtual void OnPackSuccess(const FilePath& crx_path,
+ const FilePath& output_private_key_path);
+ virtual void OnPackFailure(const std::string& error_message);
+
+ private:
+ // We need to track if this extension packing job was created on process
+ // startup or not so we know if we should Quit() the message loop after
+ // packaging the extension.
+ bool process_startup_;
+ void ShowPackExtensionMessage(const std::wstring& caption,
+ const std::wstring& message);
+
+ DISALLOW_COPY_AND_ASSIGN(PackExtensionLogger);
+};
+
+void PackExtensionLogger::OnPackSuccess(
+ const FilePath& crx_path,
+ const FilePath& output_private_key_path) {
+ ShowPackExtensionMessage(L"Extension Packaging Success",
+ PackExtensionJob::StandardSuccessMessage(
+ crx_path, output_private_key_path));
+}
+
+void PackExtensionLogger::OnPackFailure(const std::string& error_message) {
+ ShowPackExtensionMessage(L"Extension Packaging Error",
+ UTF8ToWide(error_message));
+}
+
+void PackExtensionLogger::ShowPackExtensionMessage(
+ const std::wstring& caption,
+ const std::wstring& message) {
+#if defined(OS_WIN)
+ win_util::MessageBox(NULL, message, caption, MB_OK | MB_SETFOREGROUND);
+#else
+ // Just send caption & text to stdout on mac & linux.
+ std::string out_text = WideToASCII(caption);
+ out_text.append("\n\n");
+ out_text.append(WideToASCII(message));
+ out_text.append("\n");
+ base::StringPrintf("%s", out_text.c_str());
+#endif
+
+ // We got the notification and processed it; we don't expect any further tasks
+ // to be posted to the current thread, so we should stop blocking and exit.
+ // This call to |Quit()| matches the call to |Run()| in
+ // |ProcessCmdLineImpl()|.
+ MessageLoop::current()->Quit();
+}
+
+bool HandlePackExtension(const CommandLine& cmd_line) {
+ if (cmd_line.HasSwitch(switches::kPackExtension)) {
+ // Input Paths.
+ FilePath src_dir = cmd_line.GetSwitchValuePath(
+ switches::kPackExtension);
+ FilePath private_key_path;
+ if (cmd_line.HasSwitch(switches::kPackExtensionKey)) {
+ private_key_path = cmd_line.GetSwitchValuePath(
+ switches::kPackExtensionKey);
+ }
+
+ // Launch a job to perform the packing on the file thread.
+ PackExtensionLogger pack_client;
+ scoped_refptr<PackExtensionJob> pack_job =
+ new PackExtensionJob(&pack_client, src_dir, private_key_path);
+ pack_job->Start();
+
+ // The job will post a notification task to the current thread's message
+ // loop when it is finished. We manually run the loop here so that we
+ // block and catch the notification. Otherwise, the process would exit;
+ // in particular, this would mean that |pack_client| would be destroyed
+ // and we wouldn't be able to report success or failure back to the user.
+ // This call to |Run()| is matched by a call to |Quit()| in the
+ // |PackExtensionLogger|'s notification handling code.
+ MessageLoop::current()->Run();
+
+ return true;
+ }
+
+ return false;
+}
+
+bool HandleUninstallExtension(const CommandLine& cmd_line, Profile* profile) {
+ DCHECK(profile);
+
+ if (cmd_line.HasSwitch(switches::kUninstallExtension)) {
+ ExtensionsService* extensions_service = profile->GetExtensionsService();
+ if (extensions_service) {
+ std::string extension_id = cmd_line.GetSwitchValueASCII(
+ switches::kUninstallExtension);
+ if (ExtensionsService::UninstallExtensionHelper(extensions_service,
+ extension_id)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+} // namespace extensions_startup
diff --git a/chrome/browser/extensions/extensions_startup.h b/chrome/browser/extensions/extensions_startup.h
new file mode 100644
index 0000000..85622de
--- /dev/null
+++ b/chrome/browser/extensions/extensions_startup.h
@@ -0,0 +1,24 @@
+// 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.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSIONS_STARTUP_H_
+#define CHROME_BROWSER_EXTENSIONS_EXTENSIONS_STARTUP_H_
+#pragma once
+
+class CommandLine;
+class Profile;
+
+// Initialization helpers for various Extension startup actions.
+namespace extensions_startup {
+// Handle --pack-extension flag from the |cmd_line| by packing the specified
+// extension. Returns false if the pack job could not be started.
+bool HandlePackExtension(const CommandLine& cmd_line);
+
+// Handle --uninstall-extension flag from the |cmd_line| by uninstalling the
+// specified extension from |profile|. Returns false if the uninstall job
+// could not be started.
+bool HandleUninstallExtension(const CommandLine& cmd_line, Profile* profile);
+} // namespace extensions_startup
+
+#endif // CHROME_BROWSER_EXTENSIONS_EXTENSIONS_STARTUP_H_
diff --git a/chrome/browser/process_singleton_win.cc b/chrome/browser/process_singleton_win.cc
index 52c7a96..5cbf2a5 100644
--- a/chrome/browser/process_singleton_win.cc
+++ b/chrome/browser/process_singleton_win.cc
@@ -15,11 +15,13 @@
#include "base/win_util.h"
#include "chrome/browser/browser_init.h"
#include "chrome/browser/browser_process.h"
+#include "chrome/browser/extensions/extensions_startup.h"
#include "chrome/browser/platform_util.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/profile_manager.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
+#include "chrome/common/chrome_switches.h"
#include "chrome/common/result_codes.h"
#include "chrome/installer/util/browser_distribution.h"
#include "grit/chromium_strings.h"
@@ -279,6 +281,15 @@ LRESULT ProcessSingleton::OnCopyData(HWND hwnd, const COPYDATASTRUCT* cds) {
return TRUE;
}
+ // Handle the --uninstall-extension startup action. This needs to done here
+ // in the process that is running with the target profile, otherwise the
+ // uninstall will fail to unload and remove all components.
+ if (parsed_command_line.HasSwitch(switches::kUninstallExtension)) {
+ extensions_startup::HandleUninstallExtension(parsed_command_line,
+ profile);
+ return TRUE;
+ }
+
// Run the browser startup sequence again, with the command line of the
// signalling process.
BrowserInit::ProcessCommandLine(parsed_command_line, cur_dir, false,
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index ae97345..0f3ed35 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1523,6 +1523,8 @@
'browser/extensions/extensions_quota_service.h',
'browser/extensions/extensions_service.cc',
'browser/extensions/extensions_service.h',
+ 'browser/extensions/extensions_startup.cc',
+ 'browser/extensions/extensions_startup.h',
'browser/extensions/extensions_ui.cc',
'browser/extensions/extensions_ui.h',
'browser/extensions/external_extension_provider.h',
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index ad0f613..ef77ba2 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -694,6 +694,9 @@ const char kKeepAliveForTest[] = "keep-alive-for-test";
// Load an extension from the specified directory.
const char kLoadExtension[] = "load-extension";
+// Uninstall an extension with the specified extension id.
+const char kUninstallExtension[] = "uninstall-extension";
+
// Load an NPAPI plugin from the specified path.
const char kLoadPlugin[] = "load-plugin";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index 2fd5b1e..c62241d 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -202,6 +202,7 @@ extern const char kInternalPepper[];
extern const char kJavaScriptFlags[];
extern const char kKeepAliveForTest[];
extern const char kLoadExtension[];
+extern const char kUninstallExtension[];
extern const char kLoadPlugin[];
extern const char kExtraPluginDir[];
extern const char kLogNetLog[];
diff --git a/chrome/common/result_codes.h b/chrome/common/result_codes.h
index 0b4bc3c..6625cb0 100644
--- a/chrome/common/result_codes.h
+++ b/chrome/common/result_codes.h
@@ -57,6 +57,8 @@ class ResultCodes {
PROFILE_IN_USE, // The profile was in use on another host.
+ UNINSTALL_EXTENSION_ERROR, // Failed to silently uninstall an extension.
+
EXIT_LAST_CODE // Last return code (keep it last).
};
};