summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/base.gypi2
-rw-r--r--base/values_util.cc18
-rw-r--r--base/values_util.h26
-rw-r--r--chrome/app/policy/policy_templates.json2
-rw-r--r--chrome/browser/extensions/extension_management_browsertest.cc17
-rw-r--r--chrome/browser/extensions/extension_service.cc300
-rw-r--r--chrome/browser/extensions/extension_service.h55
-rw-r--r--chrome/browser/extensions/extension_service_unittest.cc71
-rw-r--r--chrome/browser/extensions/external_extension_loader.cc29
-rw-r--r--chrome/browser/extensions/external_extension_loader.h71
-rw-r--r--chrome/browser/extensions/external_extension_provider_impl.cc (renamed from chrome/browser/extensions/stateful_external_extension_provider.cc)132
-rw-r--r--chrome/browser/extensions/external_extension_provider_impl.h99
-rw-r--r--chrome/browser/extensions/external_extension_provider_interface.h (renamed from chrome/browser/extensions/external_extension_provider.h)41
-rw-r--r--chrome/browser/extensions/external_policy_extension_loader.cc103
-rw-r--r--chrome/browser/extensions/external_policy_extension_loader.h49
-rw-r--r--chrome/browser/extensions/external_policy_extension_loader_unittest.cc (renamed from chrome/browser/extensions/external_policy_extension_provider_unittest.cc)41
-rw-r--r--chrome/browser/extensions/external_policy_extension_provider.cc77
-rw-r--r--chrome/browser/extensions/external_policy_extension_provider.h39
-rw-r--r--chrome/browser/extensions/external_pref_extension_loader.cc82
-rw-r--r--chrome/browser/extensions/external_pref_extension_loader.h56
-rw-r--r--chrome/browser/extensions/external_pref_extension_provider.cc57
-rw-r--r--chrome/browser/extensions/external_pref_extension_provider.h28
-rw-r--r--chrome/browser/extensions/external_registry_extension_loader_win.cc (renamed from chrome/browser/extensions/external_registry_extension_provider_win.cc)81
-rw-r--r--chrome/browser/extensions/external_registry_extension_loader_win.h28
-rw-r--r--chrome/browser/extensions/external_registry_extension_provider_win.h30
-rw-r--r--chrome/browser/extensions/stateful_external_extension_provider.h61
-rw-r--r--chrome/chrome_browser.gypi20
-rw-r--r--chrome/chrome_tests.gypi2
28 files changed, 898 insertions, 719 deletions
diff --git a/base/base.gypi b/base/base.gypi
index 27ec764..e2c659a 100644
--- a/base/base.gypi
+++ b/base/base.gypi
@@ -287,8 +287,6 @@
'utf_string_conversions.h',
'values.cc',
'values.h',
- 'values_util.cc',
- 'values_util.h',
'version.cc',
'version.h',
'vlog.cc',
diff --git a/base/values_util.cc b/base/values_util.cc
deleted file mode 100644
index fbc616b..0000000
--- a/base/values_util.cc
+++ /dev/null
@@ -1,18 +0,0 @@
-// 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 "base/values_util.h"
-
-RefCountedList::RefCountedList(ListValue* list) {
- list_ = list;
-}
-
-RefCountedList::~RefCountedList() {
- if (list_)
- delete list_;
-}
-
-ListValue* RefCountedList::Get() {
- return list_;
-}
diff --git a/base/values_util.h b/base/values_util.h
deleted file mode 100644
index 1626bb5..0000000
--- a/base/values_util.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// 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 BASE_VALUES_UTIL_H_
-#define BASE_VALUES_UTIL_H_
-#pragma once
-
-#include "base/values.h"
-#include "base/ref_counted.h"
-
-class RefCountedList : public base::RefCountedThreadSafe<RefCountedList> {
- public:
- // Takes ownership of |list|.
- explicit RefCountedList(ListValue* list);
- virtual ~RefCountedList();
-
- virtual ListValue* Get();
-
- private:
- ListValue* list_;
-
- DISALLOW_COPY_AND_ASSIGN(RefCountedList);
-};
-
-#endif // BASE_VALUES_UTIL_H_
diff --git a/chrome/app/policy/policy_templates.json b/chrome/app/policy/policy_templates.json
index 84cac8f..249b9b6 100644
--- a/chrome/app/policy/policy_templates.json
+++ b/chrome/app/policy/policy_templates.json
@@ -659,7 +659,7 @@
'type': 'list',
'supported_on': ['chrome.*:9-'],
'annotations': {
- 'features': {'dynamic_refresh': 0},
+ 'features': {'dynamic_refresh': 1},
'example_value': ['lcncmkcnkcdbbanbjakcencbaoegdjlp;https://clients2.google.com/service/update2/crx'],
},
'caption': '''Configure the list of force-installed extensions''',
diff --git a/chrome/browser/extensions/extension_management_browsertest.cc b/chrome/browser/extensions/extension_management_browsertest.cc
index a1eb2f6..4239940 100644
--- a/chrome/browser/extensions/extension_management_browsertest.cc
+++ b/chrome/browser/extensions/extension_management_browsertest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -352,8 +352,8 @@ IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, ExternalPolicyRefresh) {
prefs->GetMutableList(prefs::kExtensionInstallForceList);
ASSERT_TRUE(forcelist->empty());
forcelist->Append(Value::CreateStringValue(
- "ogjcoiohnmldgjemafoockdghcjciccf;"
- "http://localhost/autoupdate/manifest"));
+ std::string(kExtensionId) +
+ ";http://localhost/autoupdate/manifest"));
}
// Check if the extension got installed.
@@ -365,6 +365,13 @@ IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, ExternalPolicyRefresh) {
EXPECT_EQ(Extension::EXTERNAL_POLICY_DOWNLOAD,
extensions->at(size_before)->location());
- // Check that emptying the list doesn't cause any trouble.
- prefs->ClearPref(prefs::kExtensionInstallForceList);
+ // Check that emptying the list triggers uninstall.
+ {
+ ScopedPrefUpdate pref_update(prefs, prefs::kExtensionInstallForceList);
+ prefs->ClearPref(prefs::kExtensionInstallForceList);
+ }
+ EXPECT_EQ(size_before, extensions->size());
+ ExtensionList::const_iterator i;
+ for (i = extensions->begin(); i != extensions->end(); ++i)
+ EXPECT_NE(kExtensionId, (*i)->id());
}
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc
index 67cb44e..5ad45e9 100644
--- a/chrome/browser/extensions/extension_service.cc
+++ b/chrome/browser/extensions/extension_service.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -19,7 +19,6 @@
#include "base/time.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
-#include "base/values_util.h"
#include "base/version.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/themes/browser_theme_provider.h"
@@ -42,9 +41,8 @@
#include "chrome/browser/extensions/extension_processes_api.h"
#include "chrome/browser/extensions/extension_updater.h"
#include "chrome/browser/extensions/extension_webnavigation_api.h"
-#include "chrome/browser/extensions/external_extension_provider.h"
-#include "chrome/browser/extensions/external_policy_extension_provider.h"
-#include "chrome/browser/extensions/external_pref_extension_provider.h"
+#include "chrome/browser/extensions/external_extension_provider_interface.h"
+#include "chrome/browser/extensions/external_extension_provider_impl.h"
#include "chrome/browser/net/chrome_url_request_context.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
@@ -67,10 +65,6 @@
#include "webkit/database/database_tracker.h"
#include "webkit/database/database_util.h"
-#if defined(OS_WIN)
-#include "chrome/browser/extensions/external_registry_extension_provider_win.h"
-#endif
-
using base::Time;
namespace errors = extension_manifest_errors;
@@ -184,12 +178,10 @@ const char* ExtensionService::kCurrentVersionFileName = "Current Version";
// Implements IO for the ExtensionService.
class ExtensionServiceBackend
- : public base::RefCountedThreadSafe<ExtensionServiceBackend>,
- public ExternalExtensionProvider::Visitor {
+ : public base::RefCountedThreadSafe<ExtensionServiceBackend> {
public:
// |install_directory| is a path where to look for extensions to load.
- ExtensionServiceBackend(PrefService* prefs,
- const FilePath& install_directory);
+ explicit ExtensionServiceBackend(const FilePath& install_directory);
// Loads a single extension from |path| where |path| is the top directory of
// a specific extension where its manifest file lives.
@@ -200,36 +192,6 @@ class ExtensionServiceBackend
void LoadSingleExtension(const FilePath &path,
scoped_refptr<ExtensionService> frontend);
- // Check externally updated extensions for updates and install if necessary.
- // Errors are reported through ExtensionErrorReporter. Succcess is not
- // reported.
- void CheckForExternalUpdates(scoped_refptr<ExtensionService> frontend);
-
- // For the extension in |version_path| with |id|, check to see if it's an
- // externally managed extension. If so, tell the frontend to uninstall it.
- void CheckExternalUninstall(scoped_refptr<ExtensionService> frontend,
- const std::string& id);
-
- // Clear all ExternalExtensionProviders.
- void ClearProvidersForTesting();
-
- // Adds an ExternalExtensionProvider for the service to use during testing.
- // Takes ownership of |test_provider|.
- void AddProviderForTesting(ExternalExtensionProvider* test_provider);
-
- // ExternalExtensionProvider::Visitor implementation.
- virtual void OnExternalExtensionFileFound(const std::string& id,
- const Version* version,
- const FilePath& path,
- Extension::Location location);
-
- virtual void OnExternalExtensionUpdateUrlFound(const std::string& id,
- const GURL& update_url,
- Extension::Location location);
-
- virtual void UpdateExternalPolicyExtensionProvider(
- scoped_refptr<RefCountedList> forcelist);
-
private:
friend class base::RefCountedThreadSafe<ExtensionServiceBackend>;
@@ -261,48 +223,14 @@ class ExtensionServiceBackend
// Whether errors result in noisy alerts.
bool alert_on_error_;
- // A collection of external extension providers. Each provider reads
- // a source of external extension information. Examples include the
- // windows registry and external_extensions.json.
- typedef std::vector<linked_ptr<ExternalExtensionProvider> >
- ProviderCollection;
- ProviderCollection external_extension_providers_;
- linked_ptr<ExternalPolicyExtensionProvider>
- external_policy_extension_provider_;
-
- // Set to true by OnExternalExtensionUpdateUrlFound() when an external
- // extension URL is found. Used in CheckForExternalUpdates() to see
- // if an update check is needed to install pending extensions.
- bool external_extension_added_;
-
DISALLOW_COPY_AND_ASSIGN(ExtensionServiceBackend);
};
ExtensionServiceBackend::ExtensionServiceBackend(
- PrefService* prefs,
const FilePath& install_directory)
: frontend_(NULL),
install_directory_(install_directory),
- alert_on_error_(false),
- external_extension_added_(false) {
- // TODO(aa): This ends up doing blocking IO on the UI thread because it reads
- // pref data in the ctor and that is called on the UI thread. Would be better
- // to re-read data each time we list external extensions, anyway.
- external_extension_providers_.push_back(
- linked_ptr<ExternalExtensionProvider>(
- new ExternalPrefExtensionProvider()));
-#if defined(OS_WIN)
- external_extension_providers_.push_back(
- linked_ptr<ExternalExtensionProvider>(
- new ExternalRegistryExtensionProvider()));
-#endif
- // The policy-controlled extension provider is also stored in a member
- // variable so that UpdateExternalPolicyExtensionProvider can access it and
- // update its extension list later.
- external_policy_extension_provider_.reset(
- new ExternalPolicyExtensionProvider(
- prefs->GetList(prefs::kExtensionInstallForceList)));
- external_extension_providers_.push_back(external_policy_extension_provider_);
+ alert_on_error_(false) {
}
ExtensionServiceBackend::~ExtensionServiceBackend() {
@@ -352,108 +280,44 @@ void ExtensionServiceBackend::ReportExtensionLoadError(
error, NotificationType::EXTENSION_INSTALL_ERROR, alert_on_error_));
}
-// Some extensions will autoupdate themselves externally from Chrome. These
-// are typically part of some larger client application package. To support
-// these, the extension will register its location in the the preferences file
-// (and also, on Windows, in the registry) and this code will periodically
-// check that location for a .crx file, which it will then install locally if
-// a new version is available.
-void ExtensionServiceBackend::CheckForExternalUpdates(
- scoped_refptr<ExtensionService> frontend) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-
- // Note that this installation is intentionally silent (since it didn't
- // go through the front-end). Extensions that are registered in this
- // way are effectively considered 'pre-bundled', and so implicitly
- // trusted. In general, if something has HKLM or filesystem access,
- // they could install an extension manually themselves anyway.
- alert_on_error_ = false;
- frontend_ = frontend;
- external_extension_added_ = false;
-
- // Ask each external extension provider to give us a call back for each
- // extension they know about. See OnExternalExtension(File|UpdateUrl)Found.
- ProviderCollection::const_iterator i;
- for (i = external_extension_providers_.begin();
- i != external_extension_providers_.end(); ++i) {
- ExternalExtensionProvider* provider = i->get();
- provider->VisitRegisteredExtension(this);
- }
-
- if (external_extension_added_ && frontend->updater()) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- NewRunnableMethod(
- frontend->updater(), &ExtensionUpdater::CheckNow));
- }
-}
-
-void ExtensionServiceBackend::CheckExternalUninstall(
- scoped_refptr<ExtensionService> frontend, const std::string& id) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+void ExtensionService::CheckExternalUninstall(const std::string& id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
// Check if the providers know about this extension.
ProviderCollection::const_iterator i;
for (i = external_extension_providers_.begin();
i != external_extension_providers_.end(); ++i) {
+ DCHECK(i->get()->IsReady());
if (i->get()->HasExtension(id))
return; // Yup, known extension, don't uninstall.
}
// This is an external extension that we don't have registered. Uninstall.
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- NewRunnableMethod(
- frontend.get(), &ExtensionService::UninstallExtension, id, true));
-}
-
-void ExtensionServiceBackend::UpdateExternalPolicyExtensionProvider(
- scoped_refptr<RefCountedList> forcelist) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- external_policy_extension_provider_->SetPreferences(forcelist->Get());
+ UninstallExtension(id, true);
}
-void ExtensionServiceBackend::ClearProvidersForTesting() {
+void ExtensionService::ClearProvidersForTesting() {
external_extension_providers_.clear();
}
-void ExtensionServiceBackend::AddProviderForTesting(
- ExternalExtensionProvider* test_provider) {
+void ExtensionService::AddProviderForTesting(
+ ExternalExtensionProviderInterface* test_provider) {
DCHECK(test_provider);
external_extension_providers_.push_back(
- linked_ptr<ExternalExtensionProvider>(test_provider));
+ linked_ptr<ExternalExtensionProviderInterface>(test_provider));
}
-void ExtensionServiceBackend::OnExternalExtensionFileFound(
- const std::string& id, const Version* version, const FilePath& path,
- Extension::Location location) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-
- DCHECK(version);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- NewRunnableMethod(
- frontend_, &ExtensionService::OnExternalExtensionFileFound, id,
- version->GetString(), path, location));
-}
-
-void ExtensionServiceBackend::OnExternalExtensionUpdateUrlFound(
+void ExtensionService::OnExternalExtensionUpdateUrlFound(
const std::string& id,
const GURL& update_url,
Extension::Location location) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- if (frontend_->GetExtensionById(id, true)) {
+ if (GetExtensionById(id, true)) {
// Already installed. Do not change the update URL that the extension set.
return;
}
-
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- NewRunnableMethod(
- frontend_,
- &ExtensionService::AddPendingExtensionFromExternalUpdateUrl,
- id, update_url, location));
+ AddPendingExtensionFromExternalUpdateUrl(id, update_url, location);
external_extension_added_ |= true;
}
@@ -570,7 +434,6 @@ ExtensionService::ExtensionService(Profile* profile,
pref_change_registrar_.Init(profile->GetPrefs());
pref_change_registrar_.Add(prefs::kExtensionInstallAllowList, this);
pref_change_registrar_.Add(prefs::kExtensionInstallDenyList, this);
- pref_change_registrar_.Add(prefs::kExtensionInstallForceList, this);
// Set up the ExtensionUpdater
if (autoupdate_enabled) {
@@ -585,8 +448,10 @@ ExtensionService::ExtensionService(Profile* profile,
update_frequency);
}
- backend_ = new ExtensionServiceBackend(profile->GetPrefs(),
- install_directory_);
+ backend_ = new ExtensionServiceBackend(install_directory_);
+
+ ExternalExtensionProviderImpl::CreateExternalProviders(
+ this, profile_, &external_extension_providers_);
// Use monochrome icons for Omnibox icons.
omnibox_popup_icon_manager_.set_monochrome(true);
@@ -621,6 +486,12 @@ ExtensionService::~ExtensionService() {
if (updater_.get()) {
updater_->Stop();
}
+ ProviderCollection::const_iterator i;
+ for (i = external_extension_providers_.begin();
+ i != external_extension_providers_.end(); ++i) {
+ ExternalExtensionProviderInterface* provider = i->get();
+ provider->ServiceShutdown();
+ }
}
void ExtensionService::InitEventRouters() {
@@ -1205,16 +1076,6 @@ void ExtensionService::LoadInstalledExtension(const ExtensionInfo& info,
extension_prefs_->UpdateManifest(extension);
OnExtensionLoaded(extension);
-
- if (Extension::IsExternalLocation(info.extension_location)) {
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- NewRunnableMethod(
- backend_.get(),
- &ExtensionServiceBackend::CheckExternalUninstall,
- scoped_refptr<ExtensionService>(this),
- info.extension_id));
- }
}
void ExtensionService::NotifyExtensionLoaded(const Extension* extension) {
@@ -1460,31 +1321,69 @@ bool ExtensionService::GetBrowserActionVisibility(const Extension* extension) {
}
void ExtensionService::SetBrowserActionVisibility(const Extension* extension,
- bool visible) {
+ bool visible) {
extension_prefs_->SetBrowserActionVisibility(extension, visible);
}
+// Some extensions will autoupdate themselves externally from Chrome. These
+// are typically part of some larger client application package. To support
+// these, the extension will register its location in the the preferences file
+// (and also, on Windows, in the registry) and this code will periodically
+// check that location for a .crx file, which it will then install locally if
+// a new version is available.
+// Errors are reported through ExtensionErrorReporter. Succcess is not
+// reported.
void ExtensionService::CheckForExternalUpdates() {
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- NewRunnableMethod(
- backend_.get(), &ExtensionServiceBackend::CheckForExternalUpdates,
- scoped_refptr<ExtensionService>(this)));
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ // Note that this installation is intentionally silent (since it didn't
+ // go through the front-end). Extensions that are registered in this
+ // way are effectively considered 'pre-bundled', and so implicitly
+ // trusted. In general, if something has HKLM or filesystem access,
+ // they could install an extension manually themselves anyway.
+ external_extension_added_ = false;
+
+ // Ask each external extension provider to give us a call back for each
+ // extension they know about. See OnExternalExtension(File|UpdateUrl)Found.
+ ProviderCollection::const_iterator i;
+ for (i = external_extension_providers_.begin();
+ i != external_extension_providers_.end(); ++i) {
+ ExternalExtensionProviderInterface* provider = i->get();
+ provider->VisitRegisteredExtension();
+ }
+
+ // Uninstall of unclaimed extensions will happen after all the providers
+ // had reported ready. Trigger uninstall even if there are no providers
+ // installed:
+ OnExternalProviderReady();
}
-void ExtensionService::UpdateExternalPolicyExtensionProvider() {
- const ListValue* list_pref =
- profile_->GetPrefs()->GetList(prefs::kExtensionInstallForceList);
- ListValue* list_copy = NULL;
- if (list_pref)
- list_copy = static_cast<ListValue*>(list_pref->DeepCopy());
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- NewRunnableMethod(
- backend_.get(),
- &ExtensionServiceBackend::UpdateExternalPolicyExtensionProvider,
- scoped_refptr<RefCountedList>(
- new RefCountedList(list_copy))));
+void ExtensionService::OnExternalProviderReady() {
+ // An external provider has finished loading. We only take action
+ // if all of them are finished. So we check them first.
+ ProviderCollection::const_iterator i;
+ for (i = external_extension_providers_.begin();
+ i != external_extension_providers_.end(); ++i) {
+ ExternalExtensionProviderInterface* provider = i->get();
+ if (!provider->IsReady()) {
+ return;
+ }
+ }
+
+ // All the providers are ready. Install any pending extensions.
+ if (external_extension_added_ && updater()) {
+ external_extension_added_ = false;
+ updater()->CheckNow();
+ }
+
+ // Uninstall all the unclaimed extensions.
+ scoped_ptr<ExtensionPrefs::ExtensionsInfo> extensions_info(
+ extension_prefs_->GetInstalledExtensionsInfo());
+ for (size_t i = 0; i < extensions_info->size(); ++i) {
+ ExtensionInfo* info = extensions_info->at(i).get();
+ if (Extension::IsExternalLocation(info->extension_location))
+ CheckExternalUninstall(info->extension_id);
+ }
}
void ExtensionService::UnloadExtension(
@@ -1919,38 +1818,23 @@ const SkBitmap& ExtensionService::GetOmniboxPopupIcon(
return omnibox_popup_icon_manager_.GetIcon(extension_id);
}
-void ExtensionService::ClearProvidersForTesting() {
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- NewRunnableMethod(
- backend_.get(), &ExtensionServiceBackend::ClearProvidersForTesting));
-}
-
-void ExtensionService::AddProviderForTesting(
- ExternalExtensionProvider* test_provider) {
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- NewRunnableMethod(
- backend_.get(), &ExtensionServiceBackend::AddProviderForTesting,
- test_provider));
-}
-
void ExtensionService::OnExternalExtensionFileFound(
const std::string& id,
- const std::string& version,
+ const Version* version,
const FilePath& path,
Extension::Location location) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (extension_prefs_->IsExtensionKilled(id))
return;
+ DCHECK(version);
+
// Before even bothering to unpack, check and see if we already have this
// version. This is important because these extensions are going to get
// installed on every startup.
const Extension* existing = GetExtensionById(id, true);
- scoped_ptr<Version> other(Version::GetVersionFromString(version));
if (existing) {
- switch (existing->version()->CompareTo(*other)) {
+ switch (existing->version()->CompareTo(*version)) {
case -1: // existing version is older, we should upgrade
break;
case 0: // existing version is same, do nothing
@@ -2044,12 +1928,6 @@ void ExtensionService::Observe(NotificationType type,
if (*pref_name == prefs::kExtensionInstallAllowList ||
*pref_name == prefs::kExtensionInstallDenyList) {
CheckAdminBlacklist();
- } else if (*pref_name == prefs::kExtensionInstallForceList) {
- UpdateExternalPolicyExtensionProvider();
- CheckForExternalUpdates();
- // TODO(gfeher): Also check for external extensions that can be
- // uninstalled because they were removed from the pref.
- // (crbug.com/63667)
} else {
NOTREACHED() << "Unexpected preference name.";
}
diff --git a/chrome/browser/extensions/extension_service.h b/chrome/browser/extensions/extension_service.h
index 21c4a57..7849762 100644
--- a/chrome/browser/extensions/extension_service.h
+++ b/chrome/browser/extensions/extension_service.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -26,7 +26,7 @@
#include "chrome/browser/extensions/extension_process_manager.h"
#include "chrome/browser/extensions/extension_toolbar_model.h"
#include "chrome/browser/extensions/extensions_quota_service.h"
-#include "chrome/browser/extensions/external_extension_provider.h"
+#include "chrome/browser/extensions/external_extension_provider_interface.h"
#include "chrome/browser/extensions/sandboxed_extension_unpacker.h"
#include "chrome/browser/prefs/pref_change_registrar.h"
#include "chrome/common/notification_observer.h"
@@ -99,6 +99,7 @@ class ExtensionService
: public base::RefCountedThreadSafe<ExtensionService,
BrowserThread::DeleteOnUIThread>,
public ExtensionUpdateService,
+ public ExternalExtensionProviderInterface::VisitorInterface,
public NotificationObserver {
public:
// Information about a registered component extension.
@@ -298,10 +299,6 @@ class ExtensionService
// Check for updates (or potentially new extensions from external providers)
void CheckForExternalUpdates();
- // Copies the list of force-installed extensions from the user PrefService
- // to ExternalPolicyExtensionProvider.
- void UpdateExternalPolicyExtensionProvider();
-
// Unload the specified extension.
void UnloadExtension(const std::string& extension_id,
UnloadedExtensionInfo::Reason reason);
@@ -343,13 +340,6 @@ class ExtensionService
// extension.
const SkBitmap& GetOmniboxPopupIcon(const std::string& extension_id);
- // Clear all ExternalExtensionProviders.
- void ClearProvidersForTesting();
-
- // Sets an ExternalExtensionProvider for the service to use during testing.
- // Takes ownership of |test_provider|.
- void AddProviderForTesting(ExternalExtensionProvider* test_provider);
-
// Called when the initial extensions load has completed.
virtual void OnLoadedInstalledExtensions();
@@ -359,12 +349,6 @@ class ExtensionService
// Called by the backend when an extension has been installed.
void OnExtensionInstalled(const Extension* extension);
- // Called by the backend when an external extension is found.
- void OnExternalExtensionFileFound(const std::string& id,
- const std::string& version,
- const FilePath& path,
- Extension::Location location);
-
// Checks if the privileges requested by |extension| have increased, and if
// so, disables the extension and prompts the user to approve the change.
void DisableIfPrivilegeIncrease(const Extension* extension);
@@ -426,6 +410,29 @@ class ExtensionService
// view has been created.
void DidCreateRenderViewForBackgroundPage(ExtensionHost* host);
+ // For the extension in |version_path| with |id|, check to see if it's an
+ // externally managed extension. If so, uninstall it.
+ void CheckExternalUninstall(const std::string& id);
+
+ // Clear all ExternalExtensionProviders.
+ void ClearProvidersForTesting();
+
+ // Adds an ExternalExtensionProviderInterface for the service to use during
+ // testing. Takes ownership of |test_provider|.
+ void AddProviderForTesting(ExternalExtensionProviderInterface* test_provider);
+
+ // ExternalExtensionProvider::Visitor implementation.
+ virtual void OnExternalExtensionFileFound(const std::string& id,
+ const Version* version,
+ const FilePath& path,
+ Extension::Location location);
+
+ virtual void OnExternalExtensionUpdateUrlFound(const std::string& id,
+ const GURL& update_url,
+ Extension::Location location);
+
+ virtual void OnExternalProviderReady();
+
// NotificationObserver
virtual void Observe(NotificationType type,
const NotificationSource& source,
@@ -601,6 +608,16 @@ class ExtensionService
// Flag to make sure event routers are only initialized once.
bool event_routers_initialized_;
+ // A collection of external extension providers. Each provider reads
+ // a source of external extension information. Examples include the
+ // windows registry and external_extensions.json.
+ ProviderCollection external_extension_providers_;
+
+ // Set to true by OnExternalExtensionUpdateUrlFound() when an external
+ // extension URL is found. Used in CheckForExternalUpdates() to see
+ // if an update check is needed to install pending extensions.
+ bool external_extension_added_;
+
FRIEND_TEST_ALL_PREFIXES(ExtensionServiceTest,
UpdatePendingExtensionAlreadyInstalled);
FRIEND_TEST_ALL_PREFIXES(ExtensionServiceTest,
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc
index d9f8596..15fd66a 100644
--- a/chrome/browser/extensions/extension_service_unittest.cc
+++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -28,8 +28,9 @@
#include "chrome/browser/extensions/extension_creator.h"
#include "chrome/browser/extensions/extension_error_reporter.h"
#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/extensions/external_extension_provider.h"
-#include "chrome/browser/extensions/external_pref_extension_provider.h"
+#include "chrome/browser/extensions/external_extension_provider_interface.h"
+#include "chrome/browser/extensions/external_extension_provider_impl.h"
+#include "chrome/browser/extensions/external_pref_extension_loader.h"
#include "chrome/browser/extensions/pack_extension_job.cc"
#include "chrome/browser/file_system/browser_file_system_helper.h"
#include "chrome/browser/in_process_webkit/dom_storage_context.h"
@@ -125,10 +126,13 @@ static void AssertEqualExtents(ExtensionExtent* extent1,
} // namespace
-class MockExtensionProvider : public ExternalExtensionProvider {
+class MockExtensionProvider : public ExternalExtensionProviderInterface {
public:
- explicit MockExtensionProvider(Extension::Location location)
- : location_(location), visit_count_(0) {}
+ explicit MockExtensionProvider(
+ VisitorInterface* visitor,
+ Extension::Location location)
+ : location_(location), visitor_(visitor), visit_count_(0) {
+ }
virtual ~MockExtensionProvider() {}
void UpdateOrAddExtension(const std::string& id,
@@ -142,16 +146,17 @@ class MockExtensionProvider : public ExternalExtensionProvider {
}
// ExternalExtensionProvider implementation:
- virtual void VisitRegisteredExtension(Visitor* visitor) const {
+ virtual void VisitRegisteredExtension() const {
visit_count_++;
for (DataMap::const_iterator i = extension_map_.begin();
i != extension_map_.end(); ++i) {
scoped_ptr<Version> version;
version.reset(Version::GetVersionFromString(i->second.first));
- visitor->OnExternalExtensionFileFound(
+ visitor_->OnExternalExtensionFileFound(
i->first, version.get(), i->second.second, location_);
}
+ visitor_->OnExternalProviderReady();
}
virtual bool HasExtension(const std::string& id) const {
@@ -173,6 +178,14 @@ class MockExtensionProvider : public ExternalExtensionProvider {
return true;
}
+
+ virtual bool IsReady() {
+ return true;
+ }
+
+ virtual void ServiceShutdown() {
+ }
+
int visit_count() const { return visit_count_; }
void set_visit_count(int visit_count) {
visit_count_ = visit_count;
@@ -182,6 +195,7 @@ class MockExtensionProvider : public ExternalExtensionProvider {
typedef std::map< std::string, std::pair<std::string, FilePath> > DataMap;
DataMap extension_map_;
Extension::Location location_;
+ VisitorInterface* visitor_;
// visit_count_ tracks the number of calls to VisitRegisteredExtension().
// Mutable because it must be incremented on each call to
@@ -192,15 +206,19 @@ class MockExtensionProvider : public ExternalExtensionProvider {
DISALLOW_COPY_AND_ASSIGN(MockExtensionProvider);
};
-class MockProviderVisitor : public ExternalExtensionProvider::Visitor {
+class MockProviderVisitor
+ : public ExternalExtensionProviderInterface::VisitorInterface {
public:
MockProviderVisitor() : ids_found_(0) {
}
int Visit(const std::string& json_data) {
// Give the test json file to the provider for parsing.
- provider_.reset(new ExternalPrefExtensionProvider());
- provider_->SetPreferencesForTesting(json_data);
+ provider_.reset(new ExternalExtensionProviderImpl(
+ this,
+ new ExternalTestingExtensionLoader(json_data),
+ Extension::EXTERNAL_PREF,
+ Extension::EXTERNAL_PREF_DOWNLOAD));
// We also parse the file into a dictionary to compare what we get back
// from the provider.
@@ -219,7 +237,7 @@ class MockProviderVisitor : public ExternalExtensionProvider::Visitor {
// Reset our counter.
ids_found_ = 0;
// Ask the provider to look up all extensions and return them.
- provider_->VisitRegisteredExtension(this);
+ provider_->VisitRegisteredExtension();
return ids_found_;
}
@@ -285,10 +303,14 @@ class MockProviderVisitor : public ExternalExtensionProvider::Visitor {
}
}
+ virtual void OnExternalProviderReady() {
+ EXPECT_TRUE(provider_->IsReady());
+ }
+
private:
int ids_found_;
- scoped_ptr<ExternalPrefExtensionProvider> provider_;
+ scoped_ptr<ExternalExtensionProviderImpl> provider_;
scoped_ptr<DictionaryValue> prefs_;
DISALLOW_COPY_AND_ASSIGN(MockProviderVisitor);
@@ -471,7 +493,7 @@ class ExtensionServiceTest
}
}
- void AddMockExternalProvider(ExternalExtensionProvider* provider) {
+ void AddMockExternalProvider(ExternalExtensionProviderInterface* provider) {
service_->AddProviderForTesting(provider);
}
@@ -1071,8 +1093,10 @@ TEST_F(ExtensionServiceTest, KilledExtensions) {
FilePath path = extensions_path.AppendASCII("good.crx");
set_extensions_enabled(true);
+ scoped_ptr<Version> version;
+ version.reset(Version::GetVersionFromString("1.0.0.0"));
// Install an external extension.
- service_->OnExternalExtensionFileFound(good_crx, "1.0.0.0",
+ service_->OnExternalExtensionFileFound(good_crx, version.get(),
path, Extension::EXTERNAL_PREF);
loop_.RunAllPending();
ASSERT_TRUE(NULL != service_->GetExtensionById(good_crx, false));
@@ -1083,15 +1107,16 @@ TEST_F(ExtensionServiceTest, KilledExtensions) {
ValidateIntegerPref(good_crx, "location", Extension::KILLBIT);
// Try to re-install it externally. This should fail because of the killbit.
- service_->OnExternalExtensionFileFound(good_crx, "1.0.0.0",
+ service_->OnExternalExtensionFileFound(good_crx, version.get(),
path, Extension::EXTERNAL_PREF);
loop_.RunAllPending();
ASSERT_TRUE(NULL == service_->GetExtensionById(good_crx, false));
ValidateIntegerPref(good_crx, "location", Extension::KILLBIT);
+ version.reset(Version::GetVersionFromString("1.0.0.1"));
// Repeat the same thing with a newer version of the extension.
path = extensions_path.AppendASCII("good2.crx");
- service_->OnExternalExtensionFileFound(good_crx, "1.0.0.1",
+ service_->OnExternalExtensionFileFound(good_crx, version.get(),
path, Extension::EXTERNAL_PREF);
loop_.RunAllPending();
ASSERT_TRUE(NULL == service_->GetExtensionById(good_crx, false));
@@ -2862,8 +2887,7 @@ void ExtensionServiceTest::TestExternalProvider(
provider->RemoveExtension(good_crx);
loaded_.clear();
- service_->UnloadAllExtensions();
- service_->LoadAllExtensions();
+ service_->OnExternalProviderReady();
loop_.RunAllPending();
ASSERT_EQ(0u, loaded_.size());
ValidatePrefKeyCount(0);
@@ -2909,7 +2933,7 @@ TEST_F(ExtensionServiceTest, ExternalInstallRegistry) {
// Now add providers. Extension system takes ownership of the objects.
MockExtensionProvider* reg_provider =
- new MockExtensionProvider(Extension::EXTERNAL_REGISTRY);
+ new MockExtensionProvider(service_.get(), Extension::EXTERNAL_REGISTRY);
AddMockExternalProvider(reg_provider);
TestExternalProvider(reg_provider, Extension::EXTERNAL_REGISTRY);
}
@@ -2920,7 +2944,7 @@ TEST_F(ExtensionServiceTest, ExternalInstallPref) {
// Now add providers. Extension system takes ownership of the objects.
MockExtensionProvider* pref_provider =
- new MockExtensionProvider(Extension::EXTERNAL_PREF);
+ new MockExtensionProvider(service_.get(), Extension::EXTERNAL_PREF);
AddMockExternalProvider(pref_provider);
TestExternalProvider(pref_provider, Extension::EXTERNAL_PREF);
@@ -2939,7 +2963,8 @@ TEST_F(ExtensionServiceTest, ExternalInstallPrefUpdateUrl) {
// what the visitor does results in an extension being downloaded and
// installed.
MockExtensionProvider* pref_provider =
- new MockExtensionProvider(Extension::EXTERNAL_PREF_DOWNLOAD);
+ new MockExtensionProvider(service_.get(),
+ Extension::EXTERNAL_PREF_DOWNLOAD);
AddMockExternalProvider(pref_provider);
TestExternalProvider(pref_provider, Extension::EXTERNAL_PREF_DOWNLOAD);
}
@@ -3119,7 +3144,7 @@ TEST(ExtensionServiceTestSimple, Enabledness) {
// By default, we are enabled.
command_line.reset(new CommandLine(CommandLine::NO_PROGRAM));
service = profile->CreateExtensionService(command_line.get(),
- install_dir);
+ install_dir);
EXPECT_TRUE(service->extensions_enabled());
service->Init();
loop.RunAllPending();
@@ -3140,7 +3165,7 @@ TEST(ExtensionServiceTestSimple, Enabledness) {
profile.reset(new TestingProfile());
profile->GetPrefs()->SetBoolean(prefs::kDisableExtensions, true);
service = profile->CreateExtensionService(command_line.get(),
- install_dir);
+ install_dir);
EXPECT_FALSE(service->extensions_enabled());
service->Init();
loop.RunAllPending();
diff --git a/chrome/browser/extensions/external_extension_loader.cc b/chrome/browser/extensions/external_extension_loader.cc
new file mode 100644
index 0000000..79fc787
--- /dev/null
+++ b/chrome/browser/extensions/external_extension_loader.cc
@@ -0,0 +1,29 @@
+// Copyright (c) 2011 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/external_extension_loader.h"
+
+#include "base/logging.h"
+#include "base/values.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/extensions/external_extension_provider_impl.h"
+
+void ExternalExtensionLoader::Init(
+ ExternalExtensionProviderImpl* owner) {
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ owner_ = owner;
+}
+
+void ExternalExtensionLoader::OwnerShutdown() {
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ owner_ = NULL;
+}
+
+void ExternalExtensionLoader::LoadFinished() {
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ running_ = false;
+ if (owner_) {
+ owner_->SetPrefs(prefs_.release());
+ }
+}
diff --git a/chrome/browser/extensions/external_extension_loader.h b/chrome/browser/extensions/external_extension_loader.h
new file mode 100644
index 0000000..594fb9e
--- /dev/null
+++ b/chrome/browser/extensions/external_extension_loader.h
@@ -0,0 +1,71 @@
+// Copyright (c) 2011 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_EXTERNAL_EXTENSION_LOADER_H_
+#define CHROME_BROWSER_EXTENSIONS_EXTERNAL_EXTENSION_LOADER_H_
+#pragma once
+
+#include "base/ref_counted.h"
+#include "base/scoped_ptr.h"
+
+class DictionaryValue;
+class ExternalExtensionProviderImpl;
+
+// Base class for gathering a list of external extensions. Subclasses
+// implement loading from registry, JSON file, policy.
+// Instances are owned by ExternalExtensionProviderImpl objects.
+// Instances are created on the UI thread and expect public method calls from
+// the UI thread. Some subclasses introduce new methods that are executed on the
+// FILE thread.
+// The sequence of loading the extension list:
+// 1.) StartLoading() - checks if a loading task is already running
+// 2.) Load() - implemented in subclasses
+// 3.) FinishLoading()
+// 4.) owner_->SetPrefs()
+class ExternalExtensionLoader
+ : public base::RefCountedThreadSafe<ExternalExtensionLoader> {
+ public:
+ explicit ExternalExtensionLoader() : running_(false) {}
+
+ // Specifies the provider that owns this object.
+ void Init(ExternalExtensionProviderImpl* owner);
+
+ // Called by the owner before it gets deleted.
+ void OwnerShutdown();
+
+ // Initiates the possibly asynchronous loading of extension list.
+ // It is the responsibility of the caller to ensure that calls to
+ // this method do not overlap with each other.
+ // Implementations of this method should save the loaded results
+ // in prefs_ and then call LoadFinished.
+ virtual void StartLoading() = 0;
+
+ protected:
+ virtual ~ExternalExtensionLoader() {}
+
+ // Notifies the provider that the list of extensions has been loaded.
+ void LoadFinished();
+
+ // Used for passing the list of extensions from the method that loads them
+ // to |LoadFinished|. To ensure thread safety, the rules are the following:
+ // if this value is written on another thread than the UI, then it should
+ // only be written in a task that was posted from |StartLoading|. After that,
+ // this task should invoke |LoadFinished| with a PostTask. This scheme of
+ // posting tasks will avoid concurrent access and imply the necessary memory
+ // barriers.
+ scoped_ptr<DictionaryValue> prefs_;
+
+ private:
+ friend class base::RefCountedThreadSafe<ExternalExtensionLoader>;
+
+ ExternalExtensionProviderImpl* owner_; // weak
+
+ // Set to true if loading the extensions is already running. New requests
+ // are ignored while this is set true.
+ bool running_;
+
+ DISALLOW_COPY_AND_ASSIGN(ExternalExtensionLoader);
+};
+
+#endif // CHROME_BROWSER_EXTENSIONS_EXTERNAL_EXTENSION_LOADER_H_
diff --git a/chrome/browser/extensions/stateful_external_extension_provider.cc b/chrome/browser/extensions/external_extension_provider_impl.cc
index fd1a42a..9856cee 100644
--- a/chrome/browser/extensions/stateful_external_extension_provider.cc
+++ b/chrome/browser/extensions/external_extension_provider_impl.cc
@@ -1,44 +1,70 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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/stateful_external_extension_provider.h"
+#include "chrome/browser/extensions/external_extension_provider_impl.h"
#include "app/app_paths.h"
#include "base/file_path.h"
#include "base/logging.h"
+#include "base/linked_ptr.h"
#include "base/path_service.h"
#include "base/values.h"
#include "base/version.h"
#include "chrome/browser/browser_thread.h"
-
-namespace {
-
-// Constants for keeping track of extension preferences.
-const char kLocation[] = "location";
-const char kState[] = "state";
-const char kExternalCrx[] = "external_crx";
-const char kExternalVersion[] = "external_version";
-const char kExternalUpdateUrl[] = "external_update_url";
-
-}
-
-StatefulExternalExtensionProvider::StatefulExternalExtensionProvider(
+#include "chrome/browser/extensions/external_extension_provider_interface.h"
+#include "chrome/browser/extensions/external_policy_extension_loader.h"
+#include "chrome/browser/extensions/external_pref_extension_loader.h"
+#include "chrome/browser/profiles/profile.h"
+
+#if defined(OS_WIN)
+#include "chrome/browser/extensions/external_registry_extension_loader_win.h"
+#endif
+
+// Constants for keeping track of extension preferences in a dictionary.
+const char ExternalExtensionProviderImpl::kLocation[] = "location";
+const char ExternalExtensionProviderImpl::kState[] = "state";
+const char ExternalExtensionProviderImpl::kExternalCrx[] = "external_crx";
+const char ExternalExtensionProviderImpl::kExternalVersion[] =
+ "external_version";
+const char ExternalExtensionProviderImpl::kExternalUpdateUrl[] =
+ "external_update_url";
+
+ExternalExtensionProviderImpl::ExternalExtensionProviderImpl(
+ VisitorInterface* service,
+ ExternalExtensionLoader* loader,
Extension::Location crx_location,
Extension::Location download_location)
: crx_location_(crx_location),
- download_location_(download_location) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ download_location_(download_location),
+ service_(service),
+ prefs_(NULL),
+ ready_(false),
+ loader_(loader) {
+ loader_->Init(this);
}
-StatefulExternalExtensionProvider::~StatefulExternalExtensionProvider() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ExternalExtensionProviderImpl::~ExternalExtensionProviderImpl() {
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ loader_->OwnerShutdown();
}
-void StatefulExternalExtensionProvider::VisitRegisteredExtension(
- Visitor* visitor) const {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- DCHECK(prefs_.get());
+void ExternalExtensionProviderImpl::VisitRegisteredExtension() const {
+ // The loader will call back to SetPrefs.
+ loader_->StartLoading();
+}
+
+void ExternalExtensionProviderImpl::SetPrefs(DictionaryValue* prefs) {
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ // Check if the service is still alive. It is possible that it had went
+ // away while |loader_| was working on the FILE thread.
+ if (!service_) return;
+
+ prefs_.reset(prefs);
+ ready_ = true; // Queries for extensions are allowed from this point.
+
+ // Notify ExtensionService about all the extensions this provider has.
for (DictionaryValue::key_iterator i = prefs_->begin_keys();
i != prefs_->end_keys(); ++i) {
const std::string& extension_id = *i;
@@ -100,10 +126,10 @@ void StatefulExternalExtensionProvider::VisitRegisteredExtension(
<< external_version << "\".";
continue;
}
- visitor->OnExternalExtensionFileFound(extension_id, version.get(), path,
+ service_->OnExternalExtensionFileFound(extension_id, version.get(), path,
crx_location_);
} else { // if (has_external_update_url)
- DCHECK(has_external_update_url); // Checking of keys above ensures this.
+ CHECK(has_external_update_url); // Checking of keys above ensures this.
if (download_location_ == Extension::INVALID) {
LOG(WARNING) << "This provider does not support installing external "
<< "extensions from update URLs.";
@@ -117,24 +143,36 @@ void StatefulExternalExtensionProvider::VisitRegisteredExtension(
<< "\".";
continue;
}
- visitor->OnExternalExtensionUpdateUrlFound(
+ service_->OnExternalExtensionUpdateUrlFound(
extension_id, update_url, download_location_);
}
}
+
+ service_->OnExternalProviderReady();
+}
+
+void ExternalExtensionProviderImpl::ServiceShutdown() {
+ service_ = NULL;
+}
+
+bool ExternalExtensionProviderImpl::IsReady() {
+ return ready_;
}
-bool StatefulExternalExtensionProvider::HasExtension(
+bool ExternalExtensionProviderImpl::HasExtension(
const std::string& id) const {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- DCHECK(prefs_.get());
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ CHECK(prefs_.get());
+ CHECK(ready_);
return prefs_->HasKey(id);
}
-bool StatefulExternalExtensionProvider::GetExtensionDetails(
+bool ExternalExtensionProviderImpl::GetExtensionDetails(
const std::string& id, Extension::Location* location,
scoped_ptr<Version>* version) const {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- DCHECK(prefs_.get());
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ CHECK(prefs_.get());
+ CHECK(ready_);
DictionaryValue* extension = NULL;
if (!prefs_->GetDictionary(id, &extension))
return false;
@@ -164,6 +202,32 @@ bool StatefulExternalExtensionProvider::GetExtensionDetails(
return true;
}
-void StatefulExternalExtensionProvider::set_prefs(DictionaryValue* prefs) {
- prefs_.reset(prefs);
+// static
+void ExternalExtensionProviderImpl::CreateExternalProviders(
+ VisitorInterface* service,
+ Profile* profile,
+ ProviderCollection* provider_list) {
+ provider_list->push_back(
+ linked_ptr<ExternalExtensionProviderInterface>(
+ new ExternalExtensionProviderImpl(
+ service,
+ new ExternalPrefExtensionLoader,
+ Extension::EXTERNAL_PREF,
+ Extension::EXTERNAL_PREF_DOWNLOAD)));
+#if defined(OS_WIN)
+ provider_list->push_back(
+ linked_ptr<ExternalExtensionProviderInterface>(
+ new ExternalExtensionProviderImpl(
+ service,
+ new ExternalRegistryExtensionLoader,
+ Extension::EXTERNAL_REGISTRY,
+ Extension::INVALID)));
+#endif
+ provider_list->push_back(
+ linked_ptr<ExternalExtensionProviderInterface>(
+ new ExternalExtensionProviderImpl(
+ service,
+ new ExternalPolicyExtensionLoader(profile),
+ Extension::INVALID,
+ Extension::EXTERNAL_POLICY_DOWNLOAD)));
}
diff --git a/chrome/browser/extensions/external_extension_provider_impl.h b/chrome/browser/extensions/external_extension_provider_impl.h
new file mode 100644
index 0000000..2856db9
--- /dev/null
+++ b/chrome/browser/extensions/external_extension_provider_impl.h
@@ -0,0 +1,99 @@
+// Copyright (c) 2011 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_EXTERNAL_EXTENSION_PROVIDER_IMPL_H_
+#define CHROME_BROWSER_EXTENSIONS_EXTERNAL_EXTENSION_PROVIDER_IMPL_H_
+#pragma once
+
+#include "chrome/browser/extensions/external_extension_provider_interface.h"
+
+#include "base/ref_counted.h"
+#include "chrome/browser/extensions/external_extension_loader.h"
+
+class DictionaryValue;
+class ExternalExtensionLoader;
+class Profile;
+class ValueSerializer;
+class Version;
+
+// A specialization of the ExternalExtensionProvider that uses an instance
+// of ExternalExtensionLoader to provide external extensions. This class
+// can be seen as a bridge between the extension system and an
+// ExternalExtensionLoader. Instances live their entire life on the UI thread.
+class ExternalExtensionProviderImpl
+ : public ExternalExtensionProviderInterface {
+ public:
+ // The constructed provider will provide the extensions loaded from |loader|
+ // to |service|, that will deal with the installation. The location
+ // attributes of the provided extensions are also specified here:
+ // |crx_location|: extensions originating from crx files
+ // |download_location|: extensions originating from update URLs
+ // If either of the origins is not supported by this provider, then it should
+ // be initialized as Extensions::INVALID.
+ ExternalExtensionProviderImpl(
+ VisitorInterface* service,
+ ExternalExtensionLoader* loader,
+ Extension::Location crx_location,
+ Extension::Location download_location);
+
+ virtual ~ExternalExtensionProviderImpl();
+
+ // Populates a list with providers for all known sources.
+ static void CreateExternalProviders(
+ VisitorInterface* service,
+ Profile* profile,
+ ProviderCollection* provider_list);
+
+ // Sets underlying prefs and notifies provider. Only to be called by the
+ // owned ExternalExtensionLoader instance.
+ void SetPrefs(DictionaryValue* prefs);
+
+ // ExternalExtensionProvider implementation:
+ virtual void VisitRegisteredExtension() const;
+
+ virtual bool HasExtension(const std::string& id) const;
+
+ virtual bool GetExtensionDetails(const std::string& id,
+ Extension::Location* location,
+ scoped_ptr<Version>* version) const;
+
+ virtual void ServiceShutdown();
+
+ virtual bool IsReady();
+
+ static const char kLocation[];
+ static const char kState[];
+ static const char kExternalCrx[];
+ static const char kExternalVersion[];
+ static const char kExternalUpdateUrl[];
+
+ private:
+ // Location for external extensions that are provided by this provider from
+ // local crx files.
+ const Extension::Location crx_location_;
+
+ // Location for external extensions that are provided by this provider from
+ // update URLs.
+ const Extension::Location download_location_;
+
+ private:
+ // Weak pointer to the object that consumes the external extensions.
+ // This is zeroed out by: ServiceShutdown()
+ VisitorInterface* service_; // weak
+
+ // Dictionary of the external extensions that are provided by this provider.
+ scoped_ptr<DictionaryValue> prefs_;
+
+ // Indicates that the extensions provided by this provider are loaded
+ // entirely.
+ bool ready_;
+
+ // The loader that loads the list of external extensions and reports them
+ // via |SetPrefs|.
+ scoped_refptr<ExternalExtensionLoader> loader_;
+
+ DISALLOW_COPY_AND_ASSIGN(ExternalExtensionProviderImpl);
+};
+
+#endif // CHROME_BROWSER_EXTENSIONS_EXTERNAL_EXTENSION_PROVIDER_IMPL_H_
diff --git a/chrome/browser/extensions/external_extension_provider.h b/chrome/browser/extensions/external_extension_provider_interface.h
index 5bcce1d5..7f9d3c4 100644
--- a/chrome/browser/extensions/external_extension_provider.h
+++ b/chrome/browser/extensions/external_extension_provider_interface.h
@@ -1,11 +1,14 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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_EXTERNAL_EXTENSION_PROVIDER_H_
-#define CHROME_BROWSER_EXTENSIONS_EXTERNAL_EXTENSION_PROVIDER_H_
+#ifndef CHROME_BROWSER_EXTENSIONS_EXTERNAL_EXTENSION_PROVIDER_INTERFACE_H_
+#define CHROME_BROWSER_EXTENSIONS_EXTERNAL_EXTENSION_PROVIDER_INTERFACE_H_
#pragma once
+#include <vector>
+
+#include "base/linked_ptr.h"
#include "chrome/common/extensions/extension.h"
class FilePath;
@@ -13,13 +16,13 @@ class Version;
// This class is an abstract class for implementing external extensions
// providers.
-class ExternalExtensionProvider {
+class ExternalExtensionProviderInterface {
public:
// ExternalExtensionProvider uses this interface to communicate back to the
// caller what extensions are registered, and which |id|, |version| and |path|
// they have. See also VisitRegisteredExtension below. Ownership of |version|
// is not transferred to the visitor.
- class Visitor {
+ class VisitorInterface {
public:
virtual void OnExternalExtensionFileFound(
const std::string& id,
@@ -32,16 +35,23 @@ class ExternalExtensionProvider {
const GURL& update_url,
Extension::Location location) = 0;
+ // Called after all the external extensions have been reported through
+ // the above two methods.
+ virtual void OnExternalProviderReady() = 0;
+
protected:
- virtual ~Visitor() {}
+ virtual ~VisitorInterface() {}
};
- virtual ~ExternalExtensionProvider() {}
+ virtual ~ExternalExtensionProviderInterface() {}
+
+ // The visitor (ExtensionsService) calls this function before it goes away.
+ virtual void ServiceShutdown() = 0;
- // Enumerate registered extension, calling OnExternalExtensionFound on
- // the |visitor| object for each registered extension found. |ids_to_ignore|
- // contains a list of extension ids that should not result in a call back.
- virtual void VisitRegisteredExtension(Visitor* visitor) const = 0;
+ // Enumerate registered extensions, calling
+ // OnExternalExtension(File|UpdateUrl)Found on the |visitor| object for each
+ // registered extension found.
+ virtual void VisitRegisteredExtension() const = 0;
// Test if this provider has an extension with id |id| registered.
virtual bool HasExtension(const std::string& id) const = 0;
@@ -53,6 +63,13 @@ class ExternalExtensionProvider {
virtual bool GetExtensionDetails(const std::string& id,
Extension::Location* location,
scoped_ptr<Version>* version) const = 0;
+
+ // Determines if this provider had loaded the list of external extensions
+ // from its source.
+ virtual bool IsReady() = 0;
};
-#endif // CHROME_BROWSER_EXTENSIONS_EXTERNAL_EXTENSION_PROVIDER_H_
+typedef std::vector<linked_ptr<ExternalExtensionProviderInterface> >
+ ProviderCollection;
+
+#endif // CHROME_BROWSER_EXTENSIONS_EXTERNAL_EXTENSION_PROVIDER_INTERFACE_H_
diff --git a/chrome/browser/extensions/external_policy_extension_loader.cc b/chrome/browser/extensions/external_policy_extension_loader.cc
new file mode 100644
index 0000000..99f2922
--- /dev/null
+++ b/chrome/browser/extensions/external_policy_extension_loader.cc
@@ -0,0 +1,103 @@
+// Copyright (c) 2011 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/external_policy_extension_loader.h"
+
+#include "base/logging.h"
+#include "base/values.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/notification_type.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "googleurl/src/gurl.h"
+
+namespace {
+
+// Check an extension ID and an URL to be syntactically correct.
+bool CheckExtension(std::string id, std::string update_url) {
+ GURL url(update_url);
+ if (!url.is_valid()) {
+ LOG(WARNING) << "Policy specifies invalid update URL for external "
+ << "extension: " << update_url;
+ return false;
+ }
+ if (!Extension::IdIsValid(id)) {
+ LOG(WARNING) << "Policy specifies invalid ID for external "
+ << "extension: " << id;
+ return false;
+ }
+ return true;
+}
+
+} // namespace
+
+ExternalPolicyExtensionLoader::ExternalPolicyExtensionLoader(
+ Profile* profile)
+ : profile_(profile) {
+ pref_change_registrar_.Init(profile_->GetPrefs());
+ pref_change_registrar_.Add(prefs::kExtensionInstallForceList, this);
+ notification_registrar_.Add(this,
+ NotificationType::PROFILE_DESTROYED,
+ Source<Profile>(profile_));
+}
+
+void ExternalPolicyExtensionLoader::StartLoading() {
+ const ListValue* forcelist =
+ profile_->GetPrefs()->GetList(prefs::kExtensionInstallForceList);
+ DictionaryValue* result = new DictionaryValue();
+ if (forcelist != NULL) {
+ std::string extension_desc;
+ for (ListValue::const_iterator it = forcelist->begin();
+ it != forcelist->end(); ++it) {
+ if (!(*it)->GetAsString(&extension_desc)) {
+ LOG(WARNING) << "Failed to read forcelist string.";
+ } else {
+ // Each string item of the list has the following form:
+ // extension_id_code;extension_update_url
+ // The update URL might also contain semicolons.
+ size_t pos = extension_desc.find(';');
+ std::string id = extension_desc.substr(0, pos);
+ std::string update_url = extension_desc.substr(pos+1);
+ if (CheckExtension(id, update_url)) {
+ result->SetString(id + ".external_update_url", update_url);
+ }
+ }
+ }
+ }
+ prefs_.reset(result);
+ LoadFinished();
+}
+
+void ExternalPolicyExtensionLoader::Observe(
+ NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ if (profile_ == NULL) return;
+ switch (type.value) {
+ case NotificationType::PREF_CHANGED: {
+ if (Source<PrefService>(source).ptr() == profile_->GetPrefs()) {
+ std::string* pref_name = Details<std::string>(details).ptr();
+ if (*pref_name == prefs::kExtensionInstallForceList) {
+ StartLoading();
+ } else {
+ NOTREACHED() << "Unexpected preference name.";
+ }
+ }
+ break;
+ }
+ case NotificationType::PROFILE_DESTROYED: {
+ if (Source<Profile>(source).ptr() == profile_) {
+ notification_registrar_.RemoveAll();
+ pref_change_registrar_.RemoveAll();
+ profile_ = NULL;
+ }
+ break;
+ }
+ default:
+ NOTREACHED() << "Unexpected notification type.";
+ }
+}
diff --git a/chrome/browser/extensions/external_policy_extension_loader.h b/chrome/browser/extensions/external_policy_extension_loader.h
new file mode 100644
index 0000000..7a78071
--- /dev/null
+++ b/chrome/browser/extensions/external_policy_extension_loader.h
@@ -0,0 +1,49 @@
+// Copyright (c) 2011 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_EXTERNAL_POLICY_EXTENSION_LOADER_H_
+#define CHROME_BROWSER_EXTENSIONS_EXTERNAL_POLICY_EXTENSION_LOADER_H_
+#pragma once
+
+#include "chrome/browser/extensions/external_extension_loader.h"
+
+#include "chrome/browser/prefs/pref_change_registrar.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+
+class ListValue;
+class MockExternalPolicyExtensionProviderVisitor;
+class Profile;
+
+// A specialization of the ExternalExtensionProvider that uses
+// prefs::kExtensionInstallForceList to look up which external extensions are
+// registered.
+class ExternalPolicyExtensionLoader
+ : public ExternalExtensionLoader,
+ public NotificationObserver {
+ public:
+ explicit ExternalPolicyExtensionLoader(Profile* profile);
+
+ // NotificationObserver implementation
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
+ protected:
+ virtual void StartLoading();
+
+ private:
+ friend class base::RefCountedThreadSafe<ExternalExtensionLoader>;
+
+ virtual ~ExternalPolicyExtensionLoader() {}
+
+ PrefChangeRegistrar pref_change_registrar_;
+ NotificationRegistrar notification_registrar_;
+
+ Profile* profile_;
+
+ DISALLOW_COPY_AND_ASSIGN(ExternalPolicyExtensionLoader);
+};
+
+#endif // CHROME_BROWSER_EXTENSIONS_EXTERNAL_POLICY_EXTENSION_LOADER_H_
diff --git a/chrome/browser/extensions/external_policy_extension_provider_unittest.cc b/chrome/browser/extensions/external_policy_extension_loader_unittest.cc
index cd5a3df..d72f91c 100644
--- a/chrome/browser/extensions/external_policy_extension_provider_unittest.cc
+++ b/chrome/browser/extensions/external_policy_extension_loader_unittest.cc
@@ -1,36 +1,41 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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 "base/logging.h"
+#include "base/message_loop.h"
#include "base/values.h"
#include "base/version.h"
#include "chrome/browser/browser_thread.h"
-#include "chrome/browser/extensions/external_policy_extension_provider.h"
+#include "chrome/browser/extensions/external_extension_provider_interface.h"
+#include "chrome/browser/extensions/external_extension_provider_impl.h"
+#include "chrome/browser/extensions/external_policy_extension_loader.h"
#include "chrome/common/extensions/extension.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/testing_pref_service.h"
+#include "chrome/test/testing_profile.h"
#include "testing/gtest/include/gtest/gtest.h"
class ExternalPolicyExtensionProviderTest : public testing::Test {
public:
ExternalPolicyExtensionProviderTest()
: loop_(MessageLoop::TYPE_IO),
- ui_thread_(BrowserThread::UI, &loop_),
- file_thread_(BrowserThread::FILE, &loop_) {
+ ui_thread_(BrowserThread::UI, &loop_) {
}
- virtual ~ExternalPolicyExtensionProviderTest() {
- }
+ virtual ~ExternalPolicyExtensionProviderTest() {}
private:
+ // We need these to satisfy BrowserThread::CurrentlyOn(BrowserThread::UI)
+ // checks in ExternalExtensionProviderImpl.
MessageLoop loop_;
BrowserThread ui_thread_;
- BrowserThread file_thread_;
};
class MockExternalPolicyExtensionProviderVisitor
- : public ExternalExtensionProvider::Visitor {
+ : public ExternalExtensionProviderInterface::VisitorInterface {
public:
MockExternalPolicyExtensionProviderVisitor() {
}
@@ -40,12 +45,20 @@ class MockExternalPolicyExtensionProviderVisitor
void Visit(ListValue* policy_forcelist,
ListValue* policy_validlist,
const std::set<std::string>& ignore_list) {
- provider_.reset(new ExternalPolicyExtensionProvider(policy_forcelist));
+ profile_.reset(new TestingProfile);
+ profile_->GetTestingPrefService()->SetManagedPref(
+ prefs::kExtensionInstallForceList,
+ policy_forcelist->DeepCopy());
+ provider_.reset(new ExternalExtensionProviderImpl(
+ this,
+ new ExternalPolicyExtensionLoader(profile_.get()),
+ Extension::INVALID,
+ Extension::EXTERNAL_POLICY_DOWNLOAD));
// Extensions will be removed from this list as they visited,
// so it should be emptied by the end.
remaining_extensions = policy_validlist;
- provider_->VisitRegisteredExtension(this);
+ provider_->VisitRegisteredExtension();
EXPECT_EQ(0u, remaining_extensions->GetSize());
}
@@ -74,10 +87,16 @@ class MockExternalPolicyExtensionProviderVisitor
EXPECT_NE(-1, remaining_extensions->Remove(ext_str));
}
+ virtual void OnExternalProviderReady() {
+ EXPECT_TRUE(provider_->IsReady());
+ }
+
private:
ListValue* remaining_extensions;
- scoped_ptr<ExternalPolicyExtensionProvider> provider_;
+ scoped_ptr<TestingProfile> profile_;
+
+ scoped_ptr<ExternalExtensionProviderImpl> provider_;
DISALLOW_COPY_AND_ASSIGN(MockExternalPolicyExtensionProviderVisitor);
};
diff --git a/chrome/browser/extensions/external_policy_extension_provider.cc b/chrome/browser/extensions/external_policy_extension_provider.cc
deleted file mode 100644
index ccb5b03..0000000
--- a/chrome/browser/extensions/external_policy_extension_provider.cc
+++ /dev/null
@@ -1,77 +0,0 @@
-// 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/external_policy_extension_provider.h"
-
-#include <string>
-
-#include "base/logging.h"
-#include "base/values.h"
-#include "chrome/browser/browser_thread.h"
-#include "chrome/browser/extensions/stateful_external_extension_provider.h"
-#include "chrome/browser/prefs/pref_service.h"
-
-namespace {
-
-// Check an extension ID and an URL to be syntactically correct.
-bool CheckExtension(std::string id, std::string update_url) {
- GURL url(update_url);
- if (!url.is_valid()) {
- LOG(WARNING) << "Policy specifies invalid update URL for external "
- << "extension: " << update_url;
- return false;
- }
- if (!Extension::IdIsValid(id)) {
- LOG(WARNING) << "Policy specifies invalid ID for external "
- << "extension: " << id;
- return false;
- }
- return true;
-}
-
-} // namespace
-
-ExternalPolicyExtensionProvider::ExternalPolicyExtensionProvider(
- const ListValue* forcelist)
- : StatefulExternalExtensionProvider(
- Extension::INVALID,
- Extension::EXTERNAL_POLICY_DOWNLOAD) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- ProcessPreferences(forcelist);
-}
-
-ExternalPolicyExtensionProvider::~ExternalPolicyExtensionProvider() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-}
-
-void ExternalPolicyExtensionProvider::SetPreferences(
- const ListValue* forcelist) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- ProcessPreferences(forcelist);
-}
-
-void ExternalPolicyExtensionProvider::ProcessPreferences(
- const ListValue* forcelist) {
- DictionaryValue* result = new DictionaryValue();
- if (forcelist != NULL) {
- std::string extension_desc;
- for (ListValue::const_iterator it = forcelist->begin();
- it != forcelist->end(); ++it) {
- if (!(*it)->GetAsString(&extension_desc)) {
- LOG(WARNING) << "Failed to read forcelist string.";
- } else {
- // Each string item of the list has the following form:
- // extension_id_code;extension_update_url
- // The update URL might also contain semicolons.
- size_t pos = extension_desc.find(';');
- std::string id = extension_desc.substr(0, pos);
- std::string update_url = extension_desc.substr(pos+1);
- if (CheckExtension(id, update_url)) {
- result->SetString(id + ".external_update_url", update_url);
- }
- }
- }
- }
- set_prefs(result);
-}
diff --git a/chrome/browser/extensions/external_policy_extension_provider.h b/chrome/browser/extensions/external_policy_extension_provider.h
deleted file mode 100644
index 9c36960..0000000
--- a/chrome/browser/extensions/external_policy_extension_provider.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) 2009 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_EXTERNAL_POLICY_EXTENSION_PROVIDER_H_
-#define CHROME_BROWSER_EXTENSIONS_EXTERNAL_POLICY_EXTENSION_PROVIDER_H_
-#pragma once
-
-#include "chrome/browser/extensions/stateful_external_extension_provider.h"
-
-class ListValue;
-class MockExternalPolicyExtensionProviderVisitor;
-class PrefService;
-
-// A specialization of the ExternalExtensionProvider that uses
-// prefs::kExtensionInstallForceList to look up which external extensions are
-// registered. The value of this preference is received via the constructor and
-// via |SetPreferences| in case of run-time updates.
-// Instances of this class are expected to be created and destroyed on the UI
-// thread and they are expecting public method calls from the FILE thread.
-class ExternalPolicyExtensionProvider
- : public StatefulExternalExtensionProvider {
- public:
- explicit ExternalPolicyExtensionProvider(const ListValue* forcelist);
- virtual ~ExternalPolicyExtensionProvider();
-
- // Set the internal list of extensions based on |forcelist|.
- // Does not take ownership of |forcelist|.
- void SetPreferences(const ListValue* forcelist);
-
- private:
- friend class MockExternalPolicyExtensionProviderVisitor;
-
- // Set the internal list of extensions based on |forcelist|.
- // Does not take ownership of |forcelist|.
- void ProcessPreferences(const ListValue* forcelist);
-};
-
-#endif // CHROME_BROWSER_EXTENSIONS_EXTERNAL_POLICY_EXTENSION_PROVIDER_H_
diff --git a/chrome/browser/extensions/external_pref_extension_loader.cc b/chrome/browser/extensions/external_pref_extension_loader.cc
new file mode 100644
index 0000000..b1b5d47
--- /dev/null
+++ b/chrome/browser/extensions/external_pref_extension_loader.cc
@@ -0,0 +1,82 @@
+// Copyright (c) 2011 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/external_pref_extension_loader.h"
+
+#include "app/app_paths.h"
+#include "base/file_path.h"
+#include "base/file_util.h"
+#include "base/logging.h"
+#include "base/path_service.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/common/json_value_serializer.h"
+
+namespace {
+
+// Caller takes ownership of the returned dictionary
+DictionaryValue* ExtractPrefs(ValueSerializer* serializer) {
+ std::string error_msg;
+ Value* extensions = serializer->Deserialize(NULL, &error_msg);
+ if (!extensions) {
+ LOG(WARNING) << "Unable to deserialize json data: " << error_msg;
+ } else {
+ if (!extensions->IsType(Value::TYPE_DICTIONARY)) {
+ NOTREACHED() << "Invalid json data";
+ } else {
+ return static_cast<DictionaryValue*>(extensions);
+ }
+ }
+ return new DictionaryValue;
+}
+
+} // namespace
+
+ExternalPrefExtensionLoader::ExternalPrefExtensionLoader() {
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+}
+
+void ExternalPrefExtensionLoader::StartLoading() {
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ NewRunnableMethod(
+ this,
+ &ExternalPrefExtensionLoader::LoadOnFileThread));
+}
+
+void ExternalPrefExtensionLoader::LoadOnFileThread() {
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ FilePath json_file;
+ PathService::Get(app::DIR_EXTERNAL_EXTENSIONS, &json_file);
+ json_file = json_file.Append(FILE_PATH_LITERAL("external_extensions.json"));
+ scoped_ptr<DictionaryValue> prefs;
+
+ if (file_util::PathExists(json_file)) {
+ JSONFileValueSerializer serializer(json_file);
+ prefs.reset(ExtractPrefs(&serializer));
+ } else {
+ prefs.reset(new DictionaryValue());
+ }
+
+ prefs_.reset(prefs.release());
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(
+ this,
+ &ExternalPrefExtensionLoader::LoadFinished));
+}
+
+ExternalTestingExtensionLoader::ExternalTestingExtensionLoader(
+ const std::string& json_data) {
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ JSONStringValueSerializer serializer(json_data);
+ testing_prefs_.reset(ExtractPrefs(&serializer));
+}
+
+void ExternalTestingExtensionLoader::StartLoading() {
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ prefs_.reset(
+ static_cast<DictionaryValue*>(testing_prefs_->DeepCopy()));
+ LoadFinished();
+}
diff --git a/chrome/browser/extensions/external_pref_extension_loader.h b/chrome/browser/extensions/external_pref_extension_loader.h
new file mode 100644
index 0000000..9224b3b
--- /dev/null
+++ b/chrome/browser/extensions/external_pref_extension_loader.h
@@ -0,0 +1,56 @@
+// Copyright (c) 2011 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_EXTERNAL_PREF_EXTENSION_LOADER_H_
+#define CHROME_BROWSER_EXTENSIONS_EXTERNAL_PREF_EXTENSION_LOADER_H_
+#pragma once
+
+#include "chrome/browser/extensions/external_extension_loader.h"
+
+#include <string>
+
+#include "base/scoped_ptr.h"
+#include "base/values.h"
+
+// A specialization of the ExternalExtensionLoader that uses a json file to
+// look up which external extensions are registered.
+// Instances of this class are expected to be created and destroyed on the UI
+// thread and they are expecting public method calls from the UI thread.
+class ExternalPrefExtensionLoader : public ExternalExtensionLoader {
+ public:
+ ExternalPrefExtensionLoader();
+
+ protected:
+ virtual void StartLoading();
+
+ private:
+ friend class base::RefCountedThreadSafe<ExternalExtensionLoader>;
+
+ virtual ~ExternalPrefExtensionLoader() {}
+
+ void LoadOnFileThread();
+
+ DISALLOW_COPY_AND_ASSIGN(ExternalPrefExtensionLoader);
+};
+
+// A simplified version of ExternalPrefExtensionLoader that loads the dictionary
+// from json data specified in a string.
+class ExternalTestingExtensionLoader : public ExternalExtensionLoader {
+ public:
+ explicit ExternalTestingExtensionLoader(const std::string& json_data);
+
+ protected:
+ virtual void StartLoading();
+
+ private:
+ friend class base::RefCountedThreadSafe<ExternalExtensionLoader>;
+
+ virtual ~ExternalTestingExtensionLoader() {}
+
+ scoped_ptr<DictionaryValue> testing_prefs_;
+
+ DISALLOW_COPY_AND_ASSIGN(ExternalTestingExtensionLoader);
+};
+
+#endif // CHROME_BROWSER_EXTENSIONS_EXTERNAL_PREF_EXTENSION_LOADER_H_
diff --git a/chrome/browser/extensions/external_pref_extension_provider.cc b/chrome/browser/extensions/external_pref_extension_provider.cc
deleted file mode 100644
index 7ea5f4a..0000000
--- a/chrome/browser/extensions/external_pref_extension_provider.cc
+++ /dev/null
@@ -1,57 +0,0 @@
-// 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/external_pref_extension_provider.h"
-
-#include "app/app_paths.h"
-#include "base/file_path.h"
-#include "base/file_util.h"
-#include "base/logging.h"
-#include "base/path_service.h"
-#include "chrome/browser/browser_thread.h"
-#include "chrome/browser/extensions/stateful_external_extension_provider.h"
-#include "chrome/common/json_value_serializer.h"
-
-ExternalPrefExtensionProvider::ExternalPrefExtensionProvider()
- : StatefulExternalExtensionProvider(Extension::EXTERNAL_PREF,
- Extension::EXTERNAL_PREF_DOWNLOAD) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- FilePath json_file;
- PathService::Get(app::DIR_EXTERNAL_EXTENSIONS, &json_file);
- json_file = json_file.Append(FILE_PATH_LITERAL("external_extensions.json"));
-
- if (file_util::PathExists(json_file)) {
- JSONFileValueSerializer serializer(json_file);
- SetPreferences(&serializer);
- } else {
- set_prefs(new DictionaryValue());
- }
-}
-
-ExternalPrefExtensionProvider::~ExternalPrefExtensionProvider() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-}
-
-void ExternalPrefExtensionProvider::SetPreferencesForTesting(
- const std::string& json_data_for_testing) {
- JSONStringValueSerializer serializer(json_data_for_testing);
- SetPreferences(&serializer);
-}
-
-void ExternalPrefExtensionProvider::SetPreferences(
- ValueSerializer* serializer) {
- std::string error_msg;
- Value* extensions = serializer->Deserialize(NULL, &error_msg);
- scoped_ptr<DictionaryValue> dictionary(new DictionaryValue());
- if (!extensions) {
- LOG(WARNING) << "Unable to deserialize json data: " << error_msg;
- } else {
- if (!extensions->IsType(Value::TYPE_DICTIONARY)) {
- NOTREACHED() << "Invalid json data";
- } else {
- dictionary.reset(static_cast<DictionaryValue*>(extensions));
- }
- }
- set_prefs(dictionary.release());
-}
diff --git a/chrome/browser/extensions/external_pref_extension_provider.h b/chrome/browser/extensions/external_pref_extension_provider.h
deleted file mode 100644
index b74be39..0000000
--- a/chrome/browser/extensions/external_pref_extension_provider.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2009 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_EXTERNAL_PREF_EXTENSION_PROVIDER_H_
-#define CHROME_BROWSER_EXTENSIONS_EXTERNAL_PREF_EXTENSION_PROVIDER_H_
-#pragma once
-
-#include "chrome/browser/extensions/stateful_external_extension_provider.h"
-
-// A specialization of the ExternalExtensionProvider that uses a json file to
-// look up which external extensions are registered.
-// Instances of this class are expected to be created and destroyed on the UI
-// thread and they are expecting public method calls from the FILE thread.
-class ExternalPrefExtensionProvider : public StatefulExternalExtensionProvider {
- public:
- explicit ExternalPrefExtensionProvider();
- virtual ~ExternalPrefExtensionProvider();
-
- // Used only during testing to not use the json file for external extensions,
- // but instead parse a json file specified by the test.
- void SetPreferencesForTesting(const std::string& json_data_for_testing);
-
- private:
- void SetPreferences(ValueSerializer* serializer);
-};
-
-#endif // CHROME_BROWSER_EXTENSIONS_EXTERNAL_PREF_EXTENSION_PROVIDER_H_
diff --git a/chrome/browser/extensions/external_registry_extension_provider_win.cc b/chrome/browser/extensions/external_registry_extension_loader_win.cc
index 16b107f..7f2df55 100644
--- a/chrome/browser/extensions/external_registry_extension_provider_win.cc
+++ b/chrome/browser/extensions/external_registry_extension_loader_win.cc
@@ -2,13 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "chrome/browser/extensions/external_registry_extension_provider_win.h"
+#include "chrome/browser/extensions/external_registry_extension_loader_win.h"
#include "base/file_path.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
+#include "base/values.h"
#include "base/version.h"
#include "base/win/registry.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/extensions/external_extension_provider_impl.h"
namespace {
@@ -24,24 +27,21 @@ const wchar_t kRegistryExtensionPath[] = L"path";
// Registry value of that key that defines the current version of the .crx file.
const wchar_t kRegistryExtensionVersion[] = L"version";
-bool OpenKeyById(const std::string& id, base::win::RegKey *key) {
- std::wstring key_path = ASCIIToWide(kRegistryExtensions);
- key_path.append(L"\\");
- key_path.append(ASCIIToWide(id));
-
- return key->Open(kRegRoot, key_path.c_str(), KEY_READ);
-}
-
} // namespace
-ExternalRegistryExtensionProvider::ExternalRegistryExtensionProvider() {
+void ExternalRegistryExtensionLoader::StartLoading() {
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ NewRunnableMethod(
+ this,
+ &ExternalRegistryExtensionLoader::LoadOnFileThread));
}
-ExternalRegistryExtensionProvider::~ExternalRegistryExtensionProvider() {
-}
+void ExternalRegistryExtensionLoader::LoadOnFileThread() {
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ scoped_ptr<DictionaryValue> prefs(new DictionaryValue);
-void ExternalRegistryExtensionProvider::VisitRegisteredExtension(
- Visitor* visitor) const {
base::win::RegistryKeyIterator iterator(
kRegRoot, ASCIIToWide(kRegistryExtensions).c_str());
while (iterator.Valid()) {
@@ -57,19 +57,12 @@ void ExternalRegistryExtensionProvider::VisitRegisteredExtension(
std::string id = WideToASCII(iterator.Name());
StringToLowerASCII(&id);
- scoped_ptr<Version> version;
- version.reset(Version::GetVersionFromString(
- WideToASCII(extension_version)));
- if (!version.get()) {
- LOG(ERROR) << "Invalid version value " << extension_version
- << " for key " << key_path;
- ++iterator;
- continue;
- }
-
- FilePath path = FilePath::FromWStringHack(extension_path);
- visitor->OnExternalExtensionFileFound(id, version.get(), path,
- Extension::EXTERNAL_REGISTRY);
+ prefs->SetString(
+ id + "." + ExternalExtensionProviderImpl::kExternalVersion,
+ WideToASCII(extension_version));
+ prefs->SetString(
+ id + "." + ExternalExtensionProviderImpl::kExternalCrx,
+ extension_path);
} else {
// TODO(erikkay): find a way to get this into about:extensions
LOG(ERROR) << "Missing value " << kRegistryExtensionVersion
@@ -83,33 +76,11 @@ void ExternalRegistryExtensionProvider::VisitRegisteredExtension(
}
++iterator;
}
-}
-
-
-bool ExternalRegistryExtensionProvider::HasExtension(
- const std::string& id) const {
- base::win::RegKey key;
- return OpenKeyById(id, &key);
-}
-
-bool ExternalRegistryExtensionProvider::GetExtensionDetails(
- const std::string& id,
- Extension::Location* location,
- scoped_ptr<Version>* version) const {
- base::win::RegKey key;
- if (!OpenKeyById(id, &key))
- return false;
-
- std::wstring extension_version;
- if (!key.ReadValue(kRegistryExtensionVersion, &extension_version))
- return false;
-
- if (version) {
- version->reset(Version::GetVersionFromString(
- WideToASCII(extension_version)));
- }
- if (location)
- *location = Extension::EXTERNAL_REGISTRY;
- return true;
+ prefs_.reset(prefs.release());
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(
+ this,
+ &ExternalRegistryExtensionLoader::LoadFinished));
}
diff --git a/chrome/browser/extensions/external_registry_extension_loader_win.h b/chrome/browser/extensions/external_registry_extension_loader_win.h
new file mode 100644
index 0000000..7b0d189
--- /dev/null
+++ b/chrome/browser/extensions/external_registry_extension_loader_win.h
@@ -0,0 +1,28 @@
+// 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_EXTERNAL_REGISTRY_EXTENSION_LOADER_WIN_H_
+#define CHROME_BROWSER_EXTENSIONS_EXTERNAL_REGISTRY_EXTENSION_LOADER_WIN_H_
+#pragma once
+
+#include "chrome/browser/extensions/external_extension_loader.h"
+
+class ExternalRegistryExtensionLoader : public ExternalExtensionLoader {
+ public:
+ ExternalRegistryExtensionLoader() {}
+
+ protected:
+ virtual void StartLoading();
+
+ private:
+ friend class base::RefCountedThreadSafe<ExternalExtensionLoader>;
+
+ virtual ~ExternalRegistryExtensionLoader() {}
+
+ void LoadOnFileThread();
+
+ DISALLOW_COPY_AND_ASSIGN(ExternalRegistryExtensionLoader);
+};
+
+#endif // CHROME_BROWSER_EXTENSIONS_EXTERNAL_REGISTRY_EXTENSION_LOADER_WIN_H_
diff --git a/chrome/browser/extensions/external_registry_extension_provider_win.h b/chrome/browser/extensions/external_registry_extension_provider_win.h
deleted file mode 100644
index 34899ae..0000000
--- a/chrome/browser/extensions/external_registry_extension_provider_win.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 2009 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_EXTERNAL_REGISTRY_EXTENSION_PROVIDER_WIN_H_
-#define CHROME_BROWSER_EXTENSIONS_EXTERNAL_REGISTRY_EXTENSION_PROVIDER_WIN_H_
-#pragma once
-
-#include "chrome/browser/extensions/external_extension_provider.h"
-
-class Version;
-
-// A specialization of the ExternalExtensionProvider that uses the Registry to
-// look up which external extensions are registered.
-class ExternalRegistryExtensionProvider : public ExternalExtensionProvider {
- public:
- ExternalRegistryExtensionProvider();
- virtual ~ExternalRegistryExtensionProvider();
-
- // ExternalExtensionProvider implementation:
- virtual void VisitRegisteredExtension(Visitor* visitor) const;
-
- virtual bool HasExtension(const std::string& id) const;
-
- virtual bool GetExtensionDetails(const std::string& id,
- Extension::Location* location,
- scoped_ptr<Version>* version) const;
-};
-
-#endif // CHROME_BROWSER_EXTENSIONS_EXTERNAL_REGISTRY_EXTENSION_PROVIDER_WIN_H_
diff --git a/chrome/browser/extensions/stateful_external_extension_provider.h b/chrome/browser/extensions/stateful_external_extension_provider.h
deleted file mode 100644
index 2fd481c..0000000
--- a/chrome/browser/extensions/stateful_external_extension_provider.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (c) 2009 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_STATEFUL_EXTERNAL_EXTENSION_PROVIDER_H_
-#define CHROME_BROWSER_EXTENSIONS_STATEFUL_EXTERNAL_EXTENSION_PROVIDER_H_
-#pragma once
-
-#include "chrome/browser/extensions/external_extension_provider.h"
-
-class DictionaryValue;
-class ValueSerializer;
-class Version;
-
-// A specialization of the ExternalExtensionProvider that stores the registered
-// external extensions in a dictionary. This dictionary (|prefs_|) will be used
-// by HasExtension() and GetExtensionDetails() to return information about the
-// stored external extensions. It is the responsibility of specialized
-// subclasses to initialize this internal dictionary.
-// This provider can provide external extensions from two sources: crx files
-// and udpate URLs. The locations that the provider will report for these
-// are specified at the constructor.
-// Instances of this class are expected to be created and destroyed on the UI
-// thread and they are expecting public method calls from the FILE thread.
-class StatefulExternalExtensionProvider : public ExternalExtensionProvider {
- public:
- // Initialize the location for external extensions originating from crx
- // files: |crx_location|, and originating from update URLs:
- // |download_location|. If either of the origins is not supported by this
- // provider, then it should be initialized as Extensions::INVALID.
- StatefulExternalExtensionProvider(
- Extension::Location crx_location,
- Extension::Location download_location);
- virtual ~StatefulExternalExtensionProvider();
-
- // ExternalExtensionProvider implementation:
- virtual void VisitRegisteredExtension(Visitor* visitor) const;
-
- virtual bool HasExtension(const std::string& id) const;
-
- virtual bool GetExtensionDetails(const std::string& id,
- Extension::Location* location,
- scoped_ptr<Version>* version) const;
- protected:
- // Location for external extensions that are provided by this provider from
- // local crx files.
- const Extension::Location crx_location_;
- // Location for external extensions that are provided by this provider from
- // update URLs.
- const Extension::Location download_location_;
-
- // Stores the dictionary of external extensions internally. Takes ownership
- // of |prefs|.
- void set_prefs(DictionaryValue* prefs);
-
- private:
- // Dictionary of the external extensions that are provided by this provider.
- scoped_ptr<DictionaryValue> prefs_;
-};
-
-#endif // CHROME_BROWSER_EXTENSIONS_STATEFUL_EXTERNAL_EXTENSION_PROVIDER_H_
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 3cbdc1d..68b508f 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1200,13 +1200,17 @@
'browser/extensions/extensions_startup.h',
'browser/extensions/extensions_ui.cc',
'browser/extensions/extensions_ui.h',
- 'browser/extensions/external_extension_provider.h',
- 'browser/extensions/external_pref_extension_provider.cc',
- 'browser/extensions/external_pref_extension_provider.h',
- 'browser/extensions/external_policy_extension_provider.cc',
- 'browser/extensions/external_policy_extension_provider.h',
- 'browser/extensions/external_registry_extension_provider_win.cc',
- 'browser/extensions/external_registry_extension_provider_win.h',
+ 'browser/extensions/external_extension_provider_interface.h',
+ 'browser/extensions/external_extension_provider_impl.cc',
+ 'browser/extensions/external_extension_provider_impl.h',
+ 'browser/extensions/external_extension_loader.cc',
+ 'browser/extensions/external_extension_loader.h',
+ 'browser/extensions/external_pref_extension_loader.cc',
+ 'browser/extensions/external_pref_extension_loader.h',
+ 'browser/extensions/external_policy_extension_loader.cc',
+ 'browser/extensions/external_policy_extension_loader.h',
+ 'browser/extensions/external_registry_extension_loader_win.cc',
+ 'browser/extensions/external_registry_extension_loader_win.h',
'browser/extensions/file_reader.cc',
'browser/extensions/file_reader.h',
'browser/extensions/gtk_theme_installed_infobar_delegate.cc',
@@ -1217,8 +1221,6 @@
'browser/extensions/pack_extension_job.h',
'browser/extensions/sandboxed_extension_unpacker.cc',
'browser/extensions/sandboxed_extension_unpacker.h',
- 'browser/extensions/stateful_external_extension_provider.cc',
- 'browser/extensions/stateful_external_extension_provider.h',
'browser/extensions/theme_installed_infobar_delegate.cc',
'browser/extensions/theme_installed_infobar_delegate.h',
'browser/extensions/user_script_listener.cc',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 1db511a..931e3a7 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1175,7 +1175,7 @@
'browser/extensions/extension_updater_unittest.cc',
'browser/extensions/extension_webnavigation_unittest.cc',
'browser/extensions/extensions_quota_service_unittest.cc',
- 'browser/extensions/external_policy_extension_provider_unittest.cc',
+ 'browser/extensions/external_policy_extension_loader_unittest.cc',
'browser/extensions/file_reader_unittest.cc',
'browser/extensions/image_loading_tracker_unittest.cc',
'browser/extensions/sandboxed_extension_unpacker_unittest.cc',