1 // Copyright (c) 2011 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_unittest.h"
6
7 #include <algorithm>
8 #include <set>
9 #include <vector>
10
11 #include "base/basictypes.h"
12 #include "base/command_line.h"
13 #include "base/file_util.h"
14 #include "base/json/json_reader.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/memory/scoped_temp_dir.h"
17 #include "base/message_loop.h"
18 #include "base/path_service.h"
19 #include "base/stl_util-inl.h"
20 #include "base/string16.h"
21 #include "base/string_number_conversions.h"
22 #include "base/string_util.h"
23 #include "base/task.h"
24 #include "base/utf_string_conversions.h"
25 #include "base/version.h"
26 #include "chrome/browser/extensions/crx_installer.h"
27 #include "chrome/browser/extensions/extension_creator.h"
28 #include "chrome/browser/extensions/extension_error_reporter.h"
29 #include "chrome/browser/extensions/extension_service.h"
30 #include "chrome/browser/extensions/extension_special_storage_policy.h"
31 #include "chrome/browser/extensions/extension_sync_data.h"
32 #include "chrome/browser/extensions/extension_updater.h"
33 #include "chrome/browser/extensions/external_extension_provider_impl.h"
34 #include "chrome/browser/extensions/external_extension_provider_interface.h"
35 #include "chrome/browser/extensions/external_pref_extension_loader.h"
36 #include "chrome/browser/extensions/pack_extension_job.cc"
37 #include "chrome/browser/extensions/pending_extension_info.h"
38 #include "chrome/browser/extensions/pending_extension_manager.h"
39 #include "chrome/browser/prefs/browser_prefs.h"
40 #include "chrome/browser/prefs/pref_service_mock_builder.h"
41 #include "chrome/browser/prefs/scoped_user_pref_update.h"
42 #include "chrome/common/chrome_paths.h"
43 #include "chrome/common/chrome_switches.h"
44 #include "chrome/common/extensions/extension.h"
45 #include "chrome/common/extensions/extension_constants.h"
46 #include "chrome/common/extensions/extension_resource.h"
47 #include "chrome/common/extensions/url_pattern.h"
48 #include "chrome/common/pref_names.h"
49 #include "chrome/common/url_constants.h"
50 #include "chrome/test/testing_profile.h"
51 #include "content/browser/appcache/chrome_appcache_service.h"
52 #include "content/browser/browser_thread.h"
53 #include "content/browser/file_system/browser_file_system_helper.h"
54 #include "content/browser/in_process_webkit/dom_storage_context.h"
55 #include "content/browser/in_process_webkit/webkit_context.h"
56 #include "content/common/json_value_serializer.h"
57 #include "content/common/notification_registrar.h"
58 #include "content/common/notification_service.h"
59 #include "content/common/notification_type.h"
60 #include "googleurl/src/gurl.h"
61 #include "net/base/cookie_monster.h"
62 #include "net/base/cookie_options.h"
63 #include "net/url_request/url_request_context.h"
64 #include "net/url_request/url_request_context_getter.h"
65 #include "testing/gtest/include/gtest/gtest.h"
66 #include "testing/platform_test.h"
67 #include "webkit/database/database_tracker.h"
68 #include "webkit/database/database_util.h"
69
70 namespace keys = extension_manifest_keys;
71
72 namespace {
73
74 // Extension ids used during testing.
75 const char* const all_zero = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
76 const char* const zero_n_one = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab";
77 const char* const good0 = "behllobkkfkfnphdnhnkndlbkcpglgmj";
78 const char* const good1 = "hpiknbiabeeppbpihjehijgoemciehgk";
79 const char* const good2 = "bjafgdebaacbbbecmhlhpofkepfkgcpa";
80 const char* const good_crx = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
81 const char* const page_action = "obcimlgaoabeegjmmpldobjndiealpln";
82 const char* const theme_crx = "iamefpfkojoapidjnbafmgkgncegbkad";
83 const char* const theme2_crx = "pjpgmfcmabopnnfonnhmdjglfpjjfkbf";
84 const char* const permissions_crx = "eagpmdpfmaekmmcejjbmjoecnejeiiin";
85
86 struct ExtensionsOrder {
operator ()__anond96f6e660111::ExtensionsOrder87 bool operator()(const Extension* a, const Extension* b) {
88 return a->name() < b->name();
89 }
90 };
91
GetErrors()92 static std::vector<std::string> GetErrors() {
93 const std::vector<std::string>* errors =
94 ExtensionErrorReporter::GetInstance()->GetErrors();
95 std::vector<std::string> ret_val;
96
97 for (std::vector<std::string>::const_iterator iter = errors->begin();
98 iter != errors->end(); ++iter) {
99 if (iter->find(".svn") == std::string::npos) {
100 ret_val.push_back(*iter);
101 }
102 }
103
104 // The tests rely on the errors being in a certain order, which can vary
105 // depending on how filesystem iteration works.
106 std::stable_sort(ret_val.begin(), ret_val.end());
107
108 return ret_val;
109 }
110
AddPattern(ExtensionExtent * extent,const std::string & pattern)111 static void AddPattern(ExtensionExtent* extent, const std::string& pattern) {
112 int schemes = URLPattern::SCHEME_ALL;
113 extent->AddPattern(URLPattern(schemes, pattern));
114 }
115
AssertEqualExtents(ExtensionExtent * extent1,ExtensionExtent * extent2)116 static void AssertEqualExtents(ExtensionExtent* extent1,
117 ExtensionExtent* extent2) {
118 std::vector<URLPattern> patterns1 = extent1->patterns();
119 std::vector<URLPattern> patterns2 = extent2->patterns();
120 std::set<std::string> strings1;
121 EXPECT_EQ(patterns1.size(), patterns2.size());
122
123 for (size_t i = 0; i < patterns1.size(); ++i)
124 strings1.insert(patterns1.at(i).GetAsString());
125
126 std::set<std::string> strings2;
127 for (size_t i = 0; i < patterns2.size(); ++i)
128 strings2.insert(patterns2.at(i).GetAsString());
129
130 EXPECT_EQ(strings1, strings2);
131 }
132
133 } // namespace
134
135 class MockExtensionProvider : public ExternalExtensionProviderInterface {
136 public:
MockExtensionProvider(VisitorInterface * visitor,Extension::Location location)137 explicit MockExtensionProvider(
138 VisitorInterface* visitor,
139 Extension::Location location)
140 : location_(location), visitor_(visitor), visit_count_(0) {
141 }
~MockExtensionProvider()142 virtual ~MockExtensionProvider() {}
143
UpdateOrAddExtension(const std::string & id,const std::string & version,const FilePath & path)144 void UpdateOrAddExtension(const std::string& id,
145 const std::string& version,
146 const FilePath& path) {
147 extension_map_[id] = std::make_pair(version, path);
148 }
149
RemoveExtension(const std::string & id)150 void RemoveExtension(const std::string& id) {
151 extension_map_.erase(id);
152 }
153
154 // ExternalExtensionProvider implementation:
VisitRegisteredExtension() const155 virtual void VisitRegisteredExtension() const {
156 visit_count_++;
157 for (DataMap::const_iterator i = extension_map_.begin();
158 i != extension_map_.end(); ++i) {
159 scoped_ptr<Version> version;
160 version.reset(Version::GetVersionFromString(i->second.first));
161
162 visitor_->OnExternalExtensionFileFound(
163 i->first, version.get(), i->second.second, location_);
164 }
165 visitor_->OnExternalProviderReady();
166 }
167
HasExtension(const std::string & id) const168 virtual bool HasExtension(const std::string& id) const {
169 return extension_map_.find(id) != extension_map_.end();
170 }
171
GetExtensionDetails(const std::string & id,Extension::Location * location,scoped_ptr<Version> * version) const172 virtual bool GetExtensionDetails(const std::string& id,
173 Extension::Location* location,
174 scoped_ptr<Version>* version) const {
175 DataMap::const_iterator it = extension_map_.find(id);
176 if (it == extension_map_.end())
177 return false;
178
179 if (version)
180 version->reset(Version::GetVersionFromString(it->second.first));
181
182 if (location)
183 *location = location_;
184
185 return true;
186 }
187
IsReady()188 virtual bool IsReady() {
189 return true;
190 }
191
ServiceShutdown()192 virtual void ServiceShutdown() {
193 }
194
visit_count() const195 int visit_count() const { return visit_count_; }
set_visit_count(int visit_count)196 void set_visit_count(int visit_count) {
197 visit_count_ = visit_count;
198 }
199
200 private:
201 typedef std::map< std::string, std::pair<std::string, FilePath> > DataMap;
202 DataMap extension_map_;
203 Extension::Location location_;
204 VisitorInterface* visitor_;
205
206 // visit_count_ tracks the number of calls to VisitRegisteredExtension().
207 // Mutable because it must be incremented on each call to
208 // VisitRegisteredExtension(), which must be a const method to inherit
209 // from the class being mocked.
210 mutable int visit_count_;
211
212 DISALLOW_COPY_AND_ASSIGN(MockExtensionProvider);
213 };
214
215 class MockProviderVisitor
216 : public ExternalExtensionProviderInterface::VisitorInterface {
217 public:
218
219 // The provider will return |fake_base_path| from
220 // GetBaseCrxFilePath(). User can test the behavior with
221 // and without an empty path using this parameter.
MockProviderVisitor(FilePath fake_base_path)222 explicit MockProviderVisitor(FilePath fake_base_path)
223 : ids_found_(0),
224 fake_base_path_(fake_base_path) {
225 }
226
Visit(const std::string & json_data)227 int Visit(const std::string& json_data) {
228 // Give the test json file to the provider for parsing.
229 provider_.reset(new ExternalExtensionProviderImpl(
230 this,
231 new ExternalTestingExtensionLoader(json_data, fake_base_path_),
232 Extension::EXTERNAL_PREF,
233 Extension::EXTERNAL_PREF_DOWNLOAD));
234
235 // We also parse the file into a dictionary to compare what we get back
236 // from the provider.
237 JSONStringValueSerializer serializer(json_data);
238 Value* json_value = serializer.Deserialize(NULL, NULL);
239
240 if (!json_value || !json_value->IsType(Value::TYPE_DICTIONARY)) {
241 NOTREACHED() << "Unable to deserialize json data";
242 return -1;
243 } else {
244 DictionaryValue* external_extensions =
245 static_cast<DictionaryValue*>(json_value);
246 prefs_.reset(external_extensions);
247 }
248
249 // Reset our counter.
250 ids_found_ = 0;
251 // Ask the provider to look up all extensions and return them.
252 provider_->VisitRegisteredExtension();
253
254 return ids_found_;
255 }
256
OnExternalExtensionFileFound(const std::string & id,const Version * version,const FilePath & path,Extension::Location unused)257 virtual void OnExternalExtensionFileFound(const std::string& id,
258 const Version* version,
259 const FilePath& path,
260 Extension::Location unused) {
261 ++ids_found_;
262 DictionaryValue* pref;
263 // This tests is to make sure that the provider only notifies us of the
264 // values we gave it. So if the id we doesn't exist in our internal
265 // dictionary then something is wrong.
266 EXPECT_TRUE(prefs_->GetDictionary(id, &pref))
267 << "Got back ID (" << id.c_str() << ") we weren't expecting";
268
269 EXPECT_TRUE(path.IsAbsolute());
270 if (!fake_base_path_.empty())
271 EXPECT_TRUE(fake_base_path_.IsParent(path));
272
273 if (pref) {
274 EXPECT_TRUE(provider_->HasExtension(id));
275
276 // Ask provider if the extension we got back is registered.
277 Extension::Location location = Extension::INVALID;
278 scoped_ptr<Version> v1;
279 FilePath crx_path;
280
281 EXPECT_TRUE(provider_->GetExtensionDetails(id, NULL, &v1));
282 EXPECT_STREQ(version->GetString().c_str(), v1->GetString().c_str());
283
284 scoped_ptr<Version> v2;
285 EXPECT_TRUE(provider_->GetExtensionDetails(id, &location, &v2));
286 EXPECT_STREQ(version->GetString().c_str(), v1->GetString().c_str());
287 EXPECT_STREQ(version->GetString().c_str(), v2->GetString().c_str());
288 EXPECT_EQ(Extension::EXTERNAL_PREF, location);
289
290 // Remove it so we won't count it ever again.
291 prefs_->Remove(id, NULL);
292 }
293 }
294
OnExternalExtensionUpdateUrlFound(const std::string & id,const GURL & update_url,Extension::Location location)295 virtual void OnExternalExtensionUpdateUrlFound(
296 const std::string& id, const GURL& update_url,
297 Extension::Location location) {
298 ++ids_found_;
299 DictionaryValue* pref;
300 // This tests is to make sure that the provider only notifies us of the
301 // values we gave it. So if the id we doesn't exist in our internal
302 // dictionary then something is wrong.
303 EXPECT_TRUE(prefs_->GetDictionary(id, &pref))
304 << L"Got back ID (" << id.c_str() << ") we weren't expecting";
305 EXPECT_EQ(Extension::EXTERNAL_PREF_DOWNLOAD, location);
306
307 if (pref) {
308 EXPECT_TRUE(provider_->HasExtension(id));
309
310 // External extensions with update URLs do not have versions.
311 scoped_ptr<Version> v1;
312 Extension::Location location1 = Extension::INVALID;
313 EXPECT_TRUE(provider_->GetExtensionDetails(id, &location1, &v1));
314 EXPECT_FALSE(v1.get());
315 EXPECT_EQ(Extension::EXTERNAL_PREF_DOWNLOAD, location1);
316
317 // Remove it so we won't count it again.
318 prefs_->Remove(id, NULL);
319 }
320 }
321
OnExternalProviderReady()322 virtual void OnExternalProviderReady() {
323 EXPECT_TRUE(provider_->IsReady());
324 }
325
326 private:
327 int ids_found_;
328 FilePath fake_base_path_;
329 scoped_ptr<ExternalExtensionProviderImpl> provider_;
330 scoped_ptr<DictionaryValue> prefs_;
331
332 DISALLOW_COPY_AND_ASSIGN(MockProviderVisitor);
333 };
334
335 class ExtensionTestingProfile : public TestingProfile {
336 public:
ExtensionTestingProfile()337 ExtensionTestingProfile() : service_(NULL) {
338 }
339
set_extensions_service(ExtensionService * service)340 void set_extensions_service(ExtensionService* service) {
341 service_ = service;
342 }
GetExtensionService()343 virtual ExtensionService* GetExtensionService() { return service_; }
344
GetAppCacheService()345 virtual ChromeAppCacheService* GetAppCacheService() {
346 if (!appcache_service_) {
347 appcache_service_ = new ChromeAppCacheService;
348 BrowserThread::PostTask(
349 BrowserThread::IO, FROM_HERE,
350 NewRunnableMethod(
351 appcache_service_.get(),
352 &ChromeAppCacheService::InitializeOnIOThread,
353 IsOffTheRecord()
354 ? FilePath() : GetPath().Append(chrome::kAppCacheDirname),
355 make_scoped_refptr(GetHostContentSettingsMap()),
356 make_scoped_refptr(GetExtensionSpecialStoragePolicy()),
357 false));
358 }
359 return appcache_service_;
360 }
361
GetFileSystemContext()362 virtual fileapi::FileSystemContext* GetFileSystemContext() {
363 if (!file_system_context_)
364 file_system_context_ = CreateFileSystemContext(
365 GetPath(), IsOffTheRecord(), GetExtensionSpecialStoragePolicy());
366 return file_system_context_;
367 }
368
369 private:
370 ExtensionService* service_;
371 scoped_refptr<ChromeAppCacheService> appcache_service_;
372 scoped_refptr<fileapi::FileSystemContext> file_system_context_;
373 };
374
375 // Our message loop may be used in tests which require it to be an IO loop.
ExtensionServiceTestBase()376 ExtensionServiceTestBase::ExtensionServiceTestBase()
377 : total_successes_(0),
378 loop_(MessageLoop::TYPE_IO),
379 ui_thread_(BrowserThread::UI, &loop_),
380 db_thread_(BrowserThread::DB, &loop_),
381 webkit_thread_(BrowserThread::WEBKIT, &loop_),
382 file_thread_(BrowserThread::FILE, &loop_),
383 io_thread_(BrowserThread::IO, &loop_) {
384 FilePath test_data_dir;
385 if (!PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir)) {
386 ADD_FAILURE();
387 return;
388 }
389 data_dir_ = test_data_dir.AppendASCII("extensions");
390 }
391
~ExtensionServiceTestBase()392 ExtensionServiceTestBase::~ExtensionServiceTestBase() {
393 // Drop our reference to ExtensionService and TestingProfile, so that they
394 // can be destroyed while BrowserThreads and MessageLoop are still around
395 // (they are used in the destruction process).
396 service_ = NULL;
397 profile_.reset(NULL);
398 MessageLoop::current()->RunAllPending();
399 }
400
InitializeExtensionService(const FilePath & pref_file,const FilePath & extensions_install_dir,bool autoupdate_enabled)401 void ExtensionServiceTestBase::InitializeExtensionService(
402 const FilePath& pref_file, const FilePath& extensions_install_dir,
403 bool autoupdate_enabled) {
404 ExtensionTestingProfile* profile = new ExtensionTestingProfile();
405 // Create a PrefService that only contains user defined preference values.
406 PrefService* prefs =
407 PrefServiceMockBuilder().WithUserFilePrefs(pref_file).Create();
408 Profile::RegisterUserPrefs(prefs);
409 browser::RegisterUserPrefs(prefs);
410 profile->SetPrefService(prefs);
411
412 profile_.reset(profile);
413
414 service_ = profile->CreateExtensionService(
415 CommandLine::ForCurrentProcess(),
416 extensions_install_dir,
417 autoupdate_enabled);
418 service_->set_extensions_enabled(true);
419 service_->set_show_extensions_prompts(false);
420 profile->set_extensions_service(service_.get());
421
422 // When we start up, we want to make sure there is no external provider,
423 // since the ExtensionService on Windows will use the Registry as a default
424 // provider and if there is something already registered there then it will
425 // interfere with the tests. Those tests that need an external provider
426 // will register one specifically.
427 service_->ClearProvidersForTesting();
428
429 total_successes_ = 0;
430 }
431
InitializeInstalledExtensionService(const FilePath & prefs_file,const FilePath & source_install_dir)432 void ExtensionServiceTestBase::InitializeInstalledExtensionService(
433 const FilePath& prefs_file, const FilePath& source_install_dir) {
434 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
435 FilePath path_ = temp_dir_.path();
436 path_ = path_.Append(FILE_PATH_LITERAL("TestingExtensionsPath"));
437 file_util::Delete(path_, true);
438 file_util::CreateDirectory(path_);
439 FilePath temp_prefs = path_.Append(FILE_PATH_LITERAL("Preferences"));
440 file_util::CopyFile(prefs_file, temp_prefs);
441
442 extensions_install_dir_ = path_.Append(FILE_PATH_LITERAL("Extensions"));
443 file_util::Delete(extensions_install_dir_, true);
444 file_util::CopyDirectory(source_install_dir, extensions_install_dir_, true);
445
446 InitializeExtensionService(temp_prefs, extensions_install_dir_, false);
447 }
448
InitializeEmptyExtensionService()449 void ExtensionServiceTestBase::InitializeEmptyExtensionService() {
450 InitializeExtensionServiceHelper(false);
451 }
452
InitializeExtensionServiceWithUpdater()453 void ExtensionServiceTestBase::InitializeExtensionServiceWithUpdater() {
454 InitializeExtensionServiceHelper(true);
455 service_->updater()->Start();
456 }
457
InitializeExtensionServiceHelper(bool autoupdate_enabled)458 void ExtensionServiceTestBase::InitializeExtensionServiceHelper(
459 bool autoupdate_enabled) {
460 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
461 FilePath path_ = temp_dir_.path();
462 path_ = path_.Append(FILE_PATH_LITERAL("TestingExtensionsPath"));
463 file_util::Delete(path_, true);
464 file_util::CreateDirectory(path_);
465 FilePath prefs_filename = path_
466 .Append(FILE_PATH_LITERAL("TestPreferences"));
467 extensions_install_dir_ = path_.Append(FILE_PATH_LITERAL("Extensions"));
468 file_util::Delete(extensions_install_dir_, true);
469 file_util::CreateDirectory(extensions_install_dir_);
470
471 InitializeExtensionService(prefs_filename, extensions_install_dir_,
472 autoupdate_enabled);
473 }
474
475 // static
SetUpTestCase()476 void ExtensionServiceTestBase::SetUpTestCase() {
477 ExtensionErrorReporter::Init(false); // no noisy errors
478 }
479
SetUp()480 void ExtensionServiceTestBase::SetUp() {
481 ExtensionErrorReporter::GetInstance()->ClearErrors();
482 }
483
484 class ExtensionServiceTest
485 : public ExtensionServiceTestBase, public NotificationObserver {
486 public:
ExtensionServiceTest()487 ExtensionServiceTest() : installed_(NULL) {
488 registrar_.Add(this, NotificationType::EXTENSION_LOADED,
489 NotificationService::AllSources());
490 registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
491 NotificationService::AllSources());
492 registrar_.Add(this, NotificationType::EXTENSION_INSTALLED,
493 NotificationService::AllSources());
494 }
495
Observe(NotificationType type,const NotificationSource & source,const NotificationDetails & details)496 virtual void Observe(NotificationType type,
497 const NotificationSource& source,
498 const NotificationDetails& details) {
499 switch (type.value) {
500 case NotificationType::EXTENSION_LOADED: {
501 const Extension* extension = Details<const Extension>(details).ptr();
502 loaded_.push_back(make_scoped_refptr(extension));
503 // The tests rely on the errors being in a certain order, which can vary
504 // depending on how filesystem iteration works.
505 std::stable_sort(loaded_.begin(), loaded_.end(), ExtensionsOrder());
506 break;
507 }
508
509 case NotificationType::EXTENSION_UNLOADED: {
510 const Extension* e =
511 Details<UnloadedExtensionInfo>(details)->extension;
512 unloaded_id_ = e->id();
513 ExtensionList::iterator i =
514 std::find(loaded_.begin(), loaded_.end(), e);
515 // TODO(erikkay) fix so this can be an assert. Right now the tests
516 // are manually calling clear() on loaded_, so this isn't doable.
517 if (i == loaded_.end())
518 return;
519 loaded_.erase(i);
520 break;
521 }
522 case NotificationType::EXTENSION_INSTALLED:
523 installed_ = Details<const Extension>(details).ptr();
524 break;
525
526 default:
527 DCHECK(false);
528 }
529 }
530
AddMockExternalProvider(ExternalExtensionProviderInterface * provider)531 void AddMockExternalProvider(ExternalExtensionProviderInterface* provider) {
532 service_->AddProviderForTesting(provider);
533 }
534
535 protected:
536 void TestExternalProvider(MockExtensionProvider* provider,
537 Extension::Location location);
538
PackAndInstallCrx(const FilePath & dir_path,const FilePath & pem_path,bool should_succeed)539 void PackAndInstallCrx(const FilePath& dir_path,
540 const FilePath& pem_path,
541 bool should_succeed) {
542 FilePath crx_path;
543 ScopedTempDir temp_dir;
544 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
545 crx_path = temp_dir_.path().AppendASCII("temp.crx");
546
547 // Use the existing pem key, if provided.
548 FilePath pem_output_path;
549 if (pem_path.value().empty()) {
550 pem_output_path = crx_path.DirName().AppendASCII("temp.pem");
551 ASSERT_TRUE(file_util::Delete(pem_output_path, false));
552 } else {
553 ASSERT_TRUE(file_util::PathExists(pem_path));
554 }
555
556 ASSERT_TRUE(file_util::Delete(crx_path, false));
557
558 scoped_ptr<ExtensionCreator> creator(new ExtensionCreator());
559 ASSERT_TRUE(creator->Run(dir_path,
560 crx_path,
561 pem_path,
562 pem_output_path));
563
564 ASSERT_TRUE(file_util::PathExists(crx_path));
565
566 InstallCrx(crx_path, should_succeed);
567 }
568
PackAndInstallCrx(const FilePath & dir_path,bool should_succeed)569 void PackAndInstallCrx(const FilePath& dir_path,
570 bool should_succeed) {
571 PackAndInstallCrx(dir_path, FilePath(), should_succeed);
572 }
573
574 // Create a CrxInstaller and start installation. To allow the install
575 // to happen, use loop_.RunAllPending();. Most tests will not use this
576 // method directly. Instead, use InstallCrx(), which waits for
577 // the crx to be installed and does extra error checking.
StartCrxInstall(const FilePath & crx_path)578 void StartCrxInstall(const FilePath& crx_path) {
579 ASSERT_TRUE(file_util::PathExists(crx_path))
580 << "Path does not exist: "<< crx_path.value().c_str();
581 scoped_refptr<CrxInstaller> installer(
582 new CrxInstaller(service_, // frontend
583 NULL)); // no client (silent install)
584 installer->InstallCrx(crx_path);
585 }
586
InstallCrx(const FilePath & path,bool should_succeed)587 void InstallCrx(const FilePath& path,
588 bool should_succeed) {
589 StartCrxInstall(path);
590 WaitForCrxInstall(path, should_succeed);
591 }
592
InstallCrxWithLocation(const FilePath & crx_path,Extension::Location install_location,bool should_succeed)593 void InstallCrxWithLocation(const FilePath& crx_path,
594 Extension::Location install_location,
595 bool should_succeed) {
596 ASSERT_TRUE(file_util::PathExists(crx_path))
597 << "Path does not exist: "<< crx_path.value().c_str();
598 scoped_refptr<CrxInstaller> installer(
599 new CrxInstaller(service_, // frontend
600 NULL)); // no client (silent install)
601
602 installer->set_install_source(install_location);
603 installer->InstallCrx(crx_path);
604
605 WaitForCrxInstall(crx_path, should_succeed);
606 }
607
608 // Wait for a CrxInstaller to finish. Used by InstallCrx.
WaitForCrxInstall(const FilePath & path,bool should_succeed)609 void WaitForCrxInstall(const FilePath& path,
610 bool should_succeed) {
611 loop_.RunAllPending();
612 std::vector<std::string> errors = GetErrors();
613 if (should_succeed) {
614 ++total_successes_;
615
616 EXPECT_TRUE(installed_) << path.value();
617
618 ASSERT_EQ(1u, loaded_.size()) << path.value();
619 EXPECT_EQ(0u, errors.size()) << path.value();
620 EXPECT_EQ(total_successes_, service_->extensions()->size()) <<
621 path.value();
622 EXPECT_TRUE(service_->GetExtensionById(loaded_[0]->id(), false)) <<
623 path.value();
624 for (std::vector<std::string>::iterator err = errors.begin();
625 err != errors.end(); ++err) {
626 LOG(ERROR) << *err;
627 }
628 } else {
629 EXPECT_FALSE(installed_) << path.value();
630 EXPECT_EQ(0u, loaded_.size()) << path.value();
631 EXPECT_EQ(1u, errors.size()) << path.value();
632 }
633
634 installed_ = NULL;
635 loaded_.clear();
636 ExtensionErrorReporter::GetInstance()->ClearErrors();
637 }
638
639 enum UpdateState {
640 FAILED_SILENTLY,
641 FAILED,
642 UPDATED,
643 INSTALLED,
644 ENABLED
645 };
646
UpdateExtension(const std::string & id,const FilePath & in_path,UpdateState expected_state)647 void UpdateExtension(const std::string& id, const FilePath& in_path,
648 UpdateState expected_state) {
649 ASSERT_TRUE(file_util::PathExists(in_path));
650
651 // We need to copy this to a temporary location because Update() will delete
652 // it.
653 FilePath path = temp_dir_.path();
654 path = path.Append(in_path.BaseName());
655 ASSERT_TRUE(file_util::CopyFile(in_path, path));
656
657 int previous_enabled_extension_count =
658 service_->extensions()->size();
659 int previous_installed_extension_count =
660 previous_enabled_extension_count +
661 service_->disabled_extensions()->size();
662
663 service_->UpdateExtension(id, path, GURL());
664 loop_.RunAllPending();
665
666 std::vector<std::string> errors = GetErrors();
667 int error_count = errors.size();
668 int enabled_extension_count =
669 service_->extensions()->size();
670 int installed_extension_count =
671 enabled_extension_count + service_->disabled_extensions()->size();
672
673 int expected_error_count = (expected_state == FAILED) ? 1 : 0;
674 EXPECT_EQ(expected_error_count, error_count) << path.value();
675
676 if (expected_state <= FAILED) {
677 EXPECT_EQ(previous_enabled_extension_count,
678 enabled_extension_count);
679 EXPECT_EQ(previous_installed_extension_count,
680 installed_extension_count);
681 } else {
682 int expected_installed_extension_count =
683 (expected_state >= INSTALLED) ? 1 : 0;
684 int expected_enabled_extension_count =
685 (expected_state >= ENABLED) ? 1 : 0;
686 EXPECT_EQ(expected_installed_extension_count,
687 installed_extension_count);
688 EXPECT_EQ(expected_enabled_extension_count,
689 enabled_extension_count);
690 }
691
692 // Update() should delete the temporary input file.
693 EXPECT_FALSE(file_util::PathExists(path));
694 }
695
ValidatePrefKeyCount(size_t count)696 void ValidatePrefKeyCount(size_t count) {
697 const DictionaryValue* dict =
698 profile_->GetPrefs()->GetDictionary("extensions.settings");
699 ASSERT_TRUE(dict != NULL);
700 EXPECT_EQ(count, dict->size());
701 }
702
ValidateBooleanPref(const std::string & extension_id,const std::string & pref_path,bool expected_val)703 void ValidateBooleanPref(const std::string& extension_id,
704 const std::string& pref_path,
705 bool expected_val) {
706 std::string msg = " while checking: ";
707 msg += extension_id;
708 msg += " ";
709 msg += pref_path;
710 msg += " == ";
711 msg += expected_val ? "true" : "false";
712
713 PrefService* prefs = profile_->GetPrefs();
714 const DictionaryValue* dict =
715 prefs->GetDictionary("extensions.settings");
716 ASSERT_TRUE(dict != NULL) << msg;
717 DictionaryValue* pref = NULL;
718 ASSERT_TRUE(dict->GetDictionary(extension_id, &pref)) << msg;
719 EXPECT_TRUE(pref != NULL) << msg;
720 bool val;
721 ASSERT_TRUE(pref->GetBoolean(pref_path, &val)) << msg;
722 EXPECT_EQ(expected_val, val) << msg;
723 }
724
IsPrefExist(const std::string & extension_id,const std::string & pref_path)725 bool IsPrefExist(const std::string& extension_id,
726 const std::string& pref_path) {
727 const DictionaryValue* dict =
728 profile_->GetPrefs()->GetDictionary("extensions.settings");
729 if (dict == NULL) return false;
730 DictionaryValue* pref = NULL;
731 if (!dict->GetDictionary(extension_id, &pref)) {
732 return false;
733 }
734 if (pref == NULL) {
735 return false;
736 }
737 bool val;
738 if (!pref->GetBoolean(pref_path, &val)) {
739 return false;
740 }
741 return true;
742 }
743
ValidateIntegerPref(const std::string & extension_id,const std::string & pref_path,int expected_val)744 void ValidateIntegerPref(const std::string& extension_id,
745 const std::string& pref_path,
746 int expected_val) {
747 std::string msg = " while checking: ";
748 msg += extension_id;
749 msg += " ";
750 msg += pref_path;
751 msg += " == ";
752 msg += base::IntToString(expected_val);
753
754 PrefService* prefs = profile_->GetPrefs();
755 const DictionaryValue* dict =
756 prefs->GetDictionary("extensions.settings");
757 ASSERT_TRUE(dict != NULL) << msg;
758 DictionaryValue* pref = NULL;
759 ASSERT_TRUE(dict->GetDictionary(extension_id, &pref)) << msg;
760 EXPECT_TRUE(pref != NULL) << msg;
761 int val;
762 ASSERT_TRUE(pref->GetInteger(pref_path, &val)) << msg;
763 EXPECT_EQ(expected_val, val) << msg;
764 }
765
ValidateStringPref(const std::string & extension_id,const std::string & pref_path,const std::string & expected_val)766 void ValidateStringPref(const std::string& extension_id,
767 const std::string& pref_path,
768 const std::string& expected_val) {
769 std::string msg = " while checking: ";
770 msg += extension_id;
771 msg += ".manifest.";
772 msg += pref_path;
773 msg += " == ";
774 msg += expected_val;
775
776 const DictionaryValue* dict =
777 profile_->GetPrefs()->GetDictionary("extensions.settings");
778 ASSERT_TRUE(dict != NULL) << msg;
779 DictionaryValue* pref = NULL;
780 std::string manifest_path = extension_id + ".manifest";
781 ASSERT_TRUE(dict->GetDictionary(manifest_path, &pref)) << msg;
782 EXPECT_TRUE(pref != NULL) << msg;
783 std::string val;
784 ASSERT_TRUE(pref->GetString(pref_path, &val)) << msg;
785 EXPECT_EQ(expected_val, val) << msg;
786 }
787
SetPref(const std::string & extension_id,const std::string & pref_path,Value * value,const std::string & msg)788 void SetPref(const std::string& extension_id,
789 const std::string& pref_path,
790 Value* value,
791 const std::string& msg) {
792 DictionaryPrefUpdate update(profile_->GetPrefs(), "extensions.settings");
793 DictionaryValue* dict = update.Get();
794 ASSERT_TRUE(dict != NULL) << msg;
795 DictionaryValue* pref = NULL;
796 ASSERT_TRUE(dict->GetDictionary(extension_id, &pref)) << msg;
797 EXPECT_TRUE(pref != NULL) << msg;
798 pref->Set(pref_path, value);
799 }
800
SetPrefInteg(const std::string & extension_id,const std::string & pref_path,int value)801 void SetPrefInteg(const std::string& extension_id,
802 const std::string& pref_path,
803 int value) {
804 std::string msg = " while setting: ";
805 msg += extension_id;
806 msg += " ";
807 msg += pref_path;
808 msg += " = ";
809 msg += base::IntToString(value);
810
811 SetPref(extension_id, pref_path, Value::CreateIntegerValue(value), msg);
812 }
813
SetPrefBool(const std::string & extension_id,const std::string & pref_path,bool value)814 void SetPrefBool(const std::string& extension_id,
815 const std::string& pref_path,
816 bool value) {
817 std::string msg = " while setting: ";
818 msg += extension_id + " " + pref_path;
819 msg += " = ";
820 msg += (value ? "true" : "false");
821
822 SetPref(extension_id, pref_path, Value::CreateBooleanValue(value), msg);
823 }
824
ClearPref(const std::string & extension_id,const std::string & pref_path)825 void ClearPref(const std::string& extension_id,
826 const std::string& pref_path) {
827 std::string msg = " while clearing: ";
828 msg += extension_id + " " + pref_path;
829
830 DictionaryPrefUpdate update(profile_->GetPrefs(), "extensions.settings");
831 DictionaryValue* dict = update.Get();
832 ASSERT_TRUE(dict != NULL) << msg;
833 DictionaryValue* pref = NULL;
834 ASSERT_TRUE(dict->GetDictionary(extension_id, &pref)) << msg;
835 EXPECT_TRUE(pref != NULL) << msg;
836 pref->Remove(pref_path, NULL);
837 }
838
SetPrefStringSet(const std::string & extension_id,const std::string & pref_path,const std::set<std::string> & value)839 void SetPrefStringSet(const std::string& extension_id,
840 const std::string& pref_path,
841 const std::set<std::string>& value) {
842 std::string msg = " while setting: ";
843 msg += extension_id + " " + pref_path;
844
845 ListValue* list_value = new ListValue();
846 for (std::set<std::string>::const_iterator iter = value.begin();
847 iter != value.end(); ++iter)
848 list_value->Append(Value::CreateStringValue(*iter));
849
850 SetPref(extension_id, pref_path, list_value, msg);
851 }
852
853 protected:
854 ExtensionList loaded_;
855 std::string unloaded_id_;
856 const Extension* installed_;
857
858 private:
859 NotificationRegistrar registrar_;
860 };
861
NormalizeSeparators(const FilePath & path)862 FilePath NormalizeSeparators(const FilePath& path) {
863 #if defined(FILE_PATH_USES_WIN_SEPARATORS)
864 return path.NormalizeWindowsPathSeparators();
865 #else
866 return path;
867 #endif // FILE_PATH_USES_WIN_SEPARATORS
868 }
869
870 // Receives notifications from a PackExtensionJob, indicating either that
871 // packing succeeded or that there was some error.
872 class PackExtensionTestClient : public PackExtensionJob::Client {
873 public:
874 PackExtensionTestClient(const FilePath& expected_crx_path,
875 const FilePath& expected_private_key_path);
876 virtual void OnPackSuccess(const FilePath& crx_path,
877 const FilePath& private_key_path);
878 virtual void OnPackFailure(const std::string& error_message);
879
880 private:
881 const FilePath expected_crx_path_;
882 const FilePath expected_private_key_path_;
883 DISALLOW_COPY_AND_ASSIGN(PackExtensionTestClient);
884 };
885
PackExtensionTestClient(const FilePath & expected_crx_path,const FilePath & expected_private_key_path)886 PackExtensionTestClient::PackExtensionTestClient(
887 const FilePath& expected_crx_path,
888 const FilePath& expected_private_key_path)
889 : expected_crx_path_(expected_crx_path),
890 expected_private_key_path_(expected_private_key_path) {}
891
892 // If packing succeeded, we make sure that the package names match our
893 // expectations.
OnPackSuccess(const FilePath & crx_path,const FilePath & private_key_path)894 void PackExtensionTestClient::OnPackSuccess(const FilePath& crx_path,
895 const FilePath& private_key_path) {
896 // We got the notification and processed it; we don't expect any further tasks
897 // to be posted to the current thread, so we should stop blocking and continue
898 // on with the rest of the test.
899 // This call to |Quit()| matches the call to |Run()| in the
900 // |PackPunctuatedExtension| test.
901 MessageLoop::current()->Quit();
902 EXPECT_EQ(expected_crx_path_.value(), crx_path.value());
903 EXPECT_EQ(expected_private_key_path_.value(), private_key_path.value());
904 ASSERT_TRUE(file_util::PathExists(private_key_path));
905 }
906
907 // The tests are designed so that we never expect to see a packing error.
OnPackFailure(const std::string & error_message)908 void PackExtensionTestClient::OnPackFailure(const std::string& error_message) {
909 FAIL() << "Packing should not fail.";
910 }
911
912 // Test loading good extensions from the profile directory.
TEST_F(ExtensionServiceTest,LoadAllExtensionsFromDirectorySuccess)913 TEST_F(ExtensionServiceTest, LoadAllExtensionsFromDirectorySuccess) {
914 // Initialize the test dir with a good Preferences/extensions.
915 FilePath source_install_dir = data_dir_
916 .AppendASCII("good")
917 .AppendASCII("Extensions");
918 FilePath pref_path = source_install_dir
919 .DirName()
920 .AppendASCII("Preferences");
921 InitializeInstalledExtensionService(pref_path, source_install_dir);
922
923 service_->Init();
924
925 uint32 expected_num_extensions = 3u;
926 ASSERT_EQ(expected_num_extensions, loaded_.size());
927
928 EXPECT_EQ(std::string(good0), loaded_[0]->id());
929 EXPECT_EQ(std::string("My extension 1"),
930 loaded_[0]->name());
931 EXPECT_EQ(std::string("The first extension that I made."),
932 loaded_[0]->description());
933 EXPECT_EQ(Extension::INTERNAL, loaded_[0]->location());
934 EXPECT_TRUE(service_->GetExtensionById(loaded_[0]->id(), false));
935 EXPECT_EQ(expected_num_extensions, service_->extensions()->size());
936
937 ValidatePrefKeyCount(3);
938 ValidateIntegerPref(good0, "state", Extension::ENABLED);
939 ValidateIntegerPref(good0, "location", Extension::INTERNAL);
940 ValidateIntegerPref(good1, "state", Extension::ENABLED);
941 ValidateIntegerPref(good1, "location", Extension::INTERNAL);
942 ValidateIntegerPref(good2, "state", Extension::ENABLED);
943 ValidateIntegerPref(good2, "location", Extension::INTERNAL);
944
945 const Extension* extension = loaded_[0];
946 const UserScriptList& scripts = extension->content_scripts();
947 ASSERT_EQ(2u, scripts.size());
948 EXPECT_EQ(3u, scripts[0].url_patterns().size());
949 EXPECT_EQ("file://*",
950 scripts[0].url_patterns()[0].GetAsString());
951 EXPECT_EQ("http://*.google.com/*",
952 scripts[0].url_patterns()[1].GetAsString());
953 EXPECT_EQ("https://*.google.com/*",
954 scripts[0].url_patterns()[2].GetAsString());
955 EXPECT_EQ(2u, scripts[0].js_scripts().size());
956 ExtensionResource resource00(extension->id(),
957 scripts[0].js_scripts()[0].extension_root(),
958 scripts[0].js_scripts()[0].relative_path());
959 FilePath expected_path(extension->path().AppendASCII("script1.js"));
960 ASSERT_TRUE(file_util::AbsolutePath(&expected_path));
961 EXPECT_TRUE(resource00.ComparePathWithDefault(expected_path));
962 ExtensionResource resource01(extension->id(),
963 scripts[0].js_scripts()[1].extension_root(),
964 scripts[0].js_scripts()[1].relative_path());
965 expected_path = extension->path().AppendASCII("script2.js");
966 ASSERT_TRUE(file_util::AbsolutePath(&expected_path));
967 EXPECT_TRUE(resource01.ComparePathWithDefault(expected_path));
968 EXPECT_TRUE(extension->plugins().empty());
969 EXPECT_EQ(1u, scripts[1].url_patterns().size());
970 EXPECT_EQ("http://*.news.com/*", scripts[1].url_patterns()[0].GetAsString());
971 ExtensionResource resource10(extension->id(),
972 scripts[1].js_scripts()[0].extension_root(),
973 scripts[1].js_scripts()[0].relative_path());
974 expected_path =
975 extension->path().AppendASCII("js_files").AppendASCII("script3.js");
976 ASSERT_TRUE(file_util::AbsolutePath(&expected_path));
977 EXPECT_TRUE(resource10.ComparePathWithDefault(expected_path));
978 const std::vector<URLPattern> permissions = extension->host_permissions();
979 ASSERT_EQ(2u, permissions.size());
980 EXPECT_EQ("http://*.google.com/*", permissions[0].GetAsString());
981 EXPECT_EQ("https://*.google.com/*", permissions[1].GetAsString());
982
983 EXPECT_EQ(std::string(good1), loaded_[1]->id());
984 EXPECT_EQ(std::string("My extension 2"), loaded_[1]->name());
985 EXPECT_EQ(std::string(""), loaded_[1]->description());
986 EXPECT_EQ(loaded_[1]->GetResourceURL("background.html"),
987 loaded_[1]->background_url());
988 EXPECT_EQ(0u, loaded_[1]->content_scripts().size());
989 // We don't parse the plugins section on Chrome OS.
990 #if defined(OS_CHROMEOS)
991 EXPECT_EQ(0u, loaded_[1]->plugins().size());
992 #else
993 ASSERT_EQ(2u, loaded_[1]->plugins().size());
994 EXPECT_EQ(loaded_[1]->path().AppendASCII("content_plugin.dll").value(),
995 loaded_[1]->plugins()[0].path.value());
996 EXPECT_TRUE(loaded_[1]->plugins()[0].is_public);
997 EXPECT_EQ(loaded_[1]->path().AppendASCII("extension_plugin.dll").value(),
998 loaded_[1]->plugins()[1].path.value());
999 EXPECT_FALSE(loaded_[1]->plugins()[1].is_public);
1000 #endif
1001
1002 EXPECT_EQ(Extension::INTERNAL, loaded_[1]->location());
1003
1004 int index = expected_num_extensions - 1;
1005 EXPECT_EQ(std::string(good2), loaded_[index]->id());
1006 EXPECT_EQ(std::string("My extension 3"), loaded_[index]->name());
1007 EXPECT_EQ(std::string(""), loaded_[index]->description());
1008 EXPECT_EQ(0u, loaded_[index]->content_scripts().size());
1009 EXPECT_EQ(Extension::INTERNAL, loaded_[index]->location());
1010 };
1011
1012 // Test loading bad extensions from the profile directory.
TEST_F(ExtensionServiceTest,LoadAllExtensionsFromDirectoryFail)1013 TEST_F(ExtensionServiceTest, LoadAllExtensionsFromDirectoryFail) {
1014 // Initialize the test dir with a bad Preferences/extensions.
1015 FilePath source_install_dir = data_dir_
1016 .AppendASCII("bad")
1017 .AppendASCII("Extensions");
1018 FilePath pref_path = source_install_dir
1019 .DirName()
1020 .AppendASCII("Preferences");
1021
1022 InitializeInstalledExtensionService(pref_path, source_install_dir);
1023
1024 service_->Init();
1025 loop_.RunAllPending();
1026
1027 ASSERT_EQ(4u, GetErrors().size());
1028 ASSERT_EQ(0u, loaded_.size());
1029
1030 EXPECT_TRUE(MatchPattern(GetErrors()[0],
1031 std::string("Could not load extension from '*'. ") +
1032 extension_manifest_errors::kManifestUnreadable)) << GetErrors()[0];
1033
1034 EXPECT_TRUE(MatchPattern(GetErrors()[1],
1035 std::string("Could not load extension from '*'. ") +
1036 extension_manifest_errors::kManifestUnreadable)) << GetErrors()[1];
1037
1038 EXPECT_TRUE(MatchPattern(GetErrors()[2],
1039 std::string("Could not load extension from '*'. ") +
1040 extension_manifest_errors::kMissingFile)) << GetErrors()[2];
1041
1042 EXPECT_TRUE(MatchPattern(GetErrors()[3],
1043 std::string("Could not load extension from '*'. ") +
1044 extension_manifest_errors::kManifestUnreadable)) << GetErrors()[3];
1045 };
1046
1047 // Test that partially deleted extensions are cleaned up during startup
1048 // Test loading bad extensions from the profile directory.
TEST_F(ExtensionServiceTest,CleanupOnStartup)1049 TEST_F(ExtensionServiceTest, CleanupOnStartup) {
1050 FilePath source_install_dir = data_dir_
1051 .AppendASCII("good")
1052 .AppendASCII("Extensions");
1053 FilePath pref_path = source_install_dir
1054 .DirName()
1055 .AppendASCII("Preferences");
1056
1057 InitializeInstalledExtensionService(pref_path, source_install_dir);
1058
1059 // Simulate that one of them got partially deleted by clearing its pref.
1060 {
1061 DictionaryPrefUpdate update(profile_->GetPrefs(), "extensions.settings");
1062 DictionaryValue* dict = update.Get();
1063 ASSERT_TRUE(dict != NULL);
1064 dict->Remove("behllobkkfkfnphdnhnkndlbkcpglgmj", NULL);
1065 }
1066
1067 service_->Init();
1068 loop_.RunAllPending();
1069
1070 file_util::FileEnumerator dirs(extensions_install_dir_, false,
1071 file_util::FileEnumerator::DIRECTORIES);
1072 size_t count = 0;
1073 while (!dirs.Next().empty())
1074 count++;
1075
1076 // We should have only gotten two extensions now.
1077 EXPECT_EQ(2u, count);
1078
1079 // And extension1 dir should now be toast.
1080 FilePath extension_dir = extensions_install_dir_
1081 .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj");
1082 ASSERT_FALSE(file_util::PathExists(extension_dir));
1083 }
1084
1085 // Test installing extensions. This test tries to install few extensions using
1086 // crx files. If you need to change those crx files, feel free to repackage
1087 // them, throw away the key used and change the id's above.
TEST_F(ExtensionServiceTest,InstallExtension)1088 TEST_F(ExtensionServiceTest, InstallExtension) {
1089 InitializeEmptyExtensionService();
1090
1091 // Extensions not enabled.
1092 set_extensions_enabled(false);
1093 FilePath path = data_dir_.AppendASCII("good.crx");
1094 InstallCrx(path, false);
1095 set_extensions_enabled(true);
1096
1097 ValidatePrefKeyCount(0);
1098
1099 // A simple extension that should install without error.
1100 path = data_dir_.AppendASCII("good.crx");
1101 InstallCrx(path, true);
1102 // TODO(erikkay): verify the contents of the installed extension.
1103
1104 int pref_count = 0;
1105 ValidatePrefKeyCount(++pref_count);
1106 ValidateIntegerPref(good_crx, "state", Extension::ENABLED);
1107 ValidateIntegerPref(good_crx, "location", Extension::INTERNAL);
1108
1109 // An extension with page actions.
1110 path = data_dir_.AppendASCII("page_action.crx");
1111 InstallCrx(path, true);
1112 ValidatePrefKeyCount(++pref_count);
1113 ValidateIntegerPref(page_action, "state", Extension::ENABLED);
1114 ValidateIntegerPref(page_action, "location", Extension::INTERNAL);
1115
1116 // Bad signature.
1117 path = data_dir_.AppendASCII("bad_signature.crx");
1118 InstallCrx(path, false);
1119 ValidatePrefKeyCount(pref_count);
1120
1121 // 0-length extension file.
1122 path = data_dir_.AppendASCII("not_an_extension.crx");
1123 InstallCrx(path, false);
1124 ValidatePrefKeyCount(pref_count);
1125
1126 // Bad magic number.
1127 path = data_dir_.AppendASCII("bad_magic.crx");
1128 InstallCrx(path, false);
1129 ValidatePrefKeyCount(pref_count);
1130
1131 // Extensions cannot have folders or files that have underscores except in
1132 // certain whitelisted cases (eg _locales). This is an example of a broader
1133 // class of validation that we do to the directory structure of the extension.
1134 // We did not used to handle this correctly for installation.
1135 path = data_dir_.AppendASCII("bad_underscore.crx");
1136 InstallCrx(path, false);
1137 ValidatePrefKeyCount(pref_count);
1138
1139 // TODO(erikkay): add more tests for many of the failure cases.
1140 // TODO(erikkay): add tests for upgrade cases.
1141 }
1142
1143 // Test the handling of Extension::EXTERNAL_EXTENSION_UNINSTALLED
TEST_F(ExtensionServiceTest,UninstallingExternalExtensions)1144 TEST_F(ExtensionServiceTest, UninstallingExternalExtensions) {
1145 InitializeEmptyExtensionService();
1146
1147 FilePath path = data_dir_.AppendASCII("good.crx");
1148 set_extensions_enabled(true);
1149
1150 scoped_ptr<Version> version;
1151 version.reset(Version::GetVersionFromString("1.0.0.0"));
1152 // Install an external extension.
1153 service_->OnExternalExtensionFileFound(good_crx, version.get(),
1154 path, Extension::EXTERNAL_PREF);
1155 loop_.RunAllPending();
1156 ASSERT_TRUE(service_->GetExtensionById(good_crx, false));
1157
1158 // Uninstall it and check that its killbit gets set.
1159 service_->UninstallExtension(good_crx, false, NULL);
1160 loop_.RunAllPending();
1161 ValidateIntegerPref(good_crx, "location",
1162 Extension::EXTERNAL_EXTENSION_UNINSTALLED);
1163
1164 // Try to re-install it externally. This should fail because of the killbit.
1165 service_->OnExternalExtensionFileFound(good_crx, version.get(),
1166 path, Extension::EXTERNAL_PREF);
1167 loop_.RunAllPending();
1168 ASSERT_TRUE(NULL == service_->GetExtensionById(good_crx, false));
1169 ValidateIntegerPref(good_crx, "location",
1170 Extension::EXTERNAL_EXTENSION_UNINSTALLED);
1171
1172 version.reset(Version::GetVersionFromString("1.0.0.1"));
1173 // Repeat the same thing with a newer version of the extension.
1174 path = data_dir_.AppendASCII("good2.crx");
1175 service_->OnExternalExtensionFileFound(good_crx, version.get(),
1176 path, Extension::EXTERNAL_PREF);
1177 loop_.RunAllPending();
1178 ASSERT_TRUE(NULL == service_->GetExtensionById(good_crx, false));
1179 ValidateIntegerPref(good_crx, "location",
1180 Extension::EXTERNAL_EXTENSION_UNINSTALLED);
1181
1182 // Try adding the same extension from an external update URL.
1183 service_->pending_extension_manager()->AddFromExternalUpdateUrl(
1184 good_crx,
1185 GURL("http:://fake.update/url"),
1186 Extension::EXTERNAL_PREF_DOWNLOAD);
1187
1188 ASSERT_FALSE(service_->pending_extension_manager()->IsIdPending(good_crx));
1189 }
1190
1191 // Test that external extensions with incorrect IDs are not installed.
TEST_F(ExtensionServiceTest,FailOnWrongId)1192 TEST_F(ExtensionServiceTest, FailOnWrongId) {
1193 InitializeEmptyExtensionService();
1194 FilePath path = data_dir_.AppendASCII("good.crx");
1195 set_extensions_enabled(true);
1196
1197 scoped_ptr<Version> version;
1198 version.reset(Version::GetVersionFromString("1.0.0.0"));
1199
1200 const std::string wrong_id = all_zero;
1201 const std::string correct_id = good_crx;
1202 ASSERT_NE(correct_id, wrong_id);
1203
1204 // Install an external extension with an ID from the external
1205 // source that is not equal to the ID in the extension manifest.
1206 service_->OnExternalExtensionFileFound(
1207 wrong_id, version.get(), path, Extension::EXTERNAL_PREF);
1208
1209 loop_.RunAllPending();
1210 ASSERT_FALSE(service_->GetExtensionById(good_crx, false));
1211
1212 // Try again with the right ID. Expect success.
1213 service_->OnExternalExtensionFileFound(
1214 correct_id, version.get(), path, Extension::EXTERNAL_PREF);
1215 loop_.RunAllPending();
1216 ASSERT_TRUE(service_->GetExtensionById(good_crx, false));
1217 }
1218
1219 // Test that external extensions with incorrect versions are not installed.
TEST_F(ExtensionServiceTest,FailOnWrongVersion)1220 TEST_F(ExtensionServiceTest, FailOnWrongVersion) {
1221 InitializeEmptyExtensionService();
1222 FilePath path = data_dir_.AppendASCII("good.crx");
1223 set_extensions_enabled(true);
1224
1225 // Install an external extension with a version from the external
1226 // source that is not equal to the version in the extension manifest.
1227 scoped_ptr<Version> wrong_version;
1228 wrong_version.reset(Version::GetVersionFromString("1.2.3.4"));
1229 service_->OnExternalExtensionFileFound(
1230 good_crx, wrong_version.get(), path, Extension::EXTERNAL_PREF);
1231
1232 loop_.RunAllPending();
1233 ASSERT_FALSE(service_->GetExtensionById(good_crx, false));
1234
1235 // Try again with the right version. Expect success.
1236 scoped_ptr<Version> correct_version;
1237 correct_version.reset(Version::GetVersionFromString("1.0.0.0"));
1238 service_->OnExternalExtensionFileFound(
1239 good_crx, correct_version.get(), path, Extension::EXTERNAL_PREF);
1240 loop_.RunAllPending();
1241 ASSERT_TRUE(service_->GetExtensionById(good_crx, false));
1242 }
1243
1244 // Install a user script (they get converted automatically to an extension)
TEST_F(ExtensionServiceTest,InstallUserScript)1245 TEST_F(ExtensionServiceTest, InstallUserScript) {
1246 // The details of script conversion are tested elsewhere, this just tests
1247 // integration with ExtensionService.
1248 InitializeEmptyExtensionService();
1249
1250 FilePath path = data_dir_
1251 .AppendASCII("user_script_basic.user.js");
1252
1253 ASSERT_TRUE(file_util::PathExists(path));
1254 scoped_refptr<CrxInstaller> installer(
1255 new CrxInstaller(service_, NULL)); // silent install
1256 installer->InstallUserScript(
1257 path,
1258 GURL("http://www.aaronboodman.com/scripts/user_script_basic.user.js"));
1259
1260 loop_.RunAllPending();
1261 std::vector<std::string> errors = GetErrors();
1262 EXPECT_TRUE(installed_) << "Nothing was installed.";
1263 ASSERT_EQ(1u, loaded_.size()) << "Nothing was loaded.";
1264 EXPECT_EQ(0u, errors.size()) << "There were errors: "
1265 << JoinString(errors, ',');
1266 EXPECT_TRUE(service_->GetExtensionById(loaded_[0]->id(), false)) <<
1267 path.value();
1268
1269 installed_ = NULL;
1270 loaded_.clear();
1271 ExtensionErrorReporter::GetInstance()->ClearErrors();
1272 }
1273
1274 // This tests that the granted permissions preferences are correctly set when
1275 // installing an extension.
TEST_F(ExtensionServiceTest,GrantedPermissions)1276 TEST_F(ExtensionServiceTest, GrantedPermissions) {
1277 InitializeEmptyExtensionService();
1278 FilePath path = data_dir_
1279 .AppendASCII("permissions");
1280
1281 FilePath pem_path = path.AppendASCII("unknown.pem");
1282 path = path.AppendASCII("unknown");
1283
1284 ASSERT_TRUE(file_util::PathExists(pem_path));
1285 ASSERT_TRUE(file_util::PathExists(path));
1286
1287 ExtensionPrefs* prefs = service_->extension_prefs();
1288
1289 std::set<std::string> expected_api_perms;
1290 std::set<std::string> known_api_perms;
1291 bool full_access;
1292 ExtensionExtent expected_host_perms;
1293 ExtensionExtent known_host_perms;
1294
1295 // Make sure there aren't any granted permissions before the
1296 // extension is installed.
1297 EXPECT_FALSE(prefs->GetGrantedPermissions(
1298 permissions_crx, &full_access, &known_api_perms, &known_host_perms));
1299 EXPECT_TRUE(known_api_perms.empty());
1300 EXPECT_TRUE(known_host_perms.is_empty());
1301
1302 PackAndInstallCrx(path, pem_path, true);
1303
1304 EXPECT_EQ(0u, GetErrors().size());
1305 ASSERT_EQ(1u, service_->extensions()->size());
1306 std::string extension_id = service_->extensions()->at(0)->id();
1307 EXPECT_EQ(permissions_crx, extension_id);
1308
1309
1310 // Verify that the valid API permissions have been recognized.
1311 expected_api_perms.insert("tabs");
1312
1313 AddPattern(&expected_host_perms, "http://*.google.com/*");
1314 AddPattern(&expected_host_perms, "https://*.google.com/*");
1315 AddPattern(&expected_host_perms, "http://*.google.com.hk/*");
1316 AddPattern(&expected_host_perms, "http://www.example.com/*");
1317
1318 EXPECT_TRUE(prefs->GetGrantedPermissions(extension_id,
1319 &full_access,
1320 &known_api_perms,
1321 &known_host_perms));
1322
1323 EXPECT_EQ(expected_api_perms, known_api_perms);
1324 EXPECT_FALSE(full_access);
1325 AssertEqualExtents(&expected_host_perms, &known_host_perms);
1326 }
1327
1328 #if !defined(OS_CHROMEOS)
1329 // Tests that the granted permissions full_access bit gets set correctly when
1330 // an extension contains an NPAPI plugin. Don't run this test on Chrome OS
1331 // since they don't support plugins.
TEST_F(ExtensionServiceTest,GrantedFullAccessPermissions)1332 TEST_F(ExtensionServiceTest, GrantedFullAccessPermissions) {
1333 InitializeEmptyExtensionService();
1334
1335 FilePath path = data_dir_
1336 .AppendASCII("good")
1337 .AppendASCII("Extensions")
1338 .AppendASCII(good1)
1339 .AppendASCII("2");
1340
1341 ASSERT_TRUE(file_util::PathExists(path));
1342
1343 PackAndInstallCrx(path, true);
1344
1345 EXPECT_EQ(0u, GetErrors().size());
1346 EXPECT_EQ(1u, service_->extensions()->size());
1347 const Extension* extension = service_->extensions()->at(0);
1348 std::string extension_id = extension->id();
1349 ExtensionPrefs* prefs = service_->extension_prefs();
1350
1351 bool full_access;
1352 std::set<std::string> api_permissions;
1353 ExtensionExtent host_permissions;
1354 EXPECT_TRUE(prefs->GetGrantedPermissions(
1355 extension_id, &full_access, &api_permissions, &host_permissions));
1356
1357 EXPECT_TRUE(full_access);
1358 EXPECT_TRUE(api_permissions.empty());
1359 EXPECT_TRUE(host_permissions.is_empty());
1360 }
1361 #endif
1362
1363 // Tests that the extension is disabled when permissions are missing from
1364 // the extension's granted permissions preferences. (This simulates updating
1365 // the browser to a version which recognizes more permissions).
TEST_F(ExtensionServiceTest,GrantedAPIAndHostPermissions)1366 TEST_F(ExtensionServiceTest, GrantedAPIAndHostPermissions) {
1367 InitializeEmptyExtensionService();
1368
1369 FilePath path = data_dir_
1370 .AppendASCII("permissions")
1371 .AppendASCII("unknown");
1372
1373 ASSERT_TRUE(file_util::PathExists(path));
1374
1375 PackAndInstallCrx(path, true);
1376
1377 EXPECT_EQ(0u, GetErrors().size());
1378 EXPECT_EQ(1u, service_->extensions()->size());
1379 const Extension* extension = service_->extensions()->at(0);
1380 std::string extension_id = extension->id();
1381
1382 ExtensionPrefs* prefs = service_->extension_prefs();
1383
1384 std::set<std::string> expected_api_permissions;
1385 ExtensionExtent expected_host_permissions;
1386
1387 expected_api_permissions.insert("tabs");
1388 AddPattern(&expected_host_permissions, "http://*.google.com/*");
1389 AddPattern(&expected_host_permissions, "https://*.google.com/*");
1390 AddPattern(&expected_host_permissions, "http://*.google.com.hk/*");
1391 AddPattern(&expected_host_permissions, "http://www.example.com/*");
1392
1393 std::set<std::string> api_permissions;
1394 std::set<std::string> host_permissions;
1395
1396 // Test that the extension is disabled when an API permission is missing from
1397 // the extension's granted api permissions preference. (This simulates
1398 // updating the browser to a version which recognizes a new API permission).
1399 SetPrefStringSet(extension_id, "granted_permissions.api", api_permissions);
1400
1401 service_->ReloadExtensions();
1402
1403 EXPECT_EQ(1u, service_->disabled_extensions()->size());
1404 extension = service_->disabled_extensions()->at(0);
1405
1406 ASSERT_TRUE(prefs->GetExtensionState(extension_id) == Extension::DISABLED);
1407 ASSERT_TRUE(prefs->DidExtensionEscalatePermissions(extension_id));
1408
1409 // Now grant and re-enable the extension, making sure the prefs are updated.
1410 service_->GrantPermissionsAndEnableExtension(extension);
1411
1412 ASSERT_TRUE(prefs->GetExtensionState(extension_id) == Extension::ENABLED);
1413 ASSERT_FALSE(prefs->DidExtensionEscalatePermissions(extension_id));
1414
1415 std::set<std::string> current_api_permissions;
1416 ExtensionExtent current_host_permissions;
1417 bool current_full_access;
1418
1419 ASSERT_TRUE(prefs->GetGrantedPermissions(extension_id,
1420 ¤t_full_access,
1421 ¤t_api_permissions,
1422 ¤t_host_permissions));
1423
1424 ASSERT_FALSE(current_full_access);
1425 ASSERT_EQ(expected_api_permissions, current_api_permissions);
1426 AssertEqualExtents(&expected_host_permissions, ¤t_host_permissions);
1427
1428 // Tests that the extension is disabled when a host permission is missing from
1429 // the extension's granted host permissions preference. (This simulates
1430 // updating the browser to a version which recognizes additional host
1431 // permissions).
1432 api_permissions.clear();
1433 host_permissions.clear();
1434 current_api_permissions.clear();
1435 current_host_permissions.ClearPaths();
1436
1437 api_permissions.insert("tabs");
1438 host_permissions.insert("http://*.google.com/*");
1439 host_permissions.insert("https://*.google.com/*");
1440 host_permissions.insert("http://*.google.com.hk/*");
1441
1442 SetPrefStringSet(extension_id, "granted_permissions.api", api_permissions);
1443 SetPrefStringSet(extension_id, "granted_permissions.host", host_permissions);
1444
1445 service_->ReloadExtensions();
1446
1447 EXPECT_EQ(1u, service_->disabled_extensions()->size());
1448 extension = service_->disabled_extensions()->at(0);
1449
1450 ASSERT_TRUE(prefs->GetExtensionState(extension_id) == Extension::DISABLED);
1451 ASSERT_TRUE(prefs->DidExtensionEscalatePermissions(extension_id));
1452
1453 // Now grant and re-enable the extension, making sure the prefs are updated.
1454 service_->GrantPermissionsAndEnableExtension(extension);
1455
1456 ASSERT_TRUE(prefs->GetExtensionState(extension_id) == Extension::ENABLED);
1457 ASSERT_FALSE(prefs->DidExtensionEscalatePermissions(extension_id));
1458
1459 ASSERT_TRUE(prefs->GetGrantedPermissions(extension_id,
1460 ¤t_full_access,
1461 ¤t_api_permissions,
1462 ¤t_host_permissions));
1463
1464 ASSERT_FALSE(current_full_access);
1465 ASSERT_EQ(expected_api_permissions, current_api_permissions);
1466 AssertEqualExtents(&expected_host_permissions, ¤t_host_permissions);
1467
1468 // Tests that the granted permissions preferences are initialized when
1469 // migrating from the old pref schema.
1470 current_api_permissions.clear();
1471 current_host_permissions.ClearPaths();
1472
1473 ClearPref(extension_id, "granted_permissions");
1474
1475 service_->ReloadExtensions();
1476
1477 EXPECT_EQ(1u, service_->extensions()->size());
1478 extension = service_->extensions()->at(0);
1479
1480 ASSERT_TRUE(prefs->GetExtensionState(extension_id) == Extension::ENABLED);
1481 ASSERT_FALSE(prefs->DidExtensionEscalatePermissions(extension_id));
1482
1483 ASSERT_TRUE(prefs->GetGrantedPermissions(extension_id,
1484 ¤t_full_access,
1485 ¤t_api_permissions,
1486 ¤t_host_permissions));
1487
1488 ASSERT_FALSE(current_full_access);
1489 ASSERT_EQ(expected_api_permissions, current_api_permissions);
1490 AssertEqualExtents(&expected_host_permissions, ¤t_host_permissions);
1491 }
1492
1493 // Test Packaging and installing an extension.
TEST_F(ExtensionServiceTest,PackExtension)1494 TEST_F(ExtensionServiceTest, PackExtension) {
1495 InitializeEmptyExtensionService();
1496 FilePath input_directory = data_dir_
1497 .AppendASCII("good")
1498 .AppendASCII("Extensions")
1499 .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj")
1500 .AppendASCII("1.0.0.0");
1501
1502 ScopedTempDir temp_dir;
1503 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
1504 FilePath output_directory = temp_dir.path();
1505
1506 FilePath crx_path(output_directory.AppendASCII("ex1.crx"));
1507 FilePath privkey_path(output_directory.AppendASCII("privkey.pem"));
1508
1509 scoped_ptr<ExtensionCreator> creator(new ExtensionCreator());
1510 ASSERT_TRUE(creator->Run(input_directory, crx_path, FilePath(),
1511 privkey_path));
1512
1513 ASSERT_TRUE(file_util::PathExists(privkey_path));
1514 InstallCrx(crx_path, true);
1515
1516 // Try packing with invalid paths.
1517 creator.reset(new ExtensionCreator());
1518 ASSERT_FALSE(creator->Run(FilePath(), FilePath(), FilePath(), FilePath()));
1519
1520 // Try packing an empty directory. Should fail because an empty directory is
1521 // not a valid extension.
1522 ScopedTempDir temp_dir2;
1523 ASSERT_TRUE(temp_dir2.CreateUniqueTempDir());
1524 creator.reset(new ExtensionCreator());
1525 ASSERT_FALSE(creator->Run(temp_dir2.path(), crx_path, privkey_path,
1526 FilePath()));
1527
1528 // Try packing with an invalid manifest.
1529 std::string invalid_manifest_content = "I am not a manifest.";
1530 ASSERT_TRUE(file_util::WriteFile(
1531 temp_dir2.path().Append(Extension::kManifestFilename),
1532 invalid_manifest_content.c_str(), invalid_manifest_content.size()));
1533 creator.reset(new ExtensionCreator());
1534 ASSERT_FALSE(creator->Run(temp_dir2.path(), crx_path, privkey_path,
1535 FilePath()));
1536 }
1537
1538 // Test Packaging and installing an extension whose name contains punctuation.
TEST_F(ExtensionServiceTest,PackPunctuatedExtension)1539 TEST_F(ExtensionServiceTest, PackPunctuatedExtension) {
1540 InitializeEmptyExtensionService();
1541 FilePath input_directory = data_dir_
1542 .AppendASCII("good")
1543 .AppendASCII("Extensions")
1544 .AppendASCII(good0)
1545 .AppendASCII("1.0.0.0");
1546
1547 ScopedTempDir temp_dir;
1548 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
1549
1550 // Extension names containing punctuation, and the expected names for the
1551 // packed extensions.
1552 const FilePath punctuated_names[] = {
1553 FilePath(FilePath::StringType(
1554 FILE_PATH_LITERAL("this.extensions.name.has.periods"))),
1555 FilePath(FilePath::StringType(
1556 FILE_PATH_LITERAL(".thisextensionsnamestartswithaperiod"))),
1557 NormalizeSeparators(FilePath(FilePath::StringType(
1558 FILE_PATH_LITERAL("thisextensionhasaslashinitsname/")))),
1559 };
1560 const FilePath expected_crx_names[] = {
1561 FilePath(FilePath::StringType(
1562 FILE_PATH_LITERAL("this.extensions.name.has.periods.crx"))),
1563 FilePath(FilePath::StringType(
1564 FILE_PATH_LITERAL(".thisextensionsnamestartswithaperiod.crx"))),
1565 FilePath(FilePath::StringType(
1566 FILE_PATH_LITERAL("thisextensionhasaslashinitsname.crx"))),
1567 };
1568 const FilePath expected_private_key_names[] = {
1569 FilePath(FilePath::StringType(
1570 FILE_PATH_LITERAL("this.extensions.name.has.periods.pem"))),
1571 FilePath(FilePath::StringType(
1572 FILE_PATH_LITERAL(".thisextensionsnamestartswithaperiod.pem"))),
1573 FilePath(FilePath::StringType(
1574 FILE_PATH_LITERAL("thisextensionhasaslashinitsname.pem"))),
1575 };
1576
1577 for (size_t i = 0; i < arraysize(punctuated_names); ++i) {
1578 SCOPED_TRACE(punctuated_names[i].value().c_str());
1579 FilePath output_dir = temp_dir.path().Append(punctuated_names[i]);
1580
1581 // Copy the extension into the output directory, as PackExtensionJob doesn't
1582 // let us choose where to output the packed extension.
1583 ASSERT_TRUE(file_util::CopyDirectory(input_directory, output_dir, true));
1584
1585 FilePath expected_crx_path = temp_dir.path().Append(expected_crx_names[i]);
1586 FilePath expected_private_key_path =
1587 temp_dir.path().Append(expected_private_key_names[i]);
1588 PackExtensionTestClient pack_client(expected_crx_path,
1589 expected_private_key_path);
1590 scoped_refptr<PackExtensionJob> packer(new PackExtensionJob(&pack_client,
1591 output_dir,
1592 FilePath()));
1593 packer->Start();
1594
1595 // The packer will post a notification task to the current thread's message
1596 // loop when it is finished. We manually run the loop here so that we
1597 // block and catch the notification; otherwise, the process would exit.
1598 // This call to |Run()| is matched by a call to |Quit()| in the
1599 // |PackExtensionTestClient|'s notification handling code.
1600 MessageLoop::current()->Run();
1601
1602 if (HasFatalFailure())
1603 return;
1604
1605 InstallCrx(expected_crx_path, true);
1606 }
1607 }
1608
1609 // Test Packaging and installing an extension using an openssl generated key.
1610 // The openssl is generated with the following:
1611 // > openssl genrsa -out privkey.pem 1024
1612 // > openssl pkcs8 -topk8 -nocrypt -in privkey.pem -out privkey_asn1.pem
1613 // The privkey.pem is a PrivateKey, and the pcks8 -topk8 creates a
1614 // PrivateKeyInfo ASN.1 structure, we our RSAPrivateKey expects.
TEST_F(ExtensionServiceTest,PackExtensionOpenSSLKey)1615 TEST_F(ExtensionServiceTest, PackExtensionOpenSSLKey) {
1616 InitializeEmptyExtensionService();
1617 FilePath input_directory = data_dir_
1618 .AppendASCII("good")
1619 .AppendASCII("Extensions")
1620 .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj")
1621 .AppendASCII("1.0.0.0");
1622 FilePath privkey_path(data_dir_.AppendASCII(
1623 "openssl_privkey_asn1.pem"));
1624 ASSERT_TRUE(file_util::PathExists(privkey_path));
1625
1626 ScopedTempDir temp_dir;
1627 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
1628 FilePath output_directory = temp_dir.path();
1629
1630 FilePath crx_path(output_directory.AppendASCII("ex1.crx"));
1631
1632 scoped_ptr<ExtensionCreator> creator(new ExtensionCreator());
1633 ASSERT_TRUE(creator->Run(input_directory, crx_path, privkey_path,
1634 FilePath()));
1635
1636 InstallCrx(crx_path, true);
1637 }
1638
TEST_F(ExtensionServiceTest,InstallTheme)1639 TEST_F(ExtensionServiceTest, InstallTheme) {
1640 InitializeEmptyExtensionService();
1641
1642 // A theme.
1643 FilePath path = data_dir_.AppendASCII("theme.crx");
1644 InstallCrx(path, true);
1645 int pref_count = 0;
1646 ValidatePrefKeyCount(++pref_count);
1647 ValidateIntegerPref(theme_crx, "state", Extension::ENABLED);
1648 ValidateIntegerPref(theme_crx, "location", Extension::INTERNAL);
1649
1650 // A theme when extensions are disabled. Themes can be installed, even when
1651 // extensions are disabled.
1652 set_extensions_enabled(false);
1653 path = data_dir_.AppendASCII("theme2.crx");
1654 InstallCrx(path, true);
1655 ValidatePrefKeyCount(++pref_count);
1656 ValidateIntegerPref(theme2_crx, "state", Extension::ENABLED);
1657 ValidateIntegerPref(theme2_crx, "location", Extension::INTERNAL);
1658
1659 // A theme with extension elements. Themes cannot have extension elements so
1660 // this test should fail.
1661 set_extensions_enabled(true);
1662 path = data_dir_.AppendASCII("theme_with_extension.crx");
1663 InstallCrx(path, false);
1664 ValidatePrefKeyCount(pref_count);
1665
1666 // A theme with image resources missing (misspelt path).
1667 path = data_dir_.AppendASCII("theme_missing_image.crx");
1668 InstallCrx(path, false);
1669 ValidatePrefKeyCount(pref_count);
1670 }
1671
TEST_F(ExtensionServiceTest,LoadLocalizedTheme)1672 TEST_F(ExtensionServiceTest, LoadLocalizedTheme) {
1673 // Load.
1674 InitializeEmptyExtensionService();
1675 FilePath extension_path = data_dir_
1676 .AppendASCII("theme_i18n");
1677
1678 service_->LoadExtension(extension_path);
1679 loop_.RunAllPending();
1680 EXPECT_EQ(0u, GetErrors().size());
1681 ASSERT_EQ(1u, loaded_.size());
1682 EXPECT_EQ(1u, service_->extensions()->size());
1683 EXPECT_EQ("name", service_->extensions()->at(0)->name());
1684 EXPECT_EQ("description", service_->extensions()->at(0)->description());
1685 }
1686
TEST_F(ExtensionServiceTest,InstallLocalizedTheme)1687 TEST_F(ExtensionServiceTest, InstallLocalizedTheme) {
1688 InitializeEmptyExtensionService();
1689 FilePath theme_path = data_dir_
1690 .AppendASCII("theme_i18n");
1691
1692 PackAndInstallCrx(theme_path, true);
1693
1694 EXPECT_EQ(0u, GetErrors().size());
1695 EXPECT_EQ(1u, service_->extensions()->size());
1696 EXPECT_EQ("name", service_->extensions()->at(0)->name());
1697 EXPECT_EQ("description", service_->extensions()->at(0)->description());
1698 }
1699
TEST_F(ExtensionServiceTest,InstallApps)1700 TEST_F(ExtensionServiceTest, InstallApps) {
1701 InitializeEmptyExtensionService();
1702
1703 // An empty app.
1704 PackAndInstallCrx(data_dir_.AppendASCII("app1"), true);
1705 int pref_count = 0;
1706 ValidatePrefKeyCount(++pref_count);
1707 ASSERT_EQ(1u, service_->extensions()->size());
1708 std::string id = service_->extensions()->at(0)->id();
1709 ValidateIntegerPref(id, "state", Extension::ENABLED);
1710 ValidateIntegerPref(id, "location", Extension::INTERNAL);
1711
1712 // Another app with non-overlapping extent. Should succeed.
1713 PackAndInstallCrx(data_dir_.AppendASCII("app2"), true);
1714 ValidatePrefKeyCount(++pref_count);
1715
1716 // A third app whose extent overlaps the first. Should fail.
1717 PackAndInstallCrx(data_dir_.AppendASCII("app3"), false);
1718 ValidatePrefKeyCount(pref_count);
1719 }
1720
TEST_F(ExtensionServiceTest,UpdateApps)1721 TEST_F(ExtensionServiceTest, UpdateApps) {
1722 InitializeEmptyExtensionService();
1723 FilePath extensions_path = data_dir_.AppendASCII("app_update");
1724
1725 // First install v1 of a hosted app.
1726 InstallCrx(extensions_path.AppendASCII("v1.crx"), true);
1727 ASSERT_EQ(1u, service_->extensions()->size());
1728 std::string id = service_->extensions()->at(0)->id();
1729 ASSERT_EQ(std::string("1"),
1730 service_->extensions()->at(0)->version()->GetString());
1731
1732 // Now try updating to v2.
1733 UpdateExtension(id,
1734 extensions_path.AppendASCII("v2.crx"),
1735 ENABLED);
1736 ASSERT_EQ(std::string("2"),
1737 service_->extensions()->at(0)->version()->GetString());
1738 }
1739
TEST_F(ExtensionServiceTest,InstallAppsWithUnlimtedStorage)1740 TEST_F(ExtensionServiceTest, InstallAppsWithUnlimtedStorage) {
1741 InitializeEmptyExtensionService();
1742 EXPECT_TRUE(service_->extensions()->empty());
1743
1744 int pref_count = 0;
1745
1746 // Install app1 with unlimited storage.
1747 PackAndInstallCrx(data_dir_.AppendASCII("app1"), true);
1748 ValidatePrefKeyCount(++pref_count);
1749 ASSERT_EQ(1u, service_->extensions()->size());
1750 const Extension* extension = service_->extensions()->at(0);
1751 const std::string id1 = extension->id();
1752 EXPECT_TRUE(extension->HasApiPermission(
1753 Extension::kUnlimitedStoragePermission));
1754 EXPECT_TRUE(extension->web_extent().ContainsURL(
1755 extension->GetFullLaunchURL()));
1756 const GURL origin1(extension->GetFullLaunchURL().GetOrigin());
1757 EXPECT_TRUE(profile_->GetExtensionSpecialStoragePolicy()->
1758 IsStorageUnlimited(origin1));
1759
1760 // Install app2 from the same origin with unlimited storage.
1761 PackAndInstallCrx(data_dir_.AppendASCII("app2"), true);
1762 ValidatePrefKeyCount(++pref_count);
1763 ASSERT_EQ(2u, service_->extensions()->size());
1764 extension = service_->extensions()->at(1);
1765 const std::string id2 = extension->id();
1766 EXPECT_TRUE(extension->HasApiPermission(
1767 Extension::kUnlimitedStoragePermission));
1768 EXPECT_TRUE(extension->web_extent().ContainsURL(
1769 extension->GetFullLaunchURL()));
1770 const GURL origin2(extension->GetFullLaunchURL().GetOrigin());
1771 EXPECT_EQ(origin1, origin2);
1772 EXPECT_TRUE(profile_->GetExtensionSpecialStoragePolicy()->
1773 IsStorageUnlimited(origin2));
1774
1775
1776 // Uninstall one of them, unlimited storage should still be granted
1777 // to the origin.
1778 service_->UninstallExtension(id1, false, NULL);
1779 loop_.RunAllPending();
1780 EXPECT_EQ(1u, service_->extensions()->size());
1781 EXPECT_TRUE(profile_->GetExtensionSpecialStoragePolicy()->
1782 IsStorageUnlimited(origin1));
1783
1784
1785 // Uninstall the other, unlimited storage should be revoked.
1786 service_->UninstallExtension(id2, false, NULL);
1787 loop_.RunAllPending();
1788 EXPECT_EQ(0u, service_->extensions()->size());
1789 EXPECT_FALSE(profile_->GetExtensionSpecialStoragePolicy()->
1790 IsStorageUnlimited(origin2));
1791 }
1792
TEST_F(ExtensionServiceTest,InstallAppsAndCheckStorageProtection)1793 TEST_F(ExtensionServiceTest, InstallAppsAndCheckStorageProtection) {
1794 InitializeEmptyExtensionService();
1795 EXPECT_TRUE(service_->extensions()->empty());
1796
1797 int pref_count = 0;
1798
1799 PackAndInstallCrx(data_dir_.AppendASCII("app1"), true);
1800 ValidatePrefKeyCount(++pref_count);
1801 ASSERT_EQ(1u, service_->extensions()->size());
1802 const Extension* extension = service_->extensions()->at(0);
1803 EXPECT_TRUE(extension->is_app());
1804 const std::string id1 = extension->id();
1805 const GURL origin1(extension->GetFullLaunchURL().GetOrigin());
1806 EXPECT_TRUE(profile_->GetExtensionSpecialStoragePolicy()->
1807 IsStorageProtected(origin1));
1808
1809 // App 4 has a different origin (maps.google.com).
1810 PackAndInstallCrx(data_dir_.AppendASCII("app4"), true);
1811 ValidatePrefKeyCount(++pref_count);
1812 ASSERT_EQ(2u, service_->extensions()->size());
1813 extension = service_->extensions()->at(1);
1814 const std::string id2 = extension->id();
1815 const GURL origin2(extension->GetFullLaunchURL().GetOrigin());
1816 ASSERT_NE(origin1, origin2);
1817 EXPECT_TRUE(profile_->GetExtensionSpecialStoragePolicy()->
1818 IsStorageProtected(origin2));
1819
1820 service_->UninstallExtension(id1, false, NULL);
1821 loop_.RunAllPending();
1822 EXPECT_EQ(1u, service_->extensions()->size());
1823
1824 service_->UninstallExtension(id2, false, NULL);
1825 loop_.RunAllPending();
1826
1827 EXPECT_TRUE(service_->extensions()->empty());
1828 EXPECT_FALSE(profile_->GetExtensionSpecialStoragePolicy()->
1829 IsStorageProtected(origin1));
1830 EXPECT_FALSE(profile_->GetExtensionSpecialStoragePolicy()->
1831 IsStorageProtected(origin2));
1832 }
1833
1834 // Test that when an extension version is reinstalled, nothing happens.
TEST_F(ExtensionServiceTest,Reinstall)1835 TEST_F(ExtensionServiceTest, Reinstall) {
1836 InitializeEmptyExtensionService();
1837
1838 // A simple extension that should install without error.
1839 FilePath path = data_dir_.AppendASCII("good.crx");
1840 StartCrxInstall(path);
1841 loop_.RunAllPending();
1842
1843 ASSERT_TRUE(installed_);
1844 ASSERT_EQ(1u, loaded_.size());
1845 ASSERT_EQ(0u, GetErrors().size());
1846 ValidatePrefKeyCount(1);
1847 ValidateIntegerPref(good_crx, "state", Extension::ENABLED);
1848 ValidateIntegerPref(good_crx, "location", Extension::INTERNAL);
1849
1850 installed_ = NULL;
1851 loaded_.clear();
1852 ExtensionErrorReporter::GetInstance()->ClearErrors();
1853
1854 // Reinstall the same version, it should overwrite the previous one.
1855 StartCrxInstall(path);
1856 loop_.RunAllPending();
1857
1858 ASSERT_TRUE(installed_);
1859 ASSERT_EQ(1u, loaded_.size());
1860 ASSERT_EQ(0u, GetErrors().size());
1861 ValidatePrefKeyCount(1);
1862 ValidateIntegerPref(good_crx, "state", Extension::ENABLED);
1863 ValidateIntegerPref(good_crx, "location", Extension::INTERNAL);
1864 }
1865
1866 // Test upgrading a signed extension.
TEST_F(ExtensionServiceTest,UpgradeSignedGood)1867 TEST_F(ExtensionServiceTest, UpgradeSignedGood) {
1868 InitializeEmptyExtensionService();
1869
1870 FilePath path = data_dir_.AppendASCII("good.crx");
1871 StartCrxInstall(path);
1872 loop_.RunAllPending();
1873
1874 ASSERT_TRUE(installed_);
1875 ASSERT_EQ(1u, loaded_.size());
1876 ASSERT_EQ("1.0.0.0", loaded_[0]->version()->GetString());
1877 ASSERT_EQ(0u, GetErrors().size());
1878
1879 // Upgrade to version 2.0
1880 path = data_dir_.AppendASCII("good2.crx");
1881 StartCrxInstall(path);
1882 loop_.RunAllPending();
1883
1884 ASSERT_TRUE(installed_);
1885 ASSERT_EQ(1u, loaded_.size());
1886 ASSERT_EQ("1.0.0.1", loaded_[0]->version()->GetString());
1887 ASSERT_EQ(0u, GetErrors().size());
1888 }
1889
1890 // Test upgrading a signed extension with a bad signature.
TEST_F(ExtensionServiceTest,UpgradeSignedBad)1891 TEST_F(ExtensionServiceTest, UpgradeSignedBad) {
1892 InitializeEmptyExtensionService();
1893
1894 FilePath path = data_dir_.AppendASCII("good.crx");
1895 StartCrxInstall(path);
1896 loop_.RunAllPending();
1897
1898 ASSERT_TRUE(installed_);
1899 ASSERT_EQ(1u, loaded_.size());
1900 ASSERT_EQ(0u, GetErrors().size());
1901 installed_ = NULL;
1902
1903 // Try upgrading with a bad signature. This should fail during the unpack,
1904 // because the key will not match the signature.
1905 path = data_dir_.AppendASCII("bad_signature.crx");
1906 StartCrxInstall(path);
1907 loop_.RunAllPending();
1908
1909 ASSERT_FALSE(installed_);
1910 ASSERT_EQ(1u, loaded_.size());
1911 ASSERT_EQ(1u, GetErrors().size());
1912 }
1913
1914 // Test a normal update via the UpdateExtension API
TEST_F(ExtensionServiceTest,UpdateExtension)1915 TEST_F(ExtensionServiceTest, UpdateExtension) {
1916 InitializeEmptyExtensionService();
1917
1918 FilePath path = data_dir_.AppendASCII("good.crx");
1919
1920 InstallCrx(path, true);
1921 const Extension* good = service_->extensions()->at(0);
1922 ASSERT_EQ("1.0.0.0", good->VersionString());
1923 ASSERT_EQ(good_crx, good->id());
1924
1925 path = data_dir_.AppendASCII("good2.crx");
1926 UpdateExtension(good_crx, path, ENABLED);
1927 ASSERT_EQ("1.0.0.1", loaded_[0]->version()->GetString());
1928 }
1929
1930 // Test updating a not-already-installed extension - this should fail
TEST_F(ExtensionServiceTest,UpdateNotInstalledExtension)1931 TEST_F(ExtensionServiceTest, UpdateNotInstalledExtension) {
1932 InitializeEmptyExtensionService();
1933
1934 FilePath path = data_dir_.AppendASCII("good.crx");
1935 UpdateExtension(good_crx, path, UPDATED);
1936 loop_.RunAllPending();
1937
1938 ASSERT_EQ(0u, service_->extensions()->size());
1939 ASSERT_FALSE(installed_);
1940 ASSERT_EQ(0u, loaded_.size());
1941 }
1942
1943 // Makes sure you can't downgrade an extension via UpdateExtension
TEST_F(ExtensionServiceTest,UpdateWillNotDowngrade)1944 TEST_F(ExtensionServiceTest, UpdateWillNotDowngrade) {
1945 InitializeEmptyExtensionService();
1946
1947 FilePath path = data_dir_.AppendASCII("good2.crx");
1948
1949 InstallCrx(path, true);
1950 const Extension* good = service_->extensions()->at(0);
1951 ASSERT_EQ("1.0.0.1", good->VersionString());
1952 ASSERT_EQ(good_crx, good->id());
1953
1954 // Change path from good2.crx -> good.crx
1955 path = data_dir_.AppendASCII("good.crx");
1956 UpdateExtension(good_crx, path, FAILED);
1957 ASSERT_EQ("1.0.0.1", service_->extensions()->at(0)->VersionString());
1958 }
1959
1960 // Make sure calling update with an identical version does nothing
TEST_F(ExtensionServiceTest,UpdateToSameVersionIsNoop)1961 TEST_F(ExtensionServiceTest, UpdateToSameVersionIsNoop) {
1962 InitializeEmptyExtensionService();
1963
1964 FilePath path = data_dir_.AppendASCII("good.crx");
1965
1966 InstallCrx(path, true);
1967 const Extension* good = service_->extensions()->at(0);
1968 ASSERT_EQ(good_crx, good->id());
1969 UpdateExtension(good_crx, path, FAILED_SILENTLY);
1970 }
1971
1972 // Tests that updating an extension does not clobber old state.
TEST_F(ExtensionServiceTest,UpdateExtensionPreservesState)1973 TEST_F(ExtensionServiceTest, UpdateExtensionPreservesState) {
1974 InitializeEmptyExtensionService();
1975
1976 FilePath path = data_dir_.AppendASCII("good.crx");
1977
1978 InstallCrx(path, true);
1979 const Extension* good = service_->extensions()->at(0);
1980 ASSERT_EQ("1.0.0.0", good->VersionString());
1981 ASSERT_EQ(good_crx, good->id());
1982
1983 // Disable it and allow it to run in incognito. These settings should carry
1984 // over to the updated version.
1985 service_->DisableExtension(good->id());
1986 service_->SetIsIncognitoEnabled(good->id(), true);
1987
1988 path = data_dir_.AppendASCII("good2.crx");
1989 UpdateExtension(good_crx, path, INSTALLED);
1990 ASSERT_EQ(1u, service_->disabled_extensions()->size());
1991 const Extension* good2 = service_->disabled_extensions()->at(0);
1992 ASSERT_EQ("1.0.0.1", good2->version()->GetString());
1993 EXPECT_TRUE(service_->IsIncognitoEnabled(good2->id()));
1994 }
1995
1996 // Tests that updating preserves extension location.
TEST_F(ExtensionServiceTest,UpdateExtensionPreservesLocation)1997 TEST_F(ExtensionServiceTest, UpdateExtensionPreservesLocation) {
1998 InitializeEmptyExtensionService();
1999
2000 FilePath path = data_dir_.AppendASCII("good.crx");
2001
2002 InstallCrx(path, true);
2003 const Extension* good = service_->extensions()->at(0);
2004
2005 ASSERT_EQ("1.0.0.0", good->VersionString());
2006 ASSERT_EQ(good_crx, good->id());
2007
2008 // Simulate non-internal location.
2009 const_cast<Extension*>(good)->location_ = Extension::EXTERNAL_PREF;
2010
2011 path = data_dir_.AppendASCII("good2.crx");
2012 UpdateExtension(good_crx, path, ENABLED);
2013 const Extension* good2 = service_->extensions()->at(0);
2014 ASSERT_EQ("1.0.0.1", good2->version()->GetString());
2015 EXPECT_EQ(good2->location(), Extension::EXTERNAL_PREF);
2016 }
2017
2018 // Makes sure that LOAD extension types can downgrade.
TEST_F(ExtensionServiceTest,LoadExtensionsCanDowngrade)2019 TEST_F(ExtensionServiceTest, LoadExtensionsCanDowngrade) {
2020 InitializeEmptyExtensionService();
2021
2022 ScopedTempDir temp;
2023 ASSERT_TRUE(temp.CreateUniqueTempDir());
2024
2025 // We'll write the extension manifest dynamically to a temporary path
2026 // to make it easier to change the version number.
2027 FilePath extension_path = temp.path();
2028 FilePath manifest_path = extension_path.Append(Extension::kManifestFilename);
2029 ASSERT_FALSE(file_util::PathExists(manifest_path));
2030
2031 // Start with version 2.0.
2032 DictionaryValue manifest;
2033 manifest.SetString("version", "2.0");
2034 manifest.SetString("name", "LOAD Downgrade Test");
2035
2036 JSONFileValueSerializer serializer(manifest_path);
2037 ASSERT_TRUE(serializer.Serialize(manifest));
2038
2039 service_->LoadExtension(extension_path);
2040 loop_.RunAllPending();
2041
2042 EXPECT_EQ(0u, GetErrors().size());
2043 ASSERT_EQ(1u, loaded_.size());
2044 EXPECT_EQ(Extension::LOAD, loaded_[0]->location());
2045 EXPECT_EQ(1u, service_->extensions()->size());
2046 EXPECT_EQ("2.0", loaded_[0]->VersionString());
2047
2048 // Now set the version number to 1.0, reload the extensions and verify that
2049 // the downgrade was accepted.
2050 manifest.SetString("version", "1.0");
2051 ASSERT_TRUE(serializer.Serialize(manifest));
2052
2053 service_->LoadExtension(extension_path);
2054 loop_.RunAllPending();
2055
2056 EXPECT_EQ(0u, GetErrors().size());
2057 ASSERT_EQ(1u, loaded_.size());
2058 EXPECT_EQ(Extension::LOAD, loaded_[0]->location());
2059 EXPECT_EQ(1u, service_->extensions()->size());
2060 EXPECT_EQ("1.0", loaded_[0]->VersionString());
2061 }
2062
2063 namespace {
2064
IsExtension(const Extension & extension)2065 bool IsExtension(const Extension& extension) {
2066 return extension.GetType() == Extension::TYPE_EXTENSION;
2067 }
2068
2069 } // namespace
2070
2071 // Test adding a pending extension.
TEST_F(ExtensionServiceTest,AddPendingExtensionFromSync)2072 TEST_F(ExtensionServiceTest, AddPendingExtensionFromSync) {
2073 InitializeEmptyExtensionService();
2074
2075 const std::string kFakeId(all_zero);
2076 const GURL kFakeUpdateURL("http:://fake.update/url");
2077 const bool kFakeInstallSilently(true);
2078 const Extension::State kFakeInitialState(Extension::ENABLED);
2079 const bool kFakeInitialIncognitoEnabled(false);
2080
2081 service_->pending_extension_manager()->AddFromSync(
2082 kFakeId, kFakeUpdateURL, &IsExtension,
2083 kFakeInstallSilently, kFakeInitialState, kFakeInitialIncognitoEnabled);
2084
2085 PendingExtensionInfo pending_extension_info;
2086 ASSERT_TRUE(service_->pending_extension_manager()->GetById(
2087 kFakeId, &pending_extension_info));
2088 EXPECT_EQ(kFakeUpdateURL, pending_extension_info.update_url());
2089 EXPECT_EQ(&IsExtension, pending_extension_info.should_allow_install_);
2090 EXPECT_EQ(kFakeInstallSilently, pending_extension_info.install_silently());
2091 }
2092
2093 namespace {
2094 const char kGoodId[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
2095 const char kGoodUpdateURL[] = "http://good.update/url";
2096 const bool kGoodIsFromSync = true;
2097 const bool kGoodInstallSilently = true;
2098 const Extension::State kGoodInitialState = Extension::DISABLED;
2099 const bool kGoodInitialIncognitoEnabled = true;
2100 } // namespace
2101
2102 // Test updating a pending extension.
TEST_F(ExtensionServiceTest,UpdatePendingExtension)2103 TEST_F(ExtensionServiceTest, UpdatePendingExtension) {
2104 InitializeEmptyExtensionService();
2105 service_->pending_extension_manager()->AddFromSync(
2106 kGoodId, GURL(kGoodUpdateURL), &IsExtension,
2107 kGoodInstallSilently, kGoodInitialState,
2108 kGoodInitialIncognitoEnabled);
2109 EXPECT_TRUE(service_->pending_extension_manager()->IsIdPending(kGoodId));
2110
2111 FilePath path = data_dir_.AppendASCII("good.crx");
2112 UpdateExtension(kGoodId, path, INSTALLED);
2113
2114 EXPECT_FALSE(service_->pending_extension_manager()->IsIdPending(kGoodId));
2115
2116 const Extension* extension = service_->GetExtensionById(kGoodId, true);
2117 ASSERT_TRUE(extension);
2118
2119 bool enabled = service_->GetExtensionById(kGoodId, false);
2120 EXPECT_EQ(enabled, kGoodInitialState == Extension::ENABLED);
2121 EXPECT_EQ(kGoodInitialState,
2122 service_->extension_prefs()->GetExtensionState(extension->id()));
2123 EXPECT_EQ(kGoodInitialIncognitoEnabled,
2124 service_->IsIncognitoEnabled(extension->id()));
2125 }
2126
2127 namespace {
2128
IsTheme(const Extension & extension)2129 bool IsTheme(const Extension& extension) {
2130 return extension.is_theme();
2131 }
2132
2133 } // namespace
2134
2135 // Test updating a pending theme.
TEST_F(ExtensionServiceTest,UpdatePendingTheme)2136 TEST_F(ExtensionServiceTest, UpdatePendingTheme) {
2137 InitializeEmptyExtensionService();
2138 service_->pending_extension_manager()->AddFromSync(
2139 theme_crx, GURL(), &IsTheme,
2140 false, Extension::ENABLED, false);
2141 EXPECT_TRUE(service_->pending_extension_manager()->IsIdPending(theme_crx));
2142
2143 FilePath path = data_dir_.AppendASCII("theme.crx");
2144 UpdateExtension(theme_crx, path, ENABLED);
2145
2146 EXPECT_FALSE(service_->pending_extension_manager()->IsIdPending(theme_crx));
2147
2148 const Extension* extension = service_->GetExtensionById(theme_crx, true);
2149 ASSERT_TRUE(extension);
2150
2151 EXPECT_EQ(Extension::ENABLED,
2152 service_->extension_prefs()->GetExtensionState(extension->id()));
2153 EXPECT_FALSE(service_->IsIncognitoEnabled(extension->id()));
2154 }
2155
2156 #if defined(OS_CHROMEOS)
2157 // Always fails on ChromeOS: http://crbug.com/79737
2158 #define MAYBE_UpdatePendingExternalCrx FAILS_UpdatePendingExternalCrx
2159 #else
2160 #define MAYBE_UpdatePendingExternalCrx UpdatePendingExternalCrx
2161 #endif
2162 // Test updating a pending CRX as if the source is an external extension
2163 // with an update URL. In this case we don't know if the CRX is a theme
2164 // or not.
TEST_F(ExtensionServiceTest,MAYBE_UpdatePendingExternalCrx)2165 TEST_F(ExtensionServiceTest, MAYBE_UpdatePendingExternalCrx) {
2166 InitializeEmptyExtensionService();
2167 service_->pending_extension_manager()->AddFromExternalUpdateUrl(
2168 theme_crx, GURL(), Extension::EXTERNAL_PREF_DOWNLOAD);
2169
2170 EXPECT_TRUE(service_->pending_extension_manager()->IsIdPending(theme_crx));
2171
2172 FilePath path = data_dir_.AppendASCII("theme.crx");
2173 UpdateExtension(theme_crx, path, ENABLED);
2174
2175 EXPECT_FALSE(service_->pending_extension_manager()->IsIdPending(theme_crx));
2176
2177 const Extension* extension = service_->GetExtensionById(theme_crx, true);
2178 ASSERT_TRUE(extension);
2179
2180 EXPECT_EQ(Extension::ENABLED,
2181 service_->extension_prefs()->GetExtensionState(extension->id()));
2182 EXPECT_FALSE(service_->IsIncognitoEnabled(extension->id()));
2183 }
2184
2185 // Test updating a pending CRX as if the source is an external extension
2186 // with an update URL. The external update should overwrite a sync update,
2187 // but a sync update should not overwrite a non-sync update.
TEST_F(ExtensionServiceTest,UpdatePendingExternalCrxWinsOverSync)2188 TEST_F(ExtensionServiceTest, UpdatePendingExternalCrxWinsOverSync) {
2189 InitializeEmptyExtensionService();
2190
2191 // Add a crx to be installed from the update mechanism.
2192 service_->pending_extension_manager()->AddFromSync(
2193 kGoodId, GURL(kGoodUpdateURL), &IsExtension,
2194 kGoodInstallSilently, kGoodInitialState,
2195 kGoodInitialIncognitoEnabled);
2196
2197 // Check that there is a pending crx, with is_from_sync set to true.
2198 PendingExtensionInfo pending_extension_info;
2199 ASSERT_TRUE(service_->pending_extension_manager()->GetById(
2200 kGoodId, &pending_extension_info));
2201 EXPECT_TRUE(pending_extension_info.is_from_sync());
2202
2203 // Add a crx to be updated, with the same ID, from a non-sync source.
2204 service_->pending_extension_manager()->AddFromExternalUpdateUrl(
2205 kGoodId, GURL(kGoodUpdateURL), Extension::EXTERNAL_PREF_DOWNLOAD);
2206
2207 // Check that there is a pending crx, with is_from_sync set to false.
2208 ASSERT_TRUE(service_->pending_extension_manager()->GetById(
2209 kGoodId, &pending_extension_info));
2210 EXPECT_FALSE(pending_extension_info.is_from_sync());
2211 EXPECT_EQ(Extension::EXTERNAL_PREF_DOWNLOAD,
2212 pending_extension_info.install_source());
2213
2214 // Add a crx to be installed from the update mechanism.
2215 service_->pending_extension_manager()->AddFromSync(
2216 kGoodId, GURL(kGoodUpdateURL), &IsExtension,
2217 kGoodInstallSilently, kGoodInitialState,
2218 kGoodInitialIncognitoEnabled);
2219
2220 // Check that the external, non-sync update was not overridden.
2221 ASSERT_TRUE(service_->pending_extension_manager()->GetById(
2222 kGoodId, &pending_extension_info));
2223 EXPECT_FALSE(pending_extension_info.is_from_sync());
2224 EXPECT_EQ(Extension::EXTERNAL_PREF_DOWNLOAD,
2225 pending_extension_info.install_source());
2226 }
2227
2228 // Updating a theme should fail if the updater is explicitly told that
2229 // the CRX is not a theme.
TEST_F(ExtensionServiceTest,UpdatePendingCrxThemeMismatch)2230 TEST_F(ExtensionServiceTest, UpdatePendingCrxThemeMismatch) {
2231 InitializeEmptyExtensionService();
2232 service_->pending_extension_manager()->AddFromSync(
2233 theme_crx, GURL(), &IsExtension,
2234 true, Extension::ENABLED, false);
2235
2236 EXPECT_TRUE(service_->pending_extension_manager()->IsIdPending(theme_crx));
2237
2238 FilePath path = data_dir_.AppendASCII("theme.crx");
2239 UpdateExtension(theme_crx, path, FAILED_SILENTLY);
2240
2241 EXPECT_FALSE(service_->pending_extension_manager()->IsIdPending(theme_crx));
2242
2243 const Extension* extension = service_->GetExtensionById(theme_crx, true);
2244 ASSERT_FALSE(extension);
2245 }
2246
2247 // TODO(akalin): Test updating a pending extension non-silently once
2248 // we can mock out ExtensionInstallUI and inject our version into
2249 // UpdateExtension().
2250
2251 // Test updating a pending extension which fails the should-install test.
TEST_F(ExtensionServiceTest,UpdatePendingExtensionFailedShouldInstallTest)2252 TEST_F(ExtensionServiceTest, UpdatePendingExtensionFailedShouldInstallTest) {
2253 InitializeEmptyExtensionService();
2254 // Add pending extension with a flipped is_theme.
2255 service_->pending_extension_manager()->AddFromSync(
2256 kGoodId, GURL(kGoodUpdateURL), &IsTheme,
2257 kGoodInstallSilently, kGoodInitialState,
2258 kGoodInitialIncognitoEnabled);
2259 EXPECT_TRUE(service_->pending_extension_manager()->IsIdPending(kGoodId));
2260
2261 FilePath path = data_dir_.AppendASCII("good.crx");
2262 UpdateExtension(kGoodId, path, UPDATED);
2263
2264 // TODO(akalin): Figure out how to check that the extensions
2265 // directory is cleaned up properly in OnExtensionInstalled().
2266
2267 EXPECT_FALSE(service_->pending_extension_manager()->IsIdPending(kGoodId));
2268 }
2269
2270 // TODO(akalin): Figure out how to test that installs of pending
2271 // unsyncable extensions are blocked.
2272
2273 // Test updating a pending extension for one that is not pending.
TEST_F(ExtensionServiceTest,UpdatePendingExtensionNotPending)2274 TEST_F(ExtensionServiceTest, UpdatePendingExtensionNotPending) {
2275 InitializeEmptyExtensionService();
2276
2277 FilePath path = data_dir_.AppendASCII("good.crx");
2278 UpdateExtension(kGoodId, path, UPDATED);
2279
2280 EXPECT_FALSE(service_->pending_extension_manager()->IsIdPending(kGoodId));
2281 }
2282
2283 // Test updating a pending extension for one that is already
2284 // installed.
TEST_F(ExtensionServiceTest,UpdatePendingExtensionAlreadyInstalled)2285 TEST_F(ExtensionServiceTest, UpdatePendingExtensionAlreadyInstalled) {
2286 InitializeEmptyExtensionService();
2287
2288 FilePath path = data_dir_.AppendASCII("good.crx");
2289 InstallCrx(path, true);
2290 ASSERT_EQ(1u, service_->extensions()->size());
2291 const Extension* good = service_->extensions()->at(0);
2292
2293 EXPECT_FALSE(good->is_theme());
2294
2295 // Use AddExtensionImpl() as AddFrom*() would balk.
2296 service_->pending_extension_manager()->AddExtensionImpl(
2297 good->id(), good->update_url(), &IsExtension,
2298 kGoodIsFromSync, kGoodInstallSilently, kGoodInitialState,
2299 kGoodInitialIncognitoEnabled, Extension::INTERNAL);
2300 UpdateExtension(good->id(), path, INSTALLED);
2301
2302 EXPECT_FALSE(service_->pending_extension_manager()->IsIdPending(kGoodId));
2303 }
2304
2305 // Test pref settings for blacklist and unblacklist extensions.
TEST_F(ExtensionServiceTest,SetUnsetBlacklistInPrefs)2306 TEST_F(ExtensionServiceTest, SetUnsetBlacklistInPrefs) {
2307 InitializeEmptyExtensionService();
2308 std::vector<std::string> blacklist;
2309 blacklist.push_back(good0);
2310 blacklist.push_back("invalid_id"); // an invalid id
2311 blacklist.push_back(good1);
2312 service_->UpdateExtensionBlacklist(blacklist);
2313 // Make sure pref is updated
2314 loop_.RunAllPending();
2315
2316 // blacklist is set for good0,1,2
2317 ValidateBooleanPref(good0, "blacklist", true);
2318 ValidateBooleanPref(good1, "blacklist", true);
2319 // invalid_id should not be inserted to pref.
2320 EXPECT_FALSE(IsPrefExist("invalid_id", "blacklist"));
2321
2322 // remove good1, add good2
2323 blacklist.pop_back();
2324 blacklist.push_back(good2);
2325
2326 service_->UpdateExtensionBlacklist(blacklist);
2327 // only good0 and good1 should be set
2328 ValidateBooleanPref(good0, "blacklist", true);
2329 EXPECT_FALSE(IsPrefExist(good1, "blacklist"));
2330 ValidateBooleanPref(good2, "blacklist", true);
2331 EXPECT_FALSE(IsPrefExist("invalid_id", "blacklist"));
2332 }
2333
2334 // Unload installed extension from blacklist.
TEST_F(ExtensionServiceTest,UnloadBlacklistedExtension)2335 TEST_F(ExtensionServiceTest, UnloadBlacklistedExtension) {
2336 InitializeEmptyExtensionService();
2337
2338 FilePath path = data_dir_.AppendASCII("good.crx");
2339
2340 InstallCrx(path, true);
2341 const Extension* good = service_->extensions()->at(0);
2342 EXPECT_EQ(good_crx, good->id());
2343 UpdateExtension(good_crx, path, FAILED_SILENTLY);
2344
2345 std::vector<std::string> blacklist;
2346 blacklist.push_back(good_crx);
2347 service_->UpdateExtensionBlacklist(blacklist);
2348 // Make sure pref is updated
2349 loop_.RunAllPending();
2350
2351 // Now, the good_crx is blacklisted.
2352 ValidateBooleanPref(good_crx, "blacklist", true);
2353 EXPECT_EQ(0u, service_->extensions()->size());
2354
2355 // Remove good_crx from blacklist
2356 blacklist.pop_back();
2357 service_->UpdateExtensionBlacklist(blacklist);
2358 // Make sure pref is updated
2359 loop_.RunAllPending();
2360 // blacklist value should not be set for good_crx
2361 EXPECT_FALSE(IsPrefExist(good_crx, "blacklist"));
2362 }
2363
2364 // Unload installed extension from blacklist.
TEST_F(ExtensionServiceTest,BlacklistedExtensionWillNotInstall)2365 TEST_F(ExtensionServiceTest, BlacklistedExtensionWillNotInstall) {
2366 InitializeEmptyExtensionService();
2367 std::vector<std::string> blacklist;
2368 blacklist.push_back(good_crx);
2369 service_->UpdateExtensionBlacklist(blacklist);
2370 // Make sure pref is updated
2371 loop_.RunAllPending();
2372
2373 // Now, the good_crx is blacklisted.
2374 ValidateBooleanPref(good_crx, "blacklist", true);
2375
2376 // We can not install good_crx.
2377 FilePath path = data_dir_.AppendASCII("good.crx");
2378 StartCrxInstall(path);
2379 loop_.RunAllPending();
2380 EXPECT_EQ(0u, service_->extensions()->size());
2381 ValidateBooleanPref(good_crx, "blacklist", true);
2382 }
2383
2384 // Test loading extensions from the profile directory, except
2385 // blacklisted ones.
TEST_F(ExtensionServiceTest,WillNotLoadBlacklistedExtensionsFromDirectory)2386 TEST_F(ExtensionServiceTest, WillNotLoadBlacklistedExtensionsFromDirectory) {
2387 // Initialize the test dir with a good Preferences/extensions.
2388 FilePath source_install_dir = data_dir_
2389 .AppendASCII("good")
2390 .AppendASCII("Extensions");
2391 FilePath pref_path = source_install_dir
2392 .DirName()
2393 .AppendASCII("Preferences");
2394 InitializeInstalledExtensionService(pref_path, source_install_dir);
2395
2396 // Blacklist good1.
2397 std::vector<std::string> blacklist;
2398 blacklist.push_back(good1);
2399 service_->UpdateExtensionBlacklist(blacklist);
2400 // Make sure pref is updated
2401 loop_.RunAllPending();
2402
2403 ValidateBooleanPref(good1, "blacklist", true);
2404
2405 // Load extensions.
2406 service_->Init();
2407 loop_.RunAllPending();
2408
2409 std::vector<std::string> errors = GetErrors();
2410 for (std::vector<std::string>::iterator err = errors.begin();
2411 err != errors.end(); ++err) {
2412 LOG(ERROR) << *err;
2413 }
2414 ASSERT_EQ(2u, loaded_.size());
2415
2416 EXPECT_NE(std::string(good1), loaded_[0]->id());
2417 EXPECT_NE(std::string(good1), loaded_[1]->id());
2418 }
2419
2420 // Will not install extension blacklisted by policy.
TEST_F(ExtensionServiceTest,BlacklistedByPolicyWillNotInstall)2421 TEST_F(ExtensionServiceTest, BlacklistedByPolicyWillNotInstall) {
2422 InitializeEmptyExtensionService();
2423
2424 // Blacklist everything.
2425 {
2426 ListPrefUpdate update(profile_->GetPrefs(),
2427 prefs::kExtensionInstallDenyList);
2428 ListValue* blacklist = update.Get();
2429 blacklist->Append(Value::CreateStringValue("*"));
2430 }
2431
2432 // Blacklist prevents us from installing good_crx.
2433 FilePath path = data_dir_.AppendASCII("good.crx");
2434 StartCrxInstall(path);
2435 loop_.RunAllPending();
2436 EXPECT_EQ(0u, service_->extensions()->size());
2437
2438 // Now whitelist this particular extension.
2439 {
2440 ListPrefUpdate update(profile_->GetPrefs(),
2441 prefs::kExtensionInstallAllowList);
2442 ListValue* whitelist = update.Get();
2443 whitelist->Append(Value::CreateStringValue(good_crx));
2444 }
2445
2446
2447 // Ensure we can now install good_crx.
2448 StartCrxInstall(path);
2449 loop_.RunAllPending();
2450 EXPECT_EQ(1u, service_->extensions()->size());
2451 }
2452
2453 // Extension blacklisted by policy get unloaded after installing.
TEST_F(ExtensionServiceTest,BlacklistedByPolicyRemovedIfRunning)2454 TEST_F(ExtensionServiceTest, BlacklistedByPolicyRemovedIfRunning) {
2455 InitializeEmptyExtensionService();
2456
2457 // Install good_crx.
2458 FilePath path = data_dir_.AppendASCII("good.crx");
2459 StartCrxInstall(path);
2460 loop_.RunAllPending();
2461 EXPECT_EQ(1u, service_->extensions()->size());
2462
2463 { // Scope for pref update notification.
2464 PrefService* prefs = profile_->GetPrefs();
2465 ListPrefUpdate update(prefs, prefs::kExtensionInstallDenyList);
2466 ListValue* blacklist = update.Get();
2467 ASSERT_TRUE(blacklist != NULL);
2468
2469 // Blacklist this extension.
2470 blacklist->Append(Value::CreateStringValue(good_crx));
2471 prefs->ScheduleSavePersistentPrefs();
2472 }
2473
2474 // Extension should not be running now.
2475 loop_.RunAllPending();
2476 EXPECT_EQ(0u, service_->extensions()->size());
2477 }
2478
2479 // Tests disabling extensions
TEST_F(ExtensionServiceTest,DisableExtension)2480 TEST_F(ExtensionServiceTest, DisableExtension) {
2481 InitializeEmptyExtensionService();
2482
2483 // A simple extension that should install without error.
2484 FilePath path = data_dir_.AppendASCII("good.crx");
2485 InstallCrx(path, true);
2486
2487 const char* extension_id = good_crx;
2488 EXPECT_FALSE(service_->extensions()->empty());
2489 EXPECT_TRUE(service_->GetExtensionById(extension_id, true) != NULL);
2490 EXPECT_TRUE(service_->GetExtensionById(extension_id, false) != NULL);
2491 EXPECT_TRUE(service_->disabled_extensions()->empty());
2492
2493 // Disable it.
2494 service_->DisableExtension(extension_id);
2495
2496 EXPECT_TRUE(service_->extensions()->empty());
2497 EXPECT_TRUE(service_->GetExtensionById(extension_id, true) != NULL);
2498 EXPECT_FALSE(service_->GetExtensionById(extension_id, false) != NULL);
2499 EXPECT_FALSE(service_->disabled_extensions()->empty());
2500 }
2501
2502 // Tests disabling all extensions (simulating --disable-extensions flag).
TEST_F(ExtensionServiceTest,DisableAllExtensions)2503 TEST_F(ExtensionServiceTest, DisableAllExtensions) {
2504 InitializeEmptyExtensionService();
2505
2506
2507 FilePath path = data_dir_.AppendASCII("good.crx");
2508 InstallCrx(path, true);
2509
2510 EXPECT_EQ(1u, service_->extensions()->size());
2511 EXPECT_EQ(0u, service_->disabled_extensions()->size());
2512
2513 // Disable extensions.
2514 service_->set_extensions_enabled(false);
2515 service_->ReloadExtensions();
2516
2517 // There shouldn't be extensions in either list.
2518 EXPECT_EQ(0u, service_->extensions()->size());
2519 EXPECT_EQ(0u, service_->disabled_extensions()->size());
2520
2521 // This shouldn't do anything when all extensions are disabled.
2522 service_->EnableExtension(good_crx);
2523 service_->ReloadExtensions();
2524
2525 // There still shouldn't be extensions in either list.
2526 EXPECT_EQ(0u, service_->extensions()->size());
2527 EXPECT_EQ(0u, service_->disabled_extensions()->size());
2528
2529 // And then re-enable the extensions.
2530 service_->set_extensions_enabled(true);
2531 service_->ReloadExtensions();
2532
2533 EXPECT_EQ(1u, service_->extensions()->size());
2534 EXPECT_EQ(0u, service_->disabled_extensions()->size());
2535 }
2536
2537 // Tests reloading extensions
TEST_F(ExtensionServiceTest,ReloadExtensions)2538 TEST_F(ExtensionServiceTest, ReloadExtensions) {
2539 InitializeEmptyExtensionService();
2540
2541 // Simple extension that should install without error.
2542 FilePath path = data_dir_.AppendASCII("good.crx");
2543 InstallCrx(path, true);
2544 const char* extension_id = good_crx;
2545 service_->DisableExtension(extension_id);
2546
2547 EXPECT_EQ(0u, service_->extensions()->size());
2548 EXPECT_EQ(1u, service_->disabled_extensions()->size());
2549
2550 service_->ReloadExtensions();
2551
2552 // Extension counts shouldn't change.
2553 EXPECT_EQ(0u, service_->extensions()->size());
2554 EXPECT_EQ(1u, service_->disabled_extensions()->size());
2555
2556 service_->EnableExtension(extension_id);
2557
2558 EXPECT_EQ(1u, service_->extensions()->size());
2559 EXPECT_EQ(0u, service_->disabled_extensions()->size());
2560
2561 // Need to clear |loaded_| manually before reloading as the
2562 // EnableExtension() call above inserted into it and
2563 // UnloadAllExtensions() doesn't send out notifications.
2564 loaded_.clear();
2565 service_->ReloadExtensions();
2566
2567 // Extension counts shouldn't change.
2568 EXPECT_EQ(1u, service_->extensions()->size());
2569 EXPECT_EQ(0u, service_->disabled_extensions()->size());
2570 }
2571
2572 // Tests uninstalling normal extensions
TEST_F(ExtensionServiceTest,UninstallExtension)2573 TEST_F(ExtensionServiceTest, UninstallExtension) {
2574 InitializeEmptyExtensionService();
2575
2576 // A simple extension that should install without error.
2577 FilePath path = data_dir_.AppendASCII("good.crx");
2578 InstallCrx(path, true);
2579
2580 // The directory should be there now.
2581 const char* extension_id = good_crx;
2582 FilePath extension_path = extensions_install_dir_.AppendASCII(extension_id);
2583 EXPECT_TRUE(file_util::PathExists(extension_path));
2584
2585 ValidatePrefKeyCount(1);
2586 ValidateIntegerPref(good_crx, "state", Extension::ENABLED);
2587 ValidateIntegerPref(good_crx, "location", Extension::INTERNAL);
2588
2589 // Uninstall it.
2590 service_->UninstallExtension(extension_id, false, NULL);
2591 total_successes_ = 0;
2592
2593 // We should get an unload notification.
2594 ASSERT_TRUE(unloaded_id_.length());
2595 EXPECT_EQ(extension_id, unloaded_id_);
2596
2597 ValidatePrefKeyCount(0);
2598
2599 // The extension should not be in the service anymore.
2600 ASSERT_FALSE(service_->GetExtensionById(extension_id, false));
2601 loop_.RunAllPending();
2602
2603 // The directory should be gone.
2604 EXPECT_FALSE(file_util::PathExists(extension_path));
2605 }
2606
2607 // Tests the uninstaller helper.
TEST_F(ExtensionServiceTest,UninstallExtensionHelper)2608 TEST_F(ExtensionServiceTest, UninstallExtensionHelper) {
2609 InitializeEmptyExtensionService();
2610
2611 // A simple extension that should install without error.
2612 FilePath path = data_dir_.AppendASCII("good.crx");
2613 InstallCrx(path, true);
2614
2615 // The directory should be there now.
2616 const char* extension_id = good_crx;
2617 FilePath extension_path = extensions_install_dir_.AppendASCII(extension_id);
2618 EXPECT_TRUE(file_util::PathExists(extension_path));
2619
2620 bool result = ExtensionService::UninstallExtensionHelper(service_,
2621 extension_id);
2622 total_successes_ = 0;
2623
2624 EXPECT_TRUE(result);
2625
2626 // We should get an unload notification.
2627 ASSERT_TRUE(unloaded_id_.length());
2628 EXPECT_EQ(extension_id, unloaded_id_);
2629
2630 ValidatePrefKeyCount(0);
2631
2632 // The extension should not be in the service anymore.
2633 ASSERT_FALSE(service_->GetExtensionById(extension_id, false));
2634 loop_.RunAllPending();
2635
2636 // The directory should be gone.
2637 EXPECT_FALSE(file_util::PathExists(extension_path));
2638
2639 // Attempt to uninstall again. This should fail as we just removed the
2640 // extension.
2641 result = ExtensionService::UninstallExtensionHelper(service_, extension_id);
2642 EXPECT_FALSE(result);
2643 }
2644
2645 // Verifies extension state is removed upon uninstall
TEST_F(ExtensionServiceTest,ClearExtensionData)2646 TEST_F(ExtensionServiceTest, ClearExtensionData) {
2647 InitializeEmptyExtensionService();
2648
2649 // Load a test extension.
2650 FilePath path = data_dir_;
2651 path = path.AppendASCII("good.crx");
2652 InstallCrx(path, true);
2653 const Extension* extension = service_->GetExtensionById(good_crx, false);
2654 ASSERT_TRUE(extension);
2655 GURL ext_url(extension->url());
2656 string16 origin_id =
2657 webkit_database::DatabaseUtil::GetOriginIdentifier(ext_url);
2658
2659 // Set a cookie for the extension.
2660 net::CookieMonster* cookie_monster =
2661 profile_->GetRequestContextForExtensions()->GetURLRequestContext()->
2662 cookie_store()->GetCookieMonster();
2663 ASSERT_TRUE(cookie_monster);
2664 net::CookieOptions options;
2665 cookie_monster->SetCookieWithOptions(ext_url, "dummy=value", options);
2666 net::CookieList list = cookie_monster->GetAllCookiesForURL(ext_url);
2667 EXPECT_EQ(1U, list.size());
2668
2669 // Open a database.
2670 webkit_database::DatabaseTracker* db_tracker = profile_->GetDatabaseTracker();
2671 string16 db_name = UTF8ToUTF16("db");
2672 string16 description = UTF8ToUTF16("db_description");
2673 int64 size;
2674 int64 available;
2675 db_tracker->DatabaseOpened(origin_id, db_name, description, 1, &size,
2676 &available);
2677 db_tracker->DatabaseClosed(origin_id, db_name);
2678 std::vector<webkit_database::OriginInfo> origins;
2679 db_tracker->GetAllOriginsInfo(&origins);
2680 EXPECT_EQ(1U, origins.size());
2681 EXPECT_EQ(origin_id, origins[0].GetOrigin());
2682
2683 // Create local storage. We only simulate this by creating the backing file
2684 // since webkit is not initialized.
2685 DOMStorageContext* context =
2686 profile_->GetWebKitContext()->dom_storage_context();
2687 FilePath lso_path = context->GetLocalStorageFilePath(origin_id);
2688 EXPECT_TRUE(file_util::CreateDirectory(lso_path.DirName()));
2689 EXPECT_EQ(0, file_util::WriteFile(lso_path, NULL, 0));
2690 EXPECT_TRUE(file_util::PathExists(lso_path));
2691
2692 // Create indexed db. Again, it is enough to only simulate this by creating
2693 // the file on the disk.
2694 IndexedDBContext* idb_context =
2695 profile_->GetWebKitContext()->indexed_db_context();
2696 FilePath idb_path = idb_context->GetIndexedDBFilePath(origin_id);
2697 EXPECT_TRUE(file_util::CreateDirectory(idb_path.DirName()));
2698 EXPECT_EQ(0, file_util::WriteFile(idb_path, NULL, 0));
2699 EXPECT_TRUE(file_util::PathExists(idb_path));
2700
2701 // Uninstall the extension.
2702 service_->UninstallExtension(good_crx, false, NULL);
2703 loop_.RunAllPending();
2704
2705 // Check that the cookie is gone.
2706 list = cookie_monster->GetAllCookiesForURL(ext_url);
2707 EXPECT_EQ(0U, list.size());
2708
2709 // The database should have vanished as well.
2710 origins.clear();
2711 db_tracker->GetAllOriginsInfo(&origins);
2712 EXPECT_EQ(0U, origins.size());
2713
2714 // Check that the LSO file has been removed.
2715 EXPECT_FALSE(file_util::PathExists(lso_path));
2716
2717 // Check if the indexed db has disappeared too.
2718 EXPECT_FALSE(file_util::PathExists(idb_path));
2719 }
2720
2721 // Tests loading single extensions (like --load-extension)
TEST_F(ExtensionServiceTest,LoadExtension)2722 TEST_F(ExtensionServiceTest, LoadExtension) {
2723 InitializeEmptyExtensionService();
2724
2725 FilePath ext1 = data_dir_
2726 .AppendASCII("good")
2727 .AppendASCII("Extensions")
2728 .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj")
2729 .AppendASCII("1.0.0.0");
2730 service_->LoadExtension(ext1);
2731 loop_.RunAllPending();
2732 EXPECT_EQ(0u, GetErrors().size());
2733 ASSERT_EQ(1u, loaded_.size());
2734 EXPECT_EQ(Extension::LOAD, loaded_[0]->location());
2735 EXPECT_EQ(1u, service_->extensions()->size());
2736
2737 ValidatePrefKeyCount(1);
2738
2739 FilePath no_manifest = data_dir_
2740 .AppendASCII("bad")
2741 // .AppendASCII("Extensions")
2742 .AppendASCII("cccccccccccccccccccccccccccccccc")
2743 .AppendASCII("1");
2744 service_->LoadExtension(no_manifest);
2745 loop_.RunAllPending();
2746 EXPECT_EQ(1u, GetErrors().size());
2747 ASSERT_EQ(1u, loaded_.size());
2748 EXPECT_EQ(1u, service_->extensions()->size());
2749
2750 // Test uninstall.
2751 std::string id = loaded_[0]->id();
2752 EXPECT_FALSE(unloaded_id_.length());
2753 service_->UninstallExtension(id, false, NULL);
2754 loop_.RunAllPending();
2755 EXPECT_EQ(id, unloaded_id_);
2756 ASSERT_EQ(0u, loaded_.size());
2757 EXPECT_EQ(0u, service_->extensions()->size());
2758 }
2759
2760 // Tests that we generate IDs when they are not specified in the manifest for
2761 // --load-extension.
TEST_F(ExtensionServiceTest,GenerateID)2762 TEST_F(ExtensionServiceTest, GenerateID) {
2763 InitializeEmptyExtensionService();
2764
2765
2766 FilePath no_id_ext = data_dir_.AppendASCII("no_id");
2767 service_->LoadExtension(no_id_ext);
2768 loop_.RunAllPending();
2769 EXPECT_EQ(0u, GetErrors().size());
2770 ASSERT_EQ(1u, loaded_.size());
2771 ASSERT_TRUE(Extension::IdIsValid(loaded_[0]->id()));
2772 EXPECT_EQ(loaded_[0]->location(), Extension::LOAD);
2773
2774 ValidatePrefKeyCount(1);
2775
2776 std::string previous_id = loaded_[0]->id();
2777
2778 // If we reload the same path, we should get the same extension ID.
2779 service_->LoadExtension(no_id_ext);
2780 loop_.RunAllPending();
2781 ASSERT_EQ(1u, loaded_.size());
2782 ASSERT_EQ(previous_id, loaded_[0]->id());
2783 }
2784
TestExternalProvider(MockExtensionProvider * provider,Extension::Location location)2785 void ExtensionServiceTest::TestExternalProvider(
2786 MockExtensionProvider* provider, Extension::Location location) {
2787 // Verify that starting with no providers loads no extensions.
2788 service_->Init();
2789 loop_.RunAllPending();
2790 ASSERT_EQ(0u, loaded_.size());
2791
2792 provider->set_visit_count(0);
2793
2794 // Register a test extension externally using the mock registry provider.
2795 FilePath source_path = data_dir_.AppendASCII("good.crx");
2796
2797 // Add the extension.
2798 provider->UpdateOrAddExtension(good_crx, "1.0.0.0", source_path);
2799
2800 // Reloading extensions should find our externally registered extension
2801 // and install it.
2802 service_->CheckForExternalUpdates();
2803 loop_.RunAllPending();
2804
2805 ASSERT_EQ(0u, GetErrors().size());
2806 ASSERT_EQ(1u, loaded_.size());
2807 ASSERT_EQ(location, loaded_[0]->location());
2808 ASSERT_EQ("1.0.0.0", loaded_[0]->version()->GetString());
2809 ValidatePrefKeyCount(1);
2810 ValidateIntegerPref(good_crx, "state", Extension::ENABLED);
2811 ValidateIntegerPref(good_crx, "location", location);
2812
2813 // Reload extensions without changing anything. The extension should be
2814 // loaded again.
2815 loaded_.clear();
2816 service_->ReloadExtensions();
2817 loop_.RunAllPending();
2818 ASSERT_EQ(0u, GetErrors().size());
2819 ASSERT_EQ(1u, loaded_.size());
2820 ValidatePrefKeyCount(1);
2821 ValidateIntegerPref(good_crx, "state", Extension::ENABLED);
2822 ValidateIntegerPref(good_crx, "location", location);
2823
2824 // Now update the extension with a new version. We should get upgraded.
2825 source_path = source_path.DirName().AppendASCII("good2.crx");
2826 provider->UpdateOrAddExtension(good_crx, "1.0.0.1", source_path);
2827
2828 loaded_.clear();
2829 service_->CheckForExternalUpdates();
2830 loop_.RunAllPending();
2831 ASSERT_EQ(0u, GetErrors().size());
2832 ASSERT_EQ(1u, loaded_.size());
2833 ASSERT_EQ("1.0.0.1", loaded_[0]->version()->GetString());
2834 ValidatePrefKeyCount(1);
2835 ValidateIntegerPref(good_crx, "state", Extension::ENABLED);
2836 ValidateIntegerPref(good_crx, "location", location);
2837
2838 // Uninstall the extension and reload. Nothing should happen because the
2839 // preference should prevent us from reinstalling.
2840 std::string id = loaded_[0]->id();
2841 service_->UninstallExtension(id, false, NULL);
2842 loop_.RunAllPending();
2843
2844 FilePath install_path = extensions_install_dir_.AppendASCII(id);
2845 // It should not be possible to uninstall a policy controlled extension.
2846 if (Extension::UserMayDisable(location)) {
2847 // The extension should also be gone from the install directory.
2848 ASSERT_FALSE(file_util::PathExists(install_path));
2849 loaded_.clear();
2850 service_->CheckForExternalUpdates();
2851 loop_.RunAllPending();
2852 ASSERT_EQ(0u, loaded_.size());
2853 ValidatePrefKeyCount(1);
2854 ValidateIntegerPref(good_crx, "state",
2855 Extension::EXTERNAL_EXTENSION_UNINSTALLED);
2856 ValidateIntegerPref(good_crx, "location", location);
2857
2858 // Now clear the preference and reinstall.
2859 SetPrefInteg(good_crx, "state", Extension::ENABLED);
2860 profile_->GetPrefs()->ScheduleSavePersistentPrefs();
2861
2862 loaded_.clear();
2863 service_->CheckForExternalUpdates();
2864 loop_.RunAllPending();
2865 ASSERT_EQ(1u, loaded_.size());
2866 } else {
2867 // Policy controlled extesions should not have been touched by uninstall.
2868 ASSERT_TRUE(file_util::PathExists(install_path));
2869 }
2870 ValidatePrefKeyCount(1);
2871 ValidateIntegerPref(good_crx, "state", Extension::ENABLED);
2872 ValidateIntegerPref(good_crx, "location", location);
2873
2874 if (Extension::UserMayDisable(location)) {
2875 // Now test an externally triggered uninstall (deleting the registry key or
2876 // the pref entry).
2877 provider->RemoveExtension(good_crx);
2878
2879 loaded_.clear();
2880 service_->OnExternalProviderReady();
2881 loop_.RunAllPending();
2882 ASSERT_EQ(0u, loaded_.size());
2883 ValidatePrefKeyCount(0);
2884
2885 // The extension should also be gone from the install directory.
2886 ASSERT_FALSE(file_util::PathExists(install_path));
2887
2888 // Now test the case where user uninstalls and then the extension is removed
2889 // from the external provider.
2890
2891 provider->UpdateOrAddExtension(good_crx, "1.0.0.1", source_path);
2892 service_->CheckForExternalUpdates();
2893 loop_.RunAllPending();
2894
2895 ASSERT_EQ(1u, loaded_.size());
2896 ASSERT_EQ(0u, GetErrors().size());
2897
2898 // User uninstalls.
2899 loaded_.clear();
2900 service_->UninstallExtension(id, false, NULL);
2901 loop_.RunAllPending();
2902 ASSERT_EQ(0u, loaded_.size());
2903
2904 // Then remove the extension from the extension provider.
2905 provider->RemoveExtension(good_crx);
2906
2907 // Should still be at 0.
2908 loaded_.clear();
2909 service_->LoadAllExtensions();
2910 loop_.RunAllPending();
2911 ASSERT_EQ(0u, loaded_.size());
2912 ValidatePrefKeyCount(1);
2913
2914 EXPECT_EQ(5, provider->visit_count());
2915 } else {
2916 EXPECT_EQ(2, provider->visit_count());
2917 }
2918 }
2919
2920 // Tests the external installation feature
2921 #if defined(OS_WIN)
TEST_F(ExtensionServiceTest,ExternalInstallRegistry)2922 TEST_F(ExtensionServiceTest, ExternalInstallRegistry) {
2923 // This should all work, even when normal extension installation is disabled.
2924 InitializeEmptyExtensionService();
2925 set_extensions_enabled(false);
2926
2927 // Now add providers. Extension system takes ownership of the objects.
2928 MockExtensionProvider* reg_provider =
2929 new MockExtensionProvider(service_.get(), Extension::EXTERNAL_REGISTRY);
2930 AddMockExternalProvider(reg_provider);
2931 TestExternalProvider(reg_provider, Extension::EXTERNAL_REGISTRY);
2932 }
2933 #endif
2934
TEST_F(ExtensionServiceTest,ExternalInstallPref)2935 TEST_F(ExtensionServiceTest, ExternalInstallPref) {
2936 InitializeEmptyExtensionService();
2937
2938 // Now add providers. Extension system takes ownership of the objects.
2939 MockExtensionProvider* pref_provider =
2940 new MockExtensionProvider(service_.get(), Extension::EXTERNAL_PREF);
2941
2942 AddMockExternalProvider(pref_provider);
2943 TestExternalProvider(pref_provider, Extension::EXTERNAL_PREF);
2944 }
2945
TEST_F(ExtensionServiceTest,ExternalInstallPrefUpdateUrl)2946 TEST_F(ExtensionServiceTest, ExternalInstallPrefUpdateUrl) {
2947 // This should all work, even when normal extension installation is disabled.
2948 InitializeEmptyExtensionService();
2949 set_extensions_enabled(false);
2950
2951 // TODO(skerner): The mock provider is not a good model of a provider
2952 // that works with update URLs, because it adds file and version info.
2953 // Extend the mock to work with update URLs. This test checks the
2954 // behavior that is common to all external extension visitors. The
2955 // browser test ExtensionManagementTest.ExternalUrlUpdate tests that
2956 // what the visitor does results in an extension being downloaded and
2957 // installed.
2958 MockExtensionProvider* pref_provider =
2959 new MockExtensionProvider(service_.get(),
2960 Extension::EXTERNAL_PREF_DOWNLOAD);
2961 AddMockExternalProvider(pref_provider);
2962 TestExternalProvider(pref_provider, Extension::EXTERNAL_PREF_DOWNLOAD);
2963 }
2964
TEST_F(ExtensionServiceTest,ExternalInstallPolicyUpdateUrl)2965 TEST_F(ExtensionServiceTest, ExternalInstallPolicyUpdateUrl) {
2966 // This should all work, even when normal extension installation is disabled.
2967 InitializeEmptyExtensionService();
2968 set_extensions_enabled(false);
2969
2970 // TODO(skerner): The mock provider is not a good model of a provider
2971 // that works with update URLs, because it adds file and version info.
2972 // Extend the mock to work with update URLs. This test checks the
2973 // behavior that is common to all external extension visitors. The
2974 // browser test ExtensionManagementTest.ExternalUrlUpdate tests that
2975 // what the visitor does results in an extension being downloaded and
2976 // installed.
2977 MockExtensionProvider* pref_provider =
2978 new MockExtensionProvider(service_.get(),
2979 Extension::EXTERNAL_POLICY_DOWNLOAD);
2980 AddMockExternalProvider(pref_provider);
2981 TestExternalProvider(pref_provider, Extension::EXTERNAL_POLICY_DOWNLOAD);
2982 }
2983
2984 // Tests that external extensions get uninstalled when the external extension
2985 // providers can't account for them.
TEST_F(ExtensionServiceTest,ExternalUninstall)2986 TEST_F(ExtensionServiceTest, ExternalUninstall) {
2987 // Start the extensions service with one external extension already installed.
2988 FilePath source_install_dir = data_dir_
2989 .AppendASCII("good")
2990 .AppendASCII("Extensions");
2991 FilePath pref_path = source_install_dir
2992 .DirName()
2993 .AppendASCII("PreferencesExternal");
2994
2995 // This initializes the extensions service with no ExternalExtensionProviders.
2996 InitializeInstalledExtensionService(pref_path, source_install_dir);
2997 set_extensions_enabled(false);
2998
2999 service_->Init();
3000 loop_.RunAllPending();
3001
3002 ASSERT_EQ(0u, GetErrors().size());
3003 ASSERT_EQ(0u, loaded_.size());
3004
3005 // Verify that it's not the disabled extensions flag causing it not to load.
3006 set_extensions_enabled(true);
3007 service_->ReloadExtensions();
3008 loop_.RunAllPending();
3009
3010 ASSERT_EQ(0u, GetErrors().size());
3011 ASSERT_EQ(0u, loaded_.size());
3012 }
3013
3014 // Test that running multiple update checks simultaneously does not
3015 // keep the update from succeeding.
TEST_F(ExtensionServiceTest,MultipleExternalUpdateCheck)3016 TEST_F(ExtensionServiceTest, MultipleExternalUpdateCheck) {
3017 InitializeEmptyExtensionService();
3018
3019 MockExtensionProvider* provider =
3020 new MockExtensionProvider(service_.get(), Extension::EXTERNAL_PREF);
3021 AddMockExternalProvider(provider);
3022
3023 // Verify that starting with no providers loads no extensions.
3024 service_->Init();
3025 loop_.RunAllPending();
3026 ASSERT_EQ(0u, loaded_.size());
3027
3028 // Start two checks for updates.
3029 provider->set_visit_count(0);
3030 service_->CheckForExternalUpdates();
3031 service_->CheckForExternalUpdates();
3032 loop_.RunAllPending();
3033
3034 // Two calls should cause two checks for external extensions.
3035 EXPECT_EQ(2, provider->visit_count());
3036 EXPECT_EQ(0u, GetErrors().size());
3037 EXPECT_EQ(0u, loaded_.size());
3038
3039 // Register a test extension externally using the mock registry provider.
3040 FilePath source_path = data_dir_.AppendASCII("good.crx");
3041 provider->UpdateOrAddExtension(good_crx, "1.0.0.0", source_path);
3042
3043 // Two checks for external updates should find the extension, and install it
3044 // once.
3045 provider->set_visit_count(0);
3046 service_->CheckForExternalUpdates();
3047 service_->CheckForExternalUpdates();
3048 loop_.RunAllPending();
3049 EXPECT_EQ(2, provider->visit_count());
3050 ASSERT_EQ(0u, GetErrors().size());
3051 ASSERT_EQ(1u, loaded_.size());
3052 ASSERT_EQ(Extension::EXTERNAL_PREF, loaded_[0]->location());
3053 ASSERT_EQ("1.0.0.0", loaded_[0]->version()->GetString());
3054 ValidatePrefKeyCount(1);
3055 ValidateIntegerPref(good_crx, "state", Extension::ENABLED);
3056 ValidateIntegerPref(good_crx, "location", Extension::EXTERNAL_PREF);
3057
3058 provider->RemoveExtension(good_crx);
3059 provider->set_visit_count(0);
3060 service_->CheckForExternalUpdates();
3061 service_->CheckForExternalUpdates();
3062 loop_.RunAllPending();
3063
3064 // Two calls should cause two checks for external extensions.
3065 // Because the external source no longer includes good_crx,
3066 // good_crx will be uninstalled. So, expect that no extensions
3067 // are loaded.
3068 EXPECT_EQ(2, provider->visit_count());
3069 EXPECT_EQ(0u, GetErrors().size());
3070 EXPECT_EQ(0u, loaded_.size());
3071 }
3072
TEST_F(ExtensionServiceTest,ExternalPrefProvider)3073 TEST_F(ExtensionServiceTest, ExternalPrefProvider) {
3074 InitializeEmptyExtensionService();
3075
3076 // Test some valid extension records.
3077 // Set a base path to avoid erroring out on relative paths.
3078 // Paths starting with // are absolute on every platform we support.
3079 FilePath base_path(FILE_PATH_LITERAL("//base/path"));
3080 ASSERT_TRUE(base_path.IsAbsolute());
3081 MockProviderVisitor visitor(base_path);
3082 std::string json_data =
3083 "{"
3084 " \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\": {"
3085 " \"external_crx\": \"RandomExtension.crx\","
3086 " \"external_version\": \"1.0\""
3087 " },"
3088 " \"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\": {"
3089 " \"external_crx\": \"RandomExtension2.crx\","
3090 " \"external_version\": \"2.0\""
3091 " },"
3092 " \"cccccccccccccccccccccccccccccccc\": {"
3093 " \"external_update_url\": \"http:\\\\foo.com/update\""
3094 " }"
3095 "}";
3096 EXPECT_EQ(3, visitor.Visit(json_data));
3097
3098 // Simulate an external_extensions.json file that contains seven invalid
3099 // records:
3100 // - One that is missing the 'external_crx' key.
3101 // - One that is missing the 'external_version' key.
3102 // - One that is specifying .. in the path.
3103 // - One that specifies both a file and update URL.
3104 // - One that specifies no file or update URL.
3105 // - One that has an update URL that is not well formed.
3106 // - One that contains a malformed version.
3107 // - One that has an invalid id.
3108 // - One that has a non-dictionary value.
3109 // The final extension is valid, and we check that it is read to make sure
3110 // failures don't stop valid records from being read.
3111 json_data =
3112 "{"
3113 " \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\": {"
3114 " \"external_version\": \"1.0\""
3115 " },"
3116 " \"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\": {"
3117 " \"external_crx\": \"RandomExtension.crx\""
3118 " },"
3119 " \"cccccccccccccccccccccccccccccccc\": {"
3120 " \"external_crx\": \"..\\\\foo\\\\RandomExtension2.crx\","
3121 " \"external_version\": \"2.0\""
3122 " },"
3123 " \"dddddddddddddddddddddddddddddddd\": {"
3124 " \"external_crx\": \"RandomExtension2.crx\","
3125 " \"external_version\": \"2.0\","
3126 " \"external_update_url\": \"http:\\\\foo.com/update\""
3127 " },"
3128 " \"eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\": {"
3129 " },"
3130 " \"ffffffffffffffffffffffffffffffff\": {"
3131 " \"external_update_url\": \"This string is not a valid URL\""
3132 " },"
3133 " \"gggggggggggggggggggggggggggggggg\": {"
3134 " \"external_crx\": \"RandomExtension3.crx\","
3135 " \"external_version\": \"This is not a valid version!\""
3136 " },"
3137 " \"This is not a valid id!\": {},"
3138 " \"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh\": true,"
3139 " \"pppppppppppppppppppppppppppppppp\": {"
3140 " \"external_crx\": \"RandomValidExtension.crx\","
3141 " \"external_version\": \"1.0\""
3142 " }"
3143 "}";
3144 EXPECT_EQ(1, visitor.Visit(json_data));
3145
3146 // Check that if a base path is not provided, use of a relative
3147 // path fails.
3148 FilePath empty;
3149 MockProviderVisitor visitor_no_relative_paths(empty);
3150
3151 // Use absolute paths. Expect success.
3152 json_data =
3153 "{"
3154 " \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\": {"
3155 " \"external_crx\": \"//RandomExtension1.crx\","
3156 " \"external_version\": \"3.0\""
3157 " },"
3158 " \"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\": {"
3159 " \"external_crx\": \"//path/to/RandomExtension2.crx\","
3160 " \"external_version\": \"3.0\""
3161 " }"
3162 "}";
3163 EXPECT_EQ(2, visitor_no_relative_paths.Visit(json_data));
3164
3165 // Use a relative path. Expect that it will error out.
3166 json_data =
3167 "{"
3168 " \"cccccccccccccccccccccccccccccccc\": {"
3169 " \"external_crx\": \"RandomExtension2.crx\","
3170 " \"external_version\": \"3.0\""
3171 " }"
3172 "}";
3173 EXPECT_EQ(0, visitor_no_relative_paths.Visit(json_data));
3174 }
3175
3176 // Test loading good extensions from the profile directory.
TEST_F(ExtensionServiceTest,LoadAndRelocalizeExtensions)3177 TEST_F(ExtensionServiceTest, LoadAndRelocalizeExtensions) {
3178 // Initialize the test dir with a good Preferences/extensions.
3179 FilePath source_install_dir = data_dir_
3180 .AppendASCII("l10n");
3181 FilePath pref_path = source_install_dir.AppendASCII("Preferences");
3182 InitializeInstalledExtensionService(pref_path, source_install_dir);
3183
3184 service_->Init();
3185 loop_.RunAllPending();
3186
3187 ASSERT_EQ(3u, loaded_.size());
3188
3189 // This was equal to "sr" on load.
3190 ValidateStringPref(loaded_[0]->id(), keys::kCurrentLocale, "en");
3191
3192 // These are untouched by re-localization.
3193 ValidateStringPref(loaded_[1]->id(), keys::kCurrentLocale, "en");
3194 EXPECT_FALSE(IsPrefExist(loaded_[1]->id(), keys::kCurrentLocale));
3195
3196 // This one starts with Serbian name, and gets re-localized into English.
3197 EXPECT_EQ("My name is simple.", loaded_[0]->name());
3198
3199 // These are untouched by re-localization.
3200 EXPECT_EQ("My name is simple.", loaded_[1]->name());
3201 EXPECT_EQ("no l10n", loaded_[2]->name());
3202 }
3203
3204 class ExtensionsReadyRecorder : public NotificationObserver {
3205 public:
ExtensionsReadyRecorder()3206 ExtensionsReadyRecorder() : ready_(false) {
3207 registrar_.Add(this, NotificationType::EXTENSIONS_READY,
3208 NotificationService::AllSources());
3209 }
3210
set_ready(bool value)3211 void set_ready(bool value) { ready_ = value; }
ready()3212 bool ready() { return ready_; }
3213
3214 private:
Observe(NotificationType type,const NotificationSource & source,const NotificationDetails & details)3215 virtual void Observe(NotificationType type,
3216 const NotificationSource& source,
3217 const NotificationDetails& details) {
3218 switch (type.value) {
3219 case NotificationType::EXTENSIONS_READY:
3220 ready_ = true;
3221 break;
3222 default:
3223 NOTREACHED();
3224 }
3225 }
3226
3227 NotificationRegistrar registrar_;
3228 bool ready_;
3229 };
3230
3231 // Test that we get enabled/disabled correctly for all the pref/command-line
3232 // combinations. We don't want to derive from the ExtensionServiceTest class
3233 // for this test, so we use ExtensionServiceTestSimple.
3234 //
3235 // Also tests that we always fire EXTENSIONS_READY, no matter whether we are
3236 // enabled or not.
TEST(ExtensionServiceTestSimple,Enabledness)3237 TEST(ExtensionServiceTestSimple, Enabledness) {
3238 ExtensionsReadyRecorder recorder;
3239 scoped_ptr<TestingProfile> profile(new TestingProfile());
3240 MessageLoop loop;
3241 BrowserThread ui_thread(BrowserThread::UI, &loop);
3242 BrowserThread file_thread(BrowserThread::FILE, &loop);
3243 scoped_ptr<CommandLine> command_line;
3244 scoped_refptr<ExtensionService> service;
3245 FilePath install_dir = profile->GetPath()
3246 .AppendASCII(ExtensionService::kInstallDirectoryName);
3247
3248 // By default, we are enabled.
3249 command_line.reset(new CommandLine(CommandLine::NO_PROGRAM));
3250 service = profile->CreateExtensionService(command_line.get(),
3251 install_dir,
3252 false);
3253 EXPECT_TRUE(service->extensions_enabled());
3254 service->Init();
3255 loop.RunAllPending();
3256 EXPECT_TRUE(recorder.ready());
3257
3258 // If either the command line or pref is set, we are disabled.
3259 recorder.set_ready(false);
3260 profile.reset(new TestingProfile());
3261 command_line->AppendSwitch(switches::kDisableExtensions);
3262 service = profile->CreateExtensionService(command_line.get(),
3263 install_dir,
3264 false);
3265 EXPECT_FALSE(service->extensions_enabled());
3266 service->Init();
3267 loop.RunAllPending();
3268 EXPECT_TRUE(recorder.ready());
3269
3270 recorder.set_ready(false);
3271 profile.reset(new TestingProfile());
3272 profile->GetPrefs()->SetBoolean(prefs::kDisableExtensions, true);
3273 service = profile->CreateExtensionService(command_line.get(),
3274 install_dir,
3275 false);
3276 EXPECT_FALSE(service->extensions_enabled());
3277 service->Init();
3278 loop.RunAllPending();
3279 EXPECT_TRUE(recorder.ready());
3280
3281 recorder.set_ready(false);
3282 profile.reset(new TestingProfile());
3283 profile->GetPrefs()->SetBoolean(prefs::kDisableExtensions, true);
3284 command_line.reset(new CommandLine(CommandLine::NO_PROGRAM));
3285 service = profile->CreateExtensionService(command_line.get(),
3286 install_dir,
3287 false);
3288 EXPECT_FALSE(service->extensions_enabled());
3289 service->Init();
3290 loop.RunAllPending();
3291 EXPECT_TRUE(recorder.ready());
3292
3293 // Explicitly delete all the resources used in this test.
3294 profile.reset();
3295 service = NULL;
3296 }
3297
3298 // Test loading extensions that require limited and unlimited storage quotas.
TEST_F(ExtensionServiceTest,StorageQuota)3299 TEST_F(ExtensionServiceTest, StorageQuota) {
3300 InitializeEmptyExtensionService();
3301
3302 FilePath extensions_path = data_dir_
3303 .AppendASCII("storage_quota");
3304
3305 FilePath limited_quota_ext =
3306 extensions_path.AppendASCII("limited_quota")
3307 .AppendASCII("1.0");
3308
3309 // The old permission name for unlimited quota was "unlimited_storage", but
3310 // we changed it to "unlimitedStorage". This tests both versions.
3311 FilePath unlimited_quota_ext =
3312 extensions_path.AppendASCII("unlimited_quota")
3313 .AppendASCII("1.0");
3314 FilePath unlimited_quota_ext2 =
3315 extensions_path.AppendASCII("unlimited_quota")
3316 .AppendASCII("2.0");
3317 service_->LoadExtension(limited_quota_ext);
3318 service_->LoadExtension(unlimited_quota_ext);
3319 service_->LoadExtension(unlimited_quota_ext2);
3320 loop_.RunAllPending();
3321
3322 ASSERT_EQ(3u, loaded_.size());
3323 EXPECT_TRUE(profile_.get());
3324 EXPECT_FALSE(profile_->IsOffTheRecord());
3325
3326 // Open the database from each origin to make the tracker aware
3327 // of the existence of these origins and to get their quotas.
3328 int64 limited_quota = -1;
3329 int64 unlimited_quota = -1;
3330 string16 limited_quota_identifier =
3331 webkit_database::DatabaseUtil::GetOriginIdentifier(loaded_[0]->url());
3332 string16 unlimited_quota_identifier =
3333 webkit_database::DatabaseUtil::GetOriginIdentifier(loaded_[1]->url());
3334 string16 unlimited_quota_identifier2 =
3335 webkit_database::DatabaseUtil::GetOriginIdentifier(loaded_[2]->url());
3336 string16 db_name = UTF8ToUTF16("db");
3337 string16 description = UTF8ToUTF16("db_description");
3338 int64 database_size;
3339 webkit_database::DatabaseTracker* db_tracker = profile_->GetDatabaseTracker();
3340
3341 // First check the normal limited quota extension.
3342 db_tracker->DatabaseOpened(limited_quota_identifier, db_name, description,
3343 1, &database_size, &limited_quota);
3344 db_tracker->DatabaseClosed(limited_quota_identifier, db_name);
3345 EXPECT_EQ(profile_->GetDatabaseTracker()->GetDefaultQuota(), limited_quota);
3346
3347 // Now check the two unlimited quota ones.
3348 db_tracker->DatabaseOpened(unlimited_quota_identifier, db_name, description,
3349 1, &database_size, &unlimited_quota);
3350 db_tracker->DatabaseClosed(unlimited_quota_identifier, db_name);
3351 EXPECT_EQ(kint64max, unlimited_quota);
3352 db_tracker->DatabaseOpened(unlimited_quota_identifier2, db_name, description,
3353 1, &database_size, &unlimited_quota);
3354 db_tracker->DatabaseClosed(unlimited_quota_identifier2, db_name);
3355
3356 EXPECT_EQ(kint64max, unlimited_quota);
3357 }
3358
3359 // Tests ExtensionService::register_component_extension().
TEST_F(ExtensionServiceTest,ComponentExtensions)3360 TEST_F(ExtensionServiceTest, ComponentExtensions) {
3361 InitializeEmptyExtensionService();
3362
3363 // Component extensions should work even when extensions are disabled.
3364 set_extensions_enabled(false);
3365
3366 FilePath path = data_dir_
3367 .AppendASCII("good")
3368 .AppendASCII("Extensions")
3369 .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj")
3370 .AppendASCII("1.0.0.0");
3371
3372 std::string manifest;
3373 ASSERT_TRUE(file_util::ReadFileToString(
3374 path.Append(Extension::kManifestFilename), &manifest));
3375
3376 service_->register_component_extension(
3377 ExtensionService::ComponentExtensionInfo(manifest, path));
3378 service_->Init();
3379
3380 // Note that we do not pump messages -- the extension should be loaded
3381 // immediately.
3382
3383 EXPECT_EQ(0u, GetErrors().size());
3384 ASSERT_EQ(1u, loaded_.size());
3385 EXPECT_EQ(Extension::COMPONENT, loaded_[0]->location());
3386 EXPECT_EQ(1u, service_->extensions()->size());
3387
3388 // Component extensions shouldn't get recourded in the prefs.
3389 ValidatePrefKeyCount(0);
3390
3391 // Reload all extensions, and make sure it comes back.
3392 std::string extension_id = service_->extensions()->at(0)->id();
3393 loaded_.clear();
3394 service_->ReloadExtensions();
3395 ASSERT_EQ(1u, service_->extensions()->size());
3396 EXPECT_EQ(extension_id, service_->extensions()->at(0)->id());
3397 }
3398
3399 namespace {
3400
AlwaysInstall(const Extension & extension)3401 bool AlwaysInstall(const Extension& extension) {
3402 return true;
3403 }
3404
3405 } // namespace
3406
TEST_F(ExtensionServiceTest,ProcessSyncDataUninstall)3407 TEST_F(ExtensionServiceTest, ProcessSyncDataUninstall) {
3408 InitializeEmptyExtensionService();
3409
3410 ExtensionSyncData extension_sync_data;
3411 extension_sync_data.id = good_crx;
3412 extension_sync_data.uninstalled = true;
3413
3414 // Should do nothing.
3415 service_->ProcessSyncData(extension_sync_data, &AlwaysInstall);
3416
3417 // Install the extension.
3418 FilePath extension_path = data_dir_.AppendASCII("good.crx");
3419 InstallCrx(extension_path, true);
3420 EXPECT_TRUE(service_->GetExtensionById(good_crx, true));
3421
3422 // Should uninstall the extension.
3423 service_->ProcessSyncData(extension_sync_data, &AlwaysInstall);
3424 EXPECT_FALSE(service_->GetExtensionById(good_crx, true));
3425
3426 // Should again do nothing.
3427 service_->ProcessSyncData(extension_sync_data, &AlwaysInstall);
3428 }
3429
3430
TEST_F(ExtensionServiceTest,ProcessSyncDataSettings)3431 TEST_F(ExtensionServiceTest, ProcessSyncDataSettings) {
3432 InitializeEmptyExtensionService();
3433
3434 FilePath extension_path = data_dir_.AppendASCII("good.crx");
3435 InstallCrx(extension_path, true);
3436 EXPECT_TRUE(service_->IsExtensionEnabled(good_crx));
3437 EXPECT_FALSE(service_->IsIncognitoEnabled(good_crx));
3438
3439 ExtensionSyncData extension_sync_data;
3440 extension_sync_data.id = good_crx;
3441 extension_sync_data.version =
3442 *(service_->GetExtensionById(good_crx, true)->version());
3443
3444 extension_sync_data.enabled = false;
3445 service_->ProcessSyncData(extension_sync_data, &AlwaysInstall);
3446 EXPECT_FALSE(service_->IsExtensionEnabled(good_crx));
3447 EXPECT_FALSE(service_->IsIncognitoEnabled(good_crx));
3448
3449 extension_sync_data.enabled = true;
3450 extension_sync_data.incognito_enabled = true;
3451 service_->ProcessSyncData(extension_sync_data, &AlwaysInstall);
3452 EXPECT_TRUE(service_->IsExtensionEnabled(good_crx));
3453 EXPECT_TRUE(service_->IsIncognitoEnabled(good_crx));
3454
3455 extension_sync_data.enabled = false;
3456 extension_sync_data.incognito_enabled = true;
3457 service_->ProcessSyncData(extension_sync_data, &AlwaysInstall);
3458 EXPECT_FALSE(service_->IsExtensionEnabled(good_crx));
3459 EXPECT_TRUE(service_->IsIncognitoEnabled(good_crx));
3460
3461 EXPECT_FALSE(service_->pending_extension_manager()->IsIdPending(good_crx));
3462 }
3463
TEST_F(ExtensionServiceTest,ProcessSyncDataVersionCheck)3464 TEST_F(ExtensionServiceTest, ProcessSyncDataVersionCheck) {
3465 InitializeExtensionServiceWithUpdater();
3466
3467 // Install the extension.
3468 FilePath extension_path = data_dir_.AppendASCII("good.crx");
3469 InstallCrx(extension_path, true);
3470 EXPECT_TRUE(service_->IsExtensionEnabled(good_crx));
3471 EXPECT_FALSE(service_->IsIncognitoEnabled(good_crx));
3472
3473 ExtensionSyncData extension_sync_data;
3474 extension_sync_data.id = good_crx;
3475 extension_sync_data.enabled = true;
3476 extension_sync_data.version =
3477 *(service_->GetExtensionById(good_crx, true)->version());
3478
3479 // Should do nothing if extension version == sync version.
3480 service_->ProcessSyncData(extension_sync_data, &AlwaysInstall);
3481 EXPECT_FALSE(service_->updater()->WillCheckSoon());
3482
3483 // Should do nothing if extension version > sync version (but see
3484 // the TODO in ProcessSyncData).
3485 {
3486 scoped_ptr<Version> version(Version::GetVersionFromString("0.0.0.0"));
3487 extension_sync_data.version = *version;
3488 service_->ProcessSyncData(extension_sync_data, &AlwaysInstall);
3489 EXPECT_FALSE(service_->updater()->WillCheckSoon());
3490 }
3491
3492 // Should kick off an update if extension version < sync version.
3493 {
3494 scoped_ptr<Version> version(Version::GetVersionFromString("9.9.9.9"));
3495 extension_sync_data.version = *version;
3496 service_->ProcessSyncData(extension_sync_data, &AlwaysInstall);
3497 EXPECT_TRUE(service_->updater()->WillCheckSoon());
3498 }
3499
3500 EXPECT_FALSE(service_->pending_extension_manager()->IsIdPending(good_crx));
3501 }
3502
TEST_F(ExtensionServiceTest,ProcessSyncDataNotInstalled)3503 TEST_F(ExtensionServiceTest, ProcessSyncDataNotInstalled) {
3504 InitializeExtensionServiceWithUpdater();
3505
3506 ExtensionSyncData extension_sync_data;
3507 extension_sync_data.id = good_crx;
3508 extension_sync_data.update_url = GURL("http://www.google.com");
3509 extension_sync_data.enabled = true;
3510 {
3511 scoped_ptr<Version> version(Version::GetVersionFromString("1.2.3.4"));
3512 extension_sync_data.version = *version;
3513 }
3514
3515 service_->ProcessSyncData(extension_sync_data, &AlwaysInstall);
3516 EXPECT_TRUE(service_->updater()->WillCheckSoon());
3517
3518 PendingExtensionInfo info;
3519 EXPECT_TRUE(
3520 service_->pending_extension_manager()->GetById(good_crx, &info));
3521 EXPECT_EQ(extension_sync_data.update_url, info.update_url());
3522 EXPECT_TRUE(info.is_from_sync());
3523 EXPECT_TRUE(info.install_silently());
3524 EXPECT_EQ(extension_sync_data.enabled, info.enable_on_install());
3525 EXPECT_EQ(extension_sync_data.incognito_enabled,
3526 info.enable_incognito_on_install());
3527 EXPECT_EQ(Extension::INTERNAL, info.install_source());
3528 // TODO(akalin): Figure out a way to test |info.ShouldAllowInstall()|.
3529 }
3530
3531 // Test that when multiple sources try to install an extension,
3532 // we consistently choose the right one. To make tests easy to read,
3533 // methods that fake requests to install crx files in several ways
3534 // are provided.
3535 class ExtensionSourcePriorityTest : public ExtensionServiceTest {
3536 public:
SetUp()3537 void SetUp() {
3538 // All tests use a single extension. Put the id and path in member vars
3539 // that all methods can read.
3540 crx_id_ = kGoodId;
3541 crx_path_ = data_dir_.AppendASCII("good.crx");
3542 }
3543
3544 // Fake an external source adding a URL to fetch an extension from.
AddPendingExternalPrefUrl()3545 void AddPendingExternalPrefUrl() {
3546 service_->pending_extension_manager()->AddFromExternalUpdateUrl(
3547 crx_id_, GURL(), Extension::EXTERNAL_PREF_DOWNLOAD);
3548 }
3549
3550 // Fake an external file from external_extensions.json.
AddPendingExternalPrefFileInstall()3551 void AddPendingExternalPrefFileInstall() {
3552 scoped_ptr<Version> version;
3553 version.reset(Version::GetVersionFromString("1.0.0.0"));
3554
3555 service_->OnExternalExtensionFileFound(
3556 crx_id_, version.get(), crx_path_, Extension::EXTERNAL_PREF);
3557 }
3558
3559 // Fake a request from sync to install an extension.
AddPendingSyncInstall()3560 bool AddPendingSyncInstall() {
3561 return service_->pending_extension_manager()->AddFromSync(
3562 crx_id_, GURL(kGoodUpdateURL), &IsExtension,
3563 kGoodInstallSilently, kGoodInitialState,
3564 kGoodInitialIncognitoEnabled);
3565 }
3566
3567 // Fake a request to install a default app.
AddPendingDefaultAppInstall()3568 void AddPendingDefaultAppInstall() {
3569 service_->pending_extension_manager()->AddFromDefaultAppList(crx_id_);
3570 }
3571
3572 // Fake a policy install.
AddPendingPolicyInstall()3573 void AddPendingPolicyInstall() {
3574 scoped_ptr<Version> version;
3575 version.reset(Version::GetVersionFromString("1.0.0.0"));
3576
3577 // Get path to the CRX with id |kGoodId|.
3578 service_->OnExternalExtensionUpdateUrlFound(
3579 crx_id_, GURL(), Extension::EXTERNAL_POLICY_DOWNLOAD);
3580 }
3581
3582 // Get the install source of a pending extension.
GetPendingLocation()3583 Extension::Location GetPendingLocation() {
3584 PendingExtensionInfo info;
3585 EXPECT_TRUE(service_->pending_extension_manager()->GetById(crx_id_, &info));
3586 return info.install_source();
3587 }
3588
3589 // Is an extension pending from a sync request?
GetPendingIsFromSync()3590 bool GetPendingIsFromSync() {
3591 PendingExtensionInfo info;
3592 EXPECT_TRUE(service_->pending_extension_manager()->GetById(crx_id_, &info));
3593 return info.is_from_sync();
3594 }
3595
3596 // Is the CRX id these tests use pending?
IsCrxPending()3597 bool IsCrxPending() {
3598 return service_->pending_extension_manager()->IsIdPending(crx_id_);
3599 }
3600
3601 // Is an extension installed?
IsCrxInstalled()3602 bool IsCrxInstalled() {
3603 return (service_->GetExtensionById(crx_id_, true) != NULL);
3604 }
3605
3606 protected:
3607 // All tests use a single extension. Making the id and path member
3608 // vars avoids pasing the same argument to every method.
3609 std::string crx_id_;
3610 FilePath crx_path_;
3611 };
3612
3613 #if defined(OS_CHROMEOS)
3614 // TODO(skerner): crbug/79755
3615 #define MAYBE_PendingExternalFileOverSync DISABLED_PendingExternalFileOverSync
3616 #else
3617 #define MAYBE_PendingExternalFileOverSync PendingExternalFileOverSync
3618 #endif
3619 // Test that a pending request for installation of an external CRX from
3620 // an update URL overrides a pending request to install the same extension
3621 // from sync.
TEST_F(ExtensionSourcePriorityTest,MAYBE_PendingExternalFileOverSync)3622 TEST_F(ExtensionSourcePriorityTest, MAYBE_PendingExternalFileOverSync) {
3623 InitializeEmptyExtensionService();
3624
3625 ASSERT_FALSE(IsCrxInstalled());
3626
3627 // Install pending extension from sync.
3628 AddPendingSyncInstall();
3629 ASSERT_EQ(Extension::INTERNAL, GetPendingLocation());
3630 EXPECT_TRUE(GetPendingIsFromSync());
3631 ASSERT_FALSE(IsCrxInstalled());
3632
3633 // Install pending as external prefs json would.
3634 AddPendingExternalPrefFileInstall();
3635 ASSERT_EQ(Extension::EXTERNAL_PREF, GetPendingLocation());
3636 ASSERT_FALSE(IsCrxInstalled());
3637
3638 // Another request from sync should be ignorred.
3639 AddPendingSyncInstall();
3640 ASSERT_EQ(Extension::EXTERNAL_PREF, GetPendingLocation());
3641 ASSERT_FALSE(IsCrxInstalled());
3642
3643 WaitForCrxInstall(crx_path_, true);
3644 ASSERT_TRUE(IsCrxInstalled());
3645 }
3646
3647 #if defined(OS_CHROMEOS)
3648 // TODO(skerner): crbug/79755
3649 #define MAYBE_PendingExternalUrlOverSync DISABLED_PendingExternalUrlOverSync
3650 #else
3651 #define MAYBE_PendingExternalUrlOverSync PendingExternalUrlOverSync
3652 #endif
3653 // Test that an install of an external CRX from an update overrides
3654 // an install of the same extension from sync.
TEST_F(ExtensionSourcePriorityTest,MAYBE_PendingExternalUrlOverSync)3655 TEST_F(ExtensionSourcePriorityTest, MAYBE_PendingExternalUrlOverSync) {
3656 InitializeEmptyExtensionService();
3657 ASSERT_FALSE(IsCrxInstalled());
3658
3659 AddPendingSyncInstall();
3660 ASSERT_EQ(Extension::INTERNAL, GetPendingLocation());
3661 EXPECT_TRUE(GetPendingIsFromSync());
3662 ASSERT_FALSE(IsCrxInstalled());
3663
3664 AddPendingExternalPrefUrl();
3665 ASSERT_EQ(Extension::EXTERNAL_PREF_DOWNLOAD, GetPendingLocation());
3666 EXPECT_FALSE(GetPendingIsFromSync());
3667 ASSERT_FALSE(IsCrxInstalled());
3668
3669 AddPendingSyncInstall();
3670 ASSERT_EQ(Extension::EXTERNAL_PREF_DOWNLOAD, GetPendingLocation());
3671 EXPECT_FALSE(GetPendingIsFromSync());
3672 ASSERT_FALSE(IsCrxInstalled());
3673 }
3674
3675 #if defined(OS_CHROMEOS)
3676 // TODO(skerner): crbug/79755
3677 #define MAYBE_PendingExternalFileOverDefaultApp DISABLED_PendingExternalFileOverDefaultApp
3678 #else
3679 #define MAYBE_PendingExternalFileOverDefaultApp PendingExternalFileOverDefaultApp
3680 #endif
3681 // Test that an install of an external CRX overrides a request for a default
3682 // app.
TEST_F(ExtensionSourcePriorityTest,MAYBE_PendingExternalFileOverDefaultApp)3683 TEST_F(ExtensionSourcePriorityTest, MAYBE_PendingExternalFileOverDefaultApp) {
3684 InitializeEmptyExtensionService();
3685 ASSERT_FALSE(IsCrxInstalled());
3686
3687 AddPendingDefaultAppInstall();
3688 ASSERT_EQ(Extension::INTERNAL, GetPendingLocation());
3689 ASSERT_FALSE(IsCrxInstalled());
3690
3691 AddPendingExternalPrefFileInstall();
3692 ASSERT_EQ(Extension::EXTERNAL_PREF, GetPendingLocation());
3693 ASSERT_FALSE(IsCrxInstalled());
3694
3695 AddPendingDefaultAppInstall();
3696 ASSERT_EQ(Extension::EXTERNAL_PREF, GetPendingLocation());
3697 ASSERT_FALSE(IsCrxInstalled());
3698
3699 WaitForCrxInstall(crx_path_, true);
3700 ASSERT_TRUE(IsCrxInstalled());
3701 }
3702
3703 #if defined(OS_CHROMEOS)
3704 // TODO(skerner): crbug/79755
3705 #define MAYBE_InstallExternalBlocksSyncRequest DISABLED_InstallExternalBlocksSyncRequest
3706 #else
3707 #define MAYBE_InstallExternalBlocksSyncRequest InstallExternalBlocksSyncRequest
3708 #endif
3709 // Test that an external install request stops sync from installing
3710 // the same extension.
TEST_F(ExtensionSourcePriorityTest,MAYBE_InstallExternalBlocksSyncRequest)3711 TEST_F(ExtensionSourcePriorityTest, MAYBE_InstallExternalBlocksSyncRequest) {
3712 InitializeEmptyExtensionService();
3713 ASSERT_FALSE(IsCrxInstalled());
3714
3715 // External prefs starts an install.
3716 AddPendingExternalPrefFileInstall();
3717
3718 // Crx installer was made, but has not yet run.
3719 ASSERT_FALSE(IsCrxInstalled());
3720
3721 // Before the CRX installer runs, Sync requests that the same extension
3722 // be installed. Should fail, because an external source is pending.
3723 ASSERT_FALSE(AddPendingSyncInstall());
3724
3725 // Wait for the external source to install.
3726 WaitForCrxInstall(crx_path_, true);
3727 ASSERT_TRUE(IsCrxInstalled());
3728
3729 // Now that the extension is installed, sync request should fail
3730 // because the extension is already installed.
3731 ASSERT_FALSE(AddPendingSyncInstall());
3732 }
3733