summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorjoaodasilva@chromium.org <joaodasilva@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-11 17:54:59 +0000
committerjoaodasilva@chromium.org <joaodasilva@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-11 17:54:59 +0000
commit8a87a533efa7ac622a839499ada717f35f14dda2 (patch)
tree1fe7265c6ab1af6a488240ad291c6c66be8df3f4 /chrome
parentba0b53cfe7abf74b8c3d667a52c666350b757035 (diff)
downloadchromium_src-8a87a533efa7ac622a839499ada717f35f14dda2.zip
chromium_src-8a87a533efa7ac622a839499ada717f35f14dda2.tar.gz
chromium_src-8a87a533efa7ac622a839499ada717f35f14dda2.tar.bz2
Extensions installed by policy overrun previously installed extensions.
BUG=86519 TEST=Extensions tests, should all work as before. The test described in the bug should now work as expected. Review URL: http://codereview.chromium.org/7605001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@96420 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/extensions/extension_management_browsertest.cc113
-rw-r--r--chrome/browser/extensions/extension_service.cc17
-rw-r--r--chrome/browser/extensions/extension_service_unittest.cc27
-rw-r--r--chrome/browser/extensions/extension_updater.cc22
-rw-r--r--chrome/browser/extensions/pending_extension_manager.cc22
5 files changed, 178 insertions, 23 deletions
diff --git a/chrome/browser/extensions/extension_management_browsertest.cc b/chrome/browser/extensions/extension_management_browsertest.cc
index cace228..cd018a42 100644
--- a/chrome/browser/extensions/extension_management_browsertest.cc
+++ b/chrome/browser/extensions/extension_management_browsertest.cc
@@ -442,6 +442,16 @@ IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, ExternalUrlUpdate) {
<< "Uninstalling non-external extension should not set kill bit.";
}
+namespace {
+
+const char* kForceInstallNotEmptyHelp =
+ "A policy may already be controlling the list of force-installed "
+ "extensions. Please remove all policy settings from your computer "
+ "before running tests. E.g. from /etc/chromium/policies Linux or "
+ "from the registry on Windows, etc.";
+
+}
+
// See http://crbug.com/57378 for flakiness details.
IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, ExternalPolicyRefresh) {
ExtensionService* service = browser()->profile()->GetExtensionService();
@@ -466,11 +476,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, ExternalPolicyRefresh) {
PrefService* prefs = browser()->profile()->GetPrefs();
const ListValue* forcelist =
prefs->GetList(prefs::kExtensionInstallForceList);
- ASSERT_TRUE(forcelist->empty())
- << "A policy may already be controlling the list of force-installed "
- << "extensions. Please remove all policy settings from your computer "
- << "before running tests. E.g. from /etc/chromium/policies Linux or "
- << "from the registry on Windows, etc.";
+ ASSERT_TRUE(forcelist->empty()) << kForceInstallNotEmptyHelp;
{
// Set the policy as a user preference and fire notification observers.
@@ -516,3 +522,100 @@ IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, ExternalPolicyRefresh) {
for (i = extensions->begin(); i != extensions->end(); ++i)
EXPECT_NE(kExtensionId, (*i)->id());
}
+
+IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, PolicyOverridesUserInstall) {
+ ExtensionService* service = browser()->profile()->GetExtensionService();
+ const char* kExtensionId = "ogjcoiohnmldgjemafoockdghcjciccf";
+ service->updater()->set_blacklist_checks_enabled(false);
+ const size_t size_before = service->extensions()->size();
+ FilePath basedir = test_data_dir_.AppendASCII("autoupdate");
+ ASSERT_TRUE(service->disabled_extensions()->empty());
+
+ // Note: This interceptor gets requests on the IO thread.
+ scoped_refptr<AutoUpdateInterceptor> interceptor(new AutoUpdateInterceptor());
+ URLFetcher::enable_interception_for_tests(true);
+
+ interceptor->SetResponseOnIOThread("http://localhost/autoupdate/manifest",
+ basedir.AppendASCII("manifest_v2.xml"));
+ interceptor->SetResponseOnIOThread("http://localhost/autoupdate/v2.crx",
+ basedir.AppendASCII("v2.crx"));
+
+ // Check that the policy is initially empty.
+ PrefService* prefs = browser()->profile()->GetPrefs();
+ const ListValue* forcelist =
+ prefs->GetList(prefs::kExtensionInstallForceList);
+ ASSERT_TRUE(forcelist->empty()) << kForceInstallNotEmptyHelp;
+
+ // User install of the extension.
+ ASSERT_TRUE(InstallExtension(basedir.AppendASCII("v2.crx"), 1));
+ const ExtensionList* extensions = service->extensions();
+ ASSERT_EQ(size_before + 1, extensions->size());
+ const Extension* extension = extensions->at(size_before);
+ ASSERT_EQ(kExtensionId, extension->id());
+ EXPECT_EQ(Extension::INTERNAL, extension->location());
+ EXPECT_TRUE(service->IsExtensionEnabled(kExtensionId));
+
+ // Setup the force install policy. It should override the location.
+ {
+ ListPrefUpdate pref_update(prefs, prefs::kExtensionInstallForceList);
+ ListValue* forcelist = pref_update.Get();
+ ASSERT_TRUE(forcelist->empty());
+ forcelist->Append(Value::CreateStringValue(
+ std::string(kExtensionId) + ";http://localhost/autoupdate/manifest"));
+ }
+ ASSERT_TRUE(WaitForExtensionInstall());
+ extensions = service->extensions();
+ ASSERT_EQ(size_before + 1, extensions->size());
+ extension = extensions->at(size_before);
+ ASSERT_EQ(kExtensionId, extension->id());
+ EXPECT_EQ(Extension::EXTERNAL_POLICY_DOWNLOAD, extension->location());
+ EXPECT_TRUE(service->IsExtensionEnabled(kExtensionId));
+
+ // Remove the policy, and verify that the extension was uninstalled.
+ // TODO(joaodasilva): it would be nicer if the extension was kept instead,
+ // and reverted location to INTERNAL or whatever it was before the policy
+ // was applied.
+ {
+ ListPrefUpdate pref_update(prefs, prefs::kExtensionInstallForceList);
+ ListValue* forcelist = pref_update.Get();
+ ASSERT_TRUE(!forcelist->empty());
+ forcelist->Clear();
+ }
+ extensions = service->extensions();
+ ASSERT_EQ(size_before, extensions->size());
+ extension = service->GetExtensionById(kExtensionId, true);
+ EXPECT_TRUE(extension == NULL);
+
+ // User install again, but have it disabled too before setting the policy.
+ ASSERT_TRUE(InstallExtension(basedir.AppendASCII("v2.crx"), 1));
+ extensions = service->extensions();
+ ASSERT_EQ(size_before + 1, extensions->size());
+ extension = extensions->at(size_before);
+ ASSERT_EQ(kExtensionId, extension->id());
+ EXPECT_EQ(Extension::INTERNAL, extension->location());
+ EXPECT_TRUE(service->IsExtensionEnabled(kExtensionId));
+ EXPECT_TRUE(service->disabled_extensions()->empty());
+
+ service->DisableExtension(kExtensionId);
+ EXPECT_EQ(1u, service->disabled_extensions()->size());
+ EXPECT_EQ(kExtensionId, service->disabled_extensions()->at(0)->id());
+ EXPECT_FALSE(service->IsExtensionEnabled(kExtensionId));
+
+ // Install the policy again. It should overwrite the extension's location,
+ // and force enable it too.
+ {
+ ListPrefUpdate pref_update(prefs, prefs::kExtensionInstallForceList);
+ ListValue* forcelist = pref_update.Get();
+ ASSERT_TRUE(forcelist->empty());
+ forcelist->Append(Value::CreateStringValue(
+ std::string(kExtensionId) + ";http://localhost/autoupdate/manifest"));
+ }
+ ASSERT_TRUE(WaitForExtensionInstall());
+ extensions = service->extensions();
+ ASSERT_EQ(size_before + 1, extensions->size());
+ extension = extensions->at(size_before);
+ ASSERT_EQ(kExtensionId, extension->id());
+ EXPECT_EQ(Extension::EXTERNAL_POLICY_DOWNLOAD, extension->location());
+ EXPECT_TRUE(service->IsExtensionEnabled(kExtensionId));
+ EXPECT_TRUE(service->disabled_extensions()->empty());
+}
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc
index c729867..b49f5bd 100644
--- a/chrome/browser/extensions/extension_service.cc
+++ b/chrome/browser/extensions/extension_service.cc
@@ -415,9 +415,14 @@ void ExtensionService::OnExternalExtensionUpdateUrlFound(
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
CHECK(Extension::IdIsValid(id));
- if (GetExtensionById(id, true)) {
- // Already installed. Do not change the update URL that the extension set.
- return;
+ const Extension* extension = GetExtensionById(id, true);
+ if (extension) {
+ // Already installed. Skip this install if the current location has
+ // higher priority than |location|.
+ Extension::Location current = extension->location();
+ if (current == Extension::GetHigherPriorityLocation(current, location))
+ return;
+ // Otherwise, overwrite the current installation.
}
pending_extension_manager()->AddFromExternalUpdateUrl(
id, update_url, location);
@@ -2163,7 +2168,11 @@ void ExtensionService::OnExtensionInstalled(
// Ensure extension is deleted unless we transfer ownership.
scoped_refptr<const Extension> scoped_extension(extension);
const std::string& id = extension->id();
- bool initial_enable = !extension_prefs_->IsExtensionDisabled(id);
+ // Extensions installed by policy can't be disabled. So even if a previous
+ // installation disabled the extension, make sure it is now enabled.
+ bool initial_enable =
+ !extension_prefs_->IsExtensionDisabled(id) ||
+ !Extension::UserMayDisable(extension->location());
PendingExtensionInfo pending_extension_info;
if (pending_extension_manager()->GetById(id, &pending_extension_info)) {
pending_extension_manager()->Remove(id);
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc
index edb7772..5111f31 100644
--- a/chrome/browser/extensions/extension_service_unittest.cc
+++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -3704,6 +3704,33 @@ TEST_F(ExtensionServiceTest, ProcessSyncDataNotInstalled) {
// TODO(akalin): Figure out a way to test |info.ShouldAllowInstall()|.
}
+TEST_F(ExtensionServiceTest, HigherPriorityInstall) {
+ InitializeEmptyExtensionService();
+
+ FilePath path = data_dir_.AppendASCII("good.crx");
+ InstallCrx(path, true);
+ ValidatePrefKeyCount(1u);
+ ValidateIntegerPref(good_crx, "state", Extension::ENABLED);
+ ValidateIntegerPref(good_crx, "location", Extension::INTERNAL);
+
+ PendingExtensionManager* pending = service_->pending_extension_manager();
+ EXPECT_FALSE(pending->IsIdPending(kGoodId));
+
+ // Skip install when the location is the same.
+ service_->OnExternalExtensionUpdateUrlFound(kGoodId, GURL(kGoodUpdateURL),
+ Extension::INTERNAL);
+ EXPECT_FALSE(pending->IsIdPending(kGoodId));
+ // Force install when the location has higher priority.
+ service_->OnExternalExtensionUpdateUrlFound(kGoodId, GURL(kGoodUpdateURL),
+ Extension::EXTERNAL_POLICY_DOWNLOAD);
+ EXPECT_TRUE(pending->IsIdPending(kGoodId));
+ pending->Remove(kGoodId);
+ // Skip install when the location has lower priority.
+ service_->OnExternalExtensionUpdateUrlFound(kGoodId, GURL(kGoodUpdateURL),
+ Extension::INTERNAL);
+ EXPECT_FALSE(pending->IsIdPending(kGoodId));
+}
+
// Test that when multiple sources try to install an extension,
// we consistently choose the right one. To make tests easy to read,
// methods that fake requests to install crx files in several ways
diff --git a/chrome/browser/extensions/extension_updater.cc b/chrome/browser/extensions/extension_updater.cc
index ae62dca..32679af 100644
--- a/chrome/browser/extensions/extension_updater.cc
+++ b/chrome/browser/extensions/extension_updater.cc
@@ -1000,14 +1000,9 @@ void ExtensionUpdater::CheckNow() {
NotifyStarted();
ManifestFetchesBuilder fetches_builder(service_, extension_prefs_);
- const ExtensionList* extensions = service_->extensions();
- for (ExtensionList::const_iterator iter = extensions->begin();
- iter != extensions->end(); ++iter) {
- fetches_builder.AddExtension(**iter);
- }
-
const PendingExtensionManager* pending_extension_manager =
service_->pending_extension_manager();
+ std::set<std::string> pending_ids;
PendingExtensionManager::const_iterator iter;
for (iter = pending_extension_manager->begin();
@@ -1016,8 +1011,21 @@ void ExtensionUpdater::CheckNow() {
// class PendingExtensionManager.
Extension::Location location = iter->second.install_source();
if (location != Extension::EXTERNAL_PREF &&
- location != Extension::EXTERNAL_REGISTRY)
+ location != Extension::EXTERNAL_REGISTRY) {
fetches_builder.AddPendingExtension(iter->first, iter->second);
+ pending_ids.insert(iter->first);
+ }
+ }
+
+ const ExtensionList* extensions = service_->extensions();
+ for (ExtensionList::const_iterator iter = extensions->begin();
+ iter != extensions->end(); ++iter) {
+ // An extension might be overwritten by policy, and have its update url
+ // changed. Make sure existing extensions aren't fetched again, if a
+ // pending fetch for an extension with the same id already exists.
+ if (!ContainsKey(pending_ids, (*iter)->id())) {
+ fetches_builder.AddExtension(**iter);
+ }
}
fetches_builder.ReportStats();
diff --git a/chrome/browser/extensions/pending_extension_manager.cc b/chrome/browser/extensions/pending_extension_manager.cc
index d4446a9..c978415 100644
--- a/chrome/browser/extensions/pending_extension_manager.cc
+++ b/chrome/browser/extensions/pending_extension_manager.cc
@@ -74,13 +74,21 @@ void PendingExtensionManager::AddFromExternalUpdateUrl(
const bool kIsFromSync = false;
const bool kInstallSilently = true;
- if (service_.IsExternalExtensionUninstalled(id))
- return;
-
- if (service_.GetInstalledExtension(id)) {
- LOG(DFATAL) << "Trying to add extension " << id
- << " by external update, but it is already installed.";
- return;
+ const Extension* extension = service_.GetInstalledExtension(id);
+ if (extension &&
+ location == Extension::GetHigherPriorityLocation(location,
+ extension->location())) {
+ // If the new location has higher priority than the location of an existing
+ // extension, let the update process overwrite the existing extension.
+ } else {
+ if (service_.IsExternalExtensionUninstalled(id)) {
+ return;
+ }
+ if (extension) {
+ LOG(DFATAL) << "Trying to add extension " << id
+ << " by external update, but it is already installed.";
+ return;
+ }
}
AddExtensionImpl(id, update_url, &AlwaysInstall,