1// Copyright (c) 2012 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/test_extension_prefs.h" 6 7#include "base/bind.h" 8#include "base/bind_helpers.h" 9#include "base/file_util.h" 10#include "base/memory/scoped_ptr.h" 11#include "base/message_loop/message_loop.h" 12#include "base/message_loop/message_loop_proxy.h" 13#include "base/prefs/json_pref_store.h" 14#include "base/prefs/pref_value_store.h" 15#include "base/run_loop.h" 16#include "base/sequenced_task_runner.h" 17#include "base/synchronization/waitable_event.h" 18#include "base/values.h" 19#include "chrome/browser/prefs/pref_service_mock_factory.h" 20#include "chrome/browser/prefs/pref_service_syncable.h" 21#include "chrome/common/chrome_constants.h" 22#include "components/pref_registry/pref_registry_syncable.h" 23#include "content/public/browser/browser_thread.h" 24#include "extensions/browser/extension_pref_store.h" 25#include "extensions/browser/extension_pref_value_map.h" 26#include "extensions/browser/extension_prefs.h" 27#include "extensions/browser/extensions_browser_client.h" 28#include "extensions/common/extension.h" 29#include "extensions/common/manifest_constants.h" 30#include "sync/api/string_ordinal.h" 31#include "testing/gtest/include/gtest/gtest.h" 32 33using content::BrowserThread; 34 35namespace extensions { 36 37namespace { 38 39// A TimeProvider which returns an incrementally later time each time 40// GetCurrentTime is called. 41class IncrementalTimeProvider : public ExtensionPrefs::TimeProvider { 42 public: 43 IncrementalTimeProvider() : current_time_(base::Time::Now()) { 44 } 45 46 virtual ~IncrementalTimeProvider() { 47 } 48 49 virtual base::Time GetCurrentTime() const OVERRIDE { 50 current_time_ += base::TimeDelta::FromSeconds(10); 51 return current_time_; 52 } 53 54 private: 55 DISALLOW_COPY_AND_ASSIGN(IncrementalTimeProvider); 56 57 mutable base::Time current_time_; 58}; 59 60} // namespace 61 62TestExtensionPrefs::TestExtensionPrefs(base::SequencedTaskRunner* task_runner) 63 : task_runner_(task_runner), extensions_disabled_(false) { 64 EXPECT_TRUE(temp_dir_.CreateUniqueTempDir()); 65 preferences_file_ = temp_dir_.path().Append(chrome::kPreferencesFilename); 66 extensions_dir_ = temp_dir_.path().AppendASCII("Extensions"); 67 EXPECT_TRUE(base::CreateDirectory(extensions_dir_)); 68 69 ResetPrefRegistry(); 70 RecreateExtensionPrefs(); 71} 72 73TestExtensionPrefs::~TestExtensionPrefs() { 74} 75 76PrefService* TestExtensionPrefs::pref_service() { 77 return pref_service_.get(); 78} 79 80const scoped_refptr<user_prefs::PrefRegistrySyncable>& 81TestExtensionPrefs::pref_registry() { 82 return pref_registry_; 83} 84 85void TestExtensionPrefs::ResetPrefRegistry() { 86 pref_registry_ = new user_prefs::PrefRegistrySyncable; 87 ExtensionPrefs::RegisterProfilePrefs(pref_registry_.get()); 88} 89 90void TestExtensionPrefs::RecreateExtensionPrefs() { 91 // We persist and reload the PrefService's PrefStores because this process 92 // deletes all empty dictionaries. The ExtensionPrefs implementation 93 // needs to be able to handle this situation. 94 if (pref_service_) { 95 // Commit a pending write (which posts a task to task_runner_) and wait for 96 // it to finish. 97 pref_service_->CommitPendingWrite(); 98 base::RunLoop run_loop; 99 ASSERT_TRUE( 100 task_runner_->PostTaskAndReply( 101 FROM_HERE, 102 base::Bind(&base::DoNothing), 103 run_loop.QuitClosure())); 104 run_loop.Run(); 105 } 106 107 extension_pref_value_map_.reset(new ExtensionPrefValueMap); 108 PrefServiceMockFactory factory; 109 factory.SetUserPrefsFile(preferences_file_, task_runner_.get()); 110 factory.set_extension_prefs( 111 new ExtensionPrefStore(extension_pref_value_map_.get(), false)); 112 pref_service_ = factory.CreateSyncable(pref_registry_.get()).Pass(); 113 114 prefs_.reset(ExtensionPrefs::Create( 115 pref_service_.get(), 116 temp_dir_.path(), 117 extension_pref_value_map_.get(), 118 ExtensionsBrowserClient::Get()->CreateAppSorting().Pass(), 119 extensions_disabled_, 120 std::vector<ExtensionPrefsObserver*>(), 121 // Guarantee that no two extensions get the same installation time 122 // stamp and we can reliably assert the installation order in the tests. 123 scoped_ptr<ExtensionPrefs::TimeProvider>(new IncrementalTimeProvider()))); 124} 125 126scoped_refptr<Extension> TestExtensionPrefs::AddExtension( 127 const std::string& name) { 128 base::DictionaryValue dictionary; 129 dictionary.SetString(manifest_keys::kName, name); 130 dictionary.SetString(manifest_keys::kVersion, "0.1"); 131 return AddExtensionWithManifest(dictionary, Manifest::INTERNAL); 132} 133 134scoped_refptr<Extension> TestExtensionPrefs::AddApp(const std::string& name) { 135 base::DictionaryValue dictionary; 136 dictionary.SetString(manifest_keys::kName, name); 137 dictionary.SetString(manifest_keys::kVersion, "0.1"); 138 dictionary.SetString(manifest_keys::kApp, "true"); 139 dictionary.SetString(manifest_keys::kLaunchWebURL, "http://example.com"); 140 return AddExtensionWithManifest(dictionary, Manifest::INTERNAL); 141 142} 143 144scoped_refptr<Extension> TestExtensionPrefs::AddExtensionWithManifest( 145 const base::DictionaryValue& manifest, Manifest::Location location) { 146 return AddExtensionWithManifestAndFlags(manifest, location, 147 Extension::NO_FLAGS); 148} 149 150scoped_refptr<Extension> TestExtensionPrefs::AddExtensionWithManifestAndFlags( 151 const base::DictionaryValue& manifest, 152 Manifest::Location location, 153 int extra_flags) { 154 std::string name; 155 EXPECT_TRUE(manifest.GetString(manifest_keys::kName, &name)); 156 base::FilePath path = extensions_dir_.AppendASCII(name); 157 std::string errors; 158 scoped_refptr<Extension> extension = Extension::Create( 159 path, location, manifest, extra_flags, &errors); 160 EXPECT_TRUE(extension.get()) << errors; 161 if (!extension.get()) 162 return NULL; 163 164 EXPECT_TRUE(Extension::IdIsValid(extension->id())); 165 prefs_->OnExtensionInstalled(extension.get(), 166 Extension::ENABLED, 167 syncer::StringOrdinal::CreateInitialOrdinal(), 168 std::string()); 169 return extension; 170} 171 172std::string TestExtensionPrefs::AddExtensionAndReturnId( 173 const std::string& name) { 174 scoped_refptr<Extension> extension(AddExtension(name)); 175 return extension->id(); 176} 177 178PrefService* TestExtensionPrefs::CreateIncognitoPrefService() const { 179 return pref_service_->CreateIncognitoPrefService( 180 new ExtensionPrefStore(extension_pref_value_map_.get(), true)); 181} 182 183void TestExtensionPrefs::set_extensions_disabled(bool extensions_disabled) { 184 extensions_disabled_ = extensions_disabled; 185} 186 187} // namespace extensions 188