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