diff options
author | willchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-18 03:10:34 +0000 |
---|---|---|
committer | willchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-18 03:10:34 +0000 |
commit | 7387509129d02968481c9cd912ab60c79bd6deea (patch) | |
tree | 1cb2e357aea3217dc79f83d98528b65280d2bf21 /chrome/browser/extensions | |
parent | 653a73f611d9c3c69be17fdafcce6e41328df18a (diff) | |
download | chromium_src-7387509129d02968481c9cd912ab60c79bd6deea.zip chromium_src-7387509129d02968481c9cd912ab60c79bd6deea.tar.gz chromium_src-7387509129d02968481c9cd912ab60c79bd6deea.tar.bz2 |
Revert r18661.
Broke purify and mac valgrind. "Pull Extension-related prefs into its own class. Also add a notification for when the extensions service has finished its initial load of extensions, separate from EXTENSIONS_LOADED.TEST=noneBUG=none"
Review URL: http://codereview.chromium.org/132008
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@18682 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/extensions')
-rw-r--r-- | chrome/browser/extensions/extension_prefs.cc | 184 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_prefs.h | 85 | ||||
-rw-r--r-- | chrome/browser/extensions/extensions_service.cc | 273 | ||||
-rw-r--r-- | chrome/browser/extensions/extensions_service.h | 45 | ||||
-rw-r--r-- | chrome/browser/extensions/extensions_service_unittest.cc | 6 | ||||
-rw-r--r-- | chrome/browser/extensions/user_script_master.cc | 10 | ||||
-rw-r--r-- | chrome/browser/extensions/user_script_master.h | 4 |
7 files changed, 244 insertions, 363 deletions
diff --git a/chrome/browser/extensions/extension_prefs.cc b/chrome/browser/extensions/extension_prefs.cc deleted file mode 100644 index d4de0d5..0000000 --- a/chrome/browser/extensions/extension_prefs.cc +++ /dev/null @@ -1,184 +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. - -#include "chrome/browser/extensions/extension_prefs.h" - -#include "base/string_util.h" -#include "chrome/common/extensions/extension.h" - -namespace { - -// Preferences keys - -// A preference that keeps track of per-extension settings. This is a dictionary -// object read from the Preferences file, keyed off of extension id's. -const wchar_t kExtensionsPref[] = L"extensions.settings"; - -// Where an extension was installed from. (see Extension::Location) -const wchar_t kPrefLocation[] = L"location"; - -// Enabled, disabled, killed, etc. (see Extension::State) -const wchar_t kPrefState[] = L"state"; - -// The path to the current version's manifest file. -const wchar_t kPrefPath[] = L"path"; - -// A preference that tracks extension shelf configuration. This is a list -// object read from the Preferences file, containing a list of toolstrip URLs. -const wchar_t kExtensionShelf[] = L"extensions.shelf"; -} - -//////////////////////////////////////////////////////////////////////////////// - -InstalledExtensions::InstalledExtensions(ExtensionPrefs* prefs) { - extension_data_ = prefs->CopyCurrentExtensions(); -} - -void InstalledExtensions::VisitInstalledExtensions( - InstalledExtensions::Callback *callback) { - DictionaryValue::key_iterator extension_id = extension_data_->begin_keys(); - for (; extension_id != extension_data_->end_keys(); ++extension_id) { - DictionaryValue* ext; - if (!extension_data_->GetDictionary(*extension_id, &ext)) { - LOG(WARNING) << "Invalid pref for extension " << *extension_id; - NOTREACHED(); - continue; - } - FilePath::StringType path; - if (!ext->GetString(kPrefPath, &path)) { - LOG(WARNING) << "Missing path pref for extension " << *extension_id; - NOTREACHED(); - continue; - } - int location_value; - if (!ext->GetInteger(kPrefLocation, &location_value)) { - LOG(WARNING) << "Missing location pref for extension " << *extension_id; - NOTREACHED(); - continue; - } - Extension::Location location = - static_cast<Extension::Location>(location_value); - callback->Run(WideToASCII(*extension_id), FilePath(path), location); - } -} - -//////////////////////////////////////////////////////////////////////////////// - -ExtensionPrefs::ExtensionPrefs(PrefService* prefs) : prefs_(prefs) { - if (!prefs_->FindPreference(kExtensionsPref)) - prefs_->RegisterDictionaryPref(kExtensionsPref); - if (!prefs->FindPreference(kExtensionShelf)) - prefs->RegisterListPref(kExtensionShelf); -} - -DictionaryValue* ExtensionPrefs::CopyCurrentExtensions() { - const DictionaryValue* extensions = prefs_->GetDictionary(kExtensionsPref); - if (extensions) { - DictionaryValue* copy = - static_cast<DictionaryValue*>(extensions->DeepCopy()); - return copy; - } - return new DictionaryValue; -} - -void ExtensionPrefs::GetKilledExtensionIds(std::set<std::string>* killed_ids) { - const DictionaryValue* dict = prefs_->GetDictionary(kExtensionsPref); - if (!dict || dict->GetSize() == 0) - return; - - for (DictionaryValue::key_iterator i = dict->begin_keys(); - i != dict->end_keys(); ++i) { - std::wstring key_name = *i; - if (!Extension::IdIsValid(WideToASCII(key_name))) { - LOG(WARNING) << "Invalid external extension ID encountered: " - << WideToASCII(key_name); - continue; - } - - DictionaryValue* extension = NULL; - if (!dict->GetDictionary(key_name, &extension)) { - NOTREACHED(); - continue; - } - - // Check to see if the extension has been killed. - int state; - if (extension->GetInteger(kPrefState, &state) && - state == static_cast<int>(Extension::KILLBIT)) { - StringToLowerASCII(&key_name); - killed_ids->insert(WideToASCII(key_name)); - } - } -} - -ExtensionPrefs::URLList ExtensionPrefs::GetShelfToolstripOrder() { - URLList urls; - const ListValue* toolstrip_urls = prefs_->GetList(kExtensionShelf); - if (toolstrip_urls) { - for (size_t i = 0; i < toolstrip_urls->GetSize(); ++i) { - std::string url; - if (toolstrip_urls->GetString(i, &url)) - urls.push_back(GURL(url)); - } - } - return urls; -} - -void ExtensionPrefs::OnExtensionInstalled(Extension* extension) { - std::string id = extension->id(); - UpdateExtensionPref(id, kPrefState, - Value::CreateIntegerValue(Extension::ENABLED)); - UpdateExtensionPref(id, kPrefLocation, - Value::CreateIntegerValue(extension->location())); - UpdateExtensionPref(id, kPrefPath, - Value::CreateStringValue(extension->path().value())); - prefs_->ScheduleSavePersistentPrefs(); -} - -void ExtensionPrefs::OnExtensionUninstalled(const Extension* extension) { - // For external extensions, we save a preference reminding ourself not to try - // and install the extension anymore. - if (Extension::IsExternalLocation(extension->location())) { - UpdateExtensionPref(extension->id(), kPrefState, - Value::CreateIntegerValue(Extension::KILLBIT)); - prefs_->ScheduleSavePersistentPrefs(); - } else { - DeleteExtensionPrefs(extension->id()); - } -} - -bool ExtensionPrefs::UpdateExtensionPref(const std::string& extension_id, - const std::wstring& key, - Value* data_value) { - DictionaryValue* extension = GetOrCreateExtensionPref(extension_id); - if (!extension->Set(key, data_value)) { - NOTREACHED() << L"Cannot modify key: '" << key.c_str() - << "' for extension: '" << extension_id.c_str() << "'"; - return false; - } - return true; -} - -void ExtensionPrefs::DeleteExtensionPrefs(const std::string& extension_id) { - std::wstring id = ASCIIToWide(extension_id); - DictionaryValue* dict = prefs_->GetMutableDictionary(kExtensionsPref); - if (dict->HasKey(id)) { - dict->Remove(id, NULL); - prefs_->ScheduleSavePersistentPrefs(); - } -} - -DictionaryValue* ExtensionPrefs::GetOrCreateExtensionPref( - const std::string& extension_id) { - DictionaryValue* dict = prefs_->GetMutableDictionary(kExtensionsPref); - DictionaryValue* extension = NULL; - std::wstring id = ASCIIToWide(extension_id); - if (!dict->GetDictionary(id, &extension)) { - // Extension pref does not exist, create it. - extension = new DictionaryValue(); - dict->Set(id, extension); - } - return extension; -} - diff --git a/chrome/browser/extensions/extension_prefs.h b/chrome/browser/extensions/extension_prefs.h deleted file mode 100644 index db5847b..0000000 --- a/chrome/browser/extensions/extension_prefs.h +++ /dev/null @@ -1,85 +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_EXTENSION_PREFS_H -#define CHROME_BROWSER_EXTENSIONS_EXTENSION_PREFS_H - -#include <set> -#include <string> -#include <vector> - -#include "base/task.h" -#include "chrome/common/extensions/extension.h" -#include "chrome/common/pref_service.h" -#include "googleurl/src/gurl.h" - -// Class for managing global and per-extension preferences. -// This class is instantiated by ExtensionsService, so it should be accessed -// from there. -class ExtensionPrefs { - public: - explicit ExtensionPrefs(PrefService* prefs); - - // Returns a copy of the Extensions prefs. - // TODO(erikkay) Remove this so that external consumers don't need to be - // aware of the internal structure of the preferences. - DictionaryValue* CopyCurrentExtensions(); - - // Populate |killed_ids| with extension ids that have been killed. - void GetKilledExtensionIds(std::set<std::string>* killed_ids); - - // Get the order that toolstrip URLs appear in the shelf. - typedef std::vector<GURL> URLList; - URLList GetShelfToolstripOrder(); - - // Called when an extension is installed, so that prefs get created. - void OnExtensionInstalled(Extension* extension); - - // Called when an extension is uninstalled, so that prefs get cleaned up. - void OnExtensionUninstalled(const Extension* extension); - - private: - // Sets the pref |key| for extension |id| to |value|. - bool UpdateExtensionPref(const std::string& id, - const std::wstring& key, - Value* value); - - // Deletes the pref dictionary for extension |id|. - void DeleteExtensionPrefs(const std::string& id); - - // Ensures and returns a mutable dictionary for extension |id|'s prefs. - DictionaryValue* GetOrCreateExtensionPref(const std::string& id); - - // The pref service specific to this set of extension prefs. - PrefService* prefs_; - - // The URLs of all of the toolstrips. - URLList shelf_order_; - - DISALLOW_COPY_AND_ASSIGN(ExtensionPrefs); -}; - -// A helper class that has a list of the currently installed extensions -// and can iterate over them to a provided callback. -class InstalledExtensions { - public: - explicit InstalledExtensions(ExtensionPrefs* prefs); - - typedef Callback3<const std::string&, - const FilePath&, - Extension::Location>::Type Callback; - - // Runs |callback| for each installed extension with the path to the - // version directory and the location. - void VisitInstalledExtensions(Callback *callback); - - private: - // A copy of the extensions pref dictionary so that this can be passed - // around without a dependency on prefs. - DictionaryValue* extension_data_; - - DISALLOW_COPY_AND_ASSIGN(InstalledExtensions); -}; - -#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_PREFS_H diff --git a/chrome/browser/extensions/extensions_service.cc b/chrome/browser/extensions/extensions_service.cc index 2e655d10..a39a4cd 100644 --- a/chrome/browser/extensions/extensions_service.cc +++ b/chrome/browser/extensions/extensions_service.cc @@ -60,6 +60,24 @@ const char* ExtensionsServiceBackend::kTempExtensionName = "TEMP_INSTALL"; namespace { +//////////////////// +// Preferences keys + +// A preference that keeps track of per-extension settings. This is a dictionary +// object read from the Preferences file, keyed off of extension id's. +const wchar_t kExtensionsPref[] = L"extensions.settings"; + +// Where an extension was installed from (Extension::Location) +const wchar_t kPrefLocation[] = L"location"; + +// Enabled, disabled, killed, etc. (Extension::State) +const wchar_t kPrefState[] = L"state"; + +// The path to the current version's manifest file. +const wchar_t kPrefPath[] = L"path"; + +//////////////////// + // A temporary subdirectory where we unpack extensions. const char* kUnpackExtensionDir = "TEMP_UNPACK"; @@ -213,18 +231,22 @@ class ExtensionsServiceBackend::UnpackerClient ExtensionsService::ExtensionsService(Profile* profile, MessageLoop* frontend_loop, MessageLoop* backend_loop) - : extension_prefs_(new ExtensionPrefs(profile->GetPrefs())), + : prefs_(profile->GetPrefs()), backend_loop_(backend_loop), install_directory_(profile->GetPath().AppendASCII(kInstallDirectoryName)), extensions_enabled_( CommandLine::ForCurrentProcess()-> HasSwitch(switches::kEnableExtensions)), show_extensions_prompts_(true) { + if (!prefs_->FindPreference(kExtensionsPref)) + prefs_->RegisterDictionaryPref(kExtensionsPref); + // We pass ownership of this object to the Backend. - DictionaryValue* extensions = extension_prefs_->CopyCurrentExtensions(); + DictionaryValue* external_extensions = new DictionaryValue; + GetExternalExtensions(external_extensions, NULL); backend_ = new ExtensionsServiceBackend( install_directory_, g_browser_process->resource_dispatcher_host(), - frontend_loop, extensions); + frontend_loop, external_extensions); } ExtensionsService::~ExtensionsService() { @@ -258,12 +280,22 @@ void ExtensionsService::UninstallExtension(const std::string& extension_id) { Extension* extension = GetExtensionById(extension_id); // Callers should not send us nonexistant extensions. - DCHECK(extension); + CHECK(extension); - extension_prefs_->OnExtensionUninstalled(extension); + Extension::Location location = extension->location(); + + // For external extensions, we save a preference reminding ourself not to try + // and install the extension anymore. + if (Extension::IsExternalLocation(location)) { + UpdateExtensionPref(ASCIIToWide(extension_id), kPrefState, + Value::CreateIntegerValue(Extension::KILLBIT), true); + } else { + DeleteExtensionPrefs(ASCIIToWide(extension_id)); + } // Tell the backend to start deleting installed extensions on the file thread. - if (Extension::LOAD != extension->location()) { + if (location == Extension::INTERNAL || + Extension::IsExternalLocation(location)) { backend_loop_->PostTask(FROM_HERE, NewRunnableMethod(backend_.get(), &ExtensionsServiceBackend::UninstallExtension, extension_id)); } @@ -278,17 +310,22 @@ void ExtensionsService::LoadExtension(const FilePath& extension_path) { } void ExtensionsService::LoadAllExtensions() { - // Load the previously installed extensions. - backend_loop_->PostTask(FROM_HERE, NewRunnableMethod(backend_.get(), - &ExtensionsServiceBackend::LoadInstalledExtensions, - scoped_refptr<ExtensionsService>(this), - new InstalledExtensions(extension_prefs_.get()))); + // Load the extensions we know about from previous runs. + const DictionaryValue* extensions = prefs_->GetDictionary(kExtensionsPref); + if (extensions) { + DictionaryValue* copy = + static_cast<DictionaryValue*>(extensions->DeepCopy()); + backend_loop_->PostTask(FROM_HERE, NewRunnableMethod(backend_.get(), + &ExtensionsServiceBackend::LoadExtensionsFromPrefs, + scoped_refptr<ExtensionsService>(this), + copy)); + } } void ExtensionsService::CheckForUpdates() { // This installs or updates externally provided extensions. std::set<std::string> killed_extensions; - extension_prefs_->GetKilledExtensionIds(&killed_extensions); + GetExternalExtensions(NULL, &killed_extensions); backend_loop_->PostTask(FROM_HERE, NewRunnableMethod(backend_.get(), &ExtensionsServiceBackend::CheckForExternalUpdates, killed_extensions, @@ -342,13 +379,6 @@ void ExtensionsService::GarbageCollectExtensions() { scoped_refptr<ExtensionsService>(this))); } -void ExtensionsService::OnLoadedInstalledExtensions() { - NotificationService::current()->Notify( - NotificationType::EXTENSIONS_READY, - Source<ExtensionsService>(this), - NotificationService::NoDetails()); -} - void ExtensionsService::OnExtensionsLoaded(ExtensionList* new_extensions) { scoped_ptr<ExtensionList> cleanup(new_extensions); @@ -382,17 +412,28 @@ void ExtensionsService::OnExtensionsLoaded(ExtensionList* new_extensions) { } } - if (enabled_extensions.size()) { - NotificationService::current()->Notify( - NotificationType::EXTENSIONS_LOADED, - NotificationService::AllSources(), - Details<ExtensionList>(&enabled_extensions)); - } + // TODO(erikkay) it would be nice if we could just return and send no + // notification if the list is empty. However, UserScriptMaster depends on + // getting an initial notification after the first extensions have finished + // loading, so even if it's an empty message, we send it anyway. We should + // come up with a way to do a "started" notification that has the semantics + // that UserScriptMaster is looking for. + + NotificationService::current()->Notify( + NotificationType::EXTENSIONS_LOADED, + NotificationService::AllSources(), + Details<ExtensionList>(&enabled_extensions)); } void ExtensionsService::OnExtensionInstalled(Extension* extension, Extension::InstallType install_type) { - extension_prefs_->OnExtensionInstalled(extension); + std::wstring id = ASCIIToWide(extension->id()); + UpdateExtensionPref(id, kPrefState, + Value::CreateIntegerValue(Extension::ENABLED), false); + UpdateExtensionPref(id, kPrefLocation, + Value::CreateIntegerValue(extension->location()), false); + UpdateExtensionPref(id, kPrefPath, + Value::CreateStringValue(extension->path().value()), true); // If the extension is a theme, tell the profile (and therefore ThemeProvider) // to apply it. @@ -433,6 +474,60 @@ Extension* ExtensionsService::GetExtensionByURL(const GURL& url) { return GetExtensionById(host); } +void ExtensionsService::GetExternalExtensions( + DictionaryValue* external_extensions, + std::set<std::string>* killed_extensions) { + const DictionaryValue* dict = prefs_->GetDictionary(kExtensionsPref); + if (!dict || dict->GetSize() == 0) + return; + + for (DictionaryValue::key_iterator i = dict->begin_keys(); + i != dict->end_keys(); ++i) { + std::wstring key_name = *i; + if (!Extension::IdIsValid(WideToASCII(key_name))) { + LOG(WARNING) << "Invalid external extension ID encountered: " + << WideToASCII(key_name); + continue; + } + + DictionaryValue* extension = NULL; + if (!dict->GetDictionary(key_name, &extension)) { + NOTREACHED(); + continue; + } + + // Check to see if the extension has been killed. + int state; + if (extension->GetInteger(kPrefState, &state) && + state == static_cast<int>(Extension::KILLBIT)) { + if (killed_extensions) { + StringToLowerASCII(&key_name); + killed_extensions->insert(WideToASCII(key_name)); + } + } + // Return all extensions found. + if (external_extensions) { + DictionaryValue* result = + static_cast<DictionaryValue*>(extension->DeepCopy()); + StringToLowerASCII(&key_name); + external_extensions->Set(key_name, result); + } + } +} + +DictionaryValue* ExtensionsService::GetOrCreateExtensionPref( + const std::wstring& extension_id) { + DictionaryValue* dict = prefs_->GetMutableDictionary(kExtensionsPref); + DictionaryValue* extension = NULL; + if (!dict->GetDictionary(extension_id, &extension)) { + // Extension pref does not exist, create it. + extension = new DictionaryValue(); + dict->Set(extension_id, extension); + } + + return extension; +} + void ExtensionsService::ClearProvidersForTesting() { backend_loop_->PostTask(FROM_HERE, NewRunnableMethod(backend_.get(), &ExtensionsServiceBackend::ClearProvidersForTesting)); @@ -445,6 +540,32 @@ void ExtensionsService::SetProviderForTesting( location, test_provider)); } +bool ExtensionsService::UpdateExtensionPref(const std::wstring& extension_id, + const std::wstring& key, + Value* data_value, + bool schedule_save) { + DictionaryValue* extension = GetOrCreateExtensionPref(extension_id); + if (!extension->Set(key, data_value)) { + NOTREACHED() << L"Cannot modify key: '" << key.c_str() + << "' for extension: '" << extension_id.c_str() << "'"; + return false; + } + + if (schedule_save) + prefs_->ScheduleSavePersistentPrefs(); + return true; +} + +void ExtensionsService::DeleteExtensionPrefs( + const std::wstring& extension_id) { + DictionaryValue* dict = prefs_->GetMutableDictionary(kExtensionsPref); + if (dict->HasKey(extension_id)) { + dict->Remove(extension_id, NULL); + prefs_->ScheduleSavePersistentPrefs(); + } +} + + // ExtensionsServicesBackend ExtensionsServiceBackend::ExtensionsServiceBackend( @@ -468,20 +589,53 @@ ExtensionsServiceBackend::ExtensionsServiceBackend( ExtensionsServiceBackend::~ExtensionsServiceBackend() { } -void ExtensionsServiceBackend::LoadInstalledExtensions( +void ExtensionsServiceBackend::LoadExtensionsFromPrefs( scoped_refptr<ExtensionsService> frontend, - InstalledExtensions* installed) { - scoped_ptr<InstalledExtensions> cleanup(installed); + DictionaryValue* extension_prefs) { + scoped_ptr<DictionaryValue> prefs(extension_prefs); // for cleanup frontend_ = frontend; alert_on_error_ = false; - - // Call LoadInstalledExtension for each extension |installed| knows about. - scoped_ptr<InstalledExtensions::Callback> callback( - NewCallback(this, &ExtensionsServiceBackend::LoadInstalledExtension)); - installed->VisitInstalledExtensions(callback.get()); - - frontend_loop_->PostTask(FROM_HERE, NewRunnableMethod( - frontend_, &ExtensionsService::OnLoadedInstalledExtensions)); + scoped_ptr<ExtensionList> extensions(new ExtensionList); + DictionaryValue::key_iterator extension_id = extension_prefs->begin_keys(); + for (; extension_id != extension_prefs->end_keys(); ++extension_id) { + DictionaryValue* ext; + if (!extension_prefs->GetDictionary(*extension_id, &ext)) { + NOTREACHED(); + continue; + } + FilePath::StringType path; + if (ext->GetString(kPrefPath, &path)) { + Extension::Location location = Extension::INVALID; + int location_value; + DictionaryValue* pref = NULL; + extension_prefs->GetDictionary(*extension_id, &pref); + if (!pref || !pref->GetInteger(kPrefLocation, &location_value)) { + // TODO(erikkay) try to recover? + continue; + } else { + location = static_cast<Extension::Location>(location_value); + } + std::string id = WideToASCII(*extension_id); + if (Extension::IsExternalLocation(location) && + CheckExternalUninstall(extension_prefs, FilePath(path), id)) { + // TODO(erikkay): Possibly defer this operation to avoid slowing initial + // load of extensions. + UninstallExtension(id); + + // No error needs to be reported. The extension effectively doesn't + // exist. + continue; + } + Extension* extension = + LoadExtension(FilePath(path), location, true); // require id + if (extension) + extensions->push_back(extension); + } else { + // TODO(erikkay) bootstrap? + } + } + LOG(INFO) << "Done."; + ReportExtensionsLoaded(extensions.release()); } void ExtensionsServiceBackend::GarbageCollectExtensions( @@ -554,7 +708,7 @@ void ExtensionsServiceBackend::LoadSingleExtension( Extension* extension = LoadExtension(extension_path, Extension::LOAD, - false); // Don't require id. + false); // don't require ID if (extension) { ExtensionList* extensions = new ExtensionList; extensions->push_back(extension); @@ -562,28 +716,6 @@ void ExtensionsServiceBackend::LoadSingleExtension( } } -void ExtensionsServiceBackend::LoadInstalledExtension( - const std::string& id, const FilePath& path, Extension::Location location) { - if (CheckExternalUninstall(id, location)) { - // TODO(erikkay): Possibly defer this operation to avoid slowing initial - // load of extensions. - UninstallExtension(id); - - // No error needs to be reported. The extension effectively doesn't exist. - return; - } - - Extension* extension = - LoadExtension(FilePath(path), location, true); // Require id. - - // TODO(erikkay) now we only report a single extension loaded at a time. - // Perhaps we should change the notifications to remove ExtensionList. - ExtensionList* extensions = new ExtensionList; - if (extension) - extensions->push_back(extension); - ReportExtensionsLoaded(extensions); -} - DictionaryValue* ExtensionsServiceBackend::ReadManifest(FilePath manifest_path, std::string* error) { JSONFileValueSerializer serializer(manifest_path); @@ -1199,7 +1331,23 @@ void ExtensionsServiceBackend::CheckForExternalUpdates( } bool ExtensionsServiceBackend::CheckExternalUninstall( - const std::string& id, Extension::Location location) { + const DictionaryValue* extension_prefs, const FilePath& version_path, + const std::string& id) { + // First check the preferences for the kill-bit. + int location_value = Extension::INVALID; + DictionaryValue* extension = NULL; + if (!extension_prefs->GetDictionary(ASCIIToWide(id), &extension)) + return false; + int state; + if (extension->GetInteger(kPrefLocation, &location_value) && + location_value == Extension::EXTERNAL_PREF) { + return extension->GetInteger(kPrefState, &state) && + state == Extension::KILLBIT; + } + + Extension::Location location = + static_cast<Extension::Location>(location_value); + // Check if the providers know about this extension. ProviderMap::const_iterator i = external_extension_providers_.find(location); if (i != external_extension_providers_.end()) { @@ -1207,9 +1355,6 @@ bool ExtensionsServiceBackend::CheckExternalUninstall( version.reset(i->second->RegisteredVersion(id, NULL)); if (version.get()) return false; // Yup, known extension, don't uninstall. - } else { - // Not from an external provider, so it's fine. - return false; } return true; // This is not a known extension, uninstall. diff --git a/chrome/browser/extensions/extensions_service.h b/chrome/browser/extensions/extensions_service.h index d8fa0d0..8bf49f8 100644 --- a/chrome/browser/extensions/extensions_service.h +++ b/chrome/browser/extensions/extensions_service.h @@ -15,7 +15,6 @@ #include "base/ref_counted.h" #include "base/tuple.h" #include "base/values.h" -#include "chrome/browser/extensions/extension_prefs.h" #include "chrome/browser/extensions/external_extension_provider.h" #include "chrome/common/extensions/extension.h" @@ -121,6 +120,29 @@ class ExtensionsService // Lookup an extension by |url|. This uses the host of the URL as the id. Extension* GetExtensionByURL(const GURL& url); + // Gets a list of external extensions. If |external_extensions| is non-null, + // a dictionary with all external extensions (including extensions installed + // through the registry on Windows builds) and their preferences are + // returned. If |killed_extensions| is non-null, a set of string IDs + // containing all external extension IDs with the killbit set are returned. + void GetExternalExtensions(DictionaryValue* external_extensions, + std::set<std::string>* killed_extensions); + + // Gets the settings for an extension from preferences. If the key doesn't + // exist, this function creates it (don't need to check return for NULL). + DictionaryValue* GetOrCreateExtensionPref(const std::wstring& extension_id); + + // Writes a preference value for a particular extension |extension_id| under + // the |key| specified. If |schedule_save| is true, it will also ask the + // preference system to schedule a save to disk. + bool UpdateExtensionPref(const std::wstring& extension_id, + const std::wstring& key, + Value* data_value, + bool schedule_save); + + // Removes the entire tree of prefs for |extension_id|. + void DeleteExtensionPrefs(const std::wstring& extension_id); + // Clear all ExternalExtensionProviders. void ClearProvidersForTesting(); @@ -147,9 +169,6 @@ class ExtensionsService // OnExtensionVersionReinstalled. friend class ExtensionsServiceBackend; - // Called by the backend when the initial extension load has completed. - void OnLoadedInstalledExtensions(); - // Called by the backend when extensions have been loaded. void OnExtensionsLoaded(ExtensionList* extensions); @@ -166,7 +185,7 @@ class ExtensionsService static const char* kInstallDirectoryName; // Preferences for the owning profile. - scoped_ptr<ExtensionPrefs> extension_prefs_; + PrefService* prefs_; // The message loop to use with the backend. MessageLoop* backend_loop_; @@ -205,11 +224,12 @@ class ExtensionsServiceBackend virtual ~ExtensionsServiceBackend(); - // Loads the installed extensions. + // Loads extensions from the prefs. // Errors are reported through ExtensionErrorReporter. On completion, // OnExtensionsLoaded() is called with any successfully loaded extensions. - void LoadInstalledExtensions(scoped_refptr<ExtensionsService> frontend, - InstalledExtensions* installed); + void LoadExtensionsFromPrefs( + scoped_refptr<ExtensionsService> frontend, + DictionaryValue* extension_prefs); // Scans the extension installation directory to look for partially installed // or extensions to uninstall. @@ -258,10 +278,6 @@ class ExtensionsServiceBackend class UnpackerClient; friend class UnpackerClient; - // Loads a single installed extension. - void LoadInstalledExtension(const std::string& id, const FilePath& path, - Extension::Location location); - // Utility function to read an extension manifest and return it as a // DictionaryValue. If it fails, NULL is returned and |error| contains an // appropriate message. @@ -363,8 +379,9 @@ class ExtensionsServiceBackend // For the extension in |version_path| with |id|, check to see if it's an // externally managed extension. If so return true if it should be // uninstalled. - bool CheckExternalUninstall(const std::string& id, - Extension::Location location); + bool CheckExternalUninstall(const DictionaryValue* extension_prefs, + const FilePath& version_path, + const std::string& id); // Should an extension of |id| and |version| be installed? // Returns true if no extension of type |id| is installed or if |version| diff --git a/chrome/browser/extensions/extensions_service_unittest.cc b/chrome/browser/extensions/extensions_service_unittest.cc index 2a4c104..b3dfe7e 100644 --- a/chrome/browser/extensions/extensions_service_unittest.cc +++ b/chrome/browser/extensions/extensions_service_unittest.cc @@ -999,9 +999,9 @@ TEST_F(ExtensionsServiceTest, ExternalInstallPref) { ValidatePref(good_crx, L"state", Extension::ENABLED); ValidatePref(good_crx, L"location", Extension::EXTERNAL_PREF); - // Now uninstall the extension and verify that it doesn't get reinstalled. - service_->UninstallExtension(id); - loop_.RunAllPending(); + // Now set the kill bit and watch the extension go away. + SetPref(good_crx, L"state", Extension::KILLBIT); + profile_->GetPrefs()->ScheduleSavePersistentPrefs(); loaded_.clear(); service_->ReloadExtensions(); diff --git a/chrome/browser/extensions/user_script_master.cc b/chrome/browser/extensions/user_script_master.cc index 0c1a4b0..5cf3696 100644 --- a/chrome/browser/extensions/user_script_master.cc +++ b/chrome/browser/extensions/user_script_master.cc @@ -259,13 +259,10 @@ UserScriptMaster::UserScriptMaster(MessageLoop* worker_loop, const FilePath& script_dir) : user_script_dir_(script_dir), worker_loop_(worker_loop), - extensions_service_ready_(false), pending_scan_(false) { if (!user_script_dir_.value().empty()) AddWatchedPath(script_dir); - registrar_.Add(this, NotificationType::EXTENSIONS_READY, - NotificationService::AllSources()); registrar_.Add(this, NotificationType::EXTENSIONS_LOADED, NotificationService::AllSources()); registrar_.Add(this, NotificationType::EXTENSION_UNLOADED, @@ -330,10 +327,6 @@ void UserScriptMaster::Observe(NotificationType type, const NotificationSource& source, const NotificationDetails& details) { switch (type.value) { - case NotificationType::EXTENSIONS_READY: - extensions_service_ready_ = true; - StartScan(); - break; case NotificationType::EXTENSIONS_LOADED: { // TODO(aa): Fix race here. A page could need a content script on startup, // before the extension has loaded. We need to freeze the renderer in @@ -351,8 +344,7 @@ void UserScriptMaster::Observe(NotificationType type, lone_scripts_.push_back(*iter); } } - if (!extensions_service_ready_) - StartScan(); + StartScan(); break; } diff --git a/chrome/browser/extensions/user_script_master.h b/chrome/browser/extensions/user_script_master.h index ab87631..7a73323 100644 --- a/chrome/browser/extensions/user_script_master.h +++ b/chrome/browser/extensions/user_script_master.h @@ -148,10 +148,6 @@ class UserScriptMaster : public base::RefCounted<UserScriptMaster>, // List of scripts outside of script directories we should also load. UserScriptList lone_scripts_; - // If the extensions service has finished loading its initial set of - // extensions. - bool extensions_service_ready_; - // If the script directory is modified while we're rescanning it, we note // that we're currently mid-scan and then start over again once the scan // finishes. This boolean tracks whether another scan is pending. |