summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/extensions/extension_browsertest.cc5
-rw-r--r--chrome/browser/extensions/extension_prefs.cc10
-rw-r--r--chrome/browser/extensions/extension_prefs.h3
-rw-r--r--chrome/browser/extensions/extensions_service.cc21
-rw-r--r--chrome/browser/extensions/extensions_service.h6
-rw-r--r--chrome/browser/extensions/extensions_service_unittest.cc169
-rw-r--r--chrome/browser/extensions/extensions_ui.cc2
-rw-r--r--chrome/browser/extensions/external_extensions.json3
-rw-r--r--chrome/browser/extensions/external_pref_extension_provider.cc56
-rw-r--r--chrome/browser/extensions/external_pref_extension_provider.h11
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_