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/file_util.h"
10 #include "base/path_service.h"
11 #include "base/prefs/pref_registry_simple.h"
12 #include "chrome/browser/extensions/test_extension_service.h"
13 #include "chrome/common/chrome_paths.h"
14 #include "chrome/common/pref_names.h"
15 #include "chrome/test/base/testing_pref_service_syncable.h"
16 #include "chrome/test/base/testing_profile.h"
17 #include "components/pref_registry/pref_registry_syncable.h"
18 #include "content/public/test/test_browser_thread_bundle.h"
19 #include "extensions/common/constants.h"
20 #include "extensions/common/extension.h"
21 #include "extensions/common/extension_set.h"
22 #include "extensions/common/manifest_handlers/background_info.h"
23 #include "testing/gtest/include/gtest/gtest.h"
25 namespace extensions
{
29 class MockExtensionService
: public TestExtensionService
{
32 size_t unloaded_count_
;
33 ExtensionSet extension_set_
;
36 MockExtensionService() : ready_(false), unloaded_count_(0) {
39 virtual void AddComponentExtension(const Extension
* extension
) OVERRIDE
{
40 EXPECT_FALSE(extension_set_
.Contains(extension
->id()));
41 // ExtensionService must become the owner of the extension object.
42 extension_set_
.Insert(extension
);
45 virtual void UnloadExtension(
46 const std::string
& extension_id
,
47 UnloadedExtensionInfo::Reason reason
) OVERRIDE
{
48 ASSERT_TRUE(extension_set_
.Contains(extension_id
));
49 // Remove the extension with the matching id.
50 extension_set_
.Remove(extension_id
);
54 virtual void RemoveComponentExtension(const std::string
& extension_id
)
56 UnloadExtension(extension_id
, UnloadedExtensionInfo::REASON_DISABLE
);
59 virtual bool is_ready() OVERRIDE
{
63 virtual const ExtensionSet
* extensions() const OVERRIDE
{
64 return &extension_set_
;
67 void set_ready(bool ready
) {
71 size_t unloaded_count() const {
72 return unloaded_count_
;
75 void clear_extensions() {
76 extension_set_
.Clear();
82 class ComponentLoaderTest
: public testing::Test
{
85 // Note: we pass the same pref service here, to stand in for both
86 // user prefs and local state.
87 : component_loader_(&extension_service_
,
93 virtual void SetUp() OVERRIDE
{
95 GetBasePath().AppendASCII("good")
96 .AppendASCII("Extensions")
97 .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj")
98 .AppendASCII("1.0.0.0");
100 // Read in the extension manifest.
101 ASSERT_TRUE(base::ReadFileToString(
102 extension_path_
.Append(kManifestFilename
),
103 &manifest_contents_
));
105 // Register the local state prefs.
106 #if defined(OS_CHROMEOS)
107 local_state_
.registry()->RegisterBooleanPref(
108 prefs::kSpokenFeedbackEnabled
, false);
113 MockExtensionService extension_service_
;
114 TestingPrefServiceSyncable prefs_
;
115 TestingPrefServiceSimple local_state_
;
116 TestingProfile profile_
;
117 ComponentLoader component_loader_
;
119 // The root directory of the text extension.
120 base::FilePath extension_path_
;
122 // The contents of the text extension's manifest file.
123 std::string manifest_contents_
;
125 content::TestBrowserThreadBundle thread_bundle_
;
127 base::FilePath
GetBasePath() {
128 base::FilePath test_data_dir
;
129 PathService::Get(chrome::DIR_TEST_DATA
, &test_data_dir
);
130 return test_data_dir
.AppendASCII("extensions");
134 TEST_F(ComponentLoaderTest
, ParseManifest
) {
135 scoped_ptr
<base::DictionaryValue
> manifest
;
137 // Test invalid JSON.
139 component_loader_
.ParseManifest("{ 'test': 3 } invalid"));
140 EXPECT_FALSE(manifest
.get());
142 // Test manifests that are valid JSON, but don't have an object literal
143 // at the root. ParseManifest() should always return NULL.
145 manifest
.reset(component_loader_
.ParseManifest(std::string()));
146 EXPECT_FALSE(manifest
.get());
148 manifest
.reset(component_loader_
.ParseManifest("[{ \"foo\": 3 }]"));
149 EXPECT_FALSE(manifest
.get());
151 manifest
.reset(component_loader_
.ParseManifest("\"Test\""));
152 EXPECT_FALSE(manifest
.get());
154 manifest
.reset(component_loader_
.ParseManifest("42"));
155 EXPECT_FALSE(manifest
.get());
157 manifest
.reset(component_loader_
.ParseManifest("true"));
158 EXPECT_FALSE(manifest
.get());
160 manifest
.reset(component_loader_
.ParseManifest("false"));
161 EXPECT_FALSE(manifest
.get());
163 manifest
.reset(component_loader_
.ParseManifest("null"));
164 EXPECT_FALSE(manifest
.get());
166 // Test parsing valid JSON.
169 manifest
.reset(component_loader_
.ParseManifest(
170 "{ \"test\": { \"one\": 1 }, \"two\": 2 }"));
171 ASSERT_TRUE(manifest
.get());
172 EXPECT_TRUE(manifest
->GetInteger("test.one", &value
));
174 ASSERT_TRUE(manifest
->GetInteger("two", &value
));
177 std::string string_value
;
178 manifest
.reset(component_loader_
.ParseManifest(manifest_contents_
));
179 ASSERT_TRUE(manifest
->GetString("background.page", &string_value
));
180 EXPECT_EQ("backgroundpage.html", string_value
);
183 // Test that the extension isn't loaded if the extension service isn't ready.
184 TEST_F(ComponentLoaderTest
, AddWhenNotReady
) {
185 extension_service_
.set_ready(false);
186 std::string extension_id
=
187 component_loader_
.Add(manifest_contents_
, extension_path_
);
188 EXPECT_NE("", extension_id
);
189 EXPECT_EQ(0u, extension_service_
.extensions()->size());
192 // Test that it *is* loaded when the extension service *is* ready.
193 TEST_F(ComponentLoaderTest
, AddWhenReady
) {
194 extension_service_
.set_ready(true);
195 std::string extension_id
=
196 component_loader_
.Add(manifest_contents_
, extension_path_
);
197 EXPECT_NE("", extension_id
);
198 EXPECT_EQ(1u, extension_service_
.extensions()->size());
199 EXPECT_TRUE(extension_service_
.extensions()->GetByID(extension_id
));
202 TEST_F(ComponentLoaderTest
, Remove
) {
203 extension_service_
.set_ready(false);
205 // Removing an extension that was never added should be ok.
206 component_loader_
.Remove(extension_path_
);
207 EXPECT_EQ(0u, extension_service_
.extensions()->size());
209 // Try adding and removing before LoadAll() is called.
210 component_loader_
.Add(manifest_contents_
, extension_path_
);
211 component_loader_
.Remove(extension_path_
);
212 component_loader_
.LoadAll();
213 EXPECT_EQ(0u, extension_service_
.extensions()->size());
215 // Load an extension, and check that it's unloaded when Remove() is called.
216 extension_service_
.set_ready(true);
217 std::string extension_id
=
218 component_loader_
.Add(manifest_contents_
, extension_path_
);
219 EXPECT_EQ(1u, extension_service_
.extensions()->size());
220 component_loader_
.Remove(extension_path_
);
221 EXPECT_EQ(0u, extension_service_
.extensions()->size());
223 // And after calling LoadAll(), it shouldn't get loaded.
224 component_loader_
.LoadAll();
225 EXPECT_EQ(0u, extension_service_
.extensions()->size());
228 TEST_F(ComponentLoaderTest
, LoadAll
) {
229 extension_service_
.set_ready(false);
231 // No extensions should be loaded if none were added.
232 component_loader_
.LoadAll();
233 EXPECT_EQ(0u, extension_service_
.extensions()->size());
235 // Use LoadAll() to load the default extensions.
236 component_loader_
.AddDefaultComponentExtensions(false);
237 component_loader_
.LoadAll();
238 unsigned int default_count
= extension_service_
.extensions()->size();
240 // Clear the list of loaded extensions, and reload with one more.
241 extension_service_
.clear_extensions();
242 component_loader_
.Add(manifest_contents_
, extension_path_
);
243 component_loader_
.LoadAll();
245 EXPECT_EQ(default_count
+ 1, extension_service_
.extensions()->size());
248 TEST_F(ComponentLoaderTest
, AddOrReplace
) {
249 EXPECT_EQ(0u, component_loader_
.registered_extensions_count());
250 component_loader_
.AddDefaultComponentExtensions(false);
251 size_t const default_count
= component_loader_
.registered_extensions_count();
252 base::FilePath known_extension
= GetBasePath()
253 .AppendASCII("override_component_extension");
254 base::FilePath unknow_extension
= extension_path_
;
255 base::FilePath invalid_extension
= GetBasePath().AppendASCII("bad");
257 // Replace a default component extension.
258 component_loader_
.AddOrReplace(known_extension
);
259 EXPECT_EQ(default_count
,
260 component_loader_
.registered_extensions_count());
262 // Add a new component extension.
263 component_loader_
.AddOrReplace(unknow_extension
);
264 EXPECT_EQ(default_count
+ 1,
265 component_loader_
.registered_extensions_count());
267 extension_service_
.set_ready(true);
268 component_loader_
.LoadAll();
270 EXPECT_EQ(default_count
+ 1, extension_service_
.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, extension_service_
.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