Observe adding external extensions via windows registry.
Install the extension right away (no chrome restart).
For registry changes, we only look at 32-bit registry values
for extensions, see
https://developer.chrome.com/extensions/external_extensions#registry
A lot of the changes in this CL is to make ExternalProvider-s be
able to discover new external extensions at times other than
chrome start up. The added method is
OnExternalProviderUpdateComplete(), which provides a list of
a. Extensions that were added via update_url,
b. Extensions that were added via crx,
c. Extensions that were removed.
BUG=581756
Test=While chrome is running, add a registry entry for an extension
under HKLM or HKCU as described in
https://developer.chrome.com/extensions/external_extensions#registry
Now observe that external install would appear for that extension
in chrome shortly.
If you had some extension installed this way, removing the registry
entry would cause the extension to be uninstalled too!
Review URL: https://codereview.chromium.org/1495403002
Cr-Commit-Position: refs/heads/master@{#371911}
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc
index 8047d11b..27b95131 100644
--- a/chrome/browser/extensions/extension_service_unittest.cc
+++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -97,6 +97,7 @@
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_system.h"
+#include "extensions/browser/external_install_info.h"
#include "extensions/browser/external_provider_interface.h"
#include "extensions/browser/install_flag.h"
#include "extensions/browser/management_policy.h"
@@ -163,6 +164,9 @@
using extensions::ExtensionResource;
using extensions::ExtensionSystem;
using extensions::ExternalInstallError;
+using extensions::ExternalInstallInfoFile;
+using extensions::ExternalInstallInfoUpdateUrl;
+using extensions::ExternalProviderInterface;
using extensions::FakeSafeBrowsingDatabaseManager;
using extensions::FeatureSwitch;
using extensions::Manifest;
@@ -248,11 +252,12 @@
visit_count_++;
for (DataMap::const_iterator i = extension_map_.begin();
i != extension_map_.end(); ++i) {
- Version version(i->second.first);
+ scoped_ptr<Version> version(new Version(i->second.first));
- visitor_->OnExternalExtensionFileFound(
- i->first, &version, i->second.second, location_,
- Extension::NO_FLAGS, false, false);
+ scoped_ptr<ExternalInstallInfoFile> info(new ExternalInstallInfoFile(
+ i->first, std::move(version), i->second.second, location_,
+ Extension::NO_FLAGS, false, false));
+ visitor_->OnExternalExtensionFileFound(*info);
}
visitor_->OnExternalProviderReady(this);
}
@@ -324,26 +329,22 @@
}
int Visit(const std::string& json_data) {
+ return Visit(json_data, Manifest::EXTERNAL_PREF,
+ Manifest::EXTERNAL_PREF_DOWNLOAD);
+ }
+
+ int Visit(const std::string& json_data,
+ Manifest::Location crx_location,
+ Manifest::Location download_location) {
+ crx_location_ = crx_location;
// Give the test json file to the provider for parsing.
provider_.reset(new extensions::ExternalProviderImpl(
- this,
- new extensions::ExternalTestingLoader(json_data, fake_base_path_),
- profile_.get(),
- Manifest::EXTERNAL_PREF,
- Manifest::EXTERNAL_PREF_DOWNLOAD,
- Extension::NO_FLAGS));
+ this, new extensions::ExternalTestingLoader(json_data, fake_base_path_),
+ profile_.get(), crx_location, download_location, Extension::NO_FLAGS));
// We also parse the file into a dictionary to compare what we get back
// from the provider.
- JSONStringValueDeserializer deserializer(json_data);
- scoped_ptr<base::Value> json_value = deserializer.Deserialize(NULL, NULL);
-
- if (!json_value || !json_value->IsType(base::Value::TYPE_DICTIONARY)) {
- NOTREACHED() << "Unable to deserialize json data";
- return -1;
- } else {
- prefs_ = base::DictionaryValue::From(std::move(json_value));
- }
+ prefs_ = GetDictionaryFromJSON(json_data);
// Reset our counter.
ids_found_ = 0;
@@ -353,85 +354,90 @@
return ids_found_;
}
- bool OnExternalExtensionFileFound(const std::string& id,
- const Version* version,
- const base::FilePath& path,
- Manifest::Location unused,
- int creation_flags,
- bool mark_acknowledged,
- bool install_immediately) override {
- EXPECT_EQ(expected_creation_flags_, creation_flags);
+ bool OnExternalExtensionFileFound(
+ const ExternalInstallInfoFile& info) override {
+ EXPECT_EQ(expected_creation_flags_, info.creation_flags);
++ids_found_;
base::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(id, &pref))
- << "Got back ID (" << id.c_str() << ") we weren't expecting";
+ EXPECT_TRUE(prefs_->GetDictionary(info.extension_id, &pref))
+ << "Got back ID (" << info.extension_id.c_str()
+ << ") we weren't expecting";
- EXPECT_TRUE(path.IsAbsolute());
+ EXPECT_TRUE(info.path.IsAbsolute());
if (!fake_base_path_.empty())
- EXPECT_TRUE(fake_base_path_.IsParent(path));
+ EXPECT_TRUE(fake_base_path_.IsParent(info.path));
if (pref) {
- EXPECT_TRUE(provider_->HasExtension(id));
+ EXPECT_TRUE(provider_->HasExtension(info.extension_id));
// Ask provider if the extension we got back is registered.
Manifest::Location location = Manifest::INVALID_LOCATION;
scoped_ptr<Version> v1;
base::FilePath crx_path;
- EXPECT_TRUE(provider_->GetExtensionDetails(id, NULL, &v1));
- EXPECT_STREQ(version->GetString().c_str(), v1->GetString().c_str());
+ EXPECT_TRUE(provider_->GetExtensionDetails(info.extension_id, NULL, &v1));
+ EXPECT_STREQ(info.version->GetString().c_str(), v1->GetString().c_str());
scoped_ptr<Version> v2;
- EXPECT_TRUE(provider_->GetExtensionDetails(id, &location, &v2));
- EXPECT_STREQ(version->GetString().c_str(), v1->GetString().c_str());
- EXPECT_STREQ(version->GetString().c_str(), v2->GetString().c_str());
- EXPECT_EQ(Manifest::EXTERNAL_PREF, location);
+ EXPECT_TRUE(
+ provider_->GetExtensionDetails(info.extension_id, &location, &v2));
+ EXPECT_STREQ(info.version->GetString().c_str(), v1->GetString().c_str());
+ EXPECT_STREQ(info.version->GetString().c_str(), v2->GetString().c_str());
+ EXPECT_EQ(crx_location_, location);
// Remove it so we won't count it ever again.
- prefs_->Remove(id, NULL);
+ prefs_->Remove(info.extension_id, NULL);
}
return true;
}
- bool OnExternalExtensionUpdateUrlFound(const std::string& id,
- const std::string& install_parameter,
- const GURL& update_url,
- Manifest::Location location,
- int creation_flags,
- bool mark_acknowledged) override {
+ bool OnExternalExtensionUpdateUrlFound(
+ const ExternalInstallInfoUpdateUrl& info,
+ bool is_initial_load) override {
++ids_found_;
base::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(id, &pref))
- << L"Got back ID (" << id.c_str() << ") we weren't expecting";
- EXPECT_EQ(Manifest::EXTERNAL_PREF_DOWNLOAD, location);
+ EXPECT_TRUE(prefs_->GetDictionary(info.extension_id, &pref))
+ << L"Got back ID (" << info.extension_id.c_str()
+ << ") we weren't expecting";
+ EXPECT_EQ(Manifest::EXTERNAL_PREF_DOWNLOAD, info.download_location);
if (pref) {
- EXPECT_TRUE(provider_->HasExtension(id));
+ EXPECT_TRUE(provider_->HasExtension(info.extension_id));
// External extensions with update URLs do not have versions.
scoped_ptr<Version> v1;
Manifest::Location location1 = Manifest::INVALID_LOCATION;
- EXPECT_TRUE(provider_->GetExtensionDetails(id, &location1, &v1));
+ EXPECT_TRUE(
+ provider_->GetExtensionDetails(info.extension_id, &location1, &v1));
EXPECT_FALSE(v1.get());
EXPECT_EQ(Manifest::EXTERNAL_PREF_DOWNLOAD, location1);
std::string parsed_install_parameter;
pref->GetString("install_parameter", &parsed_install_parameter);
- EXPECT_EQ(parsed_install_parameter, install_parameter);
+ EXPECT_EQ(parsed_install_parameter, info.install_parameter);
// Remove it so we won't count it again.
- prefs_->Remove(id, NULL);
+ prefs_->Remove(info.extension_id, NULL);
}
return true;
}
+ void OnExternalProviderUpdateComplete(
+ const ExternalProviderInterface* provider,
+ const ScopedVector<ExternalInstallInfoUpdateUrl>& update_url_extensions,
+ const ScopedVector<ExternalInstallInfoFile>& file_extensions,
+ const std::set<std::string>& removed_extensions) override {
+ ADD_FAILURE() << "MockProviderVisitor does not provide incremental updates,"
+ " use MockUpdateProviderVisitor instead.";
+ }
+
void OnExternalProviderReady(
const extensions::ExternalProviderInterface* provider) override {
EXPECT_EQ(provider, provider_.get());
@@ -440,17 +446,98 @@
Profile* profile() { return profile_.get(); }
+ protected:
+ scoped_ptr<extensions::ExternalProviderImpl> provider_;
+
+ scoped_ptr<base::DictionaryValue> GetDictionaryFromJSON(
+ const std::string& json_data) {
+ // We also parse the file into a dictionary to compare what we get back
+ // from the provider.
+ JSONStringValueDeserializer deserializer(json_data);
+ scoped_ptr<base::Value> json_value = deserializer.Deserialize(NULL, NULL);
+
+ if (!json_value || !json_value->IsType(base::Value::TYPE_DICTIONARY)) {
+ ADD_FAILURE() << "Unable to deserialize json data";
+ return scoped_ptr<base::DictionaryValue>();
+ } else {
+ return base::DictionaryValue::From(std::move(json_value));
+ }
+ }
+
private:
int ids_found_;
base::FilePath fake_base_path_;
int expected_creation_flags_;
- scoped_ptr<extensions::ExternalProviderImpl> provider_;
+ Manifest::Location crx_location_;
scoped_ptr<base::DictionaryValue> prefs_;
scoped_ptr<TestingProfile> profile_;
DISALLOW_COPY_AND_ASSIGN(MockProviderVisitor);
};
+// Mock provider that can simulate incremental update like
+// ExternalRegistryLoader.
+class MockUpdateProviderVisitor : public MockProviderVisitor {
+ public:
+ // The provider will return |fake_base_path| from
+ // GetBaseCrxFilePath(). User can test the behavior with
+ // and without an empty path using this parameter.
+ explicit MockUpdateProviderVisitor(base::FilePath fake_base_path)
+ : MockProviderVisitor(fake_base_path) {}
+
+ void VisitDueToUpdate(const std::string& json_data) {
+ update_url_extension_ids_.clear();
+ file_extension_ids_.clear();
+ removed_extension_ids_.clear();
+
+ scoped_ptr<base::DictionaryValue> new_prefs =
+ GetDictionaryFromJSON(json_data);
+ if (!new_prefs)
+ return;
+ provider_->UpdatePrefs(new_prefs.release());
+ }
+
+ void OnExternalProviderUpdateComplete(
+ const ExternalProviderInterface* provider,
+ const ScopedVector<ExternalInstallInfoUpdateUrl>& update_url_extensions,
+ const ScopedVector<ExternalInstallInfoFile>& file_extensions,
+ const std::set<std::string>& removed_extensions) override {
+ for (const auto& extension_info : update_url_extensions)
+ update_url_extension_ids_.insert(extension_info->extension_id);
+ EXPECT_EQ(update_url_extension_ids_.size(), update_url_extensions.size());
+
+ for (const auto& extension_info : file_extensions)
+ file_extension_ids_.insert(extension_info->extension_id);
+ EXPECT_EQ(file_extension_ids_.size(), file_extensions.size());
+
+ for (const auto& extension_id : removed_extensions)
+ removed_extension_ids_.insert(extension_id);
+ }
+
+ size_t GetUpdateURLExtensionCount() {
+ return update_url_extension_ids_.size();
+ }
+ size_t GetFileExtensionCount() { return file_extension_ids_.size(); }
+ size_t GetRemovedExtensionCount() { return removed_extension_ids_.size(); }
+
+ bool HasSeenUpdateWithUpdateUrl(const std::string& extension_id) {
+ return update_url_extension_ids_.count(extension_id) > 0u;
+ }
+ bool HasSeenUpdateWithFile(const std::string& extension_id) {
+ return file_extension_ids_.count(extension_id) > 0u;
+ }
+ bool HasSeenRemoval(const std::string& extension_id) {
+ return removed_extension_ids_.count(extension_id) > 0u;
+ }
+
+ private:
+ std::set<std::string> update_url_extension_ids_;
+ std::set<std::string> file_extension_ids_;
+ std::set<std::string> removed_extension_ids_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockUpdateProviderVisitor);
+};
+
class ExtensionServiceTest
: public extensions::ExtensionServiceTestWithInstall {
public:
@@ -1029,20 +1116,16 @@
service()->set_extensions_enabled(true);
// Register and install an external extension.
- Version version("1.0.0.0");
+ scoped_ptr<Version> version(new Version("1.0.0.0"));
content::WindowedNotificationObserver observer(
extensions::NOTIFICATION_CRX_INSTALLER_DONE,
content::NotificationService::AllSources());
- if (service()->OnExternalExtensionFileFound(
- good_crx,
- &version,
- path,
- Manifest::EXTERNAL_PREF,
- Extension::FROM_BOOKMARK,
- false /* mark_acknowledged */,
- false /* install_immediately */)) {
+ scoped_ptr<ExternalInstallInfoFile> info(new ExternalInstallInfoFile(
+ good_crx, std::move(version), path, Manifest::EXTERNAL_PREF,
+ Extension::FROM_BOOKMARK, false /* mark_acknowledged */,
+ false /* install_immediately */));
+ if (service()->OnExternalExtensionFileFound(*info))
observer.Wait();
- }
const Extension* extension = service()->GetExtensionById(good_crx, false);
ASSERT_TRUE(extension);
@@ -1066,19 +1149,15 @@
service()->set_extensions_enabled(true);
// Install an external extension.
- Version version("1.0.0.0");
content::WindowedNotificationObserver observer(
extensions::NOTIFICATION_CRX_INSTALLER_DONE,
content::NotificationService::AllSources());
- if (service()->OnExternalExtensionFileFound(good_crx,
- &version,
- path,
- Manifest::EXTERNAL_PREF,
- Extension::NO_FLAGS,
- false,
- false)) {
+ scoped_ptr<Version> version(new Version("1.0.0.0"));
+ scoped_ptr<ExternalInstallInfoFile> info(new ExternalInstallInfoFile(
+ good_crx, std::move(version), path, Manifest::EXTERNAL_PREF,
+ Extension::NO_FLAGS, false, false));
+ if (service()->OnExternalExtensionFileFound(*info))
observer.Wait();
- }
ASSERT_TRUE(service()->GetExtensionById(good_crx, false));
@@ -1088,28 +1167,19 @@
Extension::EXTERNAL_EXTENSION_UNINSTALLED);
// Try to re-install it externally. This should fail because of the killbit.
- service()->OnExternalExtensionFileFound(good_crx,
- &version,
- path,
- Manifest::EXTERNAL_PREF,
- Extension::NO_FLAGS,
- false,
- false);
+ service()->OnExternalExtensionFileFound(*info);
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(NULL == service()->GetExtensionById(good_crx, false));
ValidateIntegerPref(good_crx, "state",
Extension::EXTERNAL_EXTENSION_UNINSTALLED);
- version = Version("1.0.0.1");
+ version.reset(new Version("1.0.0.1"));
// Repeat the same thing with a newer version of the extension.
path = data_dir().AppendASCII("good2.crx");
- service()->OnExternalExtensionFileFound(good_crx,
- &version,
- path,
- Manifest::EXTERNAL_PREF,
- Extension::NO_FLAGS,
- false,
- false);
+ info.reset(new ExternalInstallInfoFile(good_crx, std::move(version), path,
+ Manifest::EXTERNAL_PREF,
+ Extension::NO_FLAGS, false, false));
+ service()->OnExternalExtensionFileFound(*info);
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(NULL == service()->GetExtensionById(good_crx, false));
ValidateIntegerPref(good_crx, "state",
@@ -1160,7 +1230,7 @@
base::FilePath path = data_dir().AppendASCII("good.crx");
service()->set_extensions_enabled(true);
- Version version("1.0.0.0");
+ scoped_ptr<Version> version(new Version("1.0.0.0"));
const std::string wrong_id = all_zero;
const std::string correct_id = good_crx;
@@ -1171,13 +1241,10 @@
content::WindowedNotificationObserver observer(
extensions::NOTIFICATION_CRX_INSTALLER_DONE,
content::NotificationService::AllSources());
- service()->OnExternalExtensionFileFound(wrong_id,
- &version,
- path,
- Manifest::EXTERNAL_PREF,
- Extension::NO_FLAGS,
- false,
- false);
+ scoped_ptr<ExternalInstallInfoFile> info(new ExternalInstallInfoFile(
+ wrong_id, std::move(version), path, Manifest::EXTERNAL_PREF,
+ Extension::NO_FLAGS, false, false));
+ service()->OnExternalExtensionFileFound(*info);
observer.Wait();
ASSERT_FALSE(service()->GetExtensionById(good_crx, false));
@@ -1186,15 +1253,9 @@
content::WindowedNotificationObserver observer2(
extensions::NOTIFICATION_CRX_INSTALLER_DONE,
content::NotificationService::AllSources());
- if (service()->OnExternalExtensionFileFound(correct_id,
- &version,
- path,
- Manifest::EXTERNAL_PREF,
- Extension::NO_FLAGS,
- false,
- false)) {
+ info->extension_id = correct_id;
+ if (service()->OnExternalExtensionFileFound(*info))
observer2.Wait();
- }
ASSERT_TRUE(service()->GetExtensionById(good_crx, false));
}
@@ -1206,36 +1267,27 @@
// Install an external extension with a version from the external
// source that is not equal to the version in the extension manifest.
- Version wrong_version("1.2.3.4");
content::WindowedNotificationObserver observer(
extensions::NOTIFICATION_CRX_INSTALLER_DONE,
content::NotificationService::AllSources());
- service()->OnExternalExtensionFileFound(good_crx,
- &wrong_version,
- path,
- Manifest::EXTERNAL_PREF,
- Extension::NO_FLAGS,
- false,
- false);
+ scoped_ptr<Version> wrong_version(new Version("1.2.3.4"));
+ scoped_ptr<ExternalInstallInfoFile> info(new ExternalInstallInfoFile(
+ good_crx, std::move(wrong_version), path, Manifest::EXTERNAL_PREF,
+ Extension::NO_FLAGS, false, false));
+ service()->OnExternalExtensionFileFound(*info);
observer.Wait();
ASSERT_FALSE(service()->GetExtensionById(good_crx, false));
// Try again with the right version. Expect success.
service()->pending_extension_manager()->Remove(good_crx);
- Version correct_version("1.0.0.0");
+ scoped_ptr<Version> correct_version(new Version("1.0.0.0"));
+ info->version = std::move(correct_version);
content::WindowedNotificationObserver observer2(
extensions::NOTIFICATION_CRX_INSTALLER_DONE,
content::NotificationService::AllSources());
- if (service()->OnExternalExtensionFileFound(good_crx,
- &correct_version,
- path,
- Manifest::EXTERNAL_PREF,
- Extension::NO_FLAGS,
- false,
- false)) {
+ if (service()->OnExternalExtensionFileFound(*info))
observer2.Wait();
- }
ASSERT_TRUE(service()->GetExtensionById(good_crx, false));
}
@@ -5051,6 +5103,90 @@
EXPECT_EQ(1, visitor.Visit(json_data));
}
+TEST_F(ExtensionServiceTest, IncrementalUpdateThroughRegistry) {
+ InitializeEmptyExtensionService();
+
+ // Test some valid extension records.
+ // Set a base path to avoid erroring out on relative paths.
+ // Paths starting with // are absolute on every platform we support.
+ base::FilePath base_path(FILE_PATH_LITERAL("//base/path"));
+ ASSERT_TRUE(base_path.IsAbsolute());
+ MockUpdateProviderVisitor visitor(base_path);
+ std::string json_data =
+ "{"
+ " \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\": {"
+ " \"external_crx\": \"RandomExtension.crx\","
+ " \"external_version\": \"1.0\""
+ " },"
+ " \"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\": {"
+ " \"external_crx\": \"RandomExtension2.crx\","
+ " \"external_version\": \"2.0\""
+ " },"
+ " \"cccccccccccccccccccccccccccccccc\": {"
+ " \"external_update_url\": \"http:\\\\foo.com/update\","
+ " \"install_parameter\": \"id\""
+ " }"
+ "}";
+ EXPECT_EQ(3, visitor.Visit(json_data, Manifest::EXTERNAL_REGISTRY,
+ Manifest::EXTERNAL_PREF_DOWNLOAD));
+
+ // c* removed and d*, e*, f* added, a*, b* existing.
+ json_data =
+ "{"
+ " \"dddddddddddddddddddddddddddddddd\": {"
+ " \"external_crx\": \"RandomExtension3.crx\","
+ " \"external_version\": \"1.0\""
+ " },"
+ " \"eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\": {"
+ " \"external_update_url\": \"http:\\\\foo.com/update\","
+ " \"install_parameter\": \"id\""
+ " },"
+ " \"ffffffffffffffffffffffffffffffff\": {"
+ " \"external_update_url\": \"http:\\\\bar.com/update\","
+ " \"install_parameter\": \"id\""
+ " },"
+ " \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\": {"
+ " \"external_crx\": \"RandomExtension.crx\","
+ " \"external_version\": \"1.0\""
+ " },"
+ " \"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\": {"
+ " \"external_crx\": \"RandomExtension2.crx\","
+ " \"external_version\": \"2.0\""
+ " }"
+ "}";
+
+ // This will simulate registry loader observing new changes in registry and
+ // hence will discover new extensions.
+ visitor.VisitDueToUpdate(json_data);
+
+ // UpdateUrl.
+ EXPECT_EQ(2u, visitor.GetUpdateURLExtensionCount());
+ EXPECT_TRUE(
+ visitor.HasSeenUpdateWithUpdateUrl("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"));
+ EXPECT_TRUE(
+ visitor.HasSeenUpdateWithUpdateUrl("ffffffffffffffffffffffffffffffff"));
+
+ // File.
+ EXPECT_EQ(3u, visitor.GetFileExtensionCount());
+ EXPECT_TRUE(
+ visitor.HasSeenUpdateWithFile("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
+ EXPECT_TRUE(
+ visitor.HasSeenUpdateWithFile("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"));
+ EXPECT_TRUE(
+ visitor.HasSeenUpdateWithFile("dddddddddddddddddddddddddddddddd"));
+
+ // Removed extensions.
+ EXPECT_EQ(1u, visitor.GetRemovedExtensionCount());
+ EXPECT_TRUE(visitor.HasSeenRemoval("cccccccccccccccccccccccccccccccc"));
+
+ // Simulate all 5 extensions being removed.
+ json_data = "{}";
+ visitor.VisitDueToUpdate(json_data);
+ EXPECT_EQ(0u, visitor.GetUpdateURLExtensionCount());
+ EXPECT_EQ(0u, visitor.GetFileExtensionCount());
+ EXPECT_EQ(5u, visitor.GetRemovedExtensionCount());
+}
+
// Test loading good extensions from the profile directory.
TEST_F(ExtensionServiceTest, LoadAndRelocalizeExtensions) {
// Ensure we're testing in "en" and leave global state untouched.
@@ -5295,33 +5431,22 @@
EXPECT_FALSE(pending->IsIdPending(kGoodId));
// Skip install when the location is the same.
- EXPECT_FALSE(
- service()->OnExternalExtensionUpdateUrlFound(kGoodId,
- std::string(),
- GURL(kGoodUpdateURL),
- Manifest::INTERNAL,
- Extension::NO_FLAGS,
- false));
+ scoped_ptr<GURL> good_update_url(new GURL(kGoodUpdateURL));
+ scoped_ptr<ExternalInstallInfoUpdateUrl> info(
+ new ExternalInstallInfoUpdateUrl(
+ kGoodId, std::string(), std::move(good_update_url),
+ Manifest::INTERNAL, Extension::NO_FLAGS, false));
+ EXPECT_FALSE(service()->OnExternalExtensionUpdateUrlFound(*info, true));
EXPECT_FALSE(pending->IsIdPending(kGoodId));
// Install when the location has higher priority.
- EXPECT_TRUE(service()->OnExternalExtensionUpdateUrlFound(
- kGoodId,
- std::string(),
- GURL(kGoodUpdateURL),
- Manifest::EXTERNAL_POLICY_DOWNLOAD,
- Extension::NO_FLAGS,
- false));
+ info->download_location = Manifest::EXTERNAL_POLICY_DOWNLOAD;
+ EXPECT_TRUE(service()->OnExternalExtensionUpdateUrlFound(*info, true));
EXPECT_TRUE(pending->IsIdPending(kGoodId));
// Try the low priority again. Should be rejected.
- EXPECT_FALSE(service()->OnExternalExtensionUpdateUrlFound(
- kGoodId,
- std::string(),
- GURL(kGoodUpdateURL),
- Manifest::EXTERNAL_PREF_DOWNLOAD,
- Extension::NO_FLAGS,
- false));
+ info->download_location = Manifest::EXTERNAL_PREF_DOWNLOAD;
+ EXPECT_FALSE(service()->OnExternalExtensionUpdateUrlFound(*info, true));
// The existing record should still be present in the pending extension
// manager.
EXPECT_TRUE(pending->IsIdPending(kGoodId));
@@ -5330,13 +5455,8 @@
// Skip install when the location has the same priority as the installed
// location.
- EXPECT_FALSE(
- service()->OnExternalExtensionUpdateUrlFound(kGoodId,
- std::string(),
- GURL(kGoodUpdateURL),
- Manifest::INTERNAL,
- Extension::NO_FLAGS,
- false));
+ info->download_location = Manifest::INTERNAL;
+ EXPECT_FALSE(service()->OnExternalExtensionUpdateUrlFound(*info, true));
EXPECT_FALSE(pending->IsIdPending(kGoodId));
}
@@ -5374,19 +5494,17 @@
service()->pending_extension_manager();
EXPECT_FALSE(pending->IsIdPending(kGoodId));
+ scoped_ptr<Version> older_version_ptr(new Version(older_version));
+ scoped_ptr<ExternalInstallInfoFile> info(new ExternalInstallInfoFile(
+ kGoodId, std::move(older_version_ptr), kInvalidPathToCrx,
+ Manifest::INTERNAL, kCreationFlags, kDontMarkAcknowledged,
+ kDontInstallImmediately));
{
// Simulate an external source adding the extension as INTERNAL.
content::WindowedNotificationObserver observer(
extensions::NOTIFICATION_CRX_INSTALLER_DONE,
content::NotificationService::AllSources());
- EXPECT_TRUE(service()->OnExternalExtensionFileFound(
- kGoodId,
- &older_version,
- kInvalidPathToCrx,
- Manifest::INTERNAL,
- kCreationFlags,
- kDontMarkAcknowledged,
- kDontInstallImmediately));
+ EXPECT_TRUE(service()->OnExternalExtensionFileFound(*info));
EXPECT_TRUE(pending->IsIdPending(kGoodId));
observer.Wait();
VerifyCrxInstall(kInvalidPathToCrx, INSTALL_FAILED);
@@ -5397,14 +5515,8 @@
content::WindowedNotificationObserver observer(
extensions::NOTIFICATION_CRX_INSTALLER_DONE,
content::NotificationService::AllSources());
- EXPECT_TRUE(service()->OnExternalExtensionFileFound(
- kGoodId,
- &older_version,
- kInvalidPathToCrx,
- Manifest::EXTERNAL_PREF,
- kCreationFlags,
- kDontMarkAcknowledged,
- kDontInstallImmediately));
+ info->crx_location = Manifest::EXTERNAL_PREF;
+ EXPECT_TRUE(service()->OnExternalExtensionFileFound(*info));
EXPECT_TRUE(pending->IsIdPending(kGoodId));
observer.Wait();
VerifyCrxInstall(kInvalidPathToCrx, INSTALL_FAILED);
@@ -5413,25 +5525,12 @@
// Simulate an external source adding as EXTERNAL_PREF again.
// This is rejected because the version and the location are the same as
// the previous installation, which is still pending.
- EXPECT_FALSE(service()->OnExternalExtensionFileFound(
- kGoodId,
- &older_version,
- kInvalidPathToCrx,
- Manifest::EXTERNAL_PREF,
- kCreationFlags,
- kDontMarkAcknowledged,
- kDontInstallImmediately));
+ EXPECT_FALSE(service()->OnExternalExtensionFileFound(*info));
EXPECT_TRUE(pending->IsIdPending(kGoodId));
// Try INTERNAL again. Should fail.
- EXPECT_FALSE(service()->OnExternalExtensionFileFound(
- kGoodId,
- &older_version,
- kInvalidPathToCrx,
- Manifest::INTERNAL,
- kCreationFlags,
- kDontMarkAcknowledged,
- kDontInstallImmediately));
+ info->crx_location = Manifest::INTERNAL;
+ EXPECT_FALSE(service()->OnExternalExtensionFileFound(*info));
EXPECT_TRUE(pending->IsIdPending(kGoodId));
{
@@ -5439,38 +5538,20 @@
content::WindowedNotificationObserver observer(
extensions::NOTIFICATION_CRX_INSTALLER_DONE,
content::NotificationService::AllSources());
- EXPECT_TRUE(service()->OnExternalExtensionFileFound(
- kGoodId,
- &older_version,
- kInvalidPathToCrx,
- Manifest::EXTERNAL_REGISTRY,
- kCreationFlags,
- kDontMarkAcknowledged,
- kDontInstallImmediately));
+ info->crx_location = Manifest::EXTERNAL_REGISTRY;
+ EXPECT_TRUE(service()->OnExternalExtensionFileFound(*info));
EXPECT_TRUE(pending->IsIdPending(kGoodId));
observer.Wait();
VerifyCrxInstall(kInvalidPathToCrx, INSTALL_FAILED);
}
// Registry outranks both external pref and internal, so both fail.
- EXPECT_FALSE(service()->OnExternalExtensionFileFound(
- kGoodId,
- &older_version,
- kInvalidPathToCrx,
- Manifest::EXTERNAL_PREF,
- kCreationFlags,
- kDontMarkAcknowledged,
- kDontInstallImmediately));
+ info->crx_location = Manifest::EXTERNAL_PREF;
+ EXPECT_FALSE(service()->OnExternalExtensionFileFound(*info));
EXPECT_TRUE(pending->IsIdPending(kGoodId));
- EXPECT_FALSE(service()->OnExternalExtensionFileFound(
- kGoodId,
- &older_version,
- kInvalidPathToCrx,
- Manifest::INTERNAL,
- kCreationFlags,
- kDontMarkAcknowledged,
- kDontInstallImmediately));
+ info->crx_location = Manifest::INTERNAL;
+ EXPECT_FALSE(service()->OnExternalExtensionFileFound(*info));
EXPECT_TRUE(pending->IsIdPending(kGoodId));
pending->Remove(kGoodId);
@@ -5494,83 +5575,42 @@
// older, or the same, and succeed if the version is newer.
// Older than the installed version...
- EXPECT_FALSE(service()->OnExternalExtensionFileFound(
- kGoodId,
- &older_version,
- kInvalidPathToCrx,
- Manifest::INTERNAL,
- kCreationFlags,
- kDontMarkAcknowledged,
- kDontInstallImmediately));
+ info->version.reset(new Version(older_version));
+ EXPECT_FALSE(service()->OnExternalExtensionFileFound(*info));
EXPECT_FALSE(pending->IsIdPending(kGoodId));
// Same version as the installed version...
- EXPECT_FALSE(service()->OnExternalExtensionFileFound(
- kGoodId,
- ext->version(),
- kInvalidPathToCrx,
- Manifest::INTERNAL,
- kCreationFlags,
- kDontMarkAcknowledged,
- kDontInstallImmediately));
+ info->version.reset(new Version(ext->VersionString()));
+ EXPECT_FALSE(service()->OnExternalExtensionFileFound(*info));
EXPECT_FALSE(pending->IsIdPending(kGoodId));
// Newer than the installed version...
- EXPECT_TRUE(service()->OnExternalExtensionFileFound(
- kGoodId,
- &newer_version,
- kInvalidPathToCrx,
- Manifest::INTERNAL,
- kCreationFlags,
- kDontMarkAcknowledged,
- kDontInstallImmediately));
+ info->version.reset(new Version(newer_version));
+ EXPECT_TRUE(service()->OnExternalExtensionFileFound(*info));
EXPECT_TRUE(pending->IsIdPending(kGoodId));
// An external install for a higher priority install source should succeed
// if the version is greater. |older_version| is not...
- EXPECT_FALSE(service()->OnExternalExtensionFileFound(
- kGoodId,
- &older_version,
- kInvalidPathToCrx,
- Manifest::EXTERNAL_PREF,
- kCreationFlags,
- kDontMarkAcknowledged,
- kDontInstallImmediately));
+ info->version.reset(new Version(older_version));
+ info->crx_location = Manifest::EXTERNAL_PREF;
+ EXPECT_FALSE(service()->OnExternalExtensionFileFound(*info));
EXPECT_TRUE(pending->IsIdPending(kGoodId));
// |newer_version| is newer.
- EXPECT_TRUE(service()->OnExternalExtensionFileFound(
- kGoodId,
- &newer_version,
- kInvalidPathToCrx,
- Manifest::EXTERNAL_PREF,
- kCreationFlags,
- kDontMarkAcknowledged,
- kDontInstallImmediately));
+ info->version.reset(new Version(newer_version));
+ EXPECT_TRUE(service()->OnExternalExtensionFileFound(*info));
EXPECT_TRUE(pending->IsIdPending(kGoodId));
// An external install for an even higher priority install source should
// succeed if the version is greater.
- EXPECT_TRUE(service()->OnExternalExtensionFileFound(
- kGoodId,
- &newer_version,
- kInvalidPathToCrx,
- Manifest::EXTERNAL_REGISTRY,
- kCreationFlags,
- kDontMarkAcknowledged,
- kDontInstallImmediately));
+ info->crx_location = Manifest::EXTERNAL_REGISTRY;
+ EXPECT_TRUE(service()->OnExternalExtensionFileFound(*info));
EXPECT_TRUE(pending->IsIdPending(kGoodId));
// Because EXTERNAL_PREF is a lower priority source than EXTERNAL_REGISTRY,
// adding from external pref will now fail.
- EXPECT_FALSE(service()->OnExternalExtensionFileFound(
- kGoodId,
- &newer_version,
- kInvalidPathToCrx,
- Manifest::EXTERNAL_PREF,
- kCreationFlags,
- kDontMarkAcknowledged,
- kDontInstallImmediately));
+ info->crx_location = Manifest::EXTERNAL_PREF;
+ EXPECT_FALSE(service()->OnExternalExtensionFileFound(*info));
EXPECT_TRUE(pending->IsIdPending(kGoodId));
}
@@ -5590,70 +5630,48 @@
EXPECT_FALSE(pending->IsIdPending(kGoodId));
// An external provider starts installing from a local crx.
- EXPECT_TRUE(service()->OnExternalExtensionFileFound(
- kGoodId,
- &kVersion123,
- kInvalidPathToCrx,
- Manifest::EXTERNAL_PREF,
- kCreationFlags,
- kDontMarkAcknowledged,
+ scoped_ptr<ExternalInstallInfoFile> info(new ExternalInstallInfoFile(
+ kGoodId, make_scoped_ptr(new Version(kVersion123)), kInvalidPathToCrx,
+ Manifest::EXTERNAL_PREF, kCreationFlags, kDontMarkAcknowledged,
kDontInstallImmediately));
- const extensions::PendingExtensionInfo* info;
- EXPECT_TRUE((info = pending->GetById(kGoodId)));
- EXPECT_TRUE(info->version().IsValid());
- EXPECT_EQ(info->version(), kVersion123);
+ EXPECT_TRUE(service()->OnExternalExtensionFileFound(*info));
+
+ const extensions::PendingExtensionInfo* pending_info;
+ EXPECT_TRUE((pending_info = pending->GetById(kGoodId)));
+ EXPECT_TRUE(pending_info->version().IsValid());
+ EXPECT_EQ(pending_info->version(), kVersion123);
// Adding a newer version overrides the currently pending version.
- EXPECT_TRUE(service()->OnExternalExtensionFileFound(
- kGoodId,
- &kVersion124,
- kInvalidPathToCrx,
- Manifest::EXTERNAL_PREF,
- kCreationFlags,
- kDontMarkAcknowledged,
- kDontInstallImmediately));
- EXPECT_TRUE((info = pending->GetById(kGoodId)));
- EXPECT_TRUE(info->version().IsValid());
- EXPECT_EQ(info->version(), kVersion124);
+ info->version.reset(new Version(kVersion124));
+ EXPECT_TRUE(service()->OnExternalExtensionFileFound(*info));
+ EXPECT_TRUE((pending_info = pending->GetById(kGoodId)));
+ EXPECT_TRUE(pending_info->version().IsValid());
+ EXPECT_EQ(pending_info->version(), kVersion124);
// Adding an older version fails.
- EXPECT_FALSE(service()->OnExternalExtensionFileFound(
- kGoodId,
- &kVersion123,
- kInvalidPathToCrx,
- Manifest::EXTERNAL_PREF,
- kCreationFlags,
- kDontMarkAcknowledged,
- kDontInstallImmediately));
- EXPECT_TRUE((info = pending->GetById(kGoodId)));
- EXPECT_TRUE(info->version().IsValid());
- EXPECT_EQ(info->version(), kVersion124);
+ info->version.reset(new Version(kVersion123));
+ EXPECT_FALSE(service()->OnExternalExtensionFileFound(*info));
+ EXPECT_TRUE((pending_info = pending->GetById(kGoodId)));
+ EXPECT_TRUE(pending_info->version().IsValid());
+ EXPECT_EQ(pending_info->version(), kVersion124);
// Adding an older version fails even when coming from a higher-priority
// location.
- EXPECT_FALSE(service()->OnExternalExtensionFileFound(
- kGoodId,
- &kVersion123,
- kInvalidPathToCrx,
- Manifest::EXTERNAL_REGISTRY,
- kCreationFlags,
- kDontMarkAcknowledged,
- kDontInstallImmediately));
- EXPECT_TRUE((info = pending->GetById(kGoodId)));
- EXPECT_TRUE(info->version().IsValid());
- EXPECT_EQ(info->version(), kVersion124);
+ info->crx_location = Manifest::EXTERNAL_REGISTRY;
+ EXPECT_FALSE(service()->OnExternalExtensionFileFound(*info));
+ EXPECT_TRUE((pending_info = pending->GetById(kGoodId)));
+ EXPECT_TRUE(pending_info->version().IsValid());
+ EXPECT_EQ(pending_info->version(), kVersion124);
// Adding the latest version from the webstore overrides a specific version.
GURL kUpdateUrl("http://example.com/update");
- EXPECT_TRUE(service()->OnExternalExtensionUpdateUrlFound(
- kGoodId,
- std::string(),
- kUpdateUrl,
- Manifest::EXTERNAL_POLICY_DOWNLOAD,
- Extension::NO_FLAGS,
- false));
- EXPECT_TRUE((info = pending->GetById(kGoodId)));
- EXPECT_FALSE(info->version().IsValid());
+ scoped_ptr<ExternalInstallInfoUpdateUrl> update_info(
+ new ExternalInstallInfoUpdateUrl(
+ kGoodId, std::string(), make_scoped_ptr(new GURL(kUpdateUrl)),
+ Manifest::EXTERNAL_POLICY_DOWNLOAD, Extension::NO_FLAGS, false));
+ EXPECT_TRUE(service()->OnExternalExtensionUpdateUrlFound(*update_info, true));
+ EXPECT_TRUE((pending_info = pending->GetById(kGoodId)));
+ EXPECT_FALSE(pending_info->version().IsValid());
}
// This makes sure we can package and install CRX files that use whitelisted
@@ -5704,15 +5722,11 @@
// Fake an external file from external_extensions.json.
bool AddPendingExternalPrefFileInstall() {
- Version version("1.0.0.0");
-
- return service()->OnExternalExtensionFileFound(crx_id_,
- &version,
- crx_path_,
- Manifest::EXTERNAL_PREF,
- Extension::NO_FLAGS,
- false,
- false);
+ scoped_ptr<Version> version(new Version("1.0.0.0"));
+ scoped_ptr<ExternalInstallInfoFile> info(new ExternalInstallInfoFile(
+ crx_id_, std::move(version), crx_path_, Manifest::EXTERNAL_PREF,
+ Extension::NO_FLAGS, false, false));
+ return service()->OnExternalExtensionFileFound(*info);
}
// Fake a request from sync to install an extension.
@@ -5729,13 +5743,12 @@
// Fake a policy install.
bool AddPendingPolicyInstall() {
// Get path to the CRX with id |kGoodId|.
- return service()->OnExternalExtensionUpdateUrlFound(
- crx_id_,
- std::string(),
- GURL(),
- Manifest::EXTERNAL_POLICY_DOWNLOAD,
- Extension::NO_FLAGS,
- false);
+ scoped_ptr<GURL> empty_url(new GURL());
+ scoped_ptr<ExternalInstallInfoUpdateUrl> info(
+ new ExternalInstallInfoUpdateUrl(
+ crx_id_, std::string(), std::move(empty_url),
+ Manifest::EXTERNAL_POLICY_DOWNLOAD, Extension::NO_FLAGS, false));
+ return service()->OnExternalExtensionUpdateUrlFound(*info, true);
}
// Get the install source of a pending extension.