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