blob: 55d592c0955e7cd1f8099353c7de432355322a95 [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
[email protected]443e9312013-05-06 06:17:347#include <string>
8
thestig18dfb7a52014-08-26 10:44:049#include "base/files/file_util.h"
[email protected]25ae0152011-11-18 14:40:0210#include "base/path_service.h"
[email protected]3853a4c2013-02-11 17:15:5711#include "base/prefs/pref_registry_simple.h"
[email protected]25ae0152011-11-18 14:40:0212#include "chrome/browser/extensions/test_extension_service.h"
13#include "chrome/common/chrome_paths.h"
[email protected]25ae0152011-11-18 14:40:0214#include "chrome/common/pref_names.h"
[email protected]7688968a2013-02-12 21:45:1315#include "chrome/test/base/testing_pref_service_syncable.h"
[email protected]55e16cd2013-12-18 04:36:0816#include "chrome/test/base/testing_profile.h"
[email protected]f0c8c4992014-05-15 17:37:2617#include "components/pref_registry/pref_registry_syncable.h"
[email protected]75181f62014-03-19 21:41:1218#include "content/public/test/test_browser_thread_bundle.h"
reillyga3acbc12014-11-11 23:17:1219#include "extensions/browser/extension_registry.h"
[email protected]993da5e2013-03-23 21:25:1620#include "extensions/common/constants.h"
[email protected]e4452d32013-11-15 23:07:4121#include "extensions/common/extension.h"
[email protected]289c44b2013-12-17 03:26:5722#include "extensions/common/extension_set.h"
[email protected]558878cc82013-11-09 01:25:5123#include "extensions/common/manifest_handlers/background_info.h"
[email protected]25ae0152011-11-18 14:40:0224#include "testing/gtest/include/gtest/gtest.h"
25
[email protected]06492ed2013-03-24 22:13:1426namespace extensions {
[email protected]1c321ee52012-05-21 03:02:3427
[email protected]25ae0152011-11-18 14:40:0228namespace {
29
30class MockExtensionService : public TestExtensionService {
31 private:
32 bool ready_;
[email protected]43cbd7592011-12-08 08:52:1033 size_t unloaded_count_;
reillyga3acbc12014-11-11 23:17:1234 ExtensionRegistry* registry_;
[email protected]25ae0152011-11-18 14:40:0235
36 public:
reillyga3acbc12014-11-11 23:17:1237 explicit MockExtensionService(Profile* profile)
38 : ready_(false),
39 unloaded_count_(0),
40 registry_(ExtensionRegistry::Get(profile)) {}
[email protected]25ae0152011-11-18 14:40:0241
dchengae36a4a2014-10-21 12:36:3642 void AddComponentExtension(const Extension* extension) override {
reillyga3acbc12014-11-11 23:17:1243 EXPECT_FALSE(registry_->enabled_extensions().Contains(extension->id()));
[email protected]25ae0152011-11-18 14:40:0244 // ExtensionService must become the owner of the extension object.
reillyga3acbc12014-11-11 23:17:1245 registry_->AddEnabled(extension);
[email protected]25ae0152011-11-18 14:40:0246 }
47
dchengae36a4a2014-10-21 12:36:3648 void UnloadExtension(const std::string& extension_id,
49 UnloadedExtensionInfo::Reason reason) override {
reillyga3acbc12014-11-11 23:17:1250 ASSERT_TRUE(registry_->enabled_extensions().Contains(extension_id));
[email protected]25ae0152011-11-18 14:40:0251 // Remove the extension with the matching id.
reillyga3acbc12014-11-11 23:17:1252 registry_->RemoveEnabled(extension_id);
[email protected]43cbd7592011-12-08 08:52:1053 unloaded_count_++;
[email protected]25ae0152011-11-18 14:40:0254 }
55
dchengae36a4a2014-10-21 12:36:3656 void RemoveComponentExtension(const std::string& extension_id) override {
[email protected]b0af4792013-10-23 09:12:1357 UnloadExtension(extension_id, UnloadedExtensionInfo::REASON_DISABLE);
[email protected]8b1ec202013-09-05 02:09:5058 }
59
dchengae36a4a2014-10-21 12:36:3660 bool is_ready() override { return ready_; }
[email protected]25ae0152011-11-18 14:40:0261
[email protected]25ae0152011-11-18 14:40:0262 void set_ready(bool ready) {
63 ready_ = ready;
64 }
65
[email protected]43cbd7592011-12-08 08:52:1066 size_t unloaded_count() const {
67 return unloaded_count_;
68 }
69
reillyga3acbc12014-11-11 23:17:1270 void clear_extensions() { registry_->ClearAll(); }
[email protected]25ae0152011-11-18 14:40:0271};
72
73} // namespace
74
[email protected]d592b1bd2013-05-06 06:40:4775class ComponentLoaderTest : public testing::Test {
[email protected]25ae0152011-11-18 14:40:0276 public:
[email protected]e676f8f2013-04-04 09:04:3777 ComponentLoaderTest()
[email protected]25ae0152011-11-18 14:40:0278 // Note: we pass the same pref service here, to stand in for both
79 // user prefs and local state.
reillyga3acbc12014-11-11 23:17:1280 : extension_service_(&profile_),
81 component_loader_(&extension_service_,
[email protected]55e16cd2013-12-18 04:36:0882 &prefs_,
83 &local_state_,
reillyga3acbc12014-11-11 23:17:1284 &profile_) {}
[email protected]25ae0152011-11-18 14:40:0285
dcheng72191812014-10-28 20:49:5686 void SetUp() override {
[email protected]25ae0152011-11-18 14:40:0287 extension_path_ =
[email protected]43cbd7592011-12-08 08:52:1088 GetBasePath().AppendASCII("good")
[email protected]25ae0152011-11-18 14:40:0289 .AppendASCII("Extensions")
90 .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj")
91 .AppendASCII("1.0.0.0");
92
93 // Read in the extension manifest.
[email protected]82f84b92013-08-30 18:23:5094 ASSERT_TRUE(base::ReadFileToString(
[email protected]993da5e2013-03-23 21:25:1695 extension_path_.Append(kManifestFilename),
96 &manifest_contents_));
[email protected]25ae0152011-11-18 14:40:0297
[email protected]25ae0152011-11-18 14:40:0298 // Register the local state prefs.
99#if defined(OS_CHROMEOS)
[email protected]b1de2c72013-02-06 02:45:47100 local_state_.registry()->RegisterBooleanPref(
[email protected]ced247a2014-06-13 19:14:19101 prefs::kAccessibilitySpokenFeedbackEnabled, false);
[email protected]25ae0152011-11-18 14:40:02102#endif
103 }
104
105 protected:
reillyga3acbc12014-11-11 23:17:12106 TestingProfile profile_;
[email protected]25ae0152011-11-18 14:40:02107 MockExtensionService extension_service_;
[email protected]5b199522012-12-22 17:24:44108 TestingPrefServiceSyncable prefs_;
109 TestingPrefServiceSimple local_state_;
[email protected]25ae0152011-11-18 14:40:02110 ComponentLoader component_loader_;
111
112 // The root directory of the text extension.
[email protected]650b2d52013-02-10 03:41:45113 base::FilePath extension_path_;
[email protected]25ae0152011-11-18 14:40:02114
115 // The contents of the text extension's manifest file.
116 std::string manifest_contents_;
[email protected]43cbd7592011-12-08 08:52:10117
[email protected]75181f62014-03-19 21:41:12118 content::TestBrowserThreadBundle thread_bundle_;
119
[email protected]650b2d52013-02-10 03:41:45120 base::FilePath GetBasePath() {
121 base::FilePath test_data_dir;
[email protected]43cbd7592011-12-08 08:52:10122 PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir);
123 return test_data_dir.AppendASCII("extensions");
124 }
[email protected]25ae0152011-11-18 14:40:02125};
126
127TEST_F(ComponentLoaderTest, ParseManifest) {
[email protected]023b3d12013-12-23 18:46:49128 scoped_ptr<base::DictionaryValue> manifest;
[email protected]25ae0152011-11-18 14:40:02129
130 // Test invalid JSON.
131 manifest.reset(
132 component_loader_.ParseManifest("{ 'test': 3 } invalid"));
[email protected]ee837d32012-10-02 22:25:49133 EXPECT_FALSE(manifest.get());
[email protected]25ae0152011-11-18 14:40:02134
135 // Test manifests that are valid JSON, but don't have an object literal
136 // at the root. ParseManifest() should always return NULL.
137
[email protected]007b3f82013-04-09 08:46:45138 manifest.reset(component_loader_.ParseManifest(std::string()));
[email protected]ee837d32012-10-02 22:25:49139 EXPECT_FALSE(manifest.get());
[email protected]25ae0152011-11-18 14:40:02140
141 manifest.reset(component_loader_.ParseManifest("[{ \"foo\": 3 }]"));
[email protected]ee837d32012-10-02 22:25:49142 EXPECT_FALSE(manifest.get());
[email protected]25ae0152011-11-18 14:40:02143
144 manifest.reset(component_loader_.ParseManifest("\"Test\""));
[email protected]ee837d32012-10-02 22:25:49145 EXPECT_FALSE(manifest.get());
[email protected]25ae0152011-11-18 14:40:02146
147 manifest.reset(component_loader_.ParseManifest("42"));
[email protected]ee837d32012-10-02 22:25:49148 EXPECT_FALSE(manifest.get());
[email protected]25ae0152011-11-18 14:40:02149
150 manifest.reset(component_loader_.ParseManifest("true"));
[email protected]ee837d32012-10-02 22:25:49151 EXPECT_FALSE(manifest.get());
[email protected]25ae0152011-11-18 14:40:02152
153 manifest.reset(component_loader_.ParseManifest("false"));
[email protected]ee837d32012-10-02 22:25:49154 EXPECT_FALSE(manifest.get());
[email protected]25ae0152011-11-18 14:40:02155
156 manifest.reset(component_loader_.ParseManifest("null"));
[email protected]ee837d32012-10-02 22:25:49157 EXPECT_FALSE(manifest.get());
[email protected]25ae0152011-11-18 14:40:02158
159 // Test parsing valid JSON.
160
[email protected]ee837d32012-10-02 22:25:49161 int value = 0;
[email protected]25ae0152011-11-18 14:40:02162 manifest.reset(component_loader_.ParseManifest(
163 "{ \"test\": { \"one\": 1 }, \"two\": 2 }"));
[email protected]ee837d32012-10-02 22:25:49164 ASSERT_TRUE(manifest.get());
165 EXPECT_TRUE(manifest->GetInteger("test.one", &value));
166 EXPECT_EQ(1, value);
[email protected]25ae0152011-11-18 14:40:02167 ASSERT_TRUE(manifest->GetInteger("two", &value));
[email protected]ee837d32012-10-02 22:25:49168 EXPECT_EQ(2, value);
[email protected]25ae0152011-11-18 14:40:02169
170 std::string string_value;
171 manifest.reset(component_loader_.ParseManifest(manifest_contents_));
[email protected]eb75f7b2012-01-04 09:07:28172 ASSERT_TRUE(manifest->GetString("background.page", &string_value));
[email protected]ee837d32012-10-02 22:25:49173 EXPECT_EQ("backgroundpage.html", string_value);
[email protected]25ae0152011-11-18 14:40:02174}
175
176// Test that the extension isn't loaded if the extension service isn't ready.
177TEST_F(ComponentLoaderTest, AddWhenNotReady) {
[email protected]25ae0152011-11-18 14:40:02178 extension_service_.set_ready(false);
[email protected]ee837d32012-10-02 22:25:49179 std::string extension_id =
180 component_loader_.Add(manifest_contents_, extension_path_);
181 EXPECT_NE("", extension_id);
reillyga3acbc12014-11-11 23:17:12182 ExtensionRegistry* registry = ExtensionRegistry::Get(&profile_);
183 EXPECT_EQ(0u, registry->enabled_extensions().size());
[email protected]25ae0152011-11-18 14:40:02184}
185
186// Test that it *is* loaded when the extension service *is* ready.
187TEST_F(ComponentLoaderTest, AddWhenReady) {
[email protected]25ae0152011-11-18 14:40:02188 extension_service_.set_ready(true);
[email protected]ee837d32012-10-02 22:25:49189 std::string extension_id =
190 component_loader_.Add(manifest_contents_, extension_path_);
191 EXPECT_NE("", extension_id);
reillyga3acbc12014-11-11 23:17:12192 ExtensionRegistry* registry = ExtensionRegistry::Get(&profile_);
193 EXPECT_EQ(1u, registry->enabled_extensions().size());
194 EXPECT_TRUE(registry->enabled_extensions().GetByID(extension_id));
[email protected]25ae0152011-11-18 14:40:02195}
196
197TEST_F(ComponentLoaderTest, Remove) {
198 extension_service_.set_ready(false);
reillyga3acbc12014-11-11 23:17:12199 ExtensionRegistry* registry = ExtensionRegistry::Get(&profile_);
[email protected]25ae0152011-11-18 14:40:02200
201 // Removing an extension that was never added should be ok.
202 component_loader_.Remove(extension_path_);
reillyga3acbc12014-11-11 23:17:12203 EXPECT_EQ(0u, registry->enabled_extensions().size());
[email protected]25ae0152011-11-18 14:40:02204
[email protected]eac88332012-12-26 17:57:45205 // Try adding and removing before LoadAll() is called.
[email protected]25ae0152011-11-18 14:40:02206 component_loader_.Add(manifest_contents_, extension_path_);
207 component_loader_.Remove(extension_path_);
[email protected]eac88332012-12-26 17:57:45208 component_loader_.LoadAll();
reillyga3acbc12014-11-11 23:17:12209 EXPECT_EQ(0u, registry->enabled_extensions().size());
[email protected]25ae0152011-11-18 14:40:02210
211 // Load an extension, and check that it's unloaded when Remove() is called.
[email protected]25ae0152011-11-18 14:40:02212 extension_service_.set_ready(true);
[email protected]ee837d32012-10-02 22:25:49213 std::string extension_id =
214 component_loader_.Add(manifest_contents_, extension_path_);
reillyga3acbc12014-11-11 23:17:12215 EXPECT_EQ(1u, registry->enabled_extensions().size());
[email protected]25ae0152011-11-18 14:40:02216 component_loader_.Remove(extension_path_);
reillyga3acbc12014-11-11 23:17:12217 EXPECT_EQ(0u, registry->enabled_extensions().size());
[email protected]25ae0152011-11-18 14:40:02218
[email protected]eac88332012-12-26 17:57:45219 // And after calling LoadAll(), it shouldn't get loaded.
220 component_loader_.LoadAll();
reillyga3acbc12014-11-11 23:17:12221 EXPECT_EQ(0u, registry->enabled_extensions().size());
[email protected]25ae0152011-11-18 14:40:02222}
223
224TEST_F(ComponentLoaderTest, LoadAll) {
225 extension_service_.set_ready(false);
reillyga3acbc12014-11-11 23:17:12226 ExtensionRegistry* registry = ExtensionRegistry::Get(&profile_);
[email protected]25ae0152011-11-18 14:40:02227
228 // No extensions should be loaded if none were added.
[email protected]eac88332012-12-26 17:57:45229 component_loader_.LoadAll();
reillyga3acbc12014-11-11 23:17:12230 EXPECT_EQ(0u, registry->enabled_extensions().size());
[email protected]25ae0152011-11-18 14:40:02231
[email protected]eac88332012-12-26 17:57:45232 // Use LoadAll() to load the default extensions.
[email protected]bb121482012-12-08 06:49:38233 component_loader_.AddDefaultComponentExtensions(false);
[email protected]eac88332012-12-26 17:57:45234 component_loader_.LoadAll();
reillyga3acbc12014-11-11 23:17:12235 unsigned int default_count = registry->enabled_extensions().size();
[email protected]25ae0152011-11-18 14:40:02236
237 // Clear the list of loaded extensions, and reload with one more.
[email protected]84df8332011-12-06 18:22:46238 extension_service_.clear_extensions();
[email protected]25ae0152011-11-18 14:40:02239 component_loader_.Add(manifest_contents_, extension_path_);
[email protected]eac88332012-12-26 17:57:45240 component_loader_.LoadAll();
[email protected]25ae0152011-11-18 14:40:02241
reillyga3acbc12014-11-11 23:17:12242 EXPECT_EQ(default_count + 1, registry->enabled_extensions().size());
[email protected]25ae0152011-11-18 14:40:02243}
244
[email protected]43cbd7592011-12-08 08:52:10245TEST_F(ComponentLoaderTest, AddOrReplace) {
[email protected]ee837d32012-10-02 22:25:49246 EXPECT_EQ(0u, component_loader_.registered_extensions_count());
[email protected]bb121482012-12-08 06:49:38247 component_loader_.AddDefaultComponentExtensions(false);
[email protected]43cbd7592011-12-08 08:52:10248 size_t const default_count = component_loader_.registered_extensions_count();
[email protected]650b2d52013-02-10 03:41:45249 base::FilePath known_extension = GetBasePath()
[email protected]43cbd7592011-12-08 08:52:10250 .AppendASCII("override_component_extension");
[email protected]650b2d52013-02-10 03:41:45251 base::FilePath unknow_extension = extension_path_;
[email protected]5583c052013-05-29 02:18:22252 base::FilePath invalid_extension = GetBasePath().AppendASCII("bad");
[email protected]43cbd7592011-12-08 08:52:10253
254 // Replace a default component extension.
255 component_loader_.AddOrReplace(known_extension);
[email protected]ee837d32012-10-02 22:25:49256 EXPECT_EQ(default_count,
[email protected]43cbd7592011-12-08 08:52:10257 component_loader_.registered_extensions_count());
258
259 // Add a new component extension.
260 component_loader_.AddOrReplace(unknow_extension);
[email protected]ee837d32012-10-02 22:25:49261 EXPECT_EQ(default_count + 1,
[email protected]43cbd7592011-12-08 08:52:10262 component_loader_.registered_extensions_count());
263
264 extension_service_.set_ready(true);
[email protected]eac88332012-12-26 17:57:45265 component_loader_.LoadAll();
reillyga3acbc12014-11-11 23:17:12266 ExtensionRegistry* registry = ExtensionRegistry::Get(&profile_);
[email protected]43cbd7592011-12-08 08:52:10267
reillyga3acbc12014-11-11 23:17:12268 EXPECT_EQ(default_count + 1, registry->enabled_extensions().size());
[email protected]ee837d32012-10-02 22:25:49269 EXPECT_EQ(0u, extension_service_.unloaded_count());
[email protected]43cbd7592011-12-08 08:52:10270
271 // replace loaded component extension.
272 component_loader_.AddOrReplace(known_extension);
reillyga3acbc12014-11-11 23:17:12273 EXPECT_EQ(default_count + 1, registry->enabled_extensions().size());
[email protected]ee837d32012-10-02 22:25:49274 EXPECT_EQ(1u, extension_service_.unloaded_count());
[email protected]5583c052013-05-29 02:18:22275
276 // Add an invalid component extension.
277 std::string extension_id = component_loader_.AddOrReplace(invalid_extension);
278 EXPECT_TRUE(extension_id.empty());
[email protected]43cbd7592011-12-08 08:52:10279}
280
[email protected]25ae0152011-11-18 14:40:02281} // namespace extensions