diff options
author | finnur@chromium.org <finnur@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-25 17:53:15 +0000 |
---|---|---|
committer | finnur@chromium.org <finnur@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-25 17:53:15 +0000 |
commit | 27b985db86e682c821f13ec37b52a6c69aa69fbb (patch) | |
tree | af9ed515ccc19ea7b9682afbe6de7d982e12d4c8 /chrome/browser/extensions | |
parent | 8380c0910bfff5ee0af6b37536cd815023d055ef (diff) | |
download | chromium_src-27b985db86e682c821f13ec37b52a6c69aa69fbb.zip chromium_src-27b985db86e682c821f13ec37b52a6c69aa69fbb.tar.gz chromium_src-27b985db86e682c821f13ec37b52a6c69aa69fbb.tar.bz2 |
The Provider for External Extensions no longer uses
the prefs file, but instead reads a preferences file
(a json file called external_extensions.json).
This file specifies what external extensions we
installed (shipped with Chrome) and the extension
system takes care of installing them.
Having this in a separate file makes the upgrade
scenario easier, since we can during upgrade simply
blow away this file and replace it (and not have
to worry about merging/loosing user specified data).
The extension system will read the file, and figure
out whether any extension needs to be upgraded based
on the information provided.
Now, all external providers fetch data on the file
thread instead of reading and copying preferences on
the UI thread and posting them to the file thread.
BUG=http://crbug.com/14201
TEST=Covered by unit test.
Review URL: http://codereview.chromium.org/144018
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@19264 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/extensions')
-rw-r--r-- | chrome/browser/extensions/extension_browsertest.cc | 5 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_prefs.cc | 10 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_prefs.h | 3 | ||||
-rw-r--r-- | chrome/browser/extensions/extensions_service.cc | 21 | ||||
-rw-r--r-- | chrome/browser/extensions/extensions_service.h | 6 | ||||
-rw-r--r-- | chrome/browser/extensions/extensions_service_unittest.cc | 169 | ||||
-rw-r--r-- | chrome/browser/extensions/extensions_ui.cc | 2 | ||||
-rw-r--r-- | chrome/browser/extensions/external_extensions.json | 3 | ||||
-rw-r--r-- | chrome/browser/extensions/external_pref_extension_provider.cc | 56 | ||||
-rw-r--r-- | chrome/browser/extensions/external_pref_extension_provider.h | 11 |
10 files changed, 215 insertions, 71 deletions
diff --git a/chrome/browser/extensions/extension_browsertest.cc b/chrome/browser/extensions/extension_browsertest.cc index e8a93ec..3df4183 100644 --- a/chrome/browser/extensions/extension_browsertest.cc +++ b/chrome/browser/extensions/extension_browsertest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// 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. @@ -165,5 +165,6 @@ IN_PROC_BROWSER_TEST_F(ExtensionViewTest, DISABLED_Incognito) { ASSERT_TRUE(extension); // TODO(mpcomplete): wait for uninstall to complete? - browser()->profile()->GetExtensionsService()->UninstallExtension(kGoodCrxId); + browser()->profile()->GetExtensionsService()-> + UninstallExtension(kGoodCrxId, false); } diff --git a/chrome/browser/extensions/extension_prefs.cc b/chrome/browser/extensions/extension_prefs.cc index 50618b5..32d6fd5 100644 --- a/chrome/browser/extensions/extension_prefs.cc +++ b/chrome/browser/extensions/extension_prefs.cc @@ -149,10 +149,14 @@ void ExtensionPrefs::OnExtensionInstalled(Extension* extension) { prefs_->ScheduleSavePersistentPrefs(); } -void ExtensionPrefs::OnExtensionUninstalled(const Extension* extension) { +void ExtensionPrefs::OnExtensionUninstalled(const Extension* extension, + bool external_uninstall) { // For external extensions, we save a preference reminding ourself not to try - // and install the extension anymore. - if (Extension::IsExternalLocation(extension->location())) { + // and install the extension anymore (except when |external_uninstall| is + // true, which signifies that the registry key was deleted or the pref file + // no longer lists the extension). + if (!external_uninstall && + Extension::IsExternalLocation(extension->location())) { UpdateExtensionPref(extension->id(), kPrefState, Value::CreateIntegerValue(Extension::KILLBIT)); prefs_->ScheduleSavePersistentPrefs(); diff --git a/chrome/browser/extensions/extension_prefs.h b/chrome/browser/extensions/extension_prefs.h index a6e7ec4..be769a2 100644 --- a/chrome/browser/extensions/extension_prefs.h +++ b/chrome/browser/extensions/extension_prefs.h @@ -40,7 +40,8 @@ class ExtensionPrefs { void OnExtensionInstalled(Extension* extension); // Called when an extension is uninstalled, so that prefs get cleaned up. - void OnExtensionUninstalled(const Extension* extension); + void OnExtensionUninstalled(const Extension* extension, + bool external_uninstall); private: // Sets the pref |key| for extension |id| to |value|. diff --git a/chrome/browser/extensions/extensions_service.cc b/chrome/browser/extensions/extensions_service.cc index dde2ddc..0a4d2be 100644 --- a/chrome/browser/extensions/extensions_service.cc +++ b/chrome/browser/extensions/extensions_service.cc @@ -230,11 +230,9 @@ ExtensionsService::ExtensionsService(Profile* profile, else if (profile->GetPrefs()->GetBoolean(prefs::kEnableExtensions)) extensions_enabled_ = true; - // We pass ownership of this object to the Backend. - DictionaryValue* extensions = extension_prefs_->CopyCurrentExtensions(); backend_ = new ExtensionsServiceBackend( install_directory_, g_browser_process->resource_dispatcher_host(), - frontend_loop, extensions, extensions_enabled()); + frontend_loop, extensions_enabled()); } ExtensionsService::~ExtensionsService() { @@ -300,13 +298,14 @@ void ExtensionsService::UpdateExtension(const std::string& id, alert_on_error, scoped_refptr<ExtensionsService>(this))); } -void ExtensionsService::UninstallExtension(const std::string& extension_id) { +void ExtensionsService::UninstallExtension(const std::string& extension_id, + bool external_uninstall) { Extension* extension = GetExtensionById(extension_id); // Callers should not send us nonexistant extensions. DCHECK(extension); - extension_prefs_->OnExtensionUninstalled(extension); + extension_prefs_->OnExtensionUninstalled(extension, external_uninstall); // Tell the backend to start deleting installed extensions on the file thread. if (Extension::LOAD != extension->location()) { @@ -514,8 +513,7 @@ void ExtensionsService::SetProviderForTesting( ExtensionsServiceBackend::ExtensionsServiceBackend( const FilePath& install_directory, ResourceDispatcherHost* rdh, - MessageLoop* frontend_loop, DictionaryValue* extension_prefs, - bool extensions_enabled) + MessageLoop* frontend_loop, bool extensions_enabled) : frontend_(NULL), install_directory_(install_directory), resource_dispatcher_host_(rdh), @@ -524,7 +522,7 @@ ExtensionsServiceBackend::ExtensionsServiceBackend( extensions_enabled_(extensions_enabled) { external_extension_providers_[Extension::EXTERNAL_PREF] = linked_ptr<ExternalExtensionProvider>( - new ExternalPrefExtensionProvider(extension_prefs)); + new ExternalPrefExtensionProvider()); #if defined(OS_WIN) external_extension_providers_[Extension::EXTERNAL_REGISTRY] = linked_ptr<ExternalExtensionProvider>( @@ -630,9 +628,10 @@ 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); + frontend_loop_->PostTask(FROM_HERE, NewRunnableMethod( + frontend_, + &ExtensionsService::UninstallExtension, + id, true)); // No error needs to be reported. The extension effectively doesn't exist. return; diff --git a/chrome/browser/extensions/extensions_service.h b/chrome/browser/extensions/extensions_service.h index 653c29d..b239422 100644 --- a/chrome/browser/extensions/extensions_service.h +++ b/chrome/browser/extensions/extensions_service.h @@ -108,8 +108,9 @@ class ExtensionsService bool alert_on_error, Callback* callback); // Uninstalls the specified extension. Callers should only call this method - // with extensions that exist and are "internal". - void UninstallExtension(const std::string& extension_id); + // with extensions that exist. + void UninstallExtension(const std::string& extension_id, + bool external_uninstall); // Load the extension from the directory |extension_path|. void LoadExtension(const FilePath& extension_path); @@ -245,7 +246,6 @@ class ExtensionsServiceBackend ExtensionsServiceBackend(const FilePath& install_directory, ResourceDispatcherHost* rdh, MessageLoop* frontend_loop, - DictionaryValue* extension_prefs, bool extensions_enabled); virtual ~ExtensionsServiceBackend(); diff --git a/chrome/browser/extensions/extensions_service_unittest.cc b/chrome/browser/extensions/extensions_service_unittest.cc index 224018b..1d6bab4 100644 --- a/chrome/browser/extensions/extensions_service_unittest.cc +++ b/chrome/browser/extensions/extensions_service_unittest.cc @@ -16,6 +16,7 @@ #include "chrome/browser/extensions/extension_creator.h" #include "chrome/browser/extensions/extensions_service.h" #include "chrome/browser/extensions/external_extension_provider.h" +#include "chrome/browser/extensions/external_pref_extension_provider.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/url_pattern.h" #include "chrome/common/chrome_paths.h" @@ -116,6 +117,77 @@ class MockExtensionProvider : public ExternalExtensionProvider { typedef std::map< std::string, std::pair<std::string, FilePath> > DataMap; DataMap extension_map_; Extension::Location location_; + + DISALLOW_COPY_AND_ASSIGN(MockExtensionProvider); +}; + +class MockProviderVisitor : public ExternalExtensionProvider::Visitor { + public: + MockProviderVisitor() { + } + + int Visit(std::string json_data, const std::set<std::string>& ignore_list) { + // Give the test json file to the provider for parsing. + provider_.reset(new ExternalPrefExtensionProvider()); + provider_->SetPreferencesForTesting(json_data); + + // We also parse the file into a dictionary to compare what we get back + // from the provider. + JSONStringValueSerializer serializer(json_data); + std::string error_msg; + Value* json_value = serializer.Deserialize(&error_msg); + + if (!error_msg.empty() || !json_value || + !json_value->IsType(Value::TYPE_DICTIONARY)) { + NOTREACHED() << L"Unable to deserialize json data"; + return -1; + } else { + DictionaryValue* external_extensions = + static_cast<DictionaryValue*>(json_value); + prefs_.reset(external_extensions); + } + + // Reset our counter. + ids_found_ = 0; + // Ask the provider to look up all extensions (and return the ones + // found (that are not on the ignore list). + provider_->VisitRegisteredExtension(this, ignore_list); + + return ids_found_; + } + + virtual void OnExternalExtensionFound(const std::string& id, + const Version* version, + const FilePath& path) { + ++ids_found_; + DictionaryValue* pref; + // This tests is to make sure that the provider only notifies us of the + // values we gave it. So if the id we doesn't exist in our internal + // dictionary then something is wrong. + EXPECT_TRUE(prefs_->GetDictionary(ASCIIToWide(id), &pref)) + << L"Got back ID (" << id.c_str() << ") we weren't expecting"; + + if (pref) { + // Ask provider if the extension we got back is registered. + Extension::Location location = Extension::INVALID; + scoped_ptr<Version> v1(provider_->RegisteredVersion(id, NULL)); + scoped_ptr<Version> v2(provider_->RegisteredVersion(id, &location)); + EXPECT_STREQ(version->GetString().c_str(), v1->GetString().c_str()); + EXPECT_STREQ(version->GetString().c_str(), v2->GetString().c_str()); + EXPECT_EQ(Extension::EXTERNAL_PREF, location); + + // Remove it so we won't count it ever again. + prefs_->Remove(ASCIIToWide(id), NULL); + } + } + + private: + int ids_found_; + + scoped_ptr<ExternalPrefExtensionProvider> provider_; + scoped_ptr<DictionaryValue> prefs_; + + DISALLOW_COPY_AND_ASSIGN(MockProviderVisitor); }; class ExtensionsServiceTest @@ -840,7 +912,7 @@ TEST_F(ExtensionsServiceTest, UninstallExtension) { ValidatePref(good_crx, L"location", Extension::INTERNAL); // Uninstall it. - service_->UninstallExtension(extension_id); + service_->UninstallExtension(extension_id, false); total_successes_ = 0; // We should get an unload notification. @@ -863,7 +935,7 @@ TEST_F(ExtensionsServiceTest, UninstallExtension) { FilePath current_version_file = extension_path.AppendASCII(ExtensionsService::kCurrentVersionFileName); EXPECT_TRUE(file_util::Delete(current_version_file, true)); - service_->UninstallExtension(extension_id); + service_->UninstallExtension(extension_id, false); loop_.RunAllPending(); EXPECT_FALSE(file_util::PathExists(extension_path)); @@ -900,7 +972,7 @@ TEST_F(ExtensionsServiceTest, LoadExtension) { // Test uninstall. std::string id = loaded_[0]->id(); EXPECT_FALSE(unloaded_id_.length()); - service_->UninstallExtension(id); + service_->UninstallExtension(id, false); loop_.RunAllPending(); EXPECT_EQ(id, unloaded_id_); ASSERT_EQ(0u, loaded_.size()); @@ -1005,10 +1077,10 @@ TEST_F(ExtensionsServiceTest, ExternalInstallRegistry) { ValidatePref(good_crx, L"state", Extension::ENABLED); ValidatePref(good_crx, L"location", Extension::EXTERNAL_REGISTRY); - // Uninstall the extension and reinit. Nothing should happen because the + // Uninstall the extension and reload. Nothing should happen because the // preference should prevent us from reinstalling. std::string id = loaded_[0]->id(); - service_->UninstallExtension(id); + service_->UninstallExtension(id, false); loop_.RunAllPending(); // The extension should also be gone from the install directory. @@ -1037,12 +1109,17 @@ TEST_F(ExtensionsServiceTest, ExternalInstallRegistry) { ValidatePref(good_crx, L"state", Extension::ENABLED); ValidatePref(good_crx, L"location", Extension::EXTERNAL_REGISTRY); + // Now test an externally triggered uninstall (deleting the registry key). reg_provider->RemoveExtension(good_crx); loaded_.clear(); - service_->CheckForUpdates(); + service_->LoadAllExtensions(); loop_.RunAllPending(); ASSERT_EQ(0u, loaded_.size()); + ValidatePrefKeyCount(0); + + // The extension should also be gone from the install directory. + ASSERT_FALSE(file_util::PathExists(install_path)); } #endif @@ -1075,7 +1152,6 @@ TEST_F(ExtensionsServiceTest, ExternalInstallPref) { ASSERT_EQ(1u, loaded_.size()); ASSERT_EQ(Extension::EXTERNAL_PREF, loaded_[0]->location()); ASSERT_EQ("1.0.0.0", loaded_[0]->version()->GetString()); - ValidatePrefKeyCount(1); ValidatePref(good_crx, L"state", Extension::ENABLED); ValidatePref(good_crx, L"location", Extension::EXTERNAL_PREF); @@ -1087,7 +1163,6 @@ TEST_F(ExtensionsServiceTest, ExternalInstallPref) { loop_.RunAllPending(); ASSERT_EQ(0u, GetErrors().size()); ASSERT_EQ(1u, loaded_.size()); - ValidatePrefKeyCount(1); ValidatePref(good_crx, L"state", Extension::ENABLED); ValidatePref(good_crx, L"location", Extension::EXTERNAL_PREF); @@ -1102,7 +1177,6 @@ TEST_F(ExtensionsServiceTest, ExternalInstallPref) { ASSERT_EQ(0u, GetErrors().size()); ASSERT_EQ(1u, loaded_.size()); ASSERT_EQ("1.0.0.1", loaded_[0]->version()->GetString()); - ValidatePrefKeyCount(1); ValidatePref(good_crx, L"state", Extension::ENABLED); ValidatePref(good_crx, L"location", Extension::EXTERNAL_PREF); @@ -1110,7 +1184,7 @@ TEST_F(ExtensionsServiceTest, ExternalInstallPref) { // Uninstall the extension and reload. Nothing should happen because the // preference should prevent us from reinstalling. std::string id = loaded_[0]->id(); - service_->UninstallExtension(id); + service_->UninstallExtension(id, false); loop_.RunAllPending(); // The extension should also be gone from the install directory. @@ -1122,7 +1196,6 @@ TEST_F(ExtensionsServiceTest, ExternalInstallPref) { service_->CheckForUpdates(); loop_.RunAllPending(); ASSERT_EQ(0u, loaded_.size()); - ValidatePrefKeyCount(1); ValidatePref(good_crx, L"state", Extension::KILLBIT); ValidatePref(good_crx, L"location", Extension::EXTERNAL_PREF); @@ -1135,29 +1208,21 @@ TEST_F(ExtensionsServiceTest, ExternalInstallPref) { service_->CheckForUpdates(); loop_.RunAllPending(); ASSERT_EQ(1u, loaded_.size()); - ValidatePrefKeyCount(1); 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 test an externally triggered uninstall (deleting id from json file). + pref_provider->RemoveExtension(good_crx); loaded_.clear(); - service_->ReloadExtensions(); + service_->LoadAllExtensions(); loop_.RunAllPending(); ASSERT_EQ(0u, loaded_.size()); + ValidatePrefKeyCount(0); - ValidatePrefKeyCount(1); - ValidatePref(good_crx, L"state", Extension::KILLBIT); - ValidatePref(good_crx, L"location", Extension::EXTERNAL_PREF); - - // The extension should also be gone from disk. - FilePath extension_path = install_path.DirName(); - extension_path = extension_path.AppendASCII(good_crx); - EXPECT_FALSE(file_util::PathExists(extension_path)) << - extension_path.ToWStringHack(); + // The extension should also be gone from the install directory. + ASSERT_FALSE(file_util::PathExists(install_path)); // This shouldn't work if extensions are disabled. SetExtensionsEnabled(false); @@ -1168,11 +1233,61 @@ TEST_F(ExtensionsServiceTest, ExternalInstallPref) { ASSERT_EQ(0u, loaded_.size()); ASSERT_EQ(1u, GetErrors().size()); + ASSERT_TRUE(GetErrors()[0].find("Extensions are not enabled") != + std::string::npos); +} + +TEST_F(ExtensionsServiceTest, ExternalPrefProvider) { + std::string json_data = + "{" + "\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\": {" + "\"external_crx\": \"RandomExtension.crx\"," + "\"external_version\": \"1.0\"" + "}," + "\"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\": {" + "\"external_crx\": \"RandomExtension2.crx\"," + "\"external_version\": \"2.0\"" + "}" + "}"; + + MockProviderVisitor visitor; + std::set<std::string> ignore_list; + EXPECT_EQ(2, visitor.Visit(json_data, ignore_list)); + ignore_list.insert("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); + EXPECT_EQ(1, visitor.Visit(json_data, ignore_list)); + ignore_list.insert("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"); + EXPECT_EQ(0, visitor.Visit(json_data, ignore_list)); + + // Use a json that contains three invalid extensions: + // - One that is missing the 'external_crx' key. + // - One that is missing the 'external_version' key. + // - One that is specifying .. in the path. + // - Plus one valid extension to make sure the json file is parsed properly. + json_data = + "{" + "\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\": {" + "\"external_version\": \"1.0\"" + "}," + "\"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\": {" + "\"external_crx\": \"RandomExtension.crx\"" + "}," + "\"cccccccccccccccccccccccccccccccc\": {" + "\"external_crx\": \"..\\\\foo\\\\RandomExtension2.crx\"," + "\"external_version\": \"2.0\"" + "}," + "\"dddddddddddddddddddddddddddddddddd\": {" + "\"external_crx\": \"RandomValidExtension.crx\"," + "\"external_version\": \"1.0\"" + "}" + "}"; + ignore_list.clear(); + EXPECT_EQ(1, visitor.Visit(json_data, ignore_list)); } // Test that we get enabled/disabled correctly for all the pref/command-line -// combinations. -TEST(ExtensionsServiceTest2, Enabledness) { +// combinations. We don't want to derive from the ExtensionsServiceTest class +// for this test, so we use ExtensionsServiceTestSimple. +TEST(ExtensionsServiceTestSimple, Enabledness) { TestingProfile profile; MessageLoop loop; scoped_ptr<CommandLine> command_line; diff --git a/chrome/browser/extensions/extensions_ui.cc b/chrome/browser/extensions/extensions_ui.cc index 1edacb8..6f08479 100644 --- a/chrome/browser/extensions/extensions_ui.cc +++ b/chrome/browser/extensions/extensions_ui.cc @@ -127,7 +127,7 @@ void ExtensionsDOMHandler::HandleUninstallMessage(const Value* value) { CHECK(list->GetSize() == 1); std::string extension_id; CHECK(list->GetString(0, &extension_id)); - extensions_service_->UninstallExtension(extension_id); + extensions_service_->UninstallExtension(extension_id, false); } static void CreateScriptFileDetailValue( diff --git a/chrome/browser/extensions/external_extensions.json b/chrome/browser/extensions/external_extensions.json index 2021042..1ef50f3 100644 --- a/chrome/browser/extensions/external_extensions.json +++ b/chrome/browser/extensions/external_extensions.json @@ -1,2 +1,5 @@ // This json file will contain a list of extensions that will be included // in the installer. + +{ +}
\ No newline at end of file diff --git a/chrome/browser/extensions/external_pref_extension_provider.cc b/chrome/browser/extensions/external_pref_extension_provider.cc index 5d16ba0..0b31025 100644 --- a/chrome/browser/extensions/external_pref_extension_provider.cc +++ b/chrome/browser/extensions/external_pref_extension_provider.cc @@ -10,6 +10,7 @@ #include "base/path_service.h" #include "base/string_util.h" #include "base/version.h" +#include "chrome/common/json_value_serializer.h" // Constants for keeping track of extension preferences. const wchar_t kLocation[] = L"location"; @@ -17,15 +18,24 @@ const wchar_t kState[] = L"state"; const wchar_t kExternalCrx[] = L"external_crx"; const wchar_t kExternalVersion[] = L"external_version"; -ExternalPrefExtensionProvider::ExternalPrefExtensionProvider( - DictionaryValue* prefs) { - DCHECK(prefs); - prefs_.reset(prefs); +ExternalPrefExtensionProvider::ExternalPrefExtensionProvider() { + FilePath json_file; + PathService::Get(app::DIR_EXTERNAL_EXTENSIONS, &json_file); + json_file = json_file.Append(FILE_PATH_LITERAL("external_extensions.json")); + + JSONFileValueSerializer serializer(json_file); + SetPreferences(&serializer); } ExternalPrefExtensionProvider::~ExternalPrefExtensionProvider() { } +void ExternalPrefExtensionProvider::SetPreferencesForTesting( + std::string json_data_for_testing) { + JSONStringValueSerializer serializer(json_data_for_testing); + SetPreferences(&serializer); +} + void ExternalPrefExtensionProvider::VisitRegisteredExtension( Visitor* visitor, const std::set<std::string>& ids_to_ignore) const { for (DictionaryValue::key_iterator i = prefs_->begin_keys(); @@ -39,17 +49,6 @@ void ExternalPrefExtensionProvider::VisitRegisteredExtension( continue; } - int location; - if (extension->GetInteger(kLocation, &location) && - location != Extension::EXTERNAL_PREF) { - continue; - } - int state; - if (extension->GetInteger(kState, &state) && - state == Extension::KILLBIT) { - continue; - } - FilePath::StringType external_crx; std::string external_version; if (!extension->GetString(kExternalCrx, &external_crx) || @@ -74,12 +73,6 @@ void ExternalPrefExtensionProvider::VisitRegisteredExtension( path = base_path.Append(external_crx); } - if (!file_util::PathExists(path)) { - LOG(WARNING) << "Cannot find extension: " << external_crx.c_str(); - continue; // Path is neither absolute nor relative. Might be - // meta-physical, but we don't support those (yet). - } - scoped_ptr<Version> version; version.reset(Version::GetVersionFromString(external_version)); visitor->OnExternalExtensionFound( @@ -101,3 +94,24 @@ Version* ExternalPrefExtensionProvider::RegisteredVersion( *location = Extension::EXTERNAL_PREF; return Version::GetVersionFromString(external_version); } + +void ExternalPrefExtensionProvider::SetPreferences( + ValueSerializer* serializer) { + std::string error_msg; + Value* extensions = serializer->Deserialize(&error_msg); + scoped_ptr<DictionaryValue> dictionary(new DictionaryValue()); + if (!error_msg.empty()) { + NOTREACHED() << L"Unable to deserialize json data: " + << error_msg.c_str(); + } else { + // This can be null if the json file specified does not exist. + if (extensions) { + if (!extensions->IsType(Value::TYPE_DICTIONARY)) { + NOTREACHED() << L"Invalid json data"; + } else { + dictionary.reset(static_cast<DictionaryValue*>(extensions)); + } + } + } + prefs_.reset(dictionary.release()); +} diff --git a/chrome/browser/extensions/external_pref_extension_provider.h b/chrome/browser/extensions/external_pref_extension_provider.h index a52be411..67d46e3 100644 --- a/chrome/browser/extensions/external_pref_extension_provider.h +++ b/chrome/browser/extensions/external_pref_extension_provider.h @@ -13,13 +13,17 @@ class DictionaryValue; class Version; -// A specialization of the ExternalExtensionProvider that uses preferences to +// A specialization of the ExternalExtensionProvider that uses a json file to // look up which external extensions are registered. class ExternalPrefExtensionProvider : public ExternalExtensionProvider { public: - explicit ExternalPrefExtensionProvider(DictionaryValue* prefs); + 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(std::string json_data_for_testing); + // ExternalExtensionProvider implementation: virtual void VisitRegisteredExtension( Visitor* visitor, const std::set<std::string>& ids_to_ignore) const; @@ -28,6 +32,9 @@ class ExternalPrefExtensionProvider : public ExternalExtensionProvider { Extension::Location* location) const; protected: scoped_ptr<DictionaryValue> prefs_; + + private: + void SetPreferences(ValueSerializer* serializer); }; #endif // CHROME_BROWSER_EXTENSIONS_EXTERNAL_PREF_EXTENSION_PROVIDER_H_ |