1 // 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
7 #include <utility>
8
9 #include "base/bind.h"
10 #include "base/command_line.h"
11 #include "base/files/file_util.h"
12 #include "base/memory/ref_counted.h"
13 #include "base/path_service.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/stringprintf.h"
16 #include "base/test/task_environment.h"
17 #include "base/threading/thread_task_runner_handle.h"
18 #include "build/build_config.h"
19 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
20 #include "chrome/browser/bookmarks/managed_bookmark_service_factory.h"
21 #include "chrome/browser/extensions/component_loader.h"
22 #include "chrome/browser/extensions/crx_installer.h"
23 #include "chrome/browser/extensions/extension_garbage_collector_factory.h"
24 #include "chrome/browser/extensions/extension_service.h"
25 #include "chrome/browser/extensions/load_error_reporter.h"
26 #include "chrome/browser/extensions/shared_module_service.h"
27 #include "chrome/browser/extensions/test_extension_system.h"
28 #include "chrome/browser/extensions/updater/extension_updater.h"
29 #include "chrome/browser/policy/chrome_browser_policy_connector.h"
30 #include "chrome/browser/prefs/browser_prefs.h"
31 #include "chrome/browser/signin/identity_manager_factory.h"
32 #include "chrome/browser/signin/identity_test_environment_profile_adaptor.h"
33 #include "chrome/common/buildflags.h"
34 #include "chrome/common/chrome_constants.h"
35 #include "chrome/common/chrome_paths.h"
36 #include "chrome/test/base/testing_browser_process.h"
37 #include "chrome/test/base/testing_profile.h"
38 #include "components/crx_file/crx_verifier.h"
39 #include "components/policy/core/common/policy_service_impl.h"
40 #include "components/pref_registry/pref_registry_syncable.h"
41 #include "components/sync_preferences/pref_service_mock_factory.h"
42 #include "components/sync_preferences/pref_service_syncable.h"
43 #include "content/public/browser/browser_context.h"
44 #include "content/public/browser/storage_partition.h"
45 #include "content/public/test/browser_task_environment.h"
46 #include "extensions/browser/extension_prefs.h"
47 #include "extensions/browser/extension_registry.h"
48 #include "extensions/browser/pref_names.h"
49
50 #if defined(OS_CHROMEOS)
51 #include "chrome/browser/chromeos/extensions/install_limiter.h"
52 #endif
53
54 #if BUILDFLAG(ENABLE_SUPERVISED_USERS)
55 #include "chrome/browser/supervised_user/supervised_user_constants.h"
56 #endif
57
58 namespace extensions {
59
60 namespace {
61
62 // Create a testing profile according to |params|.
BuildTestingProfile(const ExtensionServiceTestBase::ExtensionServiceInitParams & params)63 std::unique_ptr<TestingProfile> BuildTestingProfile(
64 const ExtensionServiceTestBase::ExtensionServiceInitParams& params) {
65 TestingProfile::Builder profile_builder;
66 // Create a PrefService that only contains user defined preference values and
67 // policies.
68 sync_preferences::PrefServiceMockFactory factory;
69 // If pref_file is empty, TestingProfile automatically creates
70 // sync_preferences::TestingPrefServiceSyncable instance.
71 if (!params.pref_file.empty()) {
72 factory.SetUserPrefsFile(params.pref_file,
73 base::ThreadTaskRunnerHandle::Get().get());
74 if (params.policy_service) {
75 factory.SetManagedPolicies(params.policy_service,
76 g_browser_process->browser_policy_connector());
77 }
78 scoped_refptr<user_prefs::PrefRegistrySyncable> registry(
79 new user_prefs::PrefRegistrySyncable);
80 std::unique_ptr<sync_preferences::PrefServiceSyncable> prefs(
81 factory.CreateSyncable(registry.get()));
82 RegisterUserProfilePrefs(registry.get());
83 profile_builder.SetPrefService(std::move(prefs));
84 }
85
86 if (params.profile_is_supervised) {
87 #if BUILDFLAG(ENABLE_SUPERVISED_USERS)
88 profile_builder.SetSupervisedUserId(supervised_users::kChildAccountSUID);
89 #else
90 profile_builder.SetSupervisedUserId("asdf");
91 #endif
92 }
93
94 if (params.enable_bookmark_model) {
95 profile_builder.AddTestingFactory(
96 BookmarkModelFactory::GetInstance(),
97 BookmarkModelFactory::GetDefaultFactory());
98 profile_builder.AddTestingFactory(
99 ManagedBookmarkServiceFactory::GetInstance(),
100 ManagedBookmarkServiceFactory::GetDefaultFactory());
101 }
102
103 profile_builder.AddTestingFactories(
104 IdentityTestEnvironmentProfileAdaptor::
105 GetIdentityTestEnvironmentFactories());
106
107 profile_builder.SetPath(params.profile_path);
108 return profile_builder.Build();
109 }
110
111 } // namespace
112
113 ExtensionServiceTestBase::ExtensionServiceInitParams::
ExtensionServiceInitParams()114 ExtensionServiceInitParams() {}
115
116 ExtensionServiceTestBase::ExtensionServiceInitParams::
117 ExtensionServiceInitParams(const ExtensionServiceInitParams& other) =
118 default;
119
ExtensionServiceTestBase()120 ExtensionServiceTestBase::ExtensionServiceTestBase()
121 : ExtensionServiceTestBase(
122 std::make_unique<content::BrowserTaskEnvironment>(
123 base::test::TaskEnvironment::MainThreadType::IO)) {}
124
ExtensionServiceTestBase(std::unique_ptr<content::BrowserTaskEnvironment> task_environment)125 ExtensionServiceTestBase::ExtensionServiceTestBase(
126 std::unique_ptr<content::BrowserTaskEnvironment> task_environment)
127 : task_environment_(std::move(task_environment)),
128 service_(nullptr),
129 testing_local_state_(TestingBrowserProcess::GetGlobal()),
130 registry_(nullptr),
131 verifier_format_override_(crx_file::VerifierFormat::CRX3) {
132 base::FilePath test_data_dir;
133 if (!base::PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir)) {
134 ADD_FAILURE();
135 return;
136 }
137 data_dir_ = test_data_dir.AppendASCII("extensions");
138
139 policy_service_ = std::make_unique<policy::PolicyServiceImpl>(
140 std::vector<policy::ConfigurationPolicyProvider*>{&policy_provider_});
141 }
142
~ExtensionServiceTestBase()143 ExtensionServiceTestBase::~ExtensionServiceTestBase() {
144 // Why? Because |profile_| has to be destroyed before |at_exit_manager_|, but
145 // is declared above it in the class definition since it's protected.
146 profile_.reset();
147 }
148
149 ExtensionServiceTestBase::ExtensionServiceInitParams
CreateDefaultInitParams()150 ExtensionServiceTestBase::CreateDefaultInitParams() {
151 ExtensionServiceInitParams params;
152 EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
153 base::FilePath path = temp_dir_.GetPath();
154 path = path.Append(FILE_PATH_LITERAL("TestingExtensionsPath"));
155 EXPECT_TRUE(base::DeletePathRecursively(path));
156 base::File::Error error = base::File::FILE_OK;
157 EXPECT_TRUE(base::CreateDirectoryAndGetError(path, &error)) << error;
158 base::FilePath prefs_filename =
159 path.Append(FILE_PATH_LITERAL("TestPreferences"));
160 base::FilePath extensions_install_dir =
161 path.Append(FILE_PATH_LITERAL("Extensions"));
162 EXPECT_TRUE(base::DeletePathRecursively(extensions_install_dir));
163 EXPECT_TRUE(base::CreateDirectoryAndGetError(extensions_install_dir, &error))
164 << error;
165
166 params.profile_path = path;
167 params.pref_file = prefs_filename;
168 params.extensions_install_dir = extensions_install_dir;
169
170 params.policy_service = policy_service_.get();
171 return params;
172 }
173
InitializeExtensionService(const ExtensionServiceTestBase::ExtensionServiceInitParams & params)174 void ExtensionServiceTestBase::InitializeExtensionService(
175 const ExtensionServiceTestBase::ExtensionServiceInitParams& params) {
176 profile_ = BuildTestingProfile(params);
177 CreateExtensionService(params);
178
179 extensions_install_dir_ = params.extensions_install_dir;
180 registry_ = ExtensionRegistry::Get(profile_.get());
181
182 // Garbage collector is typically NULL during tests, so give it a build.
183 ExtensionGarbageCollectorFactory::GetInstance()->SetTestingFactoryAndUse(
184 profile_.get(),
185 base::BindRepeating(&ExtensionGarbageCollectorFactory::BuildInstanceFor));
186 }
187
InitializeEmptyExtensionService()188 void ExtensionServiceTestBase::InitializeEmptyExtensionService() {
189 InitializeExtensionService(CreateDefaultInitParams());
190 }
191
InitializeInstalledExtensionService(const base::FilePath & prefs_file,const base::FilePath & source_install_dir)192 void ExtensionServiceTestBase::InitializeInstalledExtensionService(
193 const base::FilePath& prefs_file,
194 const base::FilePath& source_install_dir) {
195 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
196 base::FilePath path = temp_dir_.GetPath();
197
198 path = path.Append(FILE_PATH_LITERAL("TestingExtensionsPath"));
199 ASSERT_TRUE(base::DeletePathRecursively(path));
200
201 base::File::Error error = base::File::FILE_OK;
202 ASSERT_TRUE(base::CreateDirectoryAndGetError(path, &error)) << error;
203
204 base::FilePath temp_prefs = path.Append(chrome::kPreferencesFilename);
205 ASSERT_TRUE(base::CopyFile(prefs_file, temp_prefs));
206
207 base::FilePath extensions_install_dir =
208 path.Append(FILE_PATH_LITERAL("Extensions"));
209 ASSERT_TRUE(base::DeletePathRecursively(extensions_install_dir));
210 ASSERT_TRUE(
211 base::CopyDirectory(source_install_dir, extensions_install_dir, true));
212
213 ExtensionServiceInitParams params;
214 params.profile_path = path;
215 params.pref_file = temp_prefs;
216 params.extensions_install_dir = extensions_install_dir;
217 InitializeExtensionService(params);
218 }
219
InitializeGoodInstalledExtensionService()220 void ExtensionServiceTestBase::InitializeGoodInstalledExtensionService() {
221 base::FilePath source_install_dir =
222 data_dir_.AppendASCII("good").AppendASCII("Extensions");
223 base::FilePath pref_path =
224 source_install_dir.DirName().Append(chrome::kPreferencesFilename);
225 InitializeInstalledExtensionService(pref_path, source_install_dir);
226 }
227
InitializeExtensionServiceWithUpdater()228 void ExtensionServiceTestBase::InitializeExtensionServiceWithUpdater() {
229 ExtensionServiceInitParams params = CreateDefaultInitParams();
230 params.autoupdate_enabled = true;
231 InitializeExtensionService(params);
232 service_->updater()->Start();
233 }
234
235 void ExtensionServiceTestBase::
InitializeExtensionServiceWithExtensionsDisabled()236 InitializeExtensionServiceWithExtensionsDisabled() {
237 ExtensionServiceInitParams params = CreateDefaultInitParams();
238 params.extensions_enabled = false;
239 InitializeExtensionService(params);
240 }
241
GetPrefKeyCount()242 size_t ExtensionServiceTestBase::GetPrefKeyCount() {
243 const base::DictionaryValue* dict =
244 profile()->GetPrefs()->GetDictionary(pref_names::kExtensions);
245 if (!dict) {
246 ADD_FAILURE();
247 return 0;
248 }
249 return dict->size();
250 }
251
ValidatePrefKeyCount(size_t count)252 void ExtensionServiceTestBase::ValidatePrefKeyCount(size_t count) {
253 EXPECT_EQ(count, GetPrefKeyCount());
254 }
255
ValidateBooleanPref(const std::string & extension_id,const std::string & pref_path,bool expected_val)256 testing::AssertionResult ExtensionServiceTestBase::ValidateBooleanPref(
257 const std::string& extension_id,
258 const std::string& pref_path,
259 bool expected_val) {
260 std::string msg = base::StringPrintf("while checking: %s %s == %s",
261 extension_id.c_str(), pref_path.c_str(),
262 expected_val ? "true" : "false");
263
264 PrefService* prefs = profile()->GetPrefs();
265 const base::DictionaryValue* dict =
266 prefs->GetDictionary(pref_names::kExtensions);
267 if (!dict) {
268 return testing::AssertionFailure()
269 << "extension.settings does not exist " << msg;
270 }
271
272 const base::DictionaryValue* pref = NULL;
273 if (!dict->GetDictionary(extension_id, &pref)) {
274 return testing::AssertionFailure()
275 << "extension pref does not exist " << msg;
276 }
277
278 bool val = false;
279 if (!pref->GetBoolean(pref_path, &val)) {
280 return testing::AssertionFailure()
281 << pref_path << " pref not found " << msg;
282 }
283
284 return expected_val == val
285 ? testing::AssertionSuccess()
286 : testing::AssertionFailure() << "base::Value is incorrect " << msg;
287 }
288
ValidateIntegerPref(const std::string & extension_id,const std::string & pref_path,int expected_val)289 void ExtensionServiceTestBase::ValidateIntegerPref(
290 const std::string& extension_id,
291 const std::string& pref_path,
292 int expected_val) {
293 std::string msg = base::StringPrintf(
294 "while checking: %s %s == %s", extension_id.c_str(), pref_path.c_str(),
295 base::NumberToString(expected_val).c_str());
296
297 PrefService* prefs = profile()->GetPrefs();
298 const base::DictionaryValue* dict =
299 prefs->GetDictionary(pref_names::kExtensions);
300 ASSERT_TRUE(dict != NULL) << msg;
301 const base::DictionaryValue* pref = NULL;
302 ASSERT_TRUE(dict->GetDictionary(extension_id, &pref)) << msg;
303 EXPECT_TRUE(pref != NULL) << msg;
304 int val;
305 ASSERT_TRUE(pref->GetInteger(pref_path, &val)) << msg;
306 EXPECT_EQ(expected_val, val) << msg;
307 }
308
ValidateStringPref(const std::string & extension_id,const std::string & pref_path,const std::string & expected_val)309 void ExtensionServiceTestBase::ValidateStringPref(
310 const std::string& extension_id,
311 const std::string& pref_path,
312 const std::string& expected_val) {
313 std::string msg = base::StringPrintf("while checking: %s.manifest.%s == %s",
314 extension_id.c_str(), pref_path.c_str(),
315 expected_val.c_str());
316
317 const base::DictionaryValue* dict =
318 profile()->GetPrefs()->GetDictionary(pref_names::kExtensions);
319 ASSERT_TRUE(dict != NULL) << msg;
320 const base::DictionaryValue* pref = NULL;
321 std::string manifest_path = extension_id + ".manifest";
322 ASSERT_TRUE(dict->GetDictionary(manifest_path, &pref)) << msg;
323 EXPECT_TRUE(pref != NULL) << msg;
324 std::string val;
325 ASSERT_TRUE(pref->GetString(pref_path, &val)) << msg;
326 EXPECT_EQ(expected_val, val) << msg;
327 }
328
SetUp()329 void ExtensionServiceTestBase::SetUp() {
330 LoadErrorReporter::GetInstance()->ClearErrors();
331
332 // Force TabManager/TabLifecycleUnitSource creation.
333 g_browser_process->resource_coordinator_parts();
334 }
335
TearDown()336 void ExtensionServiceTestBase::TearDown() {
337 if (profile_) {
338 auto* partition =
339 content::BrowserContext::GetDefaultStoragePartition(profile_.get());
340 if (partition)
341 partition->WaitForDeletionTasksForTesting();
342 }
343 policy_provider_.Shutdown();
344 }
345
SetUpTestCase()346 void ExtensionServiceTestBase::SetUpTestCase() {
347 // Safe to call multiple times.
348 LoadErrorReporter::Init(false); // no noisy errors.
349 }
350
351 // These are declared in the .cc so that all inheritors don't need to know
352 // that TestingProfile derives Profile derives BrowserContext.
browser_context()353 content::BrowserContext* ExtensionServiceTestBase::browser_context() {
354 return profile_.get();
355 }
356
profile()357 Profile* ExtensionServiceTestBase::profile() {
358 return profile_.get();
359 }
360
361 sync_preferences::TestingPrefServiceSyncable*
testing_pref_service()362 ExtensionServiceTestBase::testing_pref_service() {
363 return profile_->GetTestingPrefService();
364 }
365
CreateExtensionService(const ExtensionServiceInitParams & params)366 void ExtensionServiceTestBase::CreateExtensionService(
367 const ExtensionServiceInitParams& params) {
368 TestExtensionSystem* system =
369 static_cast<TestExtensionSystem*>(ExtensionSystem::Get(profile_.get()));
370 if (!params.is_first_run)
371 ExtensionPrefs::Get(profile_.get())->SetAlertSystemFirstRun();
372
373 service_ = system->CreateExtensionService(
374 base::CommandLine::ForCurrentProcess(), params.extensions_install_dir,
375 params.autoupdate_enabled, params.extensions_enabled);
376
377 service_->component_loader()->set_ignore_allowlist_for_testing(true);
378
379 // When we start up, we want to make sure there is no external provider,
380 // since the ExtensionService on Windows will use the Registry as a default
381 // provider and if there is something already registered there then it will
382 // interfere with the tests. Those tests that need an external provider
383 // will register one specifically.
384 service_->ClearProvidersForTesting();
385
386 service_->RegisterInstallGate(ExtensionPrefs::DELAY_REASON_WAIT_FOR_IMPORTS,
387 service_->shared_module_service());
388
389 #if defined(OS_CHROMEOS)
390 InstallLimiter::Get(profile_.get())->DisableForTest();
391 #endif
392 }
393
394 } // namespace extensions
395