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 "base/command_line.h"
8#include "base/files/file_util.h"
9#include "base/memory/ref_counted.h"
10#include "base/message_loop/message_loop.h"
11#include "base/path_service.h"
12#include "chrome/browser/extensions/extension_error_reporter.h"
13#include "chrome/browser/extensions/extension_garbage_collector_factory.h"
14#include "chrome/browser/extensions/extension_service.h"
15#include "chrome/browser/extensions/test_extension_system.h"
16#include "chrome/browser/extensions/updater/extension_updater.h"
17#include "chrome/browser/prefs/browser_prefs.h"
18#include "chrome/browser/prefs/pref_service_mock_factory.h"
19#include "chrome/browser/prefs/pref_service_syncable.h"
20#include "chrome/common/chrome_constants.h"
21#include "chrome/common/chrome_paths.h"
22#include "chrome/test/base/testing_profile.h"
23#include "components/pref_registry/pref_registry_syncable.h"
24#include "content/public/browser/browser_context.h"
25#include "extensions/browser/extension_prefs.h"
26#include "extensions/browser/extension_registry.h"
27
28#if defined(OS_CHROMEOS)
29#include "chrome/browser/chromeos/extensions/install_limiter.h"
30#endif
31
32namespace extensions {
33
34namespace {
35
36// Create a testing profile according to |params|.
37scoped_ptr<TestingProfile> BuildTestingProfile(
38    const ExtensionServiceTestBase::ExtensionServiceInitParams& params) {
39  TestingProfile::Builder profile_builder;
40  // Create a PrefService that only contains user defined preference values.
41  PrefServiceMockFactory factory;
42  // If pref_file is empty, TestingProfile automatically creates
43  // TestingPrefServiceSyncable instance.
44  if (!params.pref_file.empty()) {
45    factory.SetUserPrefsFile(params.pref_file,
46                             base::MessageLoopProxy::current().get());
47    scoped_refptr<user_prefs::PrefRegistrySyncable> registry(
48        new user_prefs::PrefRegistrySyncable);
49    scoped_ptr<PrefServiceSyncable> prefs(
50        factory.CreateSyncable(registry.get()));
51    chrome::RegisterUserProfilePrefs(registry.get());
52    profile_builder.SetPrefService(prefs.Pass());
53  }
54
55  if (params.profile_is_supervised)
56    profile_builder.SetSupervisedUserId("asdf");
57
58  profile_builder.SetPath(params.profile_path);
59  return profile_builder.Build();
60}
61
62}  // namespace
63
64ExtensionServiceTestBase::ExtensionServiceInitParams::
65    ExtensionServiceInitParams()
66    : autoupdate_enabled(false),
67      is_first_run(true),
68      profile_is_supervised(false) {
69}
70
71// Our message loop may be used in tests which require it to be an IO loop.
72ExtensionServiceTestBase::ExtensionServiceTestBase()
73    : service_(NULL),
74      thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
75      registry_(NULL) {
76  base::FilePath test_data_dir;
77  if (!PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir)) {
78    ADD_FAILURE();
79    return;
80  }
81  data_dir_ = test_data_dir.AppendASCII("extensions");
82}
83
84ExtensionServiceTestBase::~ExtensionServiceTestBase() {
85  // Why? Because |profile_| has to be destroyed before |at_exit_manager_|, but
86  // is declared above it in the class definition since it's protected.
87  profile_.reset();
88}
89
90ExtensionServiceTestBase::ExtensionServiceInitParams
91ExtensionServiceTestBase::CreateDefaultInitParams() {
92  ExtensionServiceInitParams params;
93  EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
94  base::FilePath path = temp_dir_.path();
95  path = path.Append(FILE_PATH_LITERAL("TestingExtensionsPath"));
96  EXPECT_TRUE(base::DeleteFile(path, true));
97  base::File::Error error = base::File::FILE_OK;
98  EXPECT_TRUE(base::CreateDirectoryAndGetError(path, &error)) << error;
99  base::FilePath prefs_filename =
100      path.Append(FILE_PATH_LITERAL("TestPreferences"));
101  base::FilePath extensions_install_dir =
102      path.Append(FILE_PATH_LITERAL("Extensions"));
103  EXPECT_TRUE(base::DeleteFile(extensions_install_dir, true));
104  EXPECT_TRUE(base::CreateDirectoryAndGetError(extensions_install_dir, &error))
105      << error;
106
107  params.profile_path = path;
108  params.pref_file = prefs_filename;
109  params.extensions_install_dir = extensions_install_dir;
110  return params;
111}
112
113void ExtensionServiceTestBase::InitializeExtensionService(
114    const ExtensionServiceTestBase::ExtensionServiceInitParams& params) {
115  profile_ = BuildTestingProfile(params);
116  CreateExtensionService(params);
117
118  extensions_install_dir_ = params.extensions_install_dir;
119  registry_ = ExtensionRegistry::Get(profile_.get());
120
121  // Garbage collector is typically NULL during tests, so give it a build.
122  ExtensionGarbageCollectorFactory::GetInstance()->SetTestingFactoryAndUse(
123      profile_.get(), &ExtensionGarbageCollectorFactory::BuildInstanceFor);
124}
125
126void ExtensionServiceTestBase::InitializeEmptyExtensionService() {
127  InitializeExtensionService(CreateDefaultInitParams());
128}
129
130void ExtensionServiceTestBase::InitializeInstalledExtensionService(
131    const base::FilePath& prefs_file,
132    const base::FilePath& source_install_dir) {
133  ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
134  base::FilePath path = temp_dir_.path();
135
136  path = path.Append(FILE_PATH_LITERAL("TestingExtensionsPath"));
137  ASSERT_TRUE(base::DeleteFile(path, true));
138
139  base::File::Error error = base::File::FILE_OK;
140  ASSERT_TRUE(base::CreateDirectoryAndGetError(path, &error)) << error;
141
142  base::FilePath temp_prefs = path.Append(chrome::kPreferencesFilename);
143  ASSERT_TRUE(base::CopyFile(prefs_file, temp_prefs));
144
145  base::FilePath extensions_install_dir =
146      path.Append(FILE_PATH_LITERAL("Extensions"));
147  ASSERT_TRUE(base::DeleteFile(extensions_install_dir, true));
148  ASSERT_TRUE(
149      base::CopyDirectory(source_install_dir, extensions_install_dir, true));
150
151  ExtensionServiceInitParams params;
152  params.profile_path = path;
153  params.pref_file = temp_prefs;
154  params.extensions_install_dir = extensions_install_dir;
155  InitializeExtensionService(params);
156}
157
158void ExtensionServiceTestBase::InitializeGoodInstalledExtensionService() {
159  base::FilePath source_install_dir =
160      data_dir_.AppendASCII("good").AppendASCII("Extensions");
161  base::FilePath pref_path =
162      source_install_dir.DirName().Append(chrome::kPreferencesFilename);
163  InitializeInstalledExtensionService(pref_path, source_install_dir);
164}
165
166void ExtensionServiceTestBase::InitializeExtensionServiceWithUpdater() {
167  ExtensionServiceInitParams params = CreateDefaultInitParams();
168  params.autoupdate_enabled = true;
169  InitializeExtensionService(params);
170  service_->updater()->Start();
171}
172
173void ExtensionServiceTestBase::InitializeProcessManager() {
174  static_cast<extensions::TestExtensionSystem*>(
175      ExtensionSystem::Get(profile_.get()))->CreateProcessManager();
176}
177
178void ExtensionServiceTestBase::SetUp() {
179  ExtensionErrorReporter::GetInstance()->ClearErrors();
180}
181
182void ExtensionServiceTestBase::SetUpTestCase() {
183  // Safe to call multiple times.
184  ExtensionErrorReporter::Init(false);  // no noisy errors.
185}
186
187// These are declared in the .cc so that all inheritors don't need to know
188// that TestingProfile derives Profile derives BrowserContext.
189content::BrowserContext* ExtensionServiceTestBase::browser_context() {
190  return profile_.get();
191}
192
193Profile* ExtensionServiceTestBase::profile() {
194  return profile_.get();
195}
196
197void ExtensionServiceTestBase::CreateExtensionService(
198    const ExtensionServiceInitParams& params) {
199  TestExtensionSystem* system =
200      static_cast<TestExtensionSystem*>(ExtensionSystem::Get(profile_.get()));
201  if (!params.is_first_run) {
202    ExtensionPrefs* prefs = system->CreateExtensionPrefs(
203        base::CommandLine::ForCurrentProcess(), params.extensions_install_dir);
204    prefs->SetAlertSystemFirstRun();
205  }
206
207  service_ =
208      system->CreateExtensionService(base::CommandLine::ForCurrentProcess(),
209                                     params.extensions_install_dir,
210                                     params.autoupdate_enabled);
211
212  service_->SetFileTaskRunnerForTesting(
213      base::MessageLoopProxy::current().get());
214  service_->set_extensions_enabled(true);
215  service_->set_show_extensions_prompts(false);
216  service_->set_install_updates_when_idle_for_test(false);
217
218  // When we start up, we want to make sure there is no external provider,
219  // since the ExtensionService on Windows will use the Registry as a default
220  // provider and if there is something already registered there then it will
221  // interfere with the tests. Those tests that need an external provider
222  // will register one specifically.
223  service_->ClearProvidersForTesting();
224
225#if defined(OS_CHROMEOS)
226  InstallLimiter::Get(profile_.get())->DisableForTest();
227#endif
228}
229
230}  // namespace extensions
231