Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Side by Side Diff: chrome/browser/extensions/extension_service_test_with_install.cc

Issue 1411773002: Move Sync-specific tests from ExtensionServiceTest into new file (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@su_ext_reenable
Patch Set: review Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 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_with_install.h"
6
7 #include "base/files/file_util.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/browser/extensions/crx_installer.h"
10 #include "chrome/browser/extensions/extension_creator.h"
11 #include "chrome/browser/extensions/extension_error_reporter.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "content/public/browser/notification_service.h"
14 #include "extensions/browser/extension_registry.h"
15 #include "extensions/browser/notification_types.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 namespace extensions {
19
20 namespace {
21
22 struct ExtensionsOrder {
23 bool operator()(const scoped_refptr<const Extension>& a,
24 const scoped_refptr<const Extension>& b) {
25 return a->name() < b->name();
26 }
27 };
28
29 // Helper method to set up a WindowedNotificationObserver to wait for a
30 // specific CrxInstaller to finish if we don't know the value of the
31 // |installer| yet.
32 bool IsCrxInstallerDone(extensions::CrxInstaller** installer,
33 const content::NotificationSource& source,
34 const content::NotificationDetails& details) {
35 return content::Source<extensions::CrxInstaller>(source).ptr() == *installer;
36 }
37
38 } // namespace
39
40 ExtensionServiceTestWithInstall::ExtensionServiceTestWithInstall()
41 : installed_(nullptr),
42 was_update_(false),
43 unloaded_reason_(UnloadedExtensionInfo::REASON_UNDEFINED),
44 expected_extensions_count_(0){
45 // TODO(treib,devlin): This should use ExtensionRegistryObserver instead.
46 registrar_.Add(this,
47 extensions::NOTIFICATION_EXTENSION_LOADED_DEPRECATED,
48 content::NotificationService::AllSources());
49 registrar_.Add(this,
50 extensions::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED,
51 content::NotificationService::AllSources());
52 registrar_.Add(
53 this,
54 extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED,
55 content::NotificationService::AllSources());
56 }
57
58 ExtensionServiceTestWithInstall::~ExtensionServiceTestWithInstall() {}
59
60 // static
61 std::vector<base::string16> ExtensionServiceTestWithInstall::GetErrors() {
62 const std::vector<base::string16>* errors =
63 ExtensionErrorReporter::GetInstance()->GetErrors();
64 std::vector<base::string16> ret_val;
65
66 for (const base::string16& error : *errors) {
67 std::string utf8_error = base::UTF16ToUTF8(error);
68 if (utf8_error.find(".svn") == std::string::npos) {
69 ret_val.push_back(error);
70 }
71 }
72
73 // The tests rely on the errors being in a certain order, which can vary
74 // depending on how filesystem iteration works.
75 std::stable_sort(ret_val.begin(), ret_val.end());
76
77 return ret_val;
78 }
79
80 void ExtensionServiceTestWithInstall::PackCRX(const base::FilePath& dir_path,
81 const base::FilePath& pem_path,
82 const base::FilePath& crx_path) {
83 // Use the existing pem key, if provided.
84 base::FilePath pem_output_path;
85 if (pem_path.value().empty()) {
86 pem_output_path = crx_path.DirName().AppendASCII("temp.pem");
87 } else {
88 ASSERT_TRUE(base::PathExists(pem_path));
89 }
90
91 ASSERT_TRUE(base::DeleteFile(crx_path, false));
92
93 scoped_ptr<ExtensionCreator> creator(new ExtensionCreator());
94 ASSERT_TRUE(creator->Run(dir_path,
95 crx_path,
96 pem_path,
97 pem_output_path,
98 ExtensionCreator::kOverwriteCRX));
99
100 ASSERT_TRUE(base::PathExists(crx_path));
101 }
102
103 const Extension* ExtensionServiceTestWithInstall::PackAndInstallCRX(
104 const base::FilePath& dir_path,
105 const base::FilePath& pem_path,
106 InstallState install_state,
107 int creation_flags) {
108 base::FilePath crx_path;
109 base::ScopedTempDir temp_dir;
110 EXPECT_TRUE(temp_dir.CreateUniqueTempDir());
111 crx_path = temp_dir.path().AppendASCII("temp.crx");
112
113 PackCRX(dir_path, pem_path, crx_path);
114 return InstallCRX(crx_path, install_state, creation_flags);
115 }
116
117 const Extension* ExtensionServiceTestWithInstall::PackAndInstallCRX(
118 const base::FilePath& dir_path,
119 const base::FilePath& pem_path,
120 InstallState install_state) {
121 return PackAndInstallCRX(dir_path, pem_path, install_state,
122 Extension::NO_FLAGS);
123 }
124
125 const Extension* ExtensionServiceTestWithInstall::PackAndInstallCRX(
126 const base::FilePath& dir_path,
127 InstallState install_state) {
128 return PackAndInstallCRX(dir_path, base::FilePath(), install_state,
129 Extension::NO_FLAGS);
130 }
131
132 // Attempts to install an extension. Use INSTALL_FAILED if the installation
133 // is expected to fail.
134 // If |install_state| is INSTALL_UPDATED, and |expected_old_name| is
135 // non-empty, expects that the existing extension's title was
136 // |expected_old_name|.
137 const Extension* ExtensionServiceTestWithInstall::InstallCRX(
138 const base::FilePath& path,
139 InstallState install_state,
140 int creation_flags,
141 const std::string& expected_old_name) {
142 InstallCRXInternal(path, creation_flags);
143 return VerifyCrxInstall(path, install_state, expected_old_name);
144 }
145
146 // Attempts to install an extension. Use INSTALL_FAILED if the installation
147 // is expected to fail.
148 const Extension* ExtensionServiceTestWithInstall::InstallCRX(
149 const base::FilePath& path,
150 InstallState install_state,
151 int creation_flags) {
152 return InstallCRX(path, install_state, creation_flags, std::string());
153 }
154
155 // Attempts to install an extension. Use INSTALL_FAILED if the installation
156 // is expected to fail.
157 const Extension* ExtensionServiceTestWithInstall::InstallCRX(
158 const base::FilePath& path,
159 InstallState install_state) {
160 return InstallCRX(path, install_state, Extension::NO_FLAGS);
161 }
162
163 const Extension* ExtensionServiceTestWithInstall::InstallCRXFromWebStore(
164 const base::FilePath& path,
165 InstallState install_state) {
166 InstallCRXInternal(path, Extension::FROM_WEBSTORE);
167 return VerifyCrxInstall(path, install_state);
168 }
169
170 const Extension* ExtensionServiceTestWithInstall::InstallCRXWithLocation(
171 const base::FilePath& crx_path,
172 Manifest::Location install_location,
173 InstallState install_state) {
174 EXPECT_TRUE(base::PathExists(crx_path))
175 << "Path does not exist: "<< crx_path.value().c_str();
176 // no client (silent install)
177 scoped_refptr<CrxInstaller> installer(
178 CrxInstaller::CreateSilent(service()));
179 installer->set_install_source(install_location);
180
181 content::WindowedNotificationObserver observer(
182 extensions::NOTIFICATION_CRX_INSTALLER_DONE,
183 content::NotificationService::AllSources());
184 installer->InstallCrx(crx_path);
185 observer.Wait();
186
187 return VerifyCrxInstall(crx_path, install_state);
188 }
189
190 const Extension* ExtensionServiceTestWithInstall::VerifyCrxInstall(
191 const base::FilePath& path,
192 InstallState install_state) {
193 return VerifyCrxInstall(path, install_state, std::string());
194 }
195
196 const Extension* ExtensionServiceTestWithInstall::VerifyCrxInstall(
197 const base::FilePath& path,
198 InstallState install_state,
199 const std::string& expected_old_name) {
200 std::vector<base::string16> errors = GetErrors();
201 const Extension* extension = NULL;
202 if (install_state != INSTALL_FAILED) {
203 if (install_state == INSTALL_NEW)
204 ++expected_extensions_count_;
205
206 EXPECT_TRUE(installed_) << path.value();
207 // If and only if INSTALL_UPDATED, it should have the is_update flag.
208 EXPECT_EQ(install_state == INSTALL_UPDATED, was_update_)
209 << path.value();
210 // If INSTALL_UPDATED, old_name_ should match the given string.
211 if (install_state == INSTALL_UPDATED && !expected_old_name.empty())
212 EXPECT_EQ(expected_old_name, old_name_);
213 EXPECT_EQ(0u, errors.size()) << path.value();
214
215 if (install_state == INSTALL_WITHOUT_LOAD) {
216 EXPECT_EQ(0u, loaded_.size()) << path.value();
217 } else {
218 EXPECT_EQ(1u, loaded_.size()) << path.value();
219 size_t actual_extension_count =
220 registry()->enabled_extensions().size() +
221 registry()->disabled_extensions().size();
222 EXPECT_EQ(expected_extensions_count_, actual_extension_count) <<
223 path.value();
224 extension = loaded_[0].get();
225 EXPECT_TRUE(service()->GetExtensionById(extension->id(), false))
226 << path.value();
227 }
228
229 for (std::vector<base::string16>::iterator err = errors.begin();
230 err != errors.end(); ++err) {
231 LOG(ERROR) << *err;
232 }
233 } else {
234 EXPECT_FALSE(installed_) << path.value();
235 EXPECT_EQ(0u, loaded_.size()) << path.value();
236 EXPECT_EQ(1u, errors.size()) << path.value();
237 }
238
239 installed_ = NULL;
240 was_update_ = false;
241 old_name_ = "";
242 loaded_.clear();
243 ExtensionErrorReporter::GetInstance()->ClearErrors();
244 return extension;
245 }
246
247 void ExtensionServiceTestWithInstall::PackCRXAndUpdateExtension(
248 const std::string& id,
249 const base::FilePath& dir_path,
250 const base::FilePath& pem_path,
251 UpdateState expected_state) {
252 base::ScopedTempDir temp_dir;
253 EXPECT_TRUE(temp_dir.CreateUniqueTempDir());
254 base::FilePath crx_path = temp_dir.path().AppendASCII("temp.crx");
255
256 PackCRX(dir_path, pem_path, crx_path);
257 UpdateExtension(id, crx_path, expected_state);
258 }
259
260 void ExtensionServiceTestWithInstall::UpdateExtension(
261 const std::string& id,
262 const base::FilePath& in_path,
263 UpdateState expected_state) {
264 ASSERT_TRUE(base::PathExists(in_path));
265
266 // We need to copy this to a temporary location because Update() will delete
267 // it.
268 base::FilePath path = temp_dir().path();
269 path = path.Append(in_path.BaseName());
270 ASSERT_TRUE(base::CopyFile(in_path, path));
271
272 int previous_enabled_extension_count =
273 registry()->enabled_extensions().size();
274 int previous_installed_extension_count =
275 previous_enabled_extension_count +
276 registry()->disabled_extensions().size();
277
278 extensions::CrxInstaller* installer = NULL;
279 content::WindowedNotificationObserver observer(
280 extensions::NOTIFICATION_CRX_INSTALLER_DONE,
281 base::Bind(&IsCrxInstallerDone, &installer));
282 service()->UpdateExtension(extensions::CRXFileInfo(id, path), true,
283 &installer);
284
285 if (installer)
286 observer.Wait();
287 else
288 base::RunLoop().RunUntilIdle();
289
290 std::vector<base::string16> errors = GetErrors();
291 int error_count = errors.size();
292 int enabled_extension_count = registry()->enabled_extensions().size();
293 int installed_extension_count =
294 enabled_extension_count + registry()->disabled_extensions().size();
295
296 int expected_error_count = (expected_state == FAILED) ? 1 : 0;
297 EXPECT_EQ(expected_error_count, error_count) << path.value();
298
299 if (expected_state <= FAILED) {
300 EXPECT_EQ(previous_enabled_extension_count,
301 enabled_extension_count);
302 EXPECT_EQ(previous_installed_extension_count,
303 installed_extension_count);
304 } else {
305 int expected_installed_extension_count =
306 (expected_state >= INSTALLED) ? 1 : 0;
307 int expected_enabled_extension_count =
308 (expected_state >= ENABLED) ? 1 : 0;
309 EXPECT_EQ(expected_installed_extension_count,
310 installed_extension_count);
311 EXPECT_EQ(expected_enabled_extension_count,
312 enabled_extension_count);
313 }
314
315 // Update() should the temporary input file.
316 EXPECT_FALSE(base::PathExists(path));
317 }
318
319 void ExtensionServiceTestWithInstall::UninstallExtension(const std::string& id,
320 bool use_helper) {
321 UninstallExtension(id, use_helper, Extension::ENABLED);
322 }
323
324 void ExtensionServiceTestWithInstall::UninstallExtension(
325 const std::string& id,
326 bool use_helper,
327 Extension::State expected_state) {
328 // Verify that the extension is installed.
329 base::FilePath extension_path = extensions_install_dir().AppendASCII(id);
330 EXPECT_TRUE(base::PathExists(extension_path));
331 size_t pref_key_count = GetPrefKeyCount();
332 EXPECT_GT(pref_key_count, 0u);
333 ValidateIntegerPref(id, "state", expected_state);
334
335 // Uninstall it.
336 if (use_helper) {
337 EXPECT_TRUE(ExtensionService::UninstallExtensionHelper(
338 service(), id, extensions::UNINSTALL_REASON_FOR_TESTING));
339 } else {
340 EXPECT_TRUE(service()->UninstallExtension(
341 id,
342 extensions::UNINSTALL_REASON_FOR_TESTING,
343 base::Bind(&base::DoNothing),
344 NULL));
345 }
346 --expected_extensions_count_;
347
348 // We should get an unload notification.
349 EXPECT_FALSE(unloaded_id_.empty());
350 EXPECT_EQ(id, unloaded_id_);
351
352 // Verify uninstalled state.
353 size_t new_pref_key_count = GetPrefKeyCount();
354 if (new_pref_key_count == pref_key_count) {
355 ValidateIntegerPref(id, "state",
356 Extension::EXTERNAL_EXTENSION_UNINSTALLED);
357 } else {
358 EXPECT_EQ(new_pref_key_count, pref_key_count - 1);
359 }
360
361 // The extension should not be in the service anymore.
362 EXPECT_FALSE(service()->GetInstalledExtension(id));
363 base::RunLoop().RunUntilIdle();
364
365 // The directory should be gone.
366 EXPECT_FALSE(base::PathExists(extension_path));
367 }
368
369 void ExtensionServiceTestWithInstall::TerminateExtension(
370 const std::string& id) {
371 const Extension* extension = service()->GetInstalledExtension(id);
372 if (!extension) {
373 ADD_FAILURE();
374 return;
375 }
376 service()->TrackTerminatedExtensionForTest(extension);
377 }
378
379 void ExtensionServiceTestWithInstall::Observe(
380 int type,
381 const content::NotificationSource& source,
382 const content::NotificationDetails& details) {
383 switch (type) {
384 case extensions::NOTIFICATION_EXTENSION_LOADED_DEPRECATED: {
385 const Extension* extension =
386 content::Details<const Extension>(details).ptr();
387 loaded_.push_back(make_scoped_refptr(extension));
388 // The tests rely on the errors being in a certain order, which can vary
389 // depending on how filesystem iteration works.
390 std::stable_sort(loaded_.begin(), loaded_.end(), ExtensionsOrder());
391 break;
392 }
393
394 case extensions::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED: {
395 UnloadedExtensionInfo* unloaded_info =
396 content::Details<UnloadedExtensionInfo>(details).ptr();
397 const Extension* e = unloaded_info->extension;
398 unloaded_id_ = e->id();
399 unloaded_reason_ = unloaded_info->reason;
400 extensions::ExtensionList::iterator i =
401 std::find(loaded_.begin(), loaded_.end(), e);
402 // TODO(erikkay) fix so this can be an assert. Right now the tests
403 // are manually calling clear() on loaded_, so this isn't doable.
404 if (i == loaded_.end())
405 return;
406 loaded_.erase(i);
407 break;
408 }
409 case extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED: {
410 const extensions::InstalledExtensionInfo* installed_info =
411 content::Details<const extensions::InstalledExtensionInfo>(details)
412 .ptr();
413 installed_ = installed_info->extension;
414 was_update_ = installed_info->is_update;
415 old_name_ = installed_info->old_name;
416 break;
417 }
418
419 default:
420 DCHECK(false);
421 }
422 }
423
424 // Create a CrxInstaller and install the CRX file.
425 // Instead of calling this method yourself, use InstallCRX(), which does extra
426 // error checking.
427 void ExtensionServiceTestWithInstall::InstallCRXInternal(
428 const base::FilePath& crx_path,
429 int creation_flags) {
430 ASSERT_TRUE(base::PathExists(crx_path))
431 << "Path does not exist: "<< crx_path.value().c_str();
432 scoped_refptr<CrxInstaller> installer(
433 CrxInstaller::CreateSilent(service()));
434 installer->set_creation_flags(creation_flags);
435 if (!(creation_flags & Extension::WAS_INSTALLED_BY_DEFAULT))
436 installer->set_allow_silent_install(true);
437
438 content::WindowedNotificationObserver observer(
439 extensions::NOTIFICATION_CRX_INSTALLER_DONE,
440 content::Source<extensions::CrxInstaller>(installer.get()));
441
442 installer->InstallCrx(crx_path);
443
444 observer.Wait();
445 }
446
447 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698