blob: e82c03b8a5b649dd54e0c8bc88b55f83aac15ad1 [file] [log] [blame]
[email protected]f484f8d52014-06-12 08:38:181// Copyright 2014 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.
4
5#include "chrome/browser/extensions/extension_service_test_base.h"
6
dcheng1fc00f12015-12-26 22:18:037#include <utility>
8
[email protected]f484f8d52014-06-12 08:38:189#include "base/command_line.h"
thestig18dfb7a52014-08-26 10:44:0410#include "base/files/file_util.h"
[email protected]f484f8d52014-06-12 08:38:1811#include "base/memory/ref_counted.h"
[email protected]f484f8d52014-06-12 08:38:1812#include "base/path_service.h"
treib9afc6212015-10-30 18:49:5813#include "base/strings/string_number_conversions.h"
14#include "base/strings/stringprintf.h"
gabb15e19072016-05-11 20:45:4115#include "base/threading/thread_task_runner_handle.h"
avia2f4804a2015-12-24 23:11:1316#include "build/build_config.h"
jam726de9f2015-06-02 15:36:0617#include "chrome/browser/extensions/component_loader.h"
[email protected]f484f8d52014-06-12 08:38:1818#include "chrome/browser/extensions/extension_error_reporter.h"
19#include "chrome/browser/extensions/extension_garbage_collector_factory.h"
20#include "chrome/browser/extensions/extension_service.h"
xiyuanf6a4c6a62016-04-19 18:14:5421#include "chrome/browser/extensions/shared_module_service.h"
[email protected]f484f8d52014-06-12 08:38:1822#include "chrome/browser/extensions/test_extension_system.h"
23#include "chrome/browser/extensions/updater/extension_updater.h"
24#include "chrome/browser/prefs/browser_prefs.h"
[email protected]f484f8d52014-06-12 08:38:1825#include "chrome/common/chrome_constants.h"
26#include "chrome/common/chrome_paths.h"
anthonyvd404d6102015-02-28 00:04:2327#include "chrome/test/base/testing_browser_process.h"
[email protected]f484f8d52014-06-12 08:38:1828#include "chrome/test/base/testing_profile.h"
29#include "components/pref_registry/pref_registry_syncable.h"
maxbogueea16ff412016-10-28 16:35:2930#include "components/sync_preferences/pref_service_mock_factory.h"
31#include "components/sync_preferences/pref_service_syncable.h"
[email protected]f484f8d52014-06-12 08:38:1832#include "content/public/browser/browser_context.h"
33#include "extensions/browser/extension_prefs.h"
34#include "extensions/browser/extension_registry.h"
35
36#if defined(OS_CHROMEOS)
37#include "chrome/browser/chromeos/extensions/install_limiter.h"
38#endif
39
40namespace extensions {
41
42namespace {
43
rdevlin.cronin529ad1a92015-02-26 21:27:3044// By default, we run on the IO loop.
45const int kThreadOptions = content::TestBrowserThreadBundle::IO_MAINLOOP;
46
[email protected]f484f8d52014-06-12 08:38:1847// Create a testing profile according to |params|.
dchengc963c7142016-04-08 03:55:2248std::unique_ptr<TestingProfile> BuildTestingProfile(
[email protected]f484f8d52014-06-12 08:38:1849 const ExtensionServiceTestBase::ExtensionServiceInitParams& params) {
50 TestingProfile::Builder profile_builder;
51 // Create a PrefService that only contains user defined preference values.
maxbogueea16ff412016-10-28 16:35:2952 sync_preferences::PrefServiceMockFactory factory;
[email protected]f484f8d52014-06-12 08:38:1853 // If pref_file is empty, TestingProfile automatically creates
maxbogueea16ff412016-10-28 16:35:2954 // sync_preferences::TestingPrefServiceSyncable instance.
[email protected]f484f8d52014-06-12 08:38:1855 if (!params.pref_file.empty()) {
56 factory.SetUserPrefsFile(params.pref_file,
pranay.kumar07300782015-05-04 14:03:5857 base::ThreadTaskRunnerHandle::Get().get());
[email protected]f484f8d52014-06-12 08:38:1858 scoped_refptr<user_prefs::PrefRegistrySyncable> registry(
59 new user_prefs::PrefRegistrySyncable);
maxbogueea16ff412016-10-28 16:35:2960 std::unique_ptr<sync_preferences::PrefServiceSyncable> prefs(
[email protected]f484f8d52014-06-12 08:38:1861 factory.CreateSyncable(registry.get()));
62 chrome::RegisterUserProfilePrefs(registry.get());
dcheng1fc00f12015-12-26 22:18:0363 profile_builder.SetPrefService(std::move(prefs));
[email protected]f484f8d52014-06-12 08:38:1864 }
65
[email protected]d20d0432014-06-12 17:14:0566 if (params.profile_is_supervised)
67 profile_builder.SetSupervisedUserId("asdf");
[email protected]f484f8d52014-06-12 08:38:1868
69 profile_builder.SetPath(params.profile_path);
70 return profile_builder.Build();
71}
72
73} // namespace
74
75ExtensionServiceTestBase::ExtensionServiceInitParams::
rdevlin.cronin7217be52017-03-24 20:47:0576 ExtensionServiceInitParams() {}
[email protected]f484f8d52014-06-12 08:38:1877
vmpstrb8aacbe2016-02-26 02:00:4878ExtensionServiceTestBase::ExtensionServiceInitParams::
79 ExtensionServiceInitParams(const ExtensionServiceInitParams& other) =
80 default;
81
[email protected]f484f8d52014-06-12 08:38:1882ExtensionServiceTestBase::ExtensionServiceTestBase()
skyostil0becb332015-04-27 17:59:3783 : thread_bundle_(new content::TestBrowserThreadBundle(kThreadOptions)),
84 service_(NULL),
anthonyvd404d6102015-02-28 00:04:2385 testing_local_state_(TestingBrowserProcess::GetGlobal()),
rdevlin.cronin529ad1a92015-02-26 21:27:3086 did_reset_thread_bundle_(false),
[email protected]f484f8d52014-06-12 08:38:1887 registry_(NULL) {
88 base::FilePath test_data_dir;
89 if (!PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir)) {
90 ADD_FAILURE();
91 return;
92 }
93 data_dir_ = test_data_dir.AppendASCII("extensions");
94}
95
96ExtensionServiceTestBase::~ExtensionServiceTestBase() {
rdevlin.cronin529ad1a92015-02-26 21:27:3097 // Parts of destruction have to happen on an IO thread, so if the thread
98 // bundle is reset, we need to change it back.
99 if (did_reset_thread_bundle_)
100 ResetThreadBundle(kThreadOptions);
101
[email protected]f484f8d52014-06-12 08:38:18102 // Why? Because |profile_| has to be destroyed before |at_exit_manager_|, but
103 // is declared above it in the class definition since it's protected.
104 profile_.reset();
105}
106
107ExtensionServiceTestBase::ExtensionServiceInitParams
108ExtensionServiceTestBase::CreateDefaultInitParams() {
109 ExtensionServiceInitParams params;
110 EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
vabr9142fe22016-09-08 13:19:22111 base::FilePath path = temp_dir_.GetPath();
[email protected]f484f8d52014-06-12 08:38:18112 path = path.Append(FILE_PATH_LITERAL("TestingExtensionsPath"));
113 EXPECT_TRUE(base::DeleteFile(path, true));
114 base::File::Error error = base::File::FILE_OK;
115 EXPECT_TRUE(base::CreateDirectoryAndGetError(path, &error)) << error;
116 base::FilePath prefs_filename =
117 path.Append(FILE_PATH_LITERAL("TestPreferences"));
118 base::FilePath extensions_install_dir =
119 path.Append(FILE_PATH_LITERAL("Extensions"));
120 EXPECT_TRUE(base::DeleteFile(extensions_install_dir, true));
121 EXPECT_TRUE(base::CreateDirectoryAndGetError(extensions_install_dir, &error))
122 << error;
123
124 params.profile_path = path;
125 params.pref_file = prefs_filename;
126 params.extensions_install_dir = extensions_install_dir;
127 return params;
128}
129
130void ExtensionServiceTestBase::InitializeExtensionService(
131 const ExtensionServiceTestBase::ExtensionServiceInitParams& params) {
132 profile_ = BuildTestingProfile(params);
133 CreateExtensionService(params);
134
135 extensions_install_dir_ = params.extensions_install_dir;
136 registry_ = ExtensionRegistry::Get(profile_.get());
137
138 // Garbage collector is typically NULL during tests, so give it a build.
139 ExtensionGarbageCollectorFactory::GetInstance()->SetTestingFactoryAndUse(
140 profile_.get(), &ExtensionGarbageCollectorFactory::BuildInstanceFor);
141}
142
143void ExtensionServiceTestBase::InitializeEmptyExtensionService() {
144 InitializeExtensionService(CreateDefaultInitParams());
145}
146
147void ExtensionServiceTestBase::InitializeInstalledExtensionService(
148 const base::FilePath& prefs_file,
149 const base::FilePath& source_install_dir) {
150 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
vabr9142fe22016-09-08 13:19:22151 base::FilePath path = temp_dir_.GetPath();
[email protected]f484f8d52014-06-12 08:38:18152
153 path = path.Append(FILE_PATH_LITERAL("TestingExtensionsPath"));
154 ASSERT_TRUE(base::DeleteFile(path, true));
155
156 base::File::Error error = base::File::FILE_OK;
157 ASSERT_TRUE(base::CreateDirectoryAndGetError(path, &error)) << error;
158
159 base::FilePath temp_prefs = path.Append(chrome::kPreferencesFilename);
160 ASSERT_TRUE(base::CopyFile(prefs_file, temp_prefs));
161
162 base::FilePath extensions_install_dir =
163 path.Append(FILE_PATH_LITERAL("Extensions"));
164 ASSERT_TRUE(base::DeleteFile(extensions_install_dir, true));
165 ASSERT_TRUE(
166 base::CopyDirectory(source_install_dir, extensions_install_dir, true));
167
168 ExtensionServiceInitParams params;
169 params.profile_path = path;
170 params.pref_file = temp_prefs;
171 params.extensions_install_dir = extensions_install_dir;
172 InitializeExtensionService(params);
173}
174
175void ExtensionServiceTestBase::InitializeGoodInstalledExtensionService() {
176 base::FilePath source_install_dir =
177 data_dir_.AppendASCII("good").AppendASCII("Extensions");
178 base::FilePath pref_path =
179 source_install_dir.DirName().Append(chrome::kPreferencesFilename);
180 InitializeInstalledExtensionService(pref_path, source_install_dir);
181}
182
183void ExtensionServiceTestBase::InitializeExtensionServiceWithUpdater() {
184 ExtensionServiceInitParams params = CreateDefaultInitParams();
185 params.autoupdate_enabled = true;
186 InitializeExtensionService(params);
187 service_->updater()->Start();
[email protected]f484f8d52014-06-12 08:38:18188}
189
rdevlin.cronin7217be52017-03-24 20:47:05190void ExtensionServiceTestBase::
191 InitializeExtensionServiceWithExtensionsDisabled() {
192 ExtensionServiceInitParams params = CreateDefaultInitParams();
193 params.extensions_enabled = false;
194 InitializeExtensionService(params);
195}
196
rdevlin.cronin529ad1a92015-02-26 21:27:30197void ExtensionServiceTestBase::ResetThreadBundle(int options) {
198 did_reset_thread_bundle_ = true;
199 thread_bundle_.reset();
200 thread_bundle_.reset(new content::TestBrowserThreadBundle(options));
201}
202
treib9afc6212015-10-30 18:49:58203size_t ExtensionServiceTestBase::GetPrefKeyCount() {
204 const base::DictionaryValue* dict =
205 profile()->GetPrefs()->GetDictionary("extensions.settings");
206 if (!dict) {
207 ADD_FAILURE();
208 return 0;
209 }
210 return dict->size();
211}
212
213void ExtensionServiceTestBase::ValidatePrefKeyCount(size_t count) {
214 EXPECT_EQ(count, GetPrefKeyCount());
215}
216
217testing::AssertionResult ExtensionServiceTestBase::ValidateBooleanPref(
218 const std::string& extension_id,
219 const std::string& pref_path,
220 bool expected_val) {
221 std::string msg = base::StringPrintf("while checking: %s %s == %s",
222 extension_id.c_str(), pref_path.c_str(),
223 expected_val ? "true" : "false");
224
225 PrefService* prefs = profile()->GetPrefs();
226 const base::DictionaryValue* dict =
227 prefs->GetDictionary("extensions.settings");
228 if (!dict) {
229 return testing::AssertionFailure()
230 << "extension.settings does not exist " << msg;
231 }
232
233 const base::DictionaryValue* pref = NULL;
234 if (!dict->GetDictionary(extension_id, &pref)) {
235 return testing::AssertionFailure()
236 << "extension pref does not exist " << msg;
237 }
238
239 bool val = false;
240 if (!pref->GetBoolean(pref_path, &val)) {
241 return testing::AssertionFailure()
242 << pref_path << " pref not found " << msg;
243 }
244
245 return expected_val == val
246 ? testing::AssertionSuccess()
247 : testing::AssertionFailure() << "base::Value is incorrect " << msg;
248}
249
250void ExtensionServiceTestBase::ValidateIntegerPref(
251 const std::string& extension_id,
252 const std::string& pref_path,
253 int expected_val) {
254 std::string msg = base::StringPrintf("while checking: %s %s == %s",
255 extension_id.c_str(), pref_path.c_str(),
256 base::IntToString(expected_val).c_str());
257
258 PrefService* prefs = profile()->GetPrefs();
259 const base::DictionaryValue* dict =
260 prefs->GetDictionary("extensions.settings");
261 ASSERT_TRUE(dict != NULL) << msg;
262 const base::DictionaryValue* pref = NULL;
263 ASSERT_TRUE(dict->GetDictionary(extension_id, &pref)) << msg;
264 EXPECT_TRUE(pref != NULL) << msg;
265 int val;
266 ASSERT_TRUE(pref->GetInteger(pref_path, &val)) << msg;
267 EXPECT_EQ(expected_val, val) << msg;
268}
269
270void ExtensionServiceTestBase::ValidateStringPref(
271 const std::string& extension_id,
272 const std::string& pref_path,
273 const std::string& expected_val) {
274 std::string msg = base::StringPrintf("while checking: %s.manifest.%s == %s",
275 extension_id.c_str(), pref_path.c_str(),
276 expected_val.c_str());
277
278 const base::DictionaryValue* dict =
279 profile()->GetPrefs()->GetDictionary("extensions.settings");
280 ASSERT_TRUE(dict != NULL) << msg;
281 const base::DictionaryValue* pref = NULL;
282 std::string manifest_path = extension_id + ".manifest";
283 ASSERT_TRUE(dict->GetDictionary(manifest_path, &pref)) << msg;
284 EXPECT_TRUE(pref != NULL) << msg;
285 std::string val;
286 ASSERT_TRUE(pref->GetString(pref_path, &val)) << msg;
287 EXPECT_EQ(expected_val, val) << msg;
288}
289
[email protected]f484f8d52014-06-12 08:38:18290void ExtensionServiceTestBase::SetUp() {
291 ExtensionErrorReporter::GetInstance()->ClearErrors();
292}
293
294void ExtensionServiceTestBase::SetUpTestCase() {
295 // Safe to call multiple times.
296 ExtensionErrorReporter::Init(false); // no noisy errors.
297}
298
299// These are declared in the .cc so that all inheritors don't need to know
300// that TestingProfile derives Profile derives BrowserContext.
301content::BrowserContext* ExtensionServiceTestBase::browser_context() {
302 return profile_.get();
303}
304
305Profile* ExtensionServiceTestBase::profile() {
306 return profile_.get();
307}
308
pmarko6e36b4632016-12-13 17:45:50309sync_preferences::TestingPrefServiceSyncable*
310ExtensionServiceTestBase::testing_pref_service() {
311 return profile_->GetTestingPrefService();
312}
313
[email protected]f484f8d52014-06-12 08:38:18314void ExtensionServiceTestBase::CreateExtensionService(
315 const ExtensionServiceInitParams& params) {
316 TestExtensionSystem* system =
317 static_cast<TestExtensionSystem*>(ExtensionSystem::Get(profile_.get()));
juncaicf523332015-06-04 00:14:04318 if (!params.is_first_run)
319 ExtensionPrefs::Get(profile_.get())->SetAlertSystemFirstRun();
[email protected]f484f8d52014-06-12 08:38:18320
rdevlin.cronin7217be52017-03-24 20:47:05321 service_ = system->CreateExtensionService(
322 base::CommandLine::ForCurrentProcess(), params.extensions_install_dir,
323 params.autoupdate_enabled, params.extensions_enabled);
[email protected]f484f8d52014-06-12 08:38:18324
325 service_->SetFileTaskRunnerForTesting(
pranay.kumar07300782015-05-04 14:03:58326 base::ThreadTaskRunnerHandle::Get().get());
jam726de9f2015-06-02 15:36:06327 service_->component_loader()->set_ignore_whitelist_for_testing(true);
[email protected]f484f8d52014-06-12 08:38:18328
329 // When we start up, we want to make sure there is no external provider,
330 // since the ExtensionService on Windows will use the Registry as a default
331 // provider and if there is something already registered there then it will
332 // interfere with the tests. Those tests that need an external provider
333 // will register one specifically.
334 service_->ClearProvidersForTesting();
335
xiyuanf6a4c6a62016-04-19 18:14:54336 service_->RegisterInstallGate(ExtensionPrefs::DELAY_REASON_WAIT_FOR_IMPORTS,
337 service_->shared_module_service());
338
[email protected]f484f8d52014-06-12 08:38:18339#if defined(OS_CHROMEOS)
340 InstallLimiter::Get(profile_.get())->DisableForTest();
341#endif
342}
343
344} // namespace extensions