blob: 0efcdbde46ecccd727ed0d12b527f1eef25ce3a6 [file] [log] [blame]
[email protected]eb75f7b2012-01-04 09:07:281// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]25ae0152011-11-18 14:40:022// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]25ae0152011-11-18 14:40:025#include "chrome/browser/extensions/component_loader.h"
6
avia2f4804a2015-12-24 23:11:137#include <stddef.h>
8
[email protected]443e9312013-05-06 06:17:349#include <string>
10
rlp997840ad2014-11-20 08:45:0311#include "base/command_line.h"
thestig18dfb7a52014-08-26 10:44:0412#include "base/files/file_util.h"
[email protected]25ae0152011-11-18 14:40:0213#include "base/path_service.h"
avia2f4804a2015-12-24 23:11:1314#include "build/build_config.h"
[email protected]25ae0152011-11-18 14:40:0215#include "chrome/browser/extensions/test_extension_service.h"
16#include "chrome/common/chrome_paths.h"
rlp997840ad2014-11-20 08:45:0317#include "chrome/common/chrome_switches.h"
[email protected]55e16cd2013-12-18 04:36:0818#include "chrome/test/base/testing_profile.h"
Gabriel Charettec7108742019-08-23 03:31:4019#include "content/public/test/browser_task_environment.h"
reillyga3acbc12014-11-11 23:17:1220#include "extensions/browser/extension_registry.h"
[email protected]993da5e2013-03-23 21:25:1621#include "extensions/common/constants.h"
[email protected]e4452d32013-11-15 23:07:4122#include "extensions/common/extension.h"
[email protected]289c44b2013-12-17 03:26:5723#include "extensions/common/extension_set.h"
[email protected]558878cc82013-11-09 01:25:5124#include "extensions/common/manifest_handlers/background_info.h"
[email protected]25ae0152011-11-18 14:40:0225#include "testing/gtest/include/gtest/gtest.h"
26
[email protected]06492ed2013-03-24 22:13:1427namespace extensions {
[email protected]1c321ee52012-05-21 03:02:3428
[email protected]25ae0152011-11-18 14:40:0229namespace {
30
31class MockExtensionService : public TestExtensionService {
32 private:
33 bool ready_;
[email protected]43cbd7592011-12-08 08:52:1034 size_t unloaded_count_;
reillyga3acbc12014-11-11 23:17:1235 ExtensionRegistry* registry_;
[email protected]25ae0152011-11-18 14:40:0236
37 public:
reillyga3acbc12014-11-11 23:17:1238 explicit MockExtensionService(Profile* profile)
39 : ready_(false),
40 unloaded_count_(0),
41 registry_(ExtensionRegistry::Get(profile)) {}
[email protected]25ae0152011-11-18 14:40:0242
dchengae36a4a2014-10-21 12:36:3643 void AddComponentExtension(const Extension* extension) override {
reillyga3acbc12014-11-11 23:17:1244 EXPECT_FALSE(registry_->enabled_extensions().Contains(extension->id()));
[email protected]25ae0152011-11-18 14:40:0245 // ExtensionService must become the owner of the extension object.
reillyga3acbc12014-11-11 23:17:1246 registry_->AddEnabled(extension);
[email protected]25ae0152011-11-18 14:40:0247 }
48
dchengae36a4a2014-10-21 12:36:3649 void UnloadExtension(const std::string& extension_id,
limasdf0deef2042017-05-03 19:17:1750 UnloadedExtensionReason reason) override {
reillyga3acbc12014-11-11 23:17:1251 ASSERT_TRUE(registry_->enabled_extensions().Contains(extension_id));
[email protected]25ae0152011-11-18 14:40:0252 // Remove the extension with the matching id.
reillyga3acbc12014-11-11 23:17:1253 registry_->RemoveEnabled(extension_id);
[email protected]43cbd7592011-12-08 08:52:1054 unloaded_count_++;
[email protected]25ae0152011-11-18 14:40:0255 }
56
dchengae36a4a2014-10-21 12:36:3657 void RemoveComponentExtension(const std::string& extension_id) override {
limasdf0deef2042017-05-03 19:17:1758 UnloadExtension(extension_id, UnloadedExtensionReason::DISABLE);
[email protected]8b1ec202013-09-05 02:09:5059 }
60
dchengae36a4a2014-10-21 12:36:3661 bool is_ready() override { return ready_; }
[email protected]25ae0152011-11-18 14:40:0262
[email protected]25ae0152011-11-18 14:40:0263 void set_ready(bool ready) {
64 ready_ = ready;
65 }
66
[email protected]43cbd7592011-12-08 08:52:1067 size_t unloaded_count() const {
68 return unloaded_count_;
69 }
70
reillyga3acbc12014-11-11 23:17:1271 void clear_extensions() { registry_->ClearAll(); }
[email protected]25ae0152011-11-18 14:40:0272};
73
74} // namespace
75
[email protected]d592b1bd2013-05-06 06:40:4776class ComponentLoaderTest : public testing::Test {
[email protected]25ae0152011-11-18 14:40:0277 public:
[email protected]e676f8f2013-04-04 09:04:3778 ComponentLoaderTest()
reillyga3acbc12014-11-11 23:17:1279 : extension_service_(&profile_),
80 component_loader_(&extension_service_,
jam726de9f2015-06-02 15:36:0681 &profile_) {
82 component_loader_.set_ignore_whitelist_for_testing(true);
83 }
[email protected]25ae0152011-11-18 14:40:0284
dcheng72191812014-10-28 20:49:5685 void SetUp() override {
[email protected]25ae0152011-11-18 14:40:0286 extension_path_ =
[email protected]43cbd7592011-12-08 08:52:1087 GetBasePath().AppendASCII("good")
[email protected]25ae0152011-11-18 14:40:0288 .AppendASCII("Extensions")
89 .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj")
90 .AppendASCII("1.0.0.0");
91
92 // Read in the extension manifest.
[email protected]82f84b92013-08-30 18:23:5093 ASSERT_TRUE(base::ReadFileToString(
[email protected]993da5e2013-03-23 21:25:1694 extension_path_.Append(kManifestFilename),
95 &manifest_contents_));
[email protected]25ae0152011-11-18 14:40:0296 }
97
98 protected:
Gabriel Charette798fde72019-08-20 22:24:0499 content::BrowserTaskEnvironment task_environment_;
reillyga3acbc12014-11-11 23:17:12100 TestingProfile profile_;
[email protected]25ae0152011-11-18 14:40:02101 MockExtensionService extension_service_;
[email protected]25ae0152011-11-18 14:40:02102 ComponentLoader component_loader_;
103
104 // The root directory of the text extension.
[email protected]650b2d52013-02-10 03:41:45105 base::FilePath extension_path_;
[email protected]25ae0152011-11-18 14:40:02106
107 // The contents of the text extension's manifest file.
108 std::string manifest_contents_;
[email protected]43cbd7592011-12-08 08:52:10109
[email protected]650b2d52013-02-10 03:41:45110 base::FilePath GetBasePath() {
111 base::FilePath test_data_dir;
Avi Drissman9098f9002018-05-04 00:11:52112 base::PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir);
[email protected]43cbd7592011-12-08 08:52:10113 return test_data_dir.AppendASCII("extensions");
114 }
[email protected]25ae0152011-11-18 14:40:02115};
116
117TEST_F(ComponentLoaderTest, ParseManifest) {
dchengc963c7142016-04-08 03:55:22118 std::unique_ptr<base::DictionaryValue> manifest;
[email protected]25ae0152011-11-18 14:40:02119
120 // Test invalid JSON.
lazyboyf4e5cdb2016-11-18 02:58:45121 manifest = component_loader_.ParseManifest("{ 'test': 3 } invalid");
122 EXPECT_FALSE(manifest);
[email protected]25ae0152011-11-18 14:40:02123
124 // Test manifests that are valid JSON, but don't have an object literal
125 // at the root. ParseManifest() should always return NULL.
126
lazyboyf4e5cdb2016-11-18 02:58:45127 manifest = component_loader_.ParseManifest(std::string());
128 EXPECT_FALSE(manifest);
[email protected]25ae0152011-11-18 14:40:02129
lazyboyf4e5cdb2016-11-18 02:58:45130 manifest = component_loader_.ParseManifest("[{ \"foo\": 3 }]");
131 EXPECT_FALSE(manifest);
[email protected]25ae0152011-11-18 14:40:02132
lazyboyf4e5cdb2016-11-18 02:58:45133 manifest = component_loader_.ParseManifest("\"Test\"");
134 EXPECT_FALSE(manifest);
[email protected]25ae0152011-11-18 14:40:02135
lazyboyf4e5cdb2016-11-18 02:58:45136 manifest = component_loader_.ParseManifest("42");
137 EXPECT_FALSE(manifest);
[email protected]25ae0152011-11-18 14:40:02138
lazyboyf4e5cdb2016-11-18 02:58:45139 manifest = component_loader_.ParseManifest("true");
140 EXPECT_FALSE(manifest);
[email protected]25ae0152011-11-18 14:40:02141
lazyboyf4e5cdb2016-11-18 02:58:45142 manifest = component_loader_.ParseManifest("false");
143 EXPECT_FALSE(manifest);
[email protected]25ae0152011-11-18 14:40:02144
lazyboyf4e5cdb2016-11-18 02:58:45145 manifest = component_loader_.ParseManifest("null");
146 EXPECT_FALSE(manifest);
[email protected]25ae0152011-11-18 14:40:02147
148 // Test parsing valid JSON.
149
[email protected]ee837d32012-10-02 22:25:49150 int value = 0;
lazyboyf4e5cdb2016-11-18 02:58:45151 manifest = component_loader_.ParseManifest(
152 "{ \"test\": { \"one\": 1 }, \"two\": 2 }");
153 ASSERT_TRUE(manifest);
[email protected]ee837d32012-10-02 22:25:49154 EXPECT_TRUE(manifest->GetInteger("test.one", &value));
155 EXPECT_EQ(1, value);
[email protected]25ae0152011-11-18 14:40:02156 ASSERT_TRUE(manifest->GetInteger("two", &value));
[email protected]ee837d32012-10-02 22:25:49157 EXPECT_EQ(2, value);
[email protected]25ae0152011-11-18 14:40:02158
159 std::string string_value;
lazyboyf4e5cdb2016-11-18 02:58:45160 manifest = component_loader_.ParseManifest(manifest_contents_);
[email protected]eb75f7b2012-01-04 09:07:28161 ASSERT_TRUE(manifest->GetString("background.page", &string_value));
[email protected]ee837d32012-10-02 22:25:49162 EXPECT_EQ("backgroundpage.html", string_value);
[email protected]25ae0152011-11-18 14:40:02163}
164
165// Test that the extension isn't loaded if the extension service isn't ready.
166TEST_F(ComponentLoaderTest, AddWhenNotReady) {
[email protected]25ae0152011-11-18 14:40:02167 extension_service_.set_ready(false);
[email protected]ee837d32012-10-02 22:25:49168 std::string extension_id =
169 component_loader_.Add(manifest_contents_, extension_path_);
170 EXPECT_NE("", extension_id);
reillyga3acbc12014-11-11 23:17:12171 ExtensionRegistry* registry = ExtensionRegistry::Get(&profile_);
172 EXPECT_EQ(0u, registry->enabled_extensions().size());
[email protected]25ae0152011-11-18 14:40:02173}
174
175// Test that it *is* loaded when the extension service *is* ready.
176TEST_F(ComponentLoaderTest, AddWhenReady) {
[email protected]25ae0152011-11-18 14:40:02177 extension_service_.set_ready(true);
[email protected]ee837d32012-10-02 22:25:49178 std::string extension_id =
179 component_loader_.Add(manifest_contents_, extension_path_);
180 EXPECT_NE("", extension_id);
reillyga3acbc12014-11-11 23:17:12181 ExtensionRegistry* registry = ExtensionRegistry::Get(&profile_);
182 EXPECT_EQ(1u, registry->enabled_extensions().size());
183 EXPECT_TRUE(registry->enabled_extensions().GetByID(extension_id));
[email protected]25ae0152011-11-18 14:40:02184}
185
186TEST_F(ComponentLoaderTest, Remove) {
187 extension_service_.set_ready(false);
reillyga3acbc12014-11-11 23:17:12188 ExtensionRegistry* registry = ExtensionRegistry::Get(&profile_);
[email protected]25ae0152011-11-18 14:40:02189
190 // Removing an extension that was never added should be ok.
191 component_loader_.Remove(extension_path_);
reillyga3acbc12014-11-11 23:17:12192 EXPECT_EQ(0u, registry->enabled_extensions().size());
[email protected]25ae0152011-11-18 14:40:02193
[email protected]eac88332012-12-26 17:57:45194 // Try adding and removing before LoadAll() is called.
[email protected]25ae0152011-11-18 14:40:02195 component_loader_.Add(manifest_contents_, extension_path_);
196 component_loader_.Remove(extension_path_);
[email protected]eac88332012-12-26 17:57:45197 component_loader_.LoadAll();
reillyga3acbc12014-11-11 23:17:12198 EXPECT_EQ(0u, registry->enabled_extensions().size());
[email protected]25ae0152011-11-18 14:40:02199
200 // Load an extension, and check that it's unloaded when Remove() is called.
[email protected]25ae0152011-11-18 14:40:02201 extension_service_.set_ready(true);
[email protected]ee837d32012-10-02 22:25:49202 std::string extension_id =
203 component_loader_.Add(manifest_contents_, extension_path_);
reillyga3acbc12014-11-11 23:17:12204 EXPECT_EQ(1u, registry->enabled_extensions().size());
[email protected]25ae0152011-11-18 14:40:02205 component_loader_.Remove(extension_path_);
reillyga3acbc12014-11-11 23:17:12206 EXPECT_EQ(0u, registry->enabled_extensions().size());
[email protected]25ae0152011-11-18 14:40:02207
[email protected]eac88332012-12-26 17:57:45208 // And after calling LoadAll(), it shouldn't get loaded.
209 component_loader_.LoadAll();
reillyga3acbc12014-11-11 23:17:12210 EXPECT_EQ(0u, registry->enabled_extensions().size());
[email protected]25ae0152011-11-18 14:40:02211}
212
213TEST_F(ComponentLoaderTest, LoadAll) {
214 extension_service_.set_ready(false);
reillyga3acbc12014-11-11 23:17:12215 ExtensionRegistry* registry = ExtensionRegistry::Get(&profile_);
[email protected]25ae0152011-11-18 14:40:02216
217 // No extensions should be loaded if none were added.
[email protected]eac88332012-12-26 17:57:45218 component_loader_.LoadAll();
reillyga3acbc12014-11-11 23:17:12219 EXPECT_EQ(0u, registry->enabled_extensions().size());
[email protected]25ae0152011-11-18 14:40:02220
[email protected]eac88332012-12-26 17:57:45221 // Use LoadAll() to load the default extensions.
[email protected]bb121482012-12-08 06:49:38222 component_loader_.AddDefaultComponentExtensions(false);
[email protected]eac88332012-12-26 17:57:45223 component_loader_.LoadAll();
reillyga3acbc12014-11-11 23:17:12224 unsigned int default_count = registry->enabled_extensions().size();
[email protected]25ae0152011-11-18 14:40:02225
226 // Clear the list of loaded extensions, and reload with one more.
[email protected]84df8332011-12-06 18:22:46227 extension_service_.clear_extensions();
[email protected]25ae0152011-11-18 14:40:02228 component_loader_.Add(manifest_contents_, extension_path_);
[email protected]eac88332012-12-26 17:57:45229 component_loader_.LoadAll();
[email protected]25ae0152011-11-18 14:40:02230
reillyga3acbc12014-11-11 23:17:12231 EXPECT_EQ(default_count + 1, registry->enabled_extensions().size());
[email protected]25ae0152011-11-18 14:40:02232}
233
[email protected]43cbd7592011-12-08 08:52:10234TEST_F(ComponentLoaderTest, AddOrReplace) {
[email protected]ee837d32012-10-02 22:25:49235 EXPECT_EQ(0u, component_loader_.registered_extensions_count());
[email protected]bb121482012-12-08 06:49:38236 component_loader_.AddDefaultComponentExtensions(false);
[email protected]43cbd7592011-12-08 08:52:10237 size_t const default_count = component_loader_.registered_extensions_count();
[email protected]650b2d52013-02-10 03:41:45238 base::FilePath known_extension = GetBasePath()
[email protected]43cbd7592011-12-08 08:52:10239 .AppendASCII("override_component_extension");
calamityae7fed42017-06-22 04:58:22240 base::FilePath unknown_extension = extension_path_;
robca0af322014-12-08 12:42:59241 base::FilePath invalid_extension = GetBasePath()
242 .AppendASCII("this_path_does_not_exist");
[email protected]43cbd7592011-12-08 08:52:10243
244 // Replace a default component extension.
245 component_loader_.AddOrReplace(known_extension);
calamityae7fed42017-06-22 04:58:22246 EXPECT_EQ(default_count, component_loader_.registered_extensions_count());
[email protected]43cbd7592011-12-08 08:52:10247
248 // Add a new component extension.
calamityae7fed42017-06-22 04:58:22249 component_loader_.AddOrReplace(unknown_extension);
250 EXPECT_EQ(default_count + 1, component_loader_.registered_extensions_count());
[email protected]43cbd7592011-12-08 08:52:10251
252 extension_service_.set_ready(true);
[email protected]eac88332012-12-26 17:57:45253 component_loader_.LoadAll();
reillyga3acbc12014-11-11 23:17:12254 ExtensionRegistry* registry = ExtensionRegistry::Get(&profile_);
[email protected]43cbd7592011-12-08 08:52:10255
reillyga3acbc12014-11-11 23:17:12256 EXPECT_EQ(default_count + 1, registry->enabled_extensions().size());
[email protected]ee837d32012-10-02 22:25:49257 EXPECT_EQ(0u, extension_service_.unloaded_count());
[email protected]43cbd7592011-12-08 08:52:10258
259 // replace loaded component extension.
260 component_loader_.AddOrReplace(known_extension);
reillyga3acbc12014-11-11 23:17:12261 EXPECT_EQ(default_count + 1, registry->enabled_extensions().size());
[email protected]ee837d32012-10-02 22:25:49262 EXPECT_EQ(1u, extension_service_.unloaded_count());
[email protected]5583c052013-05-29 02:18:22263
264 // Add an invalid component extension.
265 std::string extension_id = component_loader_.AddOrReplace(invalid_extension);
266 EXPECT_TRUE(extension_id.empty());
[email protected]43cbd7592011-12-08 08:52:10267}
268
[email protected]25ae0152011-11-18 14:40:02269} // namespace extensions