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