blob: a608afb72337b5b44bb366defd53d4f8ab0d1139 [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"
[email protected]993da5e2013-03-23 21:25:1619#include "extensions/common/constants.h"
[email protected]e4452d32013-11-15 23:07:4120#include "extensions/common/extension.h"
[email protected]289c44b2013-12-17 03:26:5721#include "extensions/common/extension_set.h"
[email protected]558878cc82013-11-09 01:25:5122#include "extensions/common/manifest_handlers/background_info.h"
[email protected]25ae0152011-11-18 14:40:0223#include "testing/gtest/include/gtest/gtest.h"
24
[email protected]06492ed2013-03-24 22:13:1425namespace extensions {
[email protected]1c321ee52012-05-21 03:02:3426
[email protected]25ae0152011-11-18 14:40:0227namespace {
28
29class MockExtensionService : public TestExtensionService {
30 private:
31 bool ready_;
[email protected]43cbd7592011-12-08 08:52:1032 size_t unloaded_count_;
[email protected]84df8332011-12-06 18:22:4633 ExtensionSet extension_set_;
[email protected]25ae0152011-11-18 14:40:0234
35 public:
[email protected]43cbd7592011-12-08 08:52:1036 MockExtensionService() : ready_(false), unloaded_count_(0) {
[email protected]25ae0152011-11-18 14:40:0237 }
38
dchengae36a4a2014-10-21 12:36:3639 void AddComponentExtension(const Extension* extension) override {
[email protected]61f5fc82012-02-15 20:10:4540 EXPECT_FALSE(extension_set_.Contains(extension->id()));
[email protected]25ae0152011-11-18 14:40:0241 // ExtensionService must become the owner of the extension object.
[email protected]84df8332011-12-06 18:22:4642 extension_set_.Insert(extension);
[email protected]25ae0152011-11-18 14:40:0243 }
44
dchengae36a4a2014-10-21 12:36:3645 void UnloadExtension(const std::string& extension_id,
46 UnloadedExtensionInfo::Reason reason) override {
[email protected]43cbd7592011-12-08 08:52:1047 ASSERT_TRUE(extension_set_.Contains(extension_id));
[email protected]25ae0152011-11-18 14:40:0248 // Remove the extension with the matching id.
[email protected]84df8332011-12-06 18:22:4649 extension_set_.Remove(extension_id);
[email protected]43cbd7592011-12-08 08:52:1050 unloaded_count_++;
[email protected]25ae0152011-11-18 14:40:0251 }
52
dchengae36a4a2014-10-21 12:36:3653 void RemoveComponentExtension(const std::string& extension_id) override {
[email protected]b0af4792013-10-23 09:12:1354 UnloadExtension(extension_id, UnloadedExtensionInfo::REASON_DISABLE);
[email protected]8b1ec202013-09-05 02:09:5055 }
56
dchengae36a4a2014-10-21 12:36:3657 bool is_ready() override { return ready_; }
[email protected]25ae0152011-11-18 14:40:0258
dchengae36a4a2014-10-21 12:36:3659 const ExtensionSet* extensions() const override { return &extension_set_; }
[email protected]25ae0152011-11-18 14:40:0260
61 void set_ready(bool ready) {
62 ready_ = ready;
63 }
64
[email protected]43cbd7592011-12-08 08:52:1065 size_t unloaded_count() const {
66 return unloaded_count_;
67 }
68
[email protected]84df8332011-12-06 18:22:4669 void clear_extensions() {
70 extension_set_.Clear();
[email protected]25ae0152011-11-18 14:40:0271 }
72};
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()
[email protected]25ae0152011-11-18 14:40:0279 // Note: we pass the same pref service here, to stand in for both
80 // user prefs and local state.
[email protected]55e16cd2013-12-18 04:36:0881 : component_loader_(&extension_service_,
82 &prefs_,
83 &local_state_,
84 &profile_) {
[email protected]25ae0152011-11-18 14:40:0285 }
86
dcheng72191812014-10-28 20:49:5687 void SetUp() override {
[email protected]25ae0152011-11-18 14:40:0288 extension_path_ =
[email protected]43cbd7592011-12-08 08:52:1089 GetBasePath().AppendASCII("good")
[email protected]25ae0152011-11-18 14:40:0290 .AppendASCII("Extensions")
91 .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj")
92 .AppendASCII("1.0.0.0");
93
94 // Read in the extension manifest.
[email protected]82f84b92013-08-30 18:23:5095 ASSERT_TRUE(base::ReadFileToString(
[email protected]993da5e2013-03-23 21:25:1696 extension_path_.Append(kManifestFilename),
97 &manifest_contents_));
[email protected]25ae0152011-11-18 14:40:0298
[email protected]25ae0152011-11-18 14:40:0299 // Register the local state prefs.
100#if defined(OS_CHROMEOS)
[email protected]b1de2c72013-02-06 02:45:47101 local_state_.registry()->RegisterBooleanPref(
[email protected]ced247a2014-06-13 19:14:19102 prefs::kAccessibilitySpokenFeedbackEnabled, false);
[email protected]25ae0152011-11-18 14:40:02103#endif
104 }
105
106 protected:
107 MockExtensionService extension_service_;
[email protected]5b199522012-12-22 17:24:44108 TestingPrefServiceSyncable prefs_;
109 TestingPrefServiceSimple local_state_;
[email protected]55e16cd2013-12-18 04:36:08110 TestingProfile profile_;
[email protected]25ae0152011-11-18 14:40:02111 ComponentLoader component_loader_;
112
113 // The root directory of the text extension.
[email protected]650b2d52013-02-10 03:41:45114 base::FilePath extension_path_;
[email protected]25ae0152011-11-18 14:40:02115
116 // The contents of the text extension's manifest file.
117 std::string manifest_contents_;
[email protected]43cbd7592011-12-08 08:52:10118
[email protected]75181f62014-03-19 21:41:12119 content::TestBrowserThreadBundle thread_bundle_;
120
[email protected]650b2d52013-02-10 03:41:45121 base::FilePath GetBasePath() {
122 base::FilePath test_data_dir;
[email protected]43cbd7592011-12-08 08:52:10123 PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir);
124 return test_data_dir.AppendASCII("extensions");
125 }
[email protected]25ae0152011-11-18 14:40:02126};
127
128TEST_F(ComponentLoaderTest, ParseManifest) {
[email protected]023b3d12013-12-23 18:46:49129 scoped_ptr<base::DictionaryValue> manifest;
[email protected]25ae0152011-11-18 14:40:02130
131 // Test invalid JSON.
132 manifest.reset(
133 component_loader_.ParseManifest("{ 'test': 3 } invalid"));
[email protected]ee837d32012-10-02 22:25:49134 EXPECT_FALSE(manifest.get());
[email protected]25ae0152011-11-18 14:40:02135
136 // Test manifests that are valid JSON, but don't have an object literal
137 // at the root. ParseManifest() should always return NULL.
138
[email protected]007b3f82013-04-09 08:46:45139 manifest.reset(component_loader_.ParseManifest(std::string()));
[email protected]ee837d32012-10-02 22:25:49140 EXPECT_FALSE(manifest.get());
[email protected]25ae0152011-11-18 14:40:02141
142 manifest.reset(component_loader_.ParseManifest("[{ \"foo\": 3 }]"));
[email protected]ee837d32012-10-02 22:25:49143 EXPECT_FALSE(manifest.get());
[email protected]25ae0152011-11-18 14:40:02144
145 manifest.reset(component_loader_.ParseManifest("\"Test\""));
[email protected]ee837d32012-10-02 22:25:49146 EXPECT_FALSE(manifest.get());
[email protected]25ae0152011-11-18 14:40:02147
148 manifest.reset(component_loader_.ParseManifest("42"));
[email protected]ee837d32012-10-02 22:25:49149 EXPECT_FALSE(manifest.get());
[email protected]25ae0152011-11-18 14:40:02150
151 manifest.reset(component_loader_.ParseManifest("true"));
[email protected]ee837d32012-10-02 22:25:49152 EXPECT_FALSE(manifest.get());
[email protected]25ae0152011-11-18 14:40:02153
154 manifest.reset(component_loader_.ParseManifest("false"));
[email protected]ee837d32012-10-02 22:25:49155 EXPECT_FALSE(manifest.get());
[email protected]25ae0152011-11-18 14:40:02156
157 manifest.reset(component_loader_.ParseManifest("null"));
[email protected]ee837d32012-10-02 22:25:49158 EXPECT_FALSE(manifest.get());
[email protected]25ae0152011-11-18 14:40:02159
160 // Test parsing valid JSON.
161
[email protected]ee837d32012-10-02 22:25:49162 int value = 0;
[email protected]25ae0152011-11-18 14:40:02163 manifest.reset(component_loader_.ParseManifest(
164 "{ \"test\": { \"one\": 1 }, \"two\": 2 }"));
[email protected]ee837d32012-10-02 22:25:49165 ASSERT_TRUE(manifest.get());
166 EXPECT_TRUE(manifest->GetInteger("test.one", &value));
167 EXPECT_EQ(1, value);
[email protected]25ae0152011-11-18 14:40:02168 ASSERT_TRUE(manifest->GetInteger("two", &value));
[email protected]ee837d32012-10-02 22:25:49169 EXPECT_EQ(2, value);
[email protected]25ae0152011-11-18 14:40:02170
171 std::string string_value;
172 manifest.reset(component_loader_.ParseManifest(manifest_contents_));
[email protected]eb75f7b2012-01-04 09:07:28173 ASSERT_TRUE(manifest->GetString("background.page", &string_value));
[email protected]ee837d32012-10-02 22:25:49174 EXPECT_EQ("backgroundpage.html", string_value);
[email protected]25ae0152011-11-18 14:40:02175}
176
177// Test that the extension isn't loaded if the extension service isn't ready.
178TEST_F(ComponentLoaderTest, AddWhenNotReady) {
[email protected]25ae0152011-11-18 14:40:02179 extension_service_.set_ready(false);
[email protected]ee837d32012-10-02 22:25:49180 std::string extension_id =
181 component_loader_.Add(manifest_contents_, extension_path_);
182 EXPECT_NE("", extension_id);
183 EXPECT_EQ(0u, extension_service_.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);
192 EXPECT_EQ(1u, extension_service_.extensions()->size());
193 EXPECT_TRUE(extension_service_.extensions()->GetByID(extension_id));
[email protected]25ae0152011-11-18 14:40:02194}
195
196TEST_F(ComponentLoaderTest, Remove) {
197 extension_service_.set_ready(false);
198
199 // Removing an extension that was never added should be ok.
200 component_loader_.Remove(extension_path_);
[email protected]ee837d32012-10-02 22:25:49201 EXPECT_EQ(0u, extension_service_.extensions()->size());
[email protected]25ae0152011-11-18 14:40:02202
[email protected]eac88332012-12-26 17:57:45203 // Try adding and removing before LoadAll() is called.
[email protected]25ae0152011-11-18 14:40:02204 component_loader_.Add(manifest_contents_, extension_path_);
205 component_loader_.Remove(extension_path_);
[email protected]eac88332012-12-26 17:57:45206 component_loader_.LoadAll();
[email protected]ee837d32012-10-02 22:25:49207 EXPECT_EQ(0u, extension_service_.extensions()->size());
[email protected]25ae0152011-11-18 14:40:02208
209 // Load an extension, and check that it's unloaded when Remove() is called.
[email protected]25ae0152011-11-18 14:40:02210 extension_service_.set_ready(true);
[email protected]ee837d32012-10-02 22:25:49211 std::string extension_id =
212 component_loader_.Add(manifest_contents_, extension_path_);
213 EXPECT_EQ(1u, extension_service_.extensions()->size());
[email protected]25ae0152011-11-18 14:40:02214 component_loader_.Remove(extension_path_);
[email protected]ee837d32012-10-02 22:25:49215 EXPECT_EQ(0u, extension_service_.extensions()->size());
[email protected]25ae0152011-11-18 14:40:02216
[email protected]eac88332012-12-26 17:57:45217 // And after calling LoadAll(), it shouldn't get loaded.
218 component_loader_.LoadAll();
[email protected]ee837d32012-10-02 22:25:49219 EXPECT_EQ(0u, extension_service_.extensions()->size());
[email protected]25ae0152011-11-18 14:40:02220}
221
222TEST_F(ComponentLoaderTest, LoadAll) {
223 extension_service_.set_ready(false);
224
225 // No extensions should be loaded if none were added.
[email protected]eac88332012-12-26 17:57:45226 component_loader_.LoadAll();
[email protected]ee837d32012-10-02 22:25:49227 EXPECT_EQ(0u, extension_service_.extensions()->size());
[email protected]25ae0152011-11-18 14:40:02228
[email protected]eac88332012-12-26 17:57:45229 // Use LoadAll() to load the default extensions.
[email protected]bb121482012-12-08 06:49:38230 component_loader_.AddDefaultComponentExtensions(false);
[email protected]eac88332012-12-26 17:57:45231 component_loader_.LoadAll();
[email protected]25ae0152011-11-18 14:40:02232 unsigned int default_count = extension_service_.extensions()->size();
233
234 // Clear the list of loaded extensions, and reload with one more.
[email protected]84df8332011-12-06 18:22:46235 extension_service_.clear_extensions();
[email protected]25ae0152011-11-18 14:40:02236 component_loader_.Add(manifest_contents_, extension_path_);
[email protected]eac88332012-12-26 17:57:45237 component_loader_.LoadAll();
[email protected]25ae0152011-11-18 14:40:02238
[email protected]ee837d32012-10-02 22:25:49239 EXPECT_EQ(default_count + 1, extension_service_.extensions()->size());
[email protected]25ae0152011-11-18 14:40:02240}
241
[email protected]43cbd7592011-12-08 08:52:10242TEST_F(ComponentLoaderTest, AddOrReplace) {
[email protected]ee837d32012-10-02 22:25:49243 EXPECT_EQ(0u, component_loader_.registered_extensions_count());
[email protected]bb121482012-12-08 06:49:38244 component_loader_.AddDefaultComponentExtensions(false);
[email protected]43cbd7592011-12-08 08:52:10245 size_t const default_count = component_loader_.registered_extensions_count();
[email protected]650b2d52013-02-10 03:41:45246 base::FilePath known_extension = GetBasePath()
[email protected]43cbd7592011-12-08 08:52:10247 .AppendASCII("override_component_extension");
[email protected]650b2d52013-02-10 03:41:45248 base::FilePath unknow_extension = extension_path_;
[email protected]5583c052013-05-29 02:18:22249 base::FilePath invalid_extension = GetBasePath().AppendASCII("bad");
[email protected]43cbd7592011-12-08 08:52:10250
251 // Replace a default component extension.
252 component_loader_.AddOrReplace(known_extension);
[email protected]ee837d32012-10-02 22:25:49253 EXPECT_EQ(default_count,
[email protected]43cbd7592011-12-08 08:52:10254 component_loader_.registered_extensions_count());
255
256 // Add a new component extension.
257 component_loader_.AddOrReplace(unknow_extension);
[email protected]ee837d32012-10-02 22:25:49258 EXPECT_EQ(default_count + 1,
[email protected]43cbd7592011-12-08 08:52:10259 component_loader_.registered_extensions_count());
260
261 extension_service_.set_ready(true);
[email protected]eac88332012-12-26 17:57:45262 component_loader_.LoadAll();
[email protected]43cbd7592011-12-08 08:52:10263
[email protected]ee837d32012-10-02 22:25:49264 EXPECT_EQ(default_count + 1, extension_service_.extensions()->size());
265 EXPECT_EQ(0u, extension_service_.unloaded_count());
[email protected]43cbd7592011-12-08 08:52:10266
267 // replace loaded component extension.
268 component_loader_.AddOrReplace(known_extension);
[email protected]ee837d32012-10-02 22:25:49269 EXPECT_EQ(default_count + 1, extension_service_.extensions()->size());
270 EXPECT_EQ(1u, extension_service_.unloaded_count());
[email protected]5583c052013-05-29 02:18:22271
272 // Add an invalid component extension.
273 std::string extension_id = component_loader_.AddOrReplace(invalid_extension);
274 EXPECT_TRUE(extension_id.empty());
[email protected]43cbd7592011-12-08 08:52:10275}
276
[email protected]25ae0152011-11-18 14:40:02277} // namespace extensions