// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/extensions/test_extension_prefs.h" #include "base/bind.h" #include "base/bind_helpers.h" #include "base/file_util.h" #include "base/memory/scoped_ptr.h" #include "base/message_loop.h" #include "base/message_loop_proxy.h" #include "base/prefs/json_pref_store.h" #include "base/prefs/pref_value_store.h" #include "base/run_loop.h" #include "base/sequenced_task_runner.h" #include "base/synchronization/waitable_event.h" #include "base/values.h" #include "chrome/browser/extensions/extension_pref_store.h" #include "chrome/browser/extensions/extension_pref_value_map.h" #include "chrome/browser/extensions/extension_prefs.h" #include "chrome/browser/prefs/pref_service_mock_builder.h" #include "chrome/browser/prefs/pref_service_syncable.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/extension_manifest_constants.h" #include "components/user_prefs/pref_registry_syncable.h" #include "content/public/browser/browser_thread.h" #include "sync/api/string_ordinal.h" #include "testing/gtest/include/gtest/gtest.h" using content::BrowserThread; namespace extensions { namespace { // A TimeProvider which returns an incrementally later time each time // GetCurrentTime is called. class IncrementalTimeProvider : public ExtensionPrefs::TimeProvider { public: IncrementalTimeProvider() : current_time_(base::Time::Now()) { } virtual ~IncrementalTimeProvider() { } virtual base::Time GetCurrentTime() const OVERRIDE { current_time_ += base::TimeDelta::FromSeconds(10); return current_time_; } private: DISALLOW_COPY_AND_ASSIGN(IncrementalTimeProvider); mutable base::Time current_time_; }; } // namespace TestExtensionPrefs::TestExtensionPrefs(base::SequencedTaskRunner* task_runner) : pref_service_(NULL), task_runner_(task_runner), extensions_disabled_(false) { EXPECT_TRUE(temp_dir_.CreateUniqueTempDir()); preferences_file_ = temp_dir_.path().AppendASCII("Preferences"); extensions_dir_ = temp_dir_.path().AppendASCII("Extensions"); EXPECT_TRUE(file_util::CreateDirectory(extensions_dir_)); ResetPrefRegistry(); RecreateExtensionPrefs(); } TestExtensionPrefs::~TestExtensionPrefs() { } PrefService* TestExtensionPrefs::pref_service() { return pref_service_.get(); } const scoped_refptr& TestExtensionPrefs::pref_registry() { return pref_registry_; } void TestExtensionPrefs::ResetPrefRegistry() { pref_registry_ = new PrefRegistrySyncable; ExtensionPrefs::RegisterUserPrefs(pref_registry_); } void TestExtensionPrefs::RecreateExtensionPrefs() { // We persist and reload the PrefService's PrefStores because this process // deletes all empty dictionaries. The ExtensionPrefs implementation // needs to be able to handle this situation. if (pref_service_) { // Commit a pending write (which posts a task to task_runner_) and wait for // it to finish. pref_service_->CommitPendingWrite(); base::RunLoop run_loop; ASSERT_TRUE( task_runner_->PostTaskAndReply( FROM_HERE, base::Bind(&base::DoNothing), run_loop.QuitClosure())); run_loop.Run(); } extension_pref_value_map_.reset(new ExtensionPrefValueMap); PrefServiceMockBuilder builder; builder.WithUserFilePrefs(preferences_file_, task_runner_); builder.WithExtensionPrefs( new ExtensionPrefStore(extension_pref_value_map_.get(), false)); pref_service_.reset(builder.CreateSyncable(pref_registry_)); prefs_ = ExtensionPrefs::Create( pref_service_.get(), temp_dir_.path(), extension_pref_value_map_.get(), extensions_disabled_, // Guarantee that no two extensions get the same installation time // stamp and we can reliably assert the installation order in the tests. scoped_ptr( new IncrementalTimeProvider())); } scoped_refptr TestExtensionPrefs::AddExtension(std::string name) { DictionaryValue dictionary; dictionary.SetString(extension_manifest_keys::kName, name); dictionary.SetString(extension_manifest_keys::kVersion, "0.1"); return AddExtensionWithManifest(dictionary, Manifest::INTERNAL); } scoped_refptr TestExtensionPrefs::AddApp(std::string name) { DictionaryValue dictionary; dictionary.SetString(extension_manifest_keys::kName, name); dictionary.SetString(extension_manifest_keys::kVersion, "0.1"); dictionary.SetString(extension_manifest_keys::kApp, "true"); dictionary.SetString(extension_manifest_keys::kLaunchWebURL, "http://example.com"); return AddExtensionWithManifest(dictionary, Manifest::INTERNAL); } scoped_refptr TestExtensionPrefs::AddExtensionWithManifest( const DictionaryValue& manifest, Manifest::Location location) { return AddExtensionWithManifestAndFlags(manifest, location, Extension::NO_FLAGS); } scoped_refptr TestExtensionPrefs::AddExtensionWithManifestAndFlags( const DictionaryValue& manifest, Manifest::Location location, int extra_flags) { std::string name; EXPECT_TRUE(manifest.GetString(extension_manifest_keys::kName, &name)); base::FilePath path = extensions_dir_.AppendASCII(name); std::string errors; scoped_refptr extension = Extension::Create( path, location, manifest, extra_flags, &errors); EXPECT_TRUE(extension) << errors; if (!extension) return NULL; EXPECT_TRUE(Extension::IdIsValid(extension->id())); prefs_->OnExtensionInstalled(extension, Extension::ENABLED, syncer::StringOrdinal::CreateInitialOrdinal()); return extension; } std::string TestExtensionPrefs::AddExtensionAndReturnId(std::string name) { scoped_refptr extension(AddExtension(name)); return extension->id(); } PrefService* TestExtensionPrefs::CreateIncognitoPrefService() const { return pref_service_->CreateIncognitoPrefService( new ExtensionPrefStore(extension_pref_value_map_.get(), true)); } void TestExtensionPrefs::set_extensions_disabled(bool extensions_disabled) { extensions_disabled_ = extensions_disabled; } } // namespace extensions