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/test_extension_prefs.h" 6 7#include "base/file_util.h" 8#include "base/memory/scoped_ptr.h" 9#include "base/message_loop.h" 10#include "base/message_loop_proxy.h" 11#include "base/values.h" 12#include "base/synchronization/waitable_event.h" 13#include "chrome/browser/extensions/extension_pref_store.h" 14#include "chrome/browser/extensions/extension_pref_value_map.h" 15#include "chrome/browser/extensions/extension_prefs.h" 16#include "chrome/browser/prefs/pref_service.h" 17#include "chrome/browser/prefs/pref_service_mock_builder.h" 18#include "chrome/browser/prefs/pref_value_store.h" 19#include "chrome/common/extensions/extension.h" 20#include "chrome/common/extensions/extension_constants.h" 21#include "chrome/common/json_pref_store.h" 22#include "chrome/test/signaling_task.h" 23#include "content/browser/browser_thread.h" 24#include "testing/gtest/include/gtest/gtest.h" 25 26namespace { 27 28// Mock ExtensionPrefs class with artificial clock to guarantee that no two 29// extensions get the same installation time stamp and we can reliably 30// assert the installation order in the tests below. 31class MockExtensionPrefs : public ExtensionPrefs { 32 public: 33 MockExtensionPrefs(PrefService* prefs, 34 const FilePath& root_dir, 35 ExtensionPrefValueMap* extension_pref_value_map) 36 : ExtensionPrefs(prefs, root_dir, extension_pref_value_map), 37 currentTime(base::Time::Now()) {} 38 ~MockExtensionPrefs() {} 39 40 protected: 41 mutable base::Time currentTime; 42 43 virtual base::Time GetCurrentTime() const { 44 currentTime += base::TimeDelta::FromSeconds(10); 45 return currentTime; 46 } 47}; 48 49} // namespace 50 51TestExtensionPrefs::TestExtensionPrefs() : pref_service_(NULL) { 52 EXPECT_TRUE(temp_dir_.CreateUniqueTempDir()); 53 preferences_file_ = temp_dir_.path().AppendASCII("Preferences"); 54 extensions_dir_ = temp_dir_.path().AppendASCII("Extensions"); 55 EXPECT_TRUE(file_util::CreateDirectory(extensions_dir_)); 56 57 RecreateExtensionPrefs(); 58} 59 60TestExtensionPrefs::~TestExtensionPrefs() {} 61 62void TestExtensionPrefs::RecreateExtensionPrefs() { 63 // We persist and reload the PrefService's PrefStores because this process 64 // deletes all empty dictionaries. The ExtensionPrefs implementation 65 // needs to be able to handle this situation. 66 if (pref_service_.get()) { 67 // The PrefService writes its persistent file on the file thread, so we 68 // need to wait for any pending I/O to complete before creating a new 69 // PrefService. 70 base::WaitableEvent io_finished(false, false); 71 pref_service_->SavePersistentPrefs(); 72 EXPECT_TRUE(BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, 73 new SignalingTask(&io_finished))); 74 75 // If the FILE thread is in fact the current thread (possible in testing 76 // scenarios), we have to ensure the task has a chance to run. If the FILE 77 // thread is a different thread, the test must ensure that thread is running 78 // (otherwise the Wait below will hang). 79 MessageLoop::current()->RunAllPending(); 80 81 EXPECT_TRUE(io_finished.Wait()); 82 } 83 84 extension_pref_value_map_.reset(new ExtensionPrefValueMap); 85 PrefServiceMockBuilder builder; 86 builder.WithUserFilePrefs(preferences_file_); 87 builder.WithExtensionPrefs( 88 new ExtensionPrefStore(extension_pref_value_map_.get(), false)); 89 pref_service_.reset(builder.Create()); 90 ExtensionPrefs::RegisterUserPrefs(pref_service_.get()); 91 92 prefs_.reset(new MockExtensionPrefs(pref_service_.get(), 93 temp_dir_.path(), 94 extension_pref_value_map_.get())); 95} 96 97scoped_refptr<Extension> TestExtensionPrefs::AddExtension(std::string name) { 98 DictionaryValue dictionary; 99 dictionary.SetString(extension_manifest_keys::kName, name); 100 dictionary.SetString(extension_manifest_keys::kVersion, "0.1"); 101 return AddExtensionWithManifest(dictionary, Extension::INTERNAL); 102} 103 104scoped_refptr<Extension> TestExtensionPrefs::AddExtensionWithManifest( 105 const DictionaryValue& manifest, Extension::Location location) { 106 std::string name; 107 EXPECT_TRUE(manifest.GetString(extension_manifest_keys::kName, &name)); 108 FilePath path = extensions_dir_.AppendASCII(name); 109 std::string errors; 110 scoped_refptr<Extension> extension = Extension::Create( 111 path, location, manifest, Extension::STRICT_ERROR_CHECKS, &errors); 112 EXPECT_TRUE(extension); 113 if (!extension) 114 return NULL; 115 116 EXPECT_TRUE(Extension::IdIsValid(extension->id())); 117 const bool kInitialIncognitoEnabled = false; 118 prefs_->OnExtensionInstalled(extension, Extension::ENABLED, 119 kInitialIncognitoEnabled); 120 return extension; 121} 122 123std::string TestExtensionPrefs::AddExtensionAndReturnId(std::string name) { 124 scoped_refptr<Extension> extension(AddExtension(name)); 125 return extension->id(); 126} 127 128PrefService* TestExtensionPrefs::CreateIncognitoPrefService() const { 129 return pref_service_->CreateIncognitoPrefService( 130 new ExtensionPrefStore(extension_pref_value_map_.get(), true)); 131} 132