15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/test_extension_prefs.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
11ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h"
12b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/prefs/json_pref_store.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_value_store.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/run_loop.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/sequenced_task_runner.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/waitable_event.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/prefs/pref_service_mock_factory.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/prefs/pref_service_syncable.h"
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/common/chrome_constants.h"
2203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "components/crx_file/id_util.h"
23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/pref_registry/pref_registry_syncable.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_pref_store.h"
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_pref_value_map.h"
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_prefs.h"
28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/extensions_browser_client.h"
29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h"
303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "extensions/common/manifest_constants.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/api/string_ordinal.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// A TimeProvider which returns an incrementally later time each time
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// GetCurrentTime is called.
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class IncrementalTimeProvider : public ExtensionPrefs::TimeProvider {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  IncrementalTimeProvider() : current_time_(base::Time::Now()) {
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~IncrementalTimeProvider() {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual base::Time GetCurrentTime() const OVERRIDE {
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    current_time_ += base::TimeDelta::FromSeconds(10);
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return current_time_;
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(IncrementalTimeProvider);
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  mutable base::Time current_time_;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciTestExtensionPrefs::TestExtensionPrefs(
641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const scoped_refptr<base::SequencedTaskRunner>& task_runner)
657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    : task_runner_(task_runner), extensions_disabled_(false) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  preferences_file_ = temp_dir_.path().Append(chrome::kPreferencesFilename);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extensions_dir_ = temp_dir_.path().AppendASCII("Extensions");
69a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_TRUE(base::CreateDirectory(extensions_dir_));
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ResetPrefRegistry();
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RecreateExtensionPrefs();
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TestExtensionPrefs::~TestExtensionPrefs() {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)PrefService* TestExtensionPrefs::pref_service() {
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return pref_service_.get();
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const scoped_refptr<user_prefs::PrefRegistrySyncable>&
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TestExtensionPrefs::pref_registry() {
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return pref_registry_;
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TestExtensionPrefs::ResetPrefRegistry() {
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  pref_registry_ = new user_prefs::PrefRegistrySyncable;
897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ExtensionPrefs::RegisterProfilePrefs(pref_registry_.get());
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestExtensionPrefs::RecreateExtensionPrefs() {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We persist and reload the PrefService's PrefStores because this process
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // deletes all empty dictionaries. The ExtensionPrefs implementation
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // needs to be able to handle this situation.
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (pref_service_) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Commit a pending write (which posts a task to task_runner_) and wait for
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // it to finish.
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pref_service_->CommitPendingWrite();
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::RunLoop run_loop;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        task_runner_->PostTaskAndReply(
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            FROM_HERE,
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            base::Bind(&base::DoNothing),
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            run_loop.QuitClosure()));
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    run_loop.Run();
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extension_pref_value_map_.reset(new ExtensionPrefValueMap);
110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  PrefServiceMockFactory factory;
111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  factory.SetUserPrefsFile(preferences_file_, task_runner_.get());
112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  factory.set_extension_prefs(
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new ExtensionPrefStore(extension_pref_value_map_.get(), false));
114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  pref_service_ = factory.CreateSyncable(pref_registry_.get()).Pass();
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  prefs_.reset(ExtensionPrefs::Create(
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      pref_service_.get(),
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      temp_dir_.path(),
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      extension_pref_value_map_.get(),
120f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      ExtensionsBrowserClient::Get()->CreateAppSorting().Pass(),
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      extensions_disabled_,
122e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      std::vector<ExtensionPrefsObserver*>(),
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Guarantee that no two extensions get the same installation time
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // stamp and we can reliably assert the installation order in the tests.
125e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      scoped_ptr<ExtensionPrefs::TimeProvider>(new IncrementalTimeProvider())));
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuscoped_refptr<Extension> TestExtensionPrefs::AddExtension(
1295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const std::string& name) {
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue dictionary;
1313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  dictionary.SetString(manifest_keys::kName, name);
1323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  dictionary.SetString(manifest_keys::kVersion, "0.1");
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return AddExtensionWithManifest(dictionary, Manifest::INTERNAL);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuscoped_refptr<Extension> TestExtensionPrefs::AddApp(const std::string& name) {
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue dictionary;
1383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  dictionary.SetString(manifest_keys::kName, name);
1393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  dictionary.SetString(manifest_keys::kVersion, "0.1");
1403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  dictionary.SetString(manifest_keys::kApp, "true");
1413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  dictionary.SetString(manifest_keys::kLaunchWebURL, "http://example.com");
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return AddExtensionWithManifest(dictionary, Manifest::INTERNAL);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_refptr<Extension> TestExtensionPrefs::AddExtensionWithManifest(
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::DictionaryValue& manifest, Manifest::Location location) {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return AddExtensionWithManifestAndFlags(manifest, location,
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          Extension::NO_FLAGS);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_refptr<Extension> TestExtensionPrefs::AddExtensionWithManifestAndFlags(
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::DictionaryValue& manifest,
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Manifest::Location location,
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int extra_flags) {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string name;
1573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_TRUE(manifest.GetString(manifest_keys::kName, &name));
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath path =  extensions_dir_.AppendASCII(name);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string errors;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<Extension> extension = Extension::Create(
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      path, location, manifest, extra_flags, &errors);
162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(extension.get()) << errors;
163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!extension.get())
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  EXPECT_TRUE(crx_file::id_util::IdIsValid(extension->id()));
167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  prefs_->OnExtensionInstalled(extension.get(),
168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               Extension::ENABLED,
169effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                               syncer::StringOrdinal::CreateInitialOrdinal(),
170effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                               std::string());
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return extension;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liustd::string TestExtensionPrefs::AddExtensionAndReturnId(
1755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const std::string& name) {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<Extension> extension(AddExtension(name));
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return extension->id();
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PrefService* TestExtensionPrefs::CreateIncognitoPrefService() const {
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return pref_service_->CreateIncognitoPrefService(
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new ExtensionPrefStore(extension_pref_value_map_.get(), true));
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestExtensionPrefs::set_extensions_disabled(bool extensions_disabled) {
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extensions_disabled_ = extensions_disabled;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace extensions
190