1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/extensions/component_loader.h"
9 #include "base/command_line.h"
10 #include "base/files/file_util.h"
11 #include "base/path_service.h"
12 #include "base/prefs/pref_registry_simple.h"
13 #include "chrome/browser/extensions/test_extension_service.h"
14 #include "chrome/common/chrome_paths.h"
15 #include "chrome/common/chrome_switches.h"
16 #include "chrome/common/pref_names.h"
17 #include "chrome/test/base/testing_pref_service_syncable.h"
18 #include "chrome/test/base/testing_profile.h"
19 #include "components/pref_registry/pref_registry_syncable.h"
20 #include "content/public/test/test_browser_thread_bundle.h"
21 #include "extensions/browser/extension_registry.h"
22 #include "extensions/common/constants.h"
23 #include "extensions/common/extension.h"
24 #include "extensions/common/extension_set.h"
25 #include "extensions/common/manifest_handlers/background_info.h"
26 #include "testing/gtest/include/gtest/gtest.h"
28 namespace extensions
{
32 class MockExtensionService
: public TestExtensionService
{
35 size_t unloaded_count_
;
36 ExtensionRegistry
* registry_
;
39 explicit MockExtensionService(Profile
* profile
)
42 registry_(ExtensionRegistry::Get(profile
)) {}
44 void AddComponentExtension(const Extension
* extension
) override
{
45 EXPECT_FALSE(registry_
->enabled_extensions().Contains(extension
->id()));
46 // ExtensionService must become the owner of the extension object.
47 registry_
->AddEnabled(extension
);
50 void UnloadExtension(const std::string
& extension_id
,
51 UnloadedExtensionInfo::Reason reason
) override
{
52 ASSERT_TRUE(registry_
->enabled_extensions().Contains(extension_id
));
53 // Remove the extension with the matching id.
54 registry_
->RemoveEnabled(extension_id
);
58 void RemoveComponentExtension(const std::string
& extension_id
) override
{
59 UnloadExtension(extension_id
, UnloadedExtensionInfo::REASON_DISABLE
);
62 bool is_ready() override
{ return ready_
; }
64 void set_ready(bool ready
) {
68 size_t unloaded_count() const {
69 return unloaded_count_
;
72 void clear_extensions() { registry_
->ClearAll(); }
77 class ComponentLoaderTest
: public testing::Test
{
80 // Note: we pass the same pref service here, to stand in for both
81 // user prefs and local state.
82 : extension_service_(&profile_
),
83 component_loader_(&extension_service_
,
88 void SetUp() override
{
90 GetBasePath().AppendASCII("good")
91 .AppendASCII("Extensions")
92 .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj")
93 .AppendASCII("1.0.0.0");
95 // Read in the extension manifest.
96 ASSERT_TRUE(base::ReadFileToString(
97 extension_path_
.Append(kManifestFilename
),
98 &manifest_contents_
));
100 // Register the local state prefs.
101 #if defined(OS_CHROMEOS)
102 local_state_
.registry()->RegisterBooleanPref(
103 prefs::kAccessibilitySpokenFeedbackEnabled
, false);
108 content::TestBrowserThreadBundle thread_bundle_
;
109 TestingProfile profile_
;
110 MockExtensionService extension_service_
;
111 TestingPrefServiceSyncable prefs_
;
112 TestingPrefServiceSimple local_state_
;
113 ComponentLoader component_loader_
;
115 // The root directory of the text extension.
116 base::FilePath extension_path_
;
118 // The contents of the text extension's manifest file.
119 std::string manifest_contents_
;
121 base::FilePath
GetBasePath() {
122 base::FilePath test_data_dir
;
123 PathService::Get(chrome::DIR_TEST_DATA
, &test_data_dir
);
124 return test_data_dir
.AppendASCII("extensions");
128 TEST_F(ComponentLoaderTest
, ParseManifest
) {
129 scoped_ptr
<base::DictionaryValue
> manifest
;
131 // Test invalid JSON.
133 component_loader_
.ParseManifest("{ 'test': 3 } invalid"));
134 EXPECT_FALSE(manifest
.get());
136 // Test manifests that are valid JSON, but don't have an object literal
137 // at the root. ParseManifest() should always return NULL.
139 manifest
.reset(component_loader_
.ParseManifest(std::string()));
140 EXPECT_FALSE(manifest
.get());
142 manifest
.reset(component_loader_
.ParseManifest("[{ \"foo\": 3 }]"));
143 EXPECT_FALSE(manifest
.get());
145 manifest
.reset(component_loader_
.ParseManifest("\"Test\""));
146 EXPECT_FALSE(manifest
.get());
148 manifest
.reset(component_loader_
.ParseManifest("42"));
149 EXPECT_FALSE(manifest
.get());
151 manifest
.reset(component_loader_
.ParseManifest("true"));
152 EXPECT_FALSE(manifest
.get());
154 manifest
.reset(component_loader_
.ParseManifest("false"));
155 EXPECT_FALSE(manifest
.get());
157 manifest
.reset(component_loader_
.ParseManifest("null"));
158 EXPECT_FALSE(manifest
.get());
160 // Test parsing valid JSON.
163 manifest
.reset(component_loader_
.ParseManifest(
164 "{ \"test\": { \"one\": 1 }, \"two\": 2 }"));
165 ASSERT_TRUE(manifest
.get());
166 EXPECT_TRUE(manifest
->GetInteger("test.one", &value
));
168 ASSERT_TRUE(manifest
->GetInteger("two", &value
));
171 std::string string_value
;
172 manifest
.reset(component_loader_
.ParseManifest(manifest_contents_
));
173 ASSERT_TRUE(manifest
->GetString("background.page", &string_value
));
174 EXPECT_EQ("backgroundpage.html", string_value
);
177 // Test that the extension isn't loaded if the extension service isn't ready.
178 TEST_F(ComponentLoaderTest
, AddWhenNotReady
) {
179 extension_service_
.set_ready(false);
180 std::string extension_id
=
181 component_loader_
.Add(manifest_contents_
, extension_path_
);
182 EXPECT_NE("", extension_id
);
183 ExtensionRegistry
* registry
= ExtensionRegistry::Get(&profile_
);
184 EXPECT_EQ(0u, registry
->enabled_extensions().size());
187 // Test that it *is* loaded when the extension service *is* ready.
188 TEST_F(ComponentLoaderTest
, AddWhenReady
) {
189 extension_service_
.set_ready(true);
190 std::string extension_id
=
191 component_loader_
.Add(manifest_contents_
, extension_path_
);
192 EXPECT_NE("", extension_id
);
193 ExtensionRegistry
* registry
= ExtensionRegistry::Get(&profile_
);
194 EXPECT_EQ(1u, registry
->enabled_extensions().size());
195 EXPECT_TRUE(registry
->enabled_extensions().GetByID(extension_id
));
198 TEST_F(ComponentLoaderTest
, Remove
) {
199 extension_service_
.set_ready(false);
200 ExtensionRegistry
* registry
= ExtensionRegistry::Get(&profile_
);
202 // Removing an extension that was never added should be ok.
203 component_loader_
.Remove(extension_path_
);
204 EXPECT_EQ(0u, registry
->enabled_extensions().size());
206 // Try adding and removing before LoadAll() is called.
207 component_loader_
.Add(manifest_contents_
, extension_path_
);
208 component_loader_
.Remove(extension_path_
);
209 component_loader_
.LoadAll();
210 EXPECT_EQ(0u, registry
->enabled_extensions().size());
212 // Load an extension, and check that it's unloaded when Remove() is called.
213 extension_service_
.set_ready(true);
214 std::string extension_id
=
215 component_loader_
.Add(manifest_contents_
, extension_path_
);
216 EXPECT_EQ(1u, registry
->enabled_extensions().size());
217 component_loader_
.Remove(extension_path_
);
218 EXPECT_EQ(0u, registry
->enabled_extensions().size());
220 // And after calling LoadAll(), it shouldn't get loaded.
221 component_loader_
.LoadAll();
222 EXPECT_EQ(0u, registry
->enabled_extensions().size());
225 TEST_F(ComponentLoaderTest
, LoadAll
) {
226 extension_service_
.set_ready(false);
227 ExtensionRegistry
* registry
= ExtensionRegistry::Get(&profile_
);
229 // No extensions should be loaded if none were added.
230 component_loader_
.LoadAll();
231 EXPECT_EQ(0u, registry
->enabled_extensions().size());
233 // Use LoadAll() to load the default extensions.
234 component_loader_
.AddDefaultComponentExtensions(false);
235 component_loader_
.LoadAll();
236 unsigned int default_count
= registry
->enabled_extensions().size();
238 // Clear the list of loaded extensions, and reload with one more.
239 extension_service_
.clear_extensions();
240 component_loader_
.Add(manifest_contents_
, extension_path_
);
241 component_loader_
.LoadAll();
243 EXPECT_EQ(default_count
+ 1, registry
->enabled_extensions().size());
246 TEST_F(ComponentLoaderTest
, AddOrReplace
) {
247 EXPECT_EQ(0u, component_loader_
.registered_extensions_count());
248 component_loader_
.AddDefaultComponentExtensions(false);
249 size_t const default_count
= component_loader_
.registered_extensions_count();
250 base::FilePath known_extension
= GetBasePath()
251 .AppendASCII("override_component_extension");
252 base::FilePath unknow_extension
= extension_path_
;
253 base::FilePath invalid_extension
= GetBasePath()
254 .AppendASCII("this_path_does_not_exist");
256 // Replace a default component extension.
257 component_loader_
.AddOrReplace(known_extension
);
258 EXPECT_EQ(default_count
,
259 component_loader_
.registered_extensions_count());
261 // Add a new component extension.
262 component_loader_
.AddOrReplace(unknow_extension
);
263 EXPECT_EQ(default_count
+ 1,
264 component_loader_
.registered_extensions_count());
266 extension_service_
.set_ready(true);
267 component_loader_
.LoadAll();
268 ExtensionRegistry
* registry
= ExtensionRegistry::Get(&profile_
);
270 EXPECT_EQ(default_count
+ 1, registry
->enabled_extensions().size());
271 EXPECT_EQ(0u, extension_service_
.unloaded_count());
273 // replace loaded component extension.
274 component_loader_
.AddOrReplace(known_extension
);
275 EXPECT_EQ(default_count
+ 1, registry
->enabled_extensions().size());
276 EXPECT_EQ(1u, extension_service_
.unloaded_count());
278 // Add an invalid component extension.
279 std::string extension_id
= component_loader_
.AddOrReplace(invalid_extension
);
280 EXPECT_TRUE(extension_id
.empty());
283 } // namespace extensions