summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbattre@chromium.org <battre@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-01-25 14:25:33 +0000
committerbattre@chromium.org <battre@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-01-25 14:25:33 +0000
commit9a8c4020cf135d7a9073cf22a69427f1259c5ed5 (patch)
treea4125b4f356d75cdea03dab1a07f3ae14e579e89
parent31a3130fedb27670365b40bc8cb6dc875957531f (diff)
downloadchromium_src-9a8c4020cf135d7a9073cf22a69427f1259c5ed5.zip
chromium_src-9a8c4020cf135d7a9073cf22a69427f1259c5ed5.tar.gz
chromium_src-9a8c4020cf135d7a9073cf22a69427f1259c5ed5.tar.bz2
Introduce incognito preference settings.
This CL introduces preference settings for incognito windows. The semantics are the following: - An extension can set regular preferences as before. These affect regular and incognito windows. - An extension can set regular preferences *and* incognito preferences. In this case, the incognito preferences affect only incognito windows. - If extension A sets reg+incognito, extension B sets reg but no incognito, extension B has higher precedence than A --> B's preferences hold for all regular and incognito windows. - Incognito preferences are never persisted to disk. In order to realize this, the ExtensionPrefs class allows setting regular and incognito extension controlled preferences. It allows creating an incognito version of the PrefService with an independent PrefValueStore. This (incognito) PrefValueStore and the original PrefValueStore share several of their PrefStores (i.e. DefaultPrefStore, CommandLinePrefStore, Configuration PrefStores) but differ in two pref stores: - We maintain two separate ExtensionPrefStores containing the effective preferences for regular and incognito windows. - We maintain two separate user pref stores. The regular JsonPrefStore is expanded by an OverlayPersistentPrefStore that maintains all write-operations in an in-memory overlay. Therefore, incognito changes are not visible in the file-backed JsonPrefStore. The two ExtensionPrefStores retrieve their effective values from a shared ExtensionPrefValueMap. The OffTheRecordProfileImpl provides a request_context_ that uses the new PrefService already. BUG=66027,69057 TEST=unit tests, will be fully testable once the Proxy Settings API allows incognito settings. Review URL: http://codereview.chromium.org/5915004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@72489 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/extensions/extension_pref_store.cc40
-rw-r--r--chrome/browser/extensions/extension_pref_store.h38
-rw-r--r--chrome/browser/extensions/extension_pref_value_map.cc181
-rw-r--r--chrome/browser/extensions/extension_pref_value_map.h144
-rw-r--r--chrome/browser/extensions/extension_pref_value_map_unittest.cc326
-rw-r--r--chrome/browser/extensions/extension_prefs.cc176
-rw-r--r--chrome/browser/extensions/extension_prefs.h38
-rw-r--r--chrome/browser/extensions/extension_prefs_unittest.cc279
-rw-r--r--chrome/browser/extensions/extension_proxy_api.cc5
-rw-r--r--chrome/browser/extensions/extension_service.cc4
-rw-r--r--chrome/browser/extensions/extension_updater_unittest.cc20
-rw-r--r--chrome/browser/extensions/test_extension_prefs.cc25
-rw-r--r--chrome/browser/extensions/test_extension_prefs.h4
-rw-r--r--chrome/browser/host_zoom_map_unittest.cc6
-rw-r--r--chrome/browser/net/chrome_url_request_context.cc9
-rw-r--r--chrome/browser/policy/configuration_policy_pref_store_unittest.cc199
-rw-r--r--chrome/browser/prefs/command_line_pref_store_unittest.cc61
-rw-r--r--chrome/browser/prefs/default_pref_store.cc20
-rw-r--r--chrome/browser/prefs/default_pref_store.h18
-rw-r--r--chrome/browser/prefs/overlay_persistent_pref_store.cc77
-rw-r--r--chrome/browser/prefs/overlay_persistent_pref_store.h54
-rw-r--r--chrome/browser/prefs/overlay_persistent_pref_store_unittest.cc119
-rw-r--r--chrome/browser/prefs/pref_change_registrar.cc4
-rw-r--r--chrome/browser/prefs/pref_member.cc9
-rw-r--r--chrome/browser/prefs/pref_member.h9
-rw-r--r--chrome/browser/prefs/pref_service.cc90
-rw-r--r--chrome/browser/prefs/pref_service.h35
-rw-r--r--chrome/browser/prefs/pref_service_mock_builder.cc52
-rw-r--r--chrome/browser/prefs/pref_service_mock_builder.h14
-rw-r--r--chrome/browser/prefs/pref_service_unittest.cc45
-rw-r--r--chrome/browser/prefs/pref_value_map.cc18
-rw-r--r--chrome/browser/prefs/pref_value_map.h10
-rw-r--r--chrome/browser/prefs/pref_value_store.cc100
-rw-r--r--chrome/browser/prefs/pref_value_store.h46
-rw-r--r--chrome/browser/prefs/pref_value_store_unittest.cc162
-rw-r--r--chrome/browser/profiles/profile.cc24
-rw-r--r--chrome/browser/profiles/profile.h5
-rw-r--r--chrome/browser/profiles/profile_impl.cc16
-rw-r--r--chrome/browser/profiles/profile_impl.h5
-rw-r--r--chrome/browser/sync/glue/preference_model_associator_unittest.cc45
-rw-r--r--chrome/browser/translate/translate_manager.cc4
-rw-r--r--chrome/browser/ui/browser.cc6
-rw-r--r--chrome/browser/ui/cocoa/browser_window_controller_unittest.mm12
-rw-r--r--chrome/browser/ui/cocoa/extensions/extension_action_context_menu.h9
-rw-r--r--chrome/browser/ui/cocoa/extensions/extension_action_context_menu.mm37
-rw-r--r--chrome/browser/ui/cocoa/extensions/extension_popup_controller_unittest.mm9
-rw-r--r--chrome/browser/ui/cocoa/window_size_autosaver_unittest.mm10
-rw-r--r--chrome/browser/ui/views/frame/browser_view.cc3
-rw-r--r--chrome/chrome_browser.gypi5
-rw-r--r--chrome/chrome_tests.gypi2
-rw-r--r--chrome/common/json_pref_store_unittest.cc52
-rw-r--r--chrome/common/persistent_pref_store.h4
-rw-r--r--chrome/common/pref_store.h11
-rw-r--r--chrome/test/testing_pref_service.cc65
-rw-r--r--chrome/test/testing_pref_service.h31
-rw-r--r--chrome/test/testing_profile.cc29
-rw-r--r--chrome/test/testing_profile.h19
-rw-r--r--net/base/network_config_watcher_mac.cc2
-rw-r--r--net/proxy/proxy_config_service_linux.cc6
59 files changed, 1909 insertions, 939 deletions
diff --git a/chrome/browser/extensions/extension_pref_store.cc b/chrome/browser/extensions/extension_pref_store.cc
index b3aba44..74504c1 100644
--- a/chrome/browser/extensions/extension_pref_store.cc
+++ b/chrome/browser/extensions/extension_pref_store.cc
@@ -1,28 +1,42 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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/extension_pref_store.h"
-ExtensionPrefStore::ExtensionPrefStore()
- : initialization_complete_(false) {
-}
+#include "base/values.h"
+#include "chrome/browser/extensions/extension_pref_value_map.h"
-void ExtensionPrefStore::SetExtensionPref(const std::string& key,
- Value* value) {
- SetValue(key, value);
+ExtensionPrefStore::ExtensionPrefStore(
+ ExtensionPrefValueMap* extension_pref_value_map,
+ bool incognito_pref_store)
+ : extension_pref_value_map_(extension_pref_value_map),
+ incognito_pref_store_(incognito_pref_store) {
+ extension_pref_value_map_->AddObserver(this);
}
-void ExtensionPrefStore::RemoveExtensionPref(const std::string& key) {
- RemoveValue(key);
+ExtensionPrefStore::~ExtensionPrefStore() {
+ if (extension_pref_value_map_)
+ extension_pref_value_map_->RemoveObserver(this);
}
void ExtensionPrefStore::OnInitializationCompleted() {
- DCHECK(!initialization_complete_);
- initialization_complete_ = true;
NotifyInitializationCompleted();
}
-bool ExtensionPrefStore::IsInitializationComplete() const {
- return initialization_complete_;
+void ExtensionPrefStore::OnPrefValueChanged(const std::string& key) {
+ CHECK(extension_pref_value_map_);
+ const Value *winner =
+ extension_pref_value_map_->GetEffectivePrefValue(key,
+ incognito_pref_store_);
+ if (winner)
+ SetValue(key, winner->DeepCopy());
+ else
+ RemoveValue(key);
+}
+
+void ExtensionPrefStore::OnExtensionPrefValueMapDestruction() {
+ CHECK(extension_pref_value_map_);
+ extension_pref_value_map_->RemoveObserver(this);
+ extension_pref_value_map_ = NULL;
}
diff --git a/chrome/browser/extensions/extension_pref_store.h b/chrome/browser/extensions/extension_pref_store.h
index f2db809..80b82e3 100644
--- a/chrome/browser/extensions/extension_pref_store.h
+++ b/chrome/browser/extensions/extension_pref_store.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -6,31 +6,33 @@
#define CHROME_BROWSER_EXTENSIONS_EXTENSION_PREF_STORE_H_
#pragma once
+#include <string>
+
+#include "base/time.h"
+#include "chrome/browser/extensions/extension_pref_value_map.h"
#include "chrome/browser/prefs/value_map_pref_store.h"
-// A PrefStore implementation that holds preferences set by extensions.
-class ExtensionPrefStore : public ValueMapPrefStore {
+// A (non-persistent) PrefStore implementation that holds effective preferences
+// set by extensions. These preferences are managed by and fetched from an
+// ExtensionPrefValueMap.
+class ExtensionPrefStore : public ValueMapPrefStore,
+ public ExtensionPrefValueMap::Observer {
public:
- ExtensionPrefStore();
- virtual ~ExtensionPrefStore() {}
-
- // Set an extension preference |value| for |key|. Takes ownership of |value|.
- void SetExtensionPref(const std::string& key, Value* value);
-
- // Remove the extension preference value for |key|.
- void RemoveExtensionPref(const std::string& key);
-
- // Tell the store it's now fully initialized.
- void OnInitializationCompleted();
+ // Constructs an ExtensionPrefStore for a regular or an incognito profile.
+ explicit ExtensionPrefStore(ExtensionPrefValueMap* extension_pref_value_map,
+ bool incognito_pref_store);
+ virtual ~ExtensionPrefStore();
private:
- // PrefStore overrides:
- virtual bool IsInitializationComplete() const;
+ // Overrides for ExtensionPrefValueMap::Observer:
+ virtual void OnInitializationCompleted();
+ virtual void OnPrefValueChanged(const std::string& key);
+ virtual void OnExtensionPrefValueMapDestruction();
- bool initialization_complete_;
+ ExtensionPrefValueMap* extension_pref_value_map_; // Weak pointer.
+ bool incognito_pref_store_;
DISALLOW_COPY_AND_ASSIGN(ExtensionPrefStore);
};
-
#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_PREF_STORE_H_
diff --git a/chrome/browser/extensions/extension_pref_value_map.cc b/chrome/browser/extensions/extension_pref_value_map.cc
new file mode 100644
index 0000000..3ae4ca9
--- /dev/null
+++ b/chrome/browser/extensions/extension_pref_value_map.cc
@@ -0,0 +1,181 @@
+// Copyright (c) 2011 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/extension_pref_value_map.h"
+
+#include "base/stl_util-inl.h"
+#include "base/values.h"
+#include "chrome/browser/prefs/pref_value_map.h"
+
+ExtensionPrefValueMap::ExtensionPrefValueMap() {
+}
+
+ExtensionPrefValueMap::~ExtensionPrefValueMap() {
+ NotifyOfDestruction();
+ STLDeleteValues(&entries_);
+ entries_.clear();
+}
+
+void ExtensionPrefValueMap::SetExtensionPref(const std::string& ext_id,
+ const std::string& key,
+ bool incognito,
+ Value* value) {
+ PrefValueMap* prefs = GetExtensionPrefValueMap(ext_id, incognito);
+
+ if (prefs->SetValue(key, value))
+ NotifyPrefValueChanged(key);
+}
+
+void ExtensionPrefValueMap::RemoveExtensionPref(const std::string& ext_id,
+ const std::string& key,
+ bool incognito) {
+ PrefValueMap* prefs = GetExtensionPrefValueMap(ext_id, incognito);
+ if (prefs->RemoveValue(key))
+ NotifyPrefValueChanged(key);
+}
+
+void ExtensionPrefValueMap::RegisterExtension(const std::string& ext_id,
+ const base::Time& install_time,
+ bool is_enabled) {
+ if (entries_.find(ext_id) != entries_.end())
+ UnregisterExtension(ext_id);
+ entries_[ext_id] = new ExtensionEntry;
+ entries_[ext_id]->install_time = install_time;
+ entries_[ext_id]->enabled = is_enabled;
+}
+
+void ExtensionPrefValueMap::UnregisterExtension(const std::string& ext_id) {
+ ExtensionEntryMap::iterator i = entries_.find(ext_id);
+ if (i == entries_.end())
+ return;
+ std::set<std::string> keys; // keys set by this extension
+ GetExtensionControlledKeys(*(i->second), &keys);
+
+ delete i->second;
+ entries_.erase(i);
+
+ NotifyPrefValueChanged(keys);
+}
+
+void ExtensionPrefValueMap::SetExtensionState(const std::string& ext_id,
+ bool is_enabled) {
+ ExtensionEntryMap::const_iterator i = entries_.find(ext_id);
+ CHECK(i != entries_.end());
+ if (i->second->enabled == is_enabled)
+ return;
+ std::set<std::string> keys; // keys set by this extension
+ GetExtensionControlledKeys(*(i->second), &keys);
+ i->second->enabled = is_enabled;
+ NotifyPrefValueChanged(keys);
+}
+
+PrefValueMap* ExtensionPrefValueMap::GetExtensionPrefValueMap(
+ const std::string& ext_id,
+ bool incognito) {
+ ExtensionEntryMap::const_iterator i = entries_.find(ext_id);
+ CHECK(i != entries_.end());
+ return incognito ? &(i->second->inc_preferences)
+ : &(i->second->reg_preferences);
+}
+
+const PrefValueMap* ExtensionPrefValueMap::GetExtensionPrefValueMap(
+ const std::string& ext_id,
+ bool incognito) const {
+ ExtensionEntryMap::const_iterator i = entries_.find(ext_id);
+ CHECK(i != entries_.end());
+ return incognito ? &(i->second->inc_preferences)
+ : &(i->second->reg_preferences);
+}
+
+void ExtensionPrefValueMap::GetExtensionControlledKeys(
+ const ExtensionEntry& entry,
+ std::set<std::string>* out) const {
+ PrefValueMap::const_iterator i;
+
+ const PrefValueMap& reg_prefs = entry.reg_preferences;
+ for (i = reg_prefs.begin(); i != reg_prefs.end(); ++i)
+ out->insert(i->first);
+
+ const PrefValueMap& inc_prefs = entry.inc_preferences;
+ for (i = inc_prefs.begin(); i != inc_prefs.end(); ++i)
+ out->insert(i->first);
+}
+
+const Value* ExtensionPrefValueMap::GetEffectivePrefValue(
+ const std::string& key,
+ bool incognito) const {
+ Value *winner = NULL;
+ base::Time winners_install_time;
+
+ ExtensionEntryMap::const_iterator i;
+ for (i = entries_.begin(); i != entries_.end(); ++i) {
+ const std::string& ext_id = i->first;
+ const base::Time& install_time = i->second->install_time;
+ const bool enabled = i->second->enabled;
+
+ if (!enabled)
+ continue;
+ if (install_time < winners_install_time)
+ continue;
+
+ Value* value = NULL;
+ const PrefValueMap* prefs = GetExtensionPrefValueMap(ext_id, false);
+ if (prefs->GetValue(key, &value)) {
+ winner = value;
+ winners_install_time = install_time;
+ }
+
+ if (!incognito)
+ continue;
+
+ prefs = GetExtensionPrefValueMap(ext_id, true);
+ if (prefs->GetValue(key, &value)) {
+ winner = value;
+ winners_install_time = install_time;
+ }
+ }
+ return winner;
+}
+
+void ExtensionPrefValueMap::AddObserver(
+ ExtensionPrefValueMap::Observer* observer) {
+ observers_.AddObserver(observer);
+
+ // Collect all currently used keys and notify the new observer.
+ std::set<std::string> keys;
+ ExtensionEntryMap::const_iterator i;
+ for (i = entries_.begin(); i != entries_.end(); ++i)
+ GetExtensionControlledKeys(*(i->second), &keys);
+
+ std::set<std::string>::const_iterator j;
+ for (j = keys.begin(); j != keys.end(); ++j)
+ observer->OnPrefValueChanged(*j);
+}
+
+void ExtensionPrefValueMap::RemoveObserver(
+ ExtensionPrefValueMap::Observer* observer) {
+ observers_.RemoveObserver(observer);
+}
+
+void ExtensionPrefValueMap::NotifyInitializationCompleted() {
+ FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_,
+ OnInitializationCompleted());
+}
+
+void ExtensionPrefValueMap::NotifyPrefValueChanged(
+ const std::set<std::string>& keys) {
+ std::set<std::string>::const_iterator i;
+ for (i = keys.begin(); i != keys.end(); ++i)
+ NotifyPrefValueChanged(*i);
+}
+
+void ExtensionPrefValueMap::NotifyPrefValueChanged(const std::string& key) {
+ FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_,
+ OnPrefValueChanged(key));
+}
+
+void ExtensionPrefValueMap::NotifyOfDestruction() {
+ FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_,
+ OnExtensionPrefValueMapDestruction());
+}
diff --git a/chrome/browser/extensions/extension_pref_value_map.h b/chrome/browser/extensions/extension_pref_value_map.h
new file mode 100644
index 0000000..63d9285
--- /dev/null
+++ b/chrome/browser/extensions/extension_pref_value_map.h
@@ -0,0 +1,144 @@
+// Copyright (c) 2011 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.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_PREF_VALUE_MAP_H_
+#define CHROME_BROWSER_EXTENSIONS_EXTENSION_PREF_VALUE_MAP_H_
+#pragma once
+
+#include <map>
+#include <set>
+#include <string>
+
+#include "base/time.h"
+#include "chrome/browser/prefs/value_map_pref_store.h"
+
+// Non-persistent data container that is shared by ExtensionPrefStores. All
+// extension pref values (incognito and regular) are stored herein and
+// provided to ExtensionPrefStores.
+//
+// The semantics of the ExtensionPrefValueMap are:
+// - The precedence of extensions is determined by their installation time.
+// The extension that has been installed later takes higher precedence.
+// - If two extensions set a value for the same preference, the following
+// rules determine which value becomes effective (visible).
+// - The effective regular extension pref value is determined by the regular
+// extension pref value of the extension with the highest precedence.
+// - The effective incognito extension pref value is determined by the incognito
+// extension pref value of the extension with the highest precedence, unless
+// another extension with higher precedence overrides it with a regular
+// extension pref value.
+//
+// The following table illustrates the behavior:
+// A.reg | A.inc | B.reg | B.inc | E.reg | E.inc
+// 1 | - | - | - | 1 | 1
+// 1 | 2 | - | - | 1 | 2
+// 1 | - | 3 | - | 3 | 3
+// 1 | - | - | 4 | 1 | 4
+// 1 | 2 | 3 | - | 3 | 3(!)
+// 1 | 2 | - | 4 | 1 | 4
+// 1 | 2 | 3 | 4 | 3 | 4
+// A = extension A, B = extension B, E = effective value
+// .reg = regular value
+// .inc = incognito value
+// Extension B has higher precedence than A.
+class ExtensionPrefValueMap {
+ public:
+ // Observer interface for monitoring ExtensionPrefValueMap.
+ class Observer {
+ public:
+ virtual ~Observer() {}
+
+ // Called when the value for the given |key| set by one of the extensions
+ // changes. This does not necessarily mean that the effective value has
+ // changed.
+ virtual void OnPrefValueChanged(const std::string& key) = 0;
+ // Notification about the ExtensionPrefValueMap being fully initialized.
+ virtual void OnInitializationCompleted() = 0;
+ // Called when the ExtensionPrefValueMap is being destroyed. When called,
+ // observers must unsubscribe.
+ virtual void OnExtensionPrefValueMapDestruction() = 0;
+ };
+
+ ExtensionPrefValueMap();
+ virtual ~ExtensionPrefValueMap();
+
+ // Set an extension preference |value| for |key| of extension |ext_id|.
+ // Takes ownership of |value|.
+ // Note that regular extension pref values need to be reported to
+ // incognito and to regular ExtensionPrefStores.
+ // Precondition: the extension must be registered.
+ void SetExtensionPref(const std::string& ext_id,
+ const std::string& key,
+ bool incognito,
+ Value* value);
+
+ // Remove the extension preference value for |key| of extension |ext_id|.
+ // Precondition: the extension must be registered.
+ void RemoveExtensionPref(const std::string& ext_id,
+ const std::string& key,
+ bool incognito);
+
+ // Tell the store it's now fully initialized.
+ void NotifyInitializationCompleted();
+
+ // Registers the time when an extension |ext_id| is installed.
+ void RegisterExtension(const std::string& ext_id,
+ const base::Time& install_time,
+ bool is_enabled);
+
+ // Deletes all entries related to extension |ext_id|.
+ void UnregisterExtension(const std::string& ext_id);
+
+ // Hides or makes the extension preference values of the specified extension
+ // visible.
+ void SetExtensionState(const std::string& ext_id, bool is_enabled);
+
+ // Adds an observer and notifies it about the currently stored keys.
+ void AddObserver(Observer* observer);
+
+ void RemoveObserver(Observer* observer);
+
+ const Value* GetEffectivePrefValue(const std::string& key,
+ bool incognito) const;
+
+ private:
+ struct ExtensionEntry {
+ // Installation time of the extension.
+ base::Time install_time;
+ // Whether extension is enabled in the profile.
+ bool enabled;
+ // Regular preferences.
+ PrefValueMap reg_preferences;
+ // Incognito preferences, empty for regular ExtensionPrefStore.
+ PrefValueMap inc_preferences;
+ };
+
+ typedef std::map<std::string, ExtensionEntry*> ExtensionEntryMap;
+
+ const PrefValueMap* GetExtensionPrefValueMap(const std::string& ext_id,
+ bool incognito) const;
+
+ PrefValueMap* GetExtensionPrefValueMap(const std::string& ext_id,
+ bool incognito);
+
+ // Returns all keys of pref values that are set by the extension of |entry|,
+ // regardless whether they are set for incognito or regular pref values.
+ void GetExtensionControlledKeys(const ExtensionEntry& entry,
+ std::set<std::string>* out) const;
+
+ void NotifyOfDestruction();
+ void NotifyPrefValueChanged(const std::string& key);
+ void NotifyPrefValueChanged(const std::set<std::string>& keys);
+
+ // Mapping of which extension set which preference value. The effective
+ // preferences values (i.e. the ones with the highest precedence)
+ // are stored in ExtensionPrefStores.
+ ExtensionEntryMap entries_;
+
+ ObserverList<Observer, true> observers_;
+
+ DISALLOW_COPY_AND_ASSIGN(ExtensionPrefValueMap);
+};
+
+#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_PREF_VALUE_MAP_H_
diff --git a/chrome/browser/extensions/extension_pref_value_map_unittest.cc b/chrome/browser/extensions/extension_pref_value_map_unittest.cc
new file mode 100644
index 0000000..642bb03
--- /dev/null
+++ b/chrome/browser/extensions/extension_pref_value_map_unittest.cc
@@ -0,0 +1,326 @@
+// Copyright (c) 2011 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 "base/basictypes.h"
+#include "base/ref_counted.h"
+#include "base/scoped_ptr.h"
+#include "base/values.h"
+#include "chrome/browser/extensions/extension_pref_value_map.h"
+#include "chrome/common/pref_store_observer_mock.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+const char kExt1[] = "ext1";
+const char kExt2[] = "ext2";
+const char kExt3[] = "ext3";
+
+const char kPref1[] = "path1.subpath";
+const char kPref2[] = "path2";
+const char kPref3[] = "path3";
+const char kPref4[] = "path4";
+} // namespace
+
+static Value* CreateVal(const char* str) {
+ return Value::CreateStringValue(str);
+}
+
+static base::Time CreateTime(int64 t) {
+ return base::Time::FromInternalValue(10);
+}
+
+template <typename BASECLASS>
+class ExtensionPrefValueMapTestBase : public BASECLASS {
+ public:
+ // Returns an empty string if the key is not set.
+ std::string GetValue(const char * key, bool incognito) const {
+ const Value *value = epvm_.GetEffectivePrefValue(key, incognito);
+ std::string string_value = "";
+ if (value)
+ value->GetAsString(&string_value);
+ return string_value;
+ }
+
+ protected:
+ ExtensionPrefValueMap epvm_;
+};
+
+class ExtensionPrefValueMapTest
+ : public ExtensionPrefValueMapTestBase<testing::Test> {
+};
+
+// A gmock-ified implementation of PrefStore::Observer.
+class ExtensionPrefValueMapObserverMock
+ : public ExtensionPrefValueMap::Observer {
+ public:
+ ExtensionPrefValueMapObserverMock() {}
+ virtual ~ExtensionPrefValueMapObserverMock() {}
+
+ MOCK_METHOD1(OnPrefValueChanged, void(const std::string&));
+ MOCK_METHOD0(OnInitializationCompleted, void());
+ MOCK_METHOD0(OnExtensionPrefValueMapDestruction, void());
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ExtensionPrefValueMapObserverMock);
+};
+
+TEST_F(ExtensionPrefValueMapTest, SetAndGetPrefValue) {
+ epvm_.RegisterExtension(kExt1, CreateTime(10), true);
+ epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val1"));
+ EXPECT_EQ("val1", GetValue(kPref1, false));
+};
+
+TEST_F(ExtensionPrefValueMapTest, GetNotSetPrefValue) {
+ epvm_.RegisterExtension(kExt1, CreateTime(10), true);
+ EXPECT_EQ("", GetValue(kPref1, false));
+};
+
+// Make sure the last-installed extension wins for each preference.
+TEST_F(ExtensionPrefValueMapTest, Override) {
+ epvm_.RegisterExtension(kExt1, CreateTime(10), true);
+ epvm_.RegisterExtension(kExt2, CreateTime(20), true);
+ epvm_.RegisterExtension(kExt3, CreateTime(30), true);
+
+ epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val1"));
+ epvm_.SetExtensionPref(kExt2, kPref1, false, CreateVal("val2"));
+ epvm_.SetExtensionPref(kExt3, kPref1, false, CreateVal("val3"));
+
+ epvm_.SetExtensionPref(kExt1, kPref2, false, CreateVal("val4"));
+ epvm_.SetExtensionPref(kExt2, kPref2, false, CreateVal("val5"));
+
+ epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val6"));
+ epvm_.SetExtensionPref(kExt1, kPref2, false, CreateVal("val7"));
+ epvm_.SetExtensionPref(kExt1, kPref3, false, CreateVal("val8"));
+
+ EXPECT_EQ("val3", GetValue(kPref1, false));
+ EXPECT_EQ("val5", GetValue(kPref2, false));
+ EXPECT_EQ("val8", GetValue(kPref3, false));
+}
+
+TEST_F(ExtensionPrefValueMapTest, SetAndGetPrefValueIncognito) {
+ epvm_.RegisterExtension(kExt1, CreateTime(10), true);
+ epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val1"));
+ EXPECT_EQ("val1", GetValue(kPref1, true));
+}
+
+TEST_F(ExtensionPrefValueMapTest, UninstallOnlyExtension) {
+ epvm_.RegisterExtension(kExt1, CreateTime(10), true);
+ epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val1"));
+ epvm_.UnregisterExtension(kExt1);
+
+ EXPECT_EQ("", GetValue(kPref1, false));
+}
+
+// Tests uninstalling an extension that wasn't winning for any preferences.
+TEST_F(ExtensionPrefValueMapTest, UninstallIrrelevantExtension) {
+ epvm_.RegisterExtension(kExt1, CreateTime(10), true);
+ epvm_.RegisterExtension(kExt2, CreateTime(10), true);
+
+ epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val1"));
+ epvm_.SetExtensionPref(kExt2, kPref1, false, CreateVal("val2"));
+
+ epvm_.SetExtensionPref(kExt1, kPref2, false, CreateVal("val3"));
+ epvm_.SetExtensionPref(kExt2, kPref2, false, CreateVal("val4"));
+
+ epvm_.UnregisterExtension(kExt1);
+
+ EXPECT_EQ("val2", GetValue(kPref1, false));
+ EXPECT_EQ("val4", GetValue(kPref2, false));
+}
+
+// Tests uninstalling an extension that was winning for all preferences.
+TEST_F(ExtensionPrefValueMapTest, UninstallExtensionFromTop) {
+ epvm_.RegisterExtension(kExt1, CreateTime(10), true);
+ epvm_.RegisterExtension(kExt2, CreateTime(20), true);
+ epvm_.RegisterExtension(kExt3, CreateTime(30), true);
+
+ epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val1"));
+ epvm_.SetExtensionPref(kExt2, kPref1, false, CreateVal("val2"));
+ epvm_.SetExtensionPref(kExt3, kPref1, false, CreateVal("val3"));
+
+ epvm_.SetExtensionPref(kExt1, kPref2, false, CreateVal("val4"));
+ epvm_.SetExtensionPref(kExt3, kPref2, false, CreateVal("val5"));
+
+ epvm_.UnregisterExtension(kExt3);
+
+ EXPECT_EQ("val2", GetValue(kPref1, false));
+ EXPECT_EQ("val4", GetValue(kPref2, false));
+}
+
+// Tests uninstalling an extension that was winning for only some preferences.
+TEST_F(ExtensionPrefValueMapTest, UninstallExtensionFromMiddle) {
+ epvm_.RegisterExtension(kExt1, CreateTime(10), true);
+ epvm_.RegisterExtension(kExt2, CreateTime(20), true);
+ epvm_.RegisterExtension(kExt3, CreateTime(30), true);
+
+ epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val1"));
+ epvm_.SetExtensionPref(kExt2, kPref1, false, CreateVal("val2"));
+ epvm_.SetExtensionPref(kExt3, kPref1, false, CreateVal("val3"));
+
+ epvm_.SetExtensionPref(kExt1, kPref2, false, CreateVal("val4"));
+ epvm_.SetExtensionPref(kExt2, kPref2, false, CreateVal("val5"));
+
+ epvm_.SetExtensionPref(kExt1, kPref3, false, CreateVal("val6"));
+
+ epvm_.SetExtensionPref(kExt2, kPref4, false, CreateVal("val7"));
+
+ epvm_.UnregisterExtension(kExt2);
+
+ EXPECT_EQ("val3", GetValue(kPref1, false));
+ EXPECT_EQ("val4", GetValue(kPref2, false));
+ EXPECT_EQ("val6", GetValue(kPref3, false));
+ EXPECT_EQ("", GetValue(kPref4, false));
+}
+
+// Tests triggering of notifications to registered observers.
+TEST_F(ExtensionPrefValueMapTest, NotifyWhenNeeded) {
+ using testing::_;
+ using testing::Mock;
+ using testing::StrEq;
+
+ epvm_.RegisterExtension(kExt1, CreateTime(10), true);
+
+ ExtensionPrefValueMapObserverMock observer;
+ epvm_.AddObserver(&observer);
+
+ EXPECT_CALL(observer, OnPrefValueChanged(std::string(kPref1)));
+ epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val1"));
+ Mock::VerifyAndClearExpectations(&observer);
+
+ // Write the same value again.
+ EXPECT_CALL(observer, OnPrefValueChanged(std::string(kPref1))).Times(0);
+ epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val1"));
+ Mock::VerifyAndClearExpectations(&observer);
+
+ // Override incognito value.
+ EXPECT_CALL(observer, OnPrefValueChanged(std::string(kPref1)));
+ epvm_.SetExtensionPref(kExt1, kPref1, true, CreateVal("val2"));
+ Mock::VerifyAndClearExpectations(&observer);
+
+ // Override non-incognito value.
+ EXPECT_CALL(observer, OnPrefValueChanged(std::string(kPref1)));
+ epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val3"));
+ Mock::VerifyAndClearExpectations(&observer);
+
+ // Disable.
+ EXPECT_CALL(observer, OnPrefValueChanged(std::string(kPref1)));
+ epvm_.SetExtensionState(kExt1, false);
+ Mock::VerifyAndClearExpectations(&observer);
+
+ // Enable.
+ EXPECT_CALL(observer, OnPrefValueChanged(std::string(kPref1)));
+ epvm_.SetExtensionState(kExt1, true);
+ Mock::VerifyAndClearExpectations(&observer);
+
+ // Uninstall
+ EXPECT_CALL(observer, OnPrefValueChanged(std::string(kPref1)));
+ epvm_.UnregisterExtension(kExt1);
+ Mock::VerifyAndClearExpectations(&observer);
+
+ epvm_.RemoveObserver(&observer);
+
+ // Write new value --> no notification after removing observer.
+ EXPECT_CALL(observer, OnPrefValueChanged(std::string(kPref1))).Times(0);
+ epvm_.RegisterExtension(kExt1, CreateTime(10), true);
+ epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val4"));
+ Mock::VerifyAndClearExpectations(&observer);
+}
+
+// Tests disabling an extension.
+TEST_F(ExtensionPrefValueMapTest, DisableExt) {
+ epvm_.RegisterExtension(kExt1, CreateTime(10), true);
+
+ epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val1"));
+ epvm_.SetExtensionState(kExt1, false);
+ EXPECT_EQ("", GetValue(kPref1, false));
+}
+
+// Tests disabling and reenabling an extension.
+TEST_F(ExtensionPrefValueMapTest, ReenableExt) {
+ epvm_.RegisterExtension(kExt1, CreateTime(10), true);
+
+ epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val1"));
+ epvm_.SetExtensionState(kExt1, false);
+ epvm_.SetExtensionState(kExt1, true);
+ EXPECT_EQ("val1", GetValue(kPref1, false));
+}
+
+struct OverrideIncognitoTestCase {
+ OverrideIncognitoTestCase(int val_ext1_regular,
+ int val_ext1_incognito,
+ int val_ext2_regular,
+ int val_ext2_incognito,
+ int effective_value_regular,
+ int effective_value_incognito)
+ : val_ext1_regular_(val_ext1_regular),
+ val_ext1_incognito_(val_ext1_incognito),
+ val_ext2_regular_(val_ext2_regular),
+ val_ext2_incognito_(val_ext2_incognito),
+ effective_value_regular_(effective_value_regular),
+ effective_value_incognito_(effective_value_incognito) {}
+
+ int val_ext1_regular_; // pref value of extension 1
+ int val_ext1_incognito_; // pref value of extension 1 incognito
+ int val_ext2_regular_; // pref value of extension 2
+ int val_ext2_incognito_; // pref value of extension 2 incognito
+ int effective_value_regular_; // desired winner regular
+ int effective_value_incognito_; // desired winner incognito
+};
+
+class ExtensionPrefValueMapTestIncognitoTests
+ : public ExtensionPrefValueMapTestBase<
+ testing::TestWithParam<OverrideIncognitoTestCase> > {
+};
+
+TEST_P(ExtensionPrefValueMapTestIncognitoTests, OverrideIncognito) {
+ OverrideIncognitoTestCase test = GetParam();
+ const char* strings[] = {
+ "undefined",
+ "val1",
+ "val2",
+ "val3",
+ "val4"
+ };
+
+ epvm_.RegisterExtension(kExt1, CreateTime(10), true);
+ epvm_.RegisterExtension(kExt2, CreateTime(20), true);
+ if (test.val_ext1_regular_) {
+ epvm_.SetExtensionPref(kExt1, kPref1, false,
+ CreateVal(strings[test.val_ext1_regular_]));
+ }
+ if (test.val_ext1_incognito_) {
+ epvm_.SetExtensionPref(kExt1, kPref1, true,
+ CreateVal(strings[test.val_ext1_incognito_]));
+ }
+ if (test.val_ext2_regular_) {
+ epvm_.SetExtensionPref(kExt2, kPref1, false,
+ CreateVal(strings[test.val_ext2_regular_]));
+ }
+ if (test.val_ext2_incognito_) {
+ epvm_.SetExtensionPref(kExt2, kPref1, true,
+ CreateVal(strings[test.val_ext2_incognito_]));
+ }
+ std::string actual;
+ EXPECT_EQ(strings[test.effective_value_regular_], GetValue(kPref1, false));
+ EXPECT_EQ(strings[test.effective_value_incognito_], GetValue(kPref1, true));
+ epvm_.UnregisterExtension(kExt1);
+ epvm_.UnregisterExtension(kExt2);
+}
+
+INSTANTIATE_TEST_CASE_P(
+ ExtensionPrefValueMapTestIncognitoTestsInstance,
+ ExtensionPrefValueMapTestIncognitoTests,
+ testing::Values(
+ // e.g. (1, 0, 0, 4, 1, 4), means:
+ // ext1 regular is set to "val1", ext2 incognito is set to "val4"
+ // --> the winning regular value is "val1", the winning incognito
+ // value is "val4".
+ OverrideIncognitoTestCase(1, 0, 0, 0, 1, 1),
+ OverrideIncognitoTestCase(1, 2, 0, 0, 1, 2),
+ OverrideIncognitoTestCase(1, 0, 3, 0, 3, 3),
+ OverrideIncognitoTestCase(1, 0, 0, 4, 1, 4),
+ // The last 3 in the following line is intentional!
+ OverrideIncognitoTestCase(1, 2, 3, 0, 3, 3),
+ OverrideIncognitoTestCase(1, 2, 0, 4, 1, 4),
+ OverrideIncognitoTestCase(1, 2, 3, 4, 3, 4)));
diff --git a/chrome/browser/extensions/extension_prefs.cc b/chrome/browser/extensions/extension_prefs.cc
index 33ced74..dfe6acb 100644
--- a/chrome/browser/extensions/extension_prefs.cc
+++ b/chrome/browser/extensions/extension_prefs.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -141,12 +141,13 @@ static void ExtentToStringSet(const ExtensionExtent& host_extent,
} // namespace
-ExtensionPrefs::ExtensionPrefs(PrefService* prefs,
- const FilePath& root_dir,
- ExtensionPrefStore* pref_store)
+ExtensionPrefs::ExtensionPrefs(
+ PrefService* prefs,
+ const FilePath& root_dir,
+ ExtensionPrefValueMap* extension_pref_value_map)
: prefs_(prefs),
install_directory_(root_dir),
- pref_store_(pref_store) {
+ extension_pref_value_map_(extension_pref_value_map) {
// TODO(asargent) - Remove this in a couple of months. (See comment above
// CleanupBadExtensionKeys).
CleanupBadExtensionKeys(prefs_);
@@ -696,15 +697,14 @@ void ExtensionPrefs::OnExtensionInstalled(
}
UpdateExtensionPref(id, kPrefAppLaunchIndex,
Value::CreateIntegerValue(GetNextAppLaunchIndex()));
+ extension_pref_value_map_->RegisterExtension(
+ id, install_time, initial_state == Extension::ENABLED);
SavePrefsAndNotify();
}
void ExtensionPrefs::OnExtensionUninstalled(const std::string& extension_id,
const Extension::Location& location,
bool external_uninstall) {
- PrefKeySet pref_keys;
- GetExtensionControlledPrefKeys(extension_id, &pref_keys);
-
// For external extensions, we save a preference reminding ourself not to try
// and install the extension anymore (except when |external_uninstall| is
// true, which signifies that the registry key was deleted or the pref file
@@ -713,11 +713,10 @@ void ExtensionPrefs::OnExtensionUninstalled(const std::string& extension_id,
UpdateExtensionPref(extension_id, kPrefState,
Value::CreateIntegerValue(Extension::KILLBIT));
SavePrefsAndNotify();
+ extension_pref_value_map_->SetExtensionState(extension_id, false);
} else {
DeleteExtensionPrefs(extension_id);
}
-
- UpdatePrefStore(pref_keys);
}
Extension::State ExtensionPrefs::GetExtensionState(
@@ -742,12 +741,10 @@ void ExtensionPrefs::SetExtensionState(const Extension* extension,
Extension::State state) {
UpdateExtensionPref(extension->id(), kPrefState,
Value::CreateIntegerValue(state));
-
- PrefKeySet pref_keys;
- GetExtensionControlledPrefKeys(extension->id(), &pref_keys);
- UpdatePrefStore(pref_keys);
-
SavePrefsAndNotify();
+
+ bool enabled = (state == Extension::ENABLED);
+ extension_pref_value_map_->SetExtensionState(extension->id(), enabled);
}
bool ExtensionPrefs::GetBrowserActionVisibility(const Extension* extension) {
@@ -827,6 +824,7 @@ void ExtensionPrefs::DeleteExtensionPrefs(const std::string& extension_id) {
dict->Remove(extension_id, NULL);
SavePrefsAndNotify();
}
+ extension_pref_value_map_->UnregisterExtension(extension_id);
}
DictionaryValue* ExtensionPrefs::GetOrCreateExtensionPref(
@@ -852,18 +850,6 @@ DictionaryValue* ExtensionPrefs::GetExtensionPref(
return extension;
}
-DictionaryValue* ExtensionPrefs::GetExtensionControlledPrefs(
- const std::string& extension_id) const {
- DictionaryValue* extension = GetExtensionPref(extension_id);
- if (!extension) {
- NOTREACHED();
- return NULL;
- }
- DictionaryValue* preferences = NULL;
- extension->GetDictionary(kPrefPreferences, &preferences);
- return preferences;
-}
-
// Helper function for GetInstalledExtensionsInfo.
static ExtensionInfo* GetInstalledExtensionInfoImpl(
DictionaryValue* extension_data,
@@ -1154,15 +1140,13 @@ base::Time ExtensionPrefs::GetInstallTime(
return base::Time::FromInternalValue(install_time_i64);
}
-void ExtensionPrefs::GetEnabledExtensions(ExtensionIdSet* out) const {
+void ExtensionPrefs::GetExtensions(ExtensionIdSet* out) const {
CHECK(out);
const DictionaryValue* extensions =
pref_service()->GetDictionary(kExtensionsPref);
for (DictionaryValue::key_iterator ext_id = extensions->begin_keys();
ext_id != extensions->end_keys(); ++ext_id) {
- if (GetExtensionState(*ext_id) != Extension::ENABLED)
- continue;
out->push_back(*ext_id);
}
}
@@ -1192,119 +1176,69 @@ void ExtensionPrefs::FixMissingPrefs(const ExtensionIdSet& extension_ids) {
SavePrefsAndNotify();
}
+DictionaryValue* ExtensionPrefs::GetExtensionControlledPrefs(
+ const std::string& extension_id) const {
+ DictionaryValue* source_dict = prefs_->GetMutableDictionary(kExtensionsPref);
+ DictionaryValue* preferences = NULL;
+ std::string key = extension_id + std::string(".") + kPrefPreferences;
+ if (!source_dict->GetDictionary(key, &preferences)) {
+ source_dict->Set(key, new DictionaryValue);
+ bool success = source_dict->GetDictionary(key, &preferences);
+ DCHECK(success);
+ }
+ return preferences;
+}
+
void ExtensionPrefs::InitPrefStore() {
// When this is called, the PrefService is initialized and provides access
// to the user preferences stored in a JSON file.
ExtensionIdSet extension_ids;
- GetEnabledExtensions(&extension_ids);
+ GetExtensions(&extension_ids);
FixMissingPrefs(extension_ids);
- // Collect the unique extension controlled preference keys of all extensions.
- PrefKeySet ext_controlled_prefs;
+ // Store extension controlled preference values in the
+ // |extension_pref_value_map_|, which then informs the subscribers
+ // (ExtensionPrefStores) about the winning values.
for (ExtensionIdSet::iterator ext_id = extension_ids.begin();
ext_id != extension_ids.end(); ++ext_id) {
- GetExtensionControlledPrefKeys(*ext_id, &ext_controlled_prefs);
- }
-
- // Store winning preference for each extension controlled preference.
- UpdatePrefStore(ext_controlled_prefs);
- pref_store_->OnInitializationCompleted();
-}
-
-const Value* ExtensionPrefs::GetWinningExtensionControlledPrefValue(
- const std::string& key) const {
- Value *winner = NULL;
- base::Time winners_install_time = base::Time();
-
- ExtensionIdSet extension_ids;
- GetEnabledExtensions(&extension_ids);
- for (ExtensionIdSet::iterator ext_id = extension_ids.begin();
- ext_id != extension_ids.end(); ++ext_id) {
- base::Time extension_install_time = GetInstallTime(*ext_id);
-
- // We do not need to consider extensions that were installed before the
- // most recent extension found that provides the requested preference.
- if (extension_install_time < winners_install_time)
- continue;
-
- DictionaryValue* preferences = GetExtensionControlledPrefs(*ext_id);
- Value *value = NULL;
- if (preferences && preferences->GetWithoutPathExpansion(key, &value)) {
- // This extension is more recent than the last one providing this pref.
- winner = value;
- winners_install_time = extension_install_time;
+ extension_pref_value_map_->RegisterExtension(
+ *ext_id,
+ GetInstallTime(*ext_id),
+ GetExtensionState(*ext_id) == Extension::ENABLED);
+
+ DictionaryValue* prefs = GetExtensionControlledPrefs(*ext_id);
+ for (DictionaryValue::key_iterator i = prefs->begin_keys();
+ i != prefs->end_keys(); ++i) {
+ Value* value;
+ if (!prefs->GetWithoutPathExpansion(*i, &value))
+ continue;
+ extension_pref_value_map_->SetExtensionPref(
+ *ext_id, *i, false, value->DeepCopy());
}
}
- return winner;
-}
-
-void ExtensionPrefs::UpdatePrefStore(
- const ExtensionPrefs::PrefKeySet& pref_keys) {
- for (PrefKeySet::const_iterator i = pref_keys.begin();
- i != pref_keys.end(); ++i) {
- UpdatePrefStore(*i);
- }
+ extension_pref_value_map_->NotifyInitializationCompleted();
}
-void ExtensionPrefs::UpdatePrefStore(const std::string& pref_key) {
- if (pref_store_ == NULL)
- return;
- const Value* winning_pref_value =
- GetWinningExtensionControlledPrefValue(pref_key);
-
- if (winning_pref_value)
- pref_store_->SetExtensionPref(pref_key, winning_pref_value->DeepCopy());
- else
- pref_store_->RemoveExtensionPref(pref_key);
-}
void ExtensionPrefs::SetExtensionControlledPref(const std::string& extension_id,
const std::string& pref_key,
+ bool incognito,
Value* value) {
- scoped_ptr<Value> scoped_value(value);
DCHECK(pref_service()->FindPreference(pref_key.c_str()))
<< "Extension controlled preference key " << pref_key
<< " not registered.";
- DictionaryValue* extension_preferences =
- GetExtensionControlledPrefs(extension_id);
-
- if (extension_preferences == NULL) { // May be pruned when writing to disk.
- DictionaryValue* extension = GetExtensionPref(extension_id);
- if (extension == NULL) {
- LOG(ERROR) << "Extension preference for " << extension_id << " undefined";
- return;
- }
- extension_preferences = new DictionaryValue;
- extension->Set(kPrefPreferences, extension_preferences);
- }
-
- Value* oldValue = NULL;
- extension_preferences->GetWithoutPathExpansion(pref_key, &oldValue);
- bool modified = !Value::Equals(oldValue, scoped_value.get());
- if (!modified)
- return;
- if (scoped_value.get() == NULL)
- extension_preferences->RemoveWithoutPathExpansion(pref_key, NULL);
- else
- extension_preferences->SetWithoutPathExpansion(pref_key,
- scoped_value.release());
- pref_service()->ScheduleSavePersistentPrefs();
-
- UpdatePrefStore(pref_key);
-}
-
-void ExtensionPrefs::GetExtensionControlledPrefKeys(
- const std::string& extension_id, PrefKeySet *out) const {
- DCHECK(out != NULL);
- DictionaryValue* ext_prefs = GetExtensionControlledPrefs(extension_id);
- if (ext_prefs) {
- for (DictionaryValue::key_iterator i = ext_prefs->begin_keys();
- i != ext_prefs->end_keys(); ++i) {
- out->insert(*i);
- }
+ if (!incognito) {
+ // Also store in persisted Preferences file to recover after a
+ // browser restart.
+ DictionaryValue* dict = GetExtensionControlledPrefs(extension_id);
+ dict->SetWithoutPathExpansion(pref_key, value->DeepCopy());
+ pref_service()->ScheduleSavePersistentPrefs();
}
+
+ extension_pref_value_map_->SetExtensionPref(
+ extension_id, pref_key, incognito, value);
}
// static
diff --git a/chrome/browser/extensions/extension_prefs.h b/chrome/browser/extensions/extension_prefs.h
index 828b98b..8eae7c1 100644
--- a/chrome/browser/extensions/extension_prefs.h
+++ b/chrome/browser/extensions/extension_prefs.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -16,7 +16,7 @@
#include "chrome/common/extensions/extension.h"
#include "googleurl/src/gurl.h"
-class ExtensionPrefStore;
+class ExtensionPrefValueMap;
// Class for managing global and per-extension preferences.
//
@@ -59,9 +59,10 @@ class ExtensionPrefs {
LAUNCH_WINDOW
};
+ // Does not assume ownership of |prefs| and |incognito_prefs|.
explicit ExtensionPrefs(PrefService* prefs,
const FilePath& root_dir,
- ExtensionPrefStore* extension_pref_store);
+ ExtensionPrefValueMap* extension_pref_value_map);
~ExtensionPrefs();
// Returns a copy of the Extensions prefs.
@@ -102,8 +103,8 @@ class ExtensionPrefs {
// Called to change the extension's state when it is enabled/disabled.
void SetExtensionState(const Extension* extension, Extension::State);
- // Returns all installed and enabled extensions
- void GetEnabledExtensions(ExtensionIdSet* out) const;
+ // Returns all installed extensions
+ void GetExtensions(ExtensionIdSet* out) const;
// Getter and setter for browser action visibility.
bool GetBrowserActionVisibility(const Extension* extension);
@@ -266,6 +267,7 @@ class ExtensionPrefs {
// global the extension wants to override.
void SetExtensionControlledPref(const std::string& extension_id,
const std::string& pref_key,
+ bool incognito,
Value* value);
static void RegisterUserPrefs(PrefService* prefs);
@@ -338,7 +340,7 @@ class ExtensionPrefs {
DictionaryValue* GetExtensionPref(const std::string& id) const;
// Returns the dictionary of preferences controlled by the specified extension
- // or NULL if unknown. All entries in the dictionary contain non-expanded
+ // or creates a new one. All entries in the dictionary contain non-expanded
// paths.
DictionaryValue* GetExtensionControlledPrefs(const std::string& id) const;
@@ -372,32 +374,14 @@ class ExtensionPrefs {
// pref store.
void InitPrefStore();
- // Returns the extension controlled preference value of the extension that was
- // installed most recently.
- const Value* GetWinningExtensionControlledPrefValue(
- const std::string& key) const;
-
- // Executes UpdatePrefStore for all |pref_keys|.
- void UpdatePrefStore(const PrefKeySet& pref_keys);
-
- // Finds the most recently installed extension that defines a preference
- // for |pref_key|, then stores its value in the PrefValueStore's extension
- // pref store and sends notifications to observers in case the value changed.
- void UpdatePrefStore(const std::string& pref_key);
-
- // Retrieves a list of preference keys that the specified extension
- // intends to manage. Keys are always appended, |out| is not cleared.
- void GetExtensionControlledPrefKeys(const std::string& extension_id,
- PrefKeySet *out) const;
-
- // The pref service specific to this set of extension prefs.
+ // The pref service specific to this set of extension prefs. Owned by profile.
PrefService* prefs_;
// Base extensions install directory.
FilePath install_directory_;
- // Used to manipulate extension preferences.
- ExtensionPrefStore* pref_store_;
+ // Weak pointer, owned by Profile.
+ ExtensionPrefValueMap* extension_pref_value_map_;
// The URLs of all of the toolstrips.
URLList shelf_order_;
diff --git a/chrome/browser/extensions/extension_prefs_unittest.cc b/chrome/browser/extensions/extension_prefs_unittest.cc
index 18949af..e11a385 100644
--- a/chrome/browser/extensions/extension_prefs_unittest.cc
+++ b/chrome/browser/extensions/extension_prefs_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -21,6 +21,8 @@
using base::Time;
using base::TimeDelta;
+namespace {
+
const char kPref1[] = "path1.subpath";
const char kPref2[] = "path2";
const char kPref3[] = "path3";
@@ -32,6 +34,8 @@ const char kDefaultPref2[] = "default pref 2";
const char kDefaultPref3[] = "default pref 3";
const char kDefaultPref4[] = "default pref 4";
+} // namespace
+
static void AddPattern(ExtensionExtent* extent, const std::string& pattern) {
int schemes = URLPattern::SCHEME_ALL;
extent->AddPattern(URLPattern(schemes, pattern));
@@ -590,21 +594,23 @@ class ExtensionPrefsPreferencesBase : public ExtensionPrefsTest {
void InstallExtControlledPref(Extension *ext,
const std::string& key,
Value* val) {
- // Install extension the first time a preference is set for it.
- Extension* extensions[] = {ext1_, ext2_, ext3_};
- for (int i = 0; i < 3; ++i) {
- if (ext == extensions[i] && !installed[i]) {
- prefs()->OnExtensionInstalled(ext, Extension::ENABLED, true);
- installed[i] = true;
- break;
- }
- }
+ EnsureExtensionInstalled(ext);
+ prefs()->SetExtensionControlledPref(ext->id(), key, false, val);
+ }
+
+ void InstallExtControlledPrefIncognito(Extension *ext,
+ const std::string& key,
+ Value* val) {
+ EnsureExtensionInstalled(ext);
+ prefs()->SetExtensionControlledPref(ext->id(), key, true, val);
+ }
- prefs()->SetExtensionControlledPref(ext->id(), key, val);
+ void InstallExtension(Extension *ext) {
+ EnsureExtensionInstalled(ext);
}
void UninstallExtension(const std::string& extension_id) {
- prefs()->OnExtensionUninstalled(extension_id, Extension::INTERNAL, false);
+ EnsureExtensionUninstalled(extension_id);
}
// Weak references, for convenience.
@@ -616,6 +622,29 @@ class ExtensionPrefsPreferencesBase : public ExtensionPrefsTest {
bool installed[3];
private:
+ void EnsureExtensionInstalled(Extension *ext) {
+ // Install extension the first time a preference is set for it.
+ Extension* extensions[] = {ext1_, ext2_, ext3_};
+ for (int i = 0; i < 3; ++i) {
+ if (ext == extensions[i] && !installed[i]) {
+ prefs()->OnExtensionInstalled(ext, Extension::ENABLED, true);
+ installed[i] = true;
+ break;
+ }
+ }
+ }
+
+ void EnsureExtensionUninstalled(const std::string& extension_id) {
+ Extension* extensions[] = {ext1_, ext2_, ext3_};
+ for (int i = 0; i < 3; ++i) {
+ if (extensions[i]->id() == extension_id) {
+ installed[i] = false;
+ break;
+ }
+ }
+ prefs()->OnExtensionUninstalled(extension_id, Extension::INTERNAL, false);
+ }
+
scoped_refptr<Extension> ext1_scoped_;
scoped_refptr<Extension> ext2_scoped_;
scoped_refptr<Extension> ext3_scoped_;
@@ -633,63 +662,40 @@ class ExtensionPrefsInstallOneExtension
};
TEST_F(ExtensionPrefsInstallOneExtension, ExtensionPrefsInstallOneExtension) {}
-// Make sure the last-installed extension wins for each preference.
-class ExtensionPrefsInstallOverwrittenExtensions
+// Check that we forget incognito values after a reload.
+class ExtensionPrefsInstallIncognito
: public ExtensionPrefsPreferencesBase {
- virtual void Initialize() {
- InstallExtControlledPref(ext1_, kPref1, Value::CreateStringValue("val1"));
- InstallExtControlledPref(ext2_, kPref1, Value::CreateStringValue("val2"));
- InstallExtControlledPref(ext3_, kPref1, Value::CreateStringValue("val3"));
-
- InstallExtControlledPref(ext1_, kPref2, Value::CreateStringValue("val4"));
- InstallExtControlledPref(ext2_, kPref2, Value::CreateStringValue("val5"));
-
- InstallExtControlledPref(ext1_, kPref1, Value::CreateStringValue("val6"));
- InstallExtControlledPref(ext1_, kPref2, Value::CreateStringValue("val7"));
- InstallExtControlledPref(ext1_, kPref3, Value::CreateStringValue("val8"));
- }
- virtual void Verify() {
- std::string actual;
- actual = prefs()->pref_service()->GetString(kPref1);
- EXPECT_EQ("val3", actual);
- actual = prefs()->pref_service()->GetString(kPref2);
- EXPECT_EQ("val5", actual);
- actual = prefs()->pref_service()->GetString(kPref3);
- EXPECT_EQ("val8", actual);
- }
-};
-TEST_F(ExtensionPrefsInstallOverwrittenExtensions,
- ExtensionPrefsInstallOverwrittenExtensions) {}
+ public:
+ ExtensionPrefsInstallIncognito() : iteration_(0) {}
-// Make sure the last-installed extension wins even if other extensions set
-// the same or different preferences later.
-class ExtensionPrefsInstallInterleavedExtensions
- : public ExtensionPrefsPreferencesBase {
virtual void Initialize() {
InstallExtControlledPref(ext1_, kPref1, Value::CreateStringValue("val1"));
- InstallExtControlledPref(ext2_, kPref2, Value::CreateStringValue("val2"));
- InstallExtControlledPref(ext3_, kPref3, Value::CreateStringValue("val3"));
-
- InstallExtControlledPref(ext3_, kPref3, Value::CreateStringValue("val4"));
- InstallExtControlledPref(ext2_, kPref3, Value::CreateStringValue("val5"));
- InstallExtControlledPref(ext1_, kPref3, Value::CreateStringValue("val6"));
-
- InstallExtControlledPref(ext3_, kPref1, Value::CreateStringValue("val7"));
+ InstallExtControlledPrefIncognito(ext1_, kPref1,
+ Value::CreateStringValue("val2"));
+ scoped_ptr<PrefService> incog_prefs(prefs_.CreateIncognitoPrefService());
+ std::string actual = incog_prefs->GetString(kPref1);
+ EXPECT_EQ("val2", actual);
}
virtual void Verify() {
- std::string actual;
- actual = prefs()->pref_service()->GetString(kPref1);
- EXPECT_EQ("val7", actual);
- actual = prefs()->pref_service()->GetString(kPref2);
- EXPECT_EQ("val2", actual);
- actual = prefs()->pref_service()->GetString(kPref3);
- EXPECT_EQ("val4", actual);
+ // Main pref service shall see only non-incognito settings.
+ std::string actual = prefs()->pref_service()->GetString(kPref1);
+ EXPECT_EQ("val1", actual);
+ // Incognito pref service shall see incognito values only during first run.
+ // Once the pref service was reloaded, all values shall be discarded.
+ scoped_ptr<PrefService> incog_prefs(prefs_.CreateIncognitoPrefService());
+ actual = incog_prefs->GetString(kPref1);
+ if (iteration_ == 0) {
+ EXPECT_EQ("val2", actual);
+ } else {
+ EXPECT_EQ("val1", actual);
+ }
+ ++iteration_;
}
+ int iteration_;
};
-TEST_F(ExtensionPrefsInstallInterleavedExtensions,
- ExtensionPrefsInstallInterleavedExtensions) {}
+TEST_F(ExtensionPrefsInstallIncognito, ExtensionPrefsInstallOneExtension) {}
-class ExtensionPrefsUninstallOnlyExtension
+class ExtensionPrefsUninstallExtension
: public ExtensionPrefsPreferencesBase {
virtual void Initialize() {
InstallExtControlledPref(ext1_, kPref1, Value::CreateStringValue("val1"));
@@ -705,89 +711,10 @@ class ExtensionPrefsUninstallOnlyExtension
EXPECT_EQ(kDefaultPref2, actual);
}
};
-TEST_F(ExtensionPrefsUninstallOnlyExtension,
- ExtensionPrefsUninstallOnlyExtension) {}
-
-// Tests uninstalling an extension that wasn't winning for any preferences.
-class ExtensionPrefsUninstallIrrelevantExtension
- : public ExtensionPrefsPreferencesBase {
- virtual void Initialize() {
- InstallExtControlledPref(ext1_, kPref1, Value::CreateStringValue("val1"));
- InstallExtControlledPref(ext2_, kPref1, Value::CreateStringValue("val2"));
+TEST_F(ExtensionPrefsUninstallExtension,
+ ExtensionPrefsUninstallExtension) {}
- InstallExtControlledPref(ext1_, kPref2, Value::CreateStringValue("val3"));
- InstallExtControlledPref(ext2_, kPref2, Value::CreateStringValue("val4"));
-
- UninstallExtension(ext1_->id());
- }
- virtual void Verify() {
- std::string actual;
- actual = prefs()->pref_service()->GetString(kPref1);
- EXPECT_EQ("val2", actual);
- actual = prefs()->pref_service()->GetString(kPref2);
- EXPECT_EQ("val4", actual);
- }
-};
-TEST_F(ExtensionPrefsUninstallIrrelevantExtension,
- ExtensionPrefsUninstallIrrelevantExtension) {}
-
-// Tests uninstalling an extension that was winning for all preferences.
-class ExtensionPrefsUninstallExtensionFromTop
- : public ExtensionPrefsPreferencesBase {
- virtual void Initialize() {
- InstallExtControlledPref(ext1_, kPref1, Value::CreateStringValue("val1"));
- InstallExtControlledPref(ext2_, kPref1, Value::CreateStringValue("val2"));
- InstallExtControlledPref(ext3_, kPref1, Value::CreateStringValue("val3"));
-
- InstallExtControlledPref(ext1_, kPref2, Value::CreateStringValue("val4"));
- InstallExtControlledPref(ext3_, kPref2, Value::CreateStringValue("val5"));
-
- UninstallExtension(ext3_->id());
- }
- virtual void Verify() {
- std::string actual;
- actual = prefs()->pref_service()->GetString(kPref1);
- EXPECT_EQ("val2", actual);
- actual = prefs()->pref_service()->GetString(kPref2);
- EXPECT_EQ("val4", actual);
- }
-};
-TEST_F(ExtensionPrefsUninstallExtensionFromTop,
- ExtensionPrefsUninstallExtensionFromTop) {}
-
-// Tests uninstalling an extension that was winning for only some preferences.
-class ExtensionPrefsUninstallExtensionFromMiddle
- : public ExtensionPrefsPreferencesBase {
- virtual void Initialize() {
- InstallExtControlledPref(ext1_, kPref1, Value::CreateStringValue("val1"));
- InstallExtControlledPref(ext2_, kPref1, Value::CreateStringValue("val2"));
- InstallExtControlledPref(ext3_, kPref1, Value::CreateStringValue("val3"));
-
- InstallExtControlledPref(ext1_, kPref2, Value::CreateStringValue("val4"));
- InstallExtControlledPref(ext2_, kPref2, Value::CreateStringValue("val5"));
-
- InstallExtControlledPref(ext1_, kPref3, Value::CreateStringValue("val6"));
-
- InstallExtControlledPref(ext2_, kPref4, Value::CreateStringValue("val7"));
-
- UninstallExtension(ext2_->id());
- }
- virtual void Verify() {
- std::string actual;
- actual = prefs()->pref_service()->GetString(kPref1);
- EXPECT_EQ("val3", actual);
- actual = prefs()->pref_service()->GetString(kPref2);
- EXPECT_EQ("val4", actual);
- actual = prefs()->pref_service()->GetString(kPref3);
- EXPECT_EQ("val6", actual);
- actual = prefs()->pref_service()->GetString(kPref4);
- EXPECT_EQ(kDefaultPref4, actual);
- }
-};
-TEST_F(ExtensionPrefsUninstallExtensionFromMiddle,
- ExtensionPrefsUninstallExtensionFromMiddle) {}
-
-// Tests triggering of notifications to registered observers
+// Tests triggering of notifications to registered observers.
class ExtensionPrefsNotifyWhenNeeded
: public ExtensionPrefsPreferencesBase {
virtual void Initialize() {
@@ -795,28 +722,58 @@ class ExtensionPrefsNotifyWhenNeeded
using testing::Mock;
using testing::StrEq;
- scoped_ptr<NotificationObserverMock> observer(
- new NotificationObserverMock());
+ NotificationObserverMock observer;
PrefChangeRegistrar registrar;
registrar.Init(prefs()->pref_service());
- registrar.Add(kPref1, observer.get());
+ registrar.Add(kPref1, &observer);
- EXPECT_CALL(*observer, Observe(_, _, _));
+ NotificationObserverMock incognito_observer;
+ scoped_ptr<PrefService> incog_prefs(prefs_.CreateIncognitoPrefService());
+ PrefChangeRegistrar incognito_registrar;
+ incognito_registrar.Init(incog_prefs.get());
+ incognito_registrar.Add(kPref1, &incognito_observer);
+
+ // Write value and check notification.
+ EXPECT_CALL(observer, Observe(_, _, _));
+ EXPECT_CALL(incognito_observer, Observe(_, _, _));
InstallExtControlledPref(ext1_, kPref1,
Value::CreateStringValue("https://www.chromium.org"));
- Mock::VerifyAndClearExpectations(observer.get());
+ Mock::VerifyAndClearExpectations(&observer);
+ Mock::VerifyAndClearExpectations(&incognito_observer);
- EXPECT_CALL(*observer, Observe(_, _, _)).Times(0);
+ // Write same value.
+ EXPECT_CALL(observer, Observe(_, _, _)).Times(0);
+ EXPECT_CALL(incognito_observer, Observe(_, _, _)).Times(0);
InstallExtControlledPref(ext1_, kPref1,
Value::CreateStringValue("https://www.chromium.org"));
- Mock::VerifyAndClearExpectations(observer.get());
+ Mock::VerifyAndClearExpectations(&observer);
+ Mock::VerifyAndClearExpectations(&incognito_observer);
- EXPECT_CALL(*observer, Observe(_, _, _)).Times(2);
+ // Change value.
+ EXPECT_CALL(observer, Observe(_, _, _));
+ EXPECT_CALL(incognito_observer, Observe(_, _, _));
InstallExtControlledPref(ext1_, kPref1,
Value::CreateStringValue("chrome://newtab"));
-
+ Mock::VerifyAndClearExpectations(&observer);
+ Mock::VerifyAndClearExpectations(&incognito_observer);
+
+ // Change only incognito value.
+ EXPECT_CALL(observer, Observe(_, _, _)).Times(0);
+ EXPECT_CALL(incognito_observer, Observe(_, _, _));
+ InstallExtControlledPrefIncognito(ext1_, kPref1,
+ Value::CreateStringValue("chrome://newtab2"));
+ Mock::VerifyAndClearExpectations(&observer);
+ Mock::VerifyAndClearExpectations(&incognito_observer);
+
+ // Uninstall.
+ EXPECT_CALL(observer, Observe(_, _, _));
+ EXPECT_CALL(incognito_observer, Observe(_, _, _));
UninstallExtension(ext1_->id());
- registrar.Remove(kPref1, observer.get());
+ Mock::VerifyAndClearExpectations(&observer);
+ Mock::VerifyAndClearExpectations(&incognito_observer);
+
+ registrar.Remove(kPref1, &observer);
+ incognito_registrar.Remove(kPref1, &incognito_observer);
}
virtual void Verify() {
std::string actual = prefs()->pref_service()->GetString(kPref1);
@@ -826,7 +783,7 @@ class ExtensionPrefsNotifyWhenNeeded
TEST_F(ExtensionPrefsNotifyWhenNeeded,
ExtensionPrefsNotifyWhenNeeded) {}
-// Tests disabling an extension
+// Tests disabling an extension.
class ExtensionPrefsDisableExt
: public ExtensionPrefsPreferencesBase {
virtual void Initialize() {
@@ -842,7 +799,7 @@ class ExtensionPrefsDisableExt
};
TEST_F(ExtensionPrefsDisableExt, ExtensionPrefsDisableExt) {}
-// Tests disabling and reenabling an extension
+// Tests disabling and reenabling an extension.
class ExtensionPrefsReenableExt
: public ExtensionPrefsPreferencesBase {
virtual void Initialize() {
@@ -875,15 +832,27 @@ class ExtensionPrefsSetExtensionControlledPref
virtual void Initialize() {
MockStringValue* v1 = new MockStringValue("https://www.chromium.org");
MockStringValue* v2 = new MockStringValue("https://www.chromium.org");
+ MockStringValue* v1i = new MockStringValue("https://www.chromium.org");
+ MockStringValue* v2i = new MockStringValue("https://www.chromium.org");
// Ownership is taken, value shall not be deleted.
EXPECT_CALL(*v1, Die()).Times(0);
+ EXPECT_CALL(*v1i, Die()).Times(0);
InstallExtControlledPref(ext1_, kPref1, v1);
+ InstallExtControlledPrefIncognito(ext1_, kPref1, v1i);
testing::Mock::VerifyAndClearExpectations(v1);
+ testing::Mock::VerifyAndClearExpectations(v1i);
// Make sure there is no memory leak and both values are deleted.
- EXPECT_CALL(*v2, Die()).Times(1);
EXPECT_CALL(*v1, Die()).Times(1);
+ EXPECT_CALL(*v1i, Die()).Times(1);
+ EXPECT_CALL(*v2, Die()).Times(1);
+ EXPECT_CALL(*v2i, Die()).Times(1);
InstallExtControlledPref(ext1_, kPref1, v2);
+ InstallExtControlledPrefIncognito(ext1_, kPref1, v2i);
prefs_.RecreateExtensionPrefs();
+ testing::Mock::VerifyAndClearExpectations(v1);
+ testing::Mock::VerifyAndClearExpectations(v1i);
+ testing::Mock::VerifyAndClearExpectations(v2);
+ testing::Mock::VerifyAndClearExpectations(v2i);
}
virtual void Verify() {
diff --git a/chrome/browser/extensions/extension_proxy_api.cc b/chrome/browser/extensions/extension_proxy_api.cc
index d71c055..7f3c503 100644
--- a/chrome/browser/extensions/extension_proxy_api.cc
+++ b/chrome/browser/extensions/extension_proxy_api.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -171,5 +171,6 @@ bool UseCustomProxySettingsFunction::ApplyProxyRules(
void UseCustomProxySettingsFunction::ApplyPreference(const char* pref_path,
Value* pref_value) {
profile()->GetExtensionService()->extension_prefs()
- ->SetExtensionControlledPref(extension_id(), pref_path, pref_value);
+ ->SetExtensionControlledPref(extension_id(), pref_path, false,
+ pref_value);
}
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc
index 4651a3d..51b654a 100644
--- a/chrome/browser/extensions/extension_service.cc
+++ b/chrome/browser/extensions/extension_service.cc
@@ -554,8 +554,8 @@ namespace {
} // namespace
void ExtensionService::UpdateExtension(const std::string& id,
- const FilePath& extension_path,
- const GURL& download_url) {
+ const FilePath& extension_path,
+ const GURL& download_url) {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
PendingExtensionMap::const_iterator it = pending_extensions_.find(id);
diff --git a/chrome/browser/extensions/extension_updater_unittest.cc b/chrome/browser/extensions/extension_updater_unittest.cc
index 03610fb..aca27e4 100644
--- a/chrome/browser/extensions/extension_updater_unittest.cc
+++ b/chrome/browser/extensions/extension_updater_unittest.cc
@@ -91,7 +91,9 @@ class MockService : public ExtensionUpdateService {
// Creates test extensions and inserts them into list. The name and
// version are all based on their index. If |update_url| is non-null, it
// will be used as the update_url for each extension.
- void CreateTestExtensions(int count, ExtensionList *list,
+ // The |id| is used to distinguish extension names and make sure that
+ // no two extensions share the same name.
+ void CreateTestExtensions(int id, int count, ExtensionList *list,
const std::string* update_url,
Extension::Location location) {
for (int i = 1; i <= count; i++) {
@@ -99,7 +101,7 @@ class MockService : public ExtensionUpdateService {
manifest.SetString(extension_manifest_keys::kVersion,
base::StringPrintf("%d.0.0.0", i));
manifest.SetString(extension_manifest_keys::kName,
- base::StringPrintf("Extension %d", i));
+ base::StringPrintf("Extension %d.%d", id, i));
if (update_url)
manifest.SetString(extension_manifest_keys::kUpdateURL, *update_url);
scoped_refptr<Extension> e =
@@ -316,7 +318,7 @@ class ExtensionUpdaterTest : public testing::Test {
CreateTestPendingExtensions(1, GURL(update_url), &pending_extensions);
service.set_pending_extensions(pending_extensions);
} else {
- service.CreateTestExtensions(1, &extensions, &update_url,
+ service.CreateTestExtensions(1, 1, &extensions, &update_url,
Extension::INTERNAL);
service.set_extensions(extensions);
}
@@ -468,7 +470,7 @@ class ExtensionUpdaterTest : public testing::Test {
ExtensionList extensions;
std::string url(gallery_url);
- service.CreateTestExtensions(1, &extensions, &url, Extension::INTERNAL);
+ service.CreateTestExtensions(1, 1, &extensions, &url, Extension::INTERNAL);
builder.AddExtension(*extensions[0]);
std::vector<ManifestFetchData*> fetches = builder.GetFetches();
EXPECT_EQ(1u, fetches.size());
@@ -488,7 +490,7 @@ class ExtensionUpdaterTest : public testing::Test {
// Create a set of test extensions
ServiceForManifestTests service;
ExtensionList tmp;
- service.CreateTestExtensions(3, &tmp, NULL, Extension::INTERNAL);
+ service.CreateTestExtensions(1, 3, &tmp, NULL, Extension::INTERNAL);
service.set_extensions(tmp);
MessageLoop message_loop;
@@ -812,9 +814,9 @@ class ExtensionUpdaterTest : public testing::Test {
ExtensionList tmp;
GURL url1("http://clients2.google.com/service/update2/crx");
GURL url2("http://www.somewebsite.com");
- service.CreateTestExtensions(1, &tmp, &url1.possibly_invalid_spec(),
+ service.CreateTestExtensions(1, 1, &tmp, &url1.possibly_invalid_spec(),
Extension::INTERNAL);
- service.CreateTestExtensions(1, &tmp, &url2.possibly_invalid_spec(),
+ service.CreateTestExtensions(2, 1, &tmp, &url2.possibly_invalid_spec(),
Extension::INTERNAL);
EXPECT_EQ(2u, tmp.size());
service.set_extensions(tmp);
@@ -892,7 +894,7 @@ class ExtensionUpdaterTest : public testing::Test {
GURL update_url("http://www.google.com/manifest");
ExtensionList tmp;
- service.CreateTestExtensions(1, &tmp, &update_url.spec(),
+ service.CreateTestExtensions(1, 1, &tmp, &update_url.spec(),
Extension::INTERNAL);
service.set_extensions(tmp);
@@ -987,7 +989,7 @@ TEST(ExtensionUpdaterTest, TestManifestFetchesBuilderAddExtension) {
// Non-internal non-external extensions should be rejected.
{
ExtensionList extensions;
- service.CreateTestExtensions(1, &extensions, NULL, Extension::INVALID);
+ service.CreateTestExtensions(1, 1, &extensions, NULL, Extension::INVALID);
ASSERT_FALSE(extensions.empty());
builder.AddExtension(*extensions[0]);
EXPECT_TRUE(builder.GetFetches().empty());
diff --git a/chrome/browser/extensions/test_extension_prefs.cc b/chrome/browser/extensions/test_extension_prefs.cc
index 5b0ee7b..c88fffb 100644
--- a/chrome/browser/extensions/test_extension_prefs.cc
+++ b/chrome/browser/extensions/test_extension_prefs.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -11,6 +11,7 @@
#include "base/values.h"
#include "chrome/browser/browser_thread.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.h"
#include "chrome/browser/prefs/pref_service_mock_builder.h"
@@ -28,9 +29,9 @@ namespace {
class MockExtensionPrefs : public ExtensionPrefs {
public:
MockExtensionPrefs(PrefService* prefs,
- const FilePath& root_dir_,
- ExtensionPrefStore* pref_store)
- : ExtensionPrefs(prefs, root_dir_, pref_store),
+ const FilePath& root_dir,
+ ExtensionPrefValueMap* extension_pref_value_map)
+ : ExtensionPrefs(prefs, root_dir, extension_pref_value_map),
currentTime(base::Time::Now()) {}
~MockExtensionPrefs() {}
@@ -70,14 +71,17 @@ void TestExtensionPrefs::RecreateExtensionPrefs() {
file_loop.RunAllPending();
}
- ExtensionPrefStore* pref_store = new ExtensionPrefStore;
+ extension_pref_value_map_.reset(new ExtensionPrefValueMap);
PrefServiceMockBuilder builder;
builder.WithUserFilePrefs(preferences_file_);
- builder.WithExtensionPrefs(pref_store);
+ builder.WithExtensionPrefs(
+ new ExtensionPrefStore(extension_pref_value_map_.get(), false));
pref_service_.reset(builder.Create());
ExtensionPrefs::RegisterUserPrefs(pref_service_.get());
- prefs_.reset(new MockExtensionPrefs(pref_service_.get(), temp_dir_.path(),
- pref_store));
+
+ prefs_.reset(new MockExtensionPrefs(pref_service_.get(),
+ temp_dir_.path(),
+ extension_pref_value_map_.get()));
}
scoped_refptr<Extension> TestExtensionPrefs::AddExtension(std::string name) {
@@ -110,3 +114,8 @@ std::string TestExtensionPrefs::AddExtensionAndReturnId(std::string name) {
scoped_refptr<Extension> extension(AddExtension(name));
return extension->id();
}
+
+PrefService* TestExtensionPrefs::CreateIncognitoPrefService() const {
+ return pref_service_->CreateIncognitoPrefService(
+ new ExtensionPrefStore(extension_pref_value_map_.get(), true));
+}
diff --git a/chrome/browser/extensions/test_extension_prefs.h b/chrome/browser/extensions/test_extension_prefs.h
index 3220d7a..1fa2351 100644
--- a/chrome/browser/extensions/test_extension_prefs.h
+++ b/chrome/browser/extensions/test_extension_prefs.h
@@ -14,6 +14,7 @@
class DictionaryValue;
class ExtensionPrefs;
+class ExtensionPrefValueMap;
class PrefService;
// This is a test class intended to make it easier to work with ExtensionPrefs
@@ -44,12 +45,15 @@ class TestExtensionPrefs {
// assigned.
std::string AddExtensionAndReturnId(std::string name);
+ PrefService* CreateIncognitoPrefService() const;
+
protected:
ScopedTempDir temp_dir_;
FilePath preferences_file_;
FilePath extensions_dir_;
scoped_ptr<PrefService> pref_service_;
scoped_ptr<ExtensionPrefs> prefs_;
+ scoped_ptr<ExtensionPrefValueMap> extension_pref_value_map_;
private:
DISALLOW_COPY_AND_ASSIGN(TestExtensionPrefs);
diff --git a/chrome/browser/host_zoom_map_unittest.cc b/chrome/browser/host_zoom_map_unittest.cc
index d99bfbf..1d3b792 100644
--- a/chrome/browser/host_zoom_map_unittest.cc
+++ b/chrome/browser/host_zoom_map_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -100,7 +100,9 @@ TEST_F(HostZoomMapTest, ResetToDefaults) {
SetPrefObserverExpectation();
map->ResetToDefaults();
EXPECT_EQ(0, map->GetZoomLevel(url_));
- EXPECT_EQ(NULL, prefs_->GetDictionary(prefs::kPerHostZoomLevels));
+ DictionaryValue empty;
+ EXPECT_TRUE(
+ Value::Equals(&empty, prefs_->GetDictionary(prefs::kPerHostZoomLevels)));
}
TEST_F(HostZoomMapTest, ReloadOnPrefChange) {
diff --git a/chrome/browser/net/chrome_url_request_context.cc b/chrome/browser/net/chrome_url_request_context.cc
index e742430..e09802f 100644
--- a/chrome/browser/net/chrome_url_request_context.cc
+++ b/chrome/browser/net/chrome_url_request_context.cc
@@ -380,6 +380,7 @@ class FactoryForOffTheRecord : public ChromeURLRequestContextFactory {
public:
explicit FactoryForOffTheRecord(Profile* profile)
: ChromeURLRequestContextFactory(profile),
+ proxy_config_service_(CreateProxyConfigService(profile)),
original_context_getter_(
static_cast<ChromeURLRequestContextGetter*>(
profile->GetOriginalProfile()->GetRequestContext())) {
@@ -388,6 +389,7 @@ class FactoryForOffTheRecord : public ChromeURLRequestContextFactory {
virtual ChromeURLRequestContext* Create();
private:
+ scoped_ptr<net::ProxyConfigService> proxy_config_service_;
scoped_refptr<ChromeURLRequestContextGetter> original_context_getter_;
};
@@ -404,7 +406,12 @@ ChromeURLRequestContext* FactoryForOffTheRecord::Create() {
// and http_auth_handler_factory as the original profile.
context->set_host_resolver(original_context->host_resolver());
context->set_cert_verifier(original_context->cert_verifier());
- context->set_proxy_service(original_context->proxy_service());
+ const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ context->set_proxy_service(
+ CreateProxyService(io_thread()->net_log(),
+ io_thread_globals->proxy_script_fetcher_context.get(),
+ proxy_config_service_.release(),
+ command_line));
context->set_http_auth_handler_factory(
original_context->http_auth_handler_factory());
diff --git a/chrome/browser/policy/configuration_policy_pref_store_unittest.cc b/chrome/browser/policy/configuration_policy_pref_store_unittest.cc
index e133bc9..0ad9eb6d 100644
--- a/chrome/browser/policy/configuration_policy_pref_store_unittest.cc
+++ b/chrome/browser/policy/configuration_policy_pref_store_unittest.cc
@@ -1,8 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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 "base/file_path.h"
+#include "base/ref_counted.h"
#include "chrome/browser/policy/configuration_policy_pref_store.h"
#include "chrome/browser/policy/mock_configuration_policy_provider.h"
#include "chrome/browser/prefs/proxy_prefs.h"
@@ -37,10 +38,10 @@ class ConfigurationPolicyPrefStoreTestBase : public TESTBASE {
protected:
ConfigurationPolicyPrefStoreTestBase()
: provider_(),
- store_(&provider_) {}
+ store_(new ConfigurationPolicyPrefStore(&provider_)) {}
MockConfigurationPolicyProvider provider_;
- ConfigurationPolicyPrefStore store_;
+ scoped_refptr<ConfigurationPolicyPrefStore> store_;
};
// Test cases for list-valued policy settings.
@@ -51,7 +52,7 @@ class ConfigurationPolicyPrefStoreListTest
TEST_P(ConfigurationPolicyPrefStoreListTest, GetDefault) {
EXPECT_EQ(PrefStore::READ_NO_VALUE,
- store_.GetValue(GetParam().pref_name(), NULL));
+ store_->GetValue(GetParam().pref_name(), NULL));
}
TEST_P(ConfigurationPolicyPrefStoreListTest, SetValue) {
@@ -59,10 +60,10 @@ TEST_P(ConfigurationPolicyPrefStoreListTest, SetValue) {
in_value->Append(Value::CreateStringValue("test1"));
in_value->Append(Value::CreateStringValue("test2,"));
provider_.AddPolicy(GetParam().type(), in_value);
- store_.OnUpdatePolicy();
+ store_->OnUpdatePolicy();
Value* value;
EXPECT_EQ(PrefStore::READ_OK,
- store_.GetValue(GetParam().pref_name(), &value));
+ store_->GetValue(GetParam().pref_name(), &value));
EXPECT_TRUE(in_value->Equals(value));
}
@@ -87,16 +88,16 @@ class ConfigurationPolicyPrefStoreStringTest
TEST_P(ConfigurationPolicyPrefStoreStringTest, GetDefault) {
EXPECT_EQ(PrefStore::READ_NO_VALUE,
- store_.GetValue(GetParam().pref_name(), NULL));
+ store_->GetValue(GetParam().pref_name(), NULL));
}
TEST_P(ConfigurationPolicyPrefStoreStringTest, SetValue) {
provider_.AddPolicy(GetParam().type(),
Value::CreateStringValue("http://chromium.org"));
- store_.OnUpdatePolicy();
+ store_->OnUpdatePolicy();
Value* value;
EXPECT_EQ(PrefStore::READ_OK,
- store_.GetValue(GetParam().pref_name(), &value));
+ store_->GetValue(GetParam().pref_name(), &value));
EXPECT_TRUE(StringValue("http://chromium.org").Equals(value));
}
@@ -127,23 +128,23 @@ class ConfigurationPolicyPrefStoreBooleanTest
TEST_P(ConfigurationPolicyPrefStoreBooleanTest, GetDefault) {
EXPECT_EQ(PrefStore::READ_NO_VALUE,
- store_.GetValue(GetParam().pref_name(), NULL));
+ store_->GetValue(GetParam().pref_name(), NULL));
}
TEST_P(ConfigurationPolicyPrefStoreBooleanTest, SetValue) {
provider_.AddPolicy(GetParam().type(), Value::CreateBooleanValue(false));
- store_.OnUpdatePolicy();
+ store_->OnUpdatePolicy();
Value* value;
bool result = true;
EXPECT_EQ(PrefStore::READ_OK,
- store_.GetValue(GetParam().pref_name(), &value));
+ store_->GetValue(GetParam().pref_name(), &value));
EXPECT_TRUE(FundamentalValue(false).Equals(value));
provider_.AddPolicy(GetParam().type(), Value::CreateBooleanValue(true));
- store_.OnUpdatePolicy();
+ store_->OnUpdatePolicy();
result = false;
EXPECT_EQ(PrefStore::READ_OK,
- store_.GetValue(GetParam().pref_name(), &value));
+ store_->GetValue(GetParam().pref_name(), &value));
EXPECT_TRUE(FundamentalValue(true).Equals(value));
}
@@ -203,15 +204,15 @@ class ConfigurationPolicyPrefStoreIntegerTest
TEST_P(ConfigurationPolicyPrefStoreIntegerTest, GetDefault) {
EXPECT_EQ(PrefStore::READ_NO_VALUE,
- store_.GetValue(GetParam().pref_name(), NULL));
+ store_->GetValue(GetParam().pref_name(), NULL));
}
TEST_P(ConfigurationPolicyPrefStoreIntegerTest, SetValue) {
provider_.AddPolicy(GetParam().type(), Value::CreateIntegerValue(2));
- store_.OnUpdatePolicy();
+ store_->OnUpdatePolicy();
Value* value = NULL;
EXPECT_EQ(PrefStore::READ_OK,
- store_.GetValue(GetParam().pref_name(), &value));
+ store_->GetValue(GetParam().pref_name(), &value));
EXPECT_TRUE(FundamentalValue(2).Equals(value));
}
@@ -275,9 +276,10 @@ TEST_F(ConfigurationPolicyPrefStoreProxyTest, ManualOptions) {
Value::CreateIntegerValue(
kPolicyManuallyConfiguredProxyServerMode));
- ConfigurationPolicyPrefStore store(&provider);
+ scoped_refptr<ConfigurationPolicyPrefStore> store(
+ new ConfigurationPolicyPrefStore(&provider));
VerifyProxyPrefs(
- store, "chromium.org", "", "http://chromium.org/override",
+ *store, "chromium.org", "", "http://chromium.org/override",
ProxyPrefs::MODE_FIXED_SERVERS);
}
@@ -290,10 +292,10 @@ TEST_F(ConfigurationPolicyPrefStoreProxyTest, ManualOptionsReversedApplyOrder) {
Value::CreateStringValue("http://chromium.org/override"));
provider.AddPolicy(kPolicyProxyServer,
Value::CreateStringValue("chromium.org"));
-
- ConfigurationPolicyPrefStore store(&provider);
+ scoped_refptr<ConfigurationPolicyPrefStore> store(
+ new ConfigurationPolicyPrefStore(&provider));
VerifyProxyPrefs(
- store, "chromium.org", "", "http://chromium.org/override",
+ *store, "chromium.org", "", "http://chromium.org/override",
ProxyPrefs::MODE_FIXED_SERVERS);
}
@@ -302,8 +304,9 @@ TEST_F(ConfigurationPolicyPrefStoreProxyTest, NoProxyServerMode) {
provider.AddPolicy(kPolicyProxyServerMode,
Value::CreateIntegerValue(kPolicyNoProxyServerMode));
- ConfigurationPolicyPrefStore store(&provider);
- VerifyProxyPrefs(store, "", "", "", ProxyPrefs::MODE_DIRECT);
+ scoped_refptr<ConfigurationPolicyPrefStore> store(
+ new ConfigurationPolicyPrefStore(&provider));
+ VerifyProxyPrefs(*store, "", "", "", ProxyPrefs::MODE_DIRECT);
}
TEST_F(ConfigurationPolicyPrefStoreProxyTest, NoProxyModeName) {
@@ -312,8 +315,9 @@ TEST_F(ConfigurationPolicyPrefStoreProxyTest, NoProxyModeName) {
kPolicyProxyMode,
Value::CreateStringValue(ProxyPrefs::kDirectProxyModeName));
- ConfigurationPolicyPrefStore store(&provider);
- VerifyProxyPrefs(store, "", "", "", ProxyPrefs::MODE_DIRECT);
+ scoped_refptr<ConfigurationPolicyPrefStore> store(
+ new ConfigurationPolicyPrefStore(&provider));
+ VerifyProxyPrefs(*store, "", "", "", ProxyPrefs::MODE_DIRECT);
}
TEST_F(ConfigurationPolicyPrefStoreProxyTest, AutoDetectProxyServerMode) {
@@ -322,8 +326,9 @@ TEST_F(ConfigurationPolicyPrefStoreProxyTest, AutoDetectProxyServerMode) {
kPolicyProxyServerMode,
Value::CreateIntegerValue(kPolicyAutoDetectProxyServerMode));
- ConfigurationPolicyPrefStore store(&provider);
- VerifyProxyPrefs(store, "", "", "", ProxyPrefs::MODE_AUTO_DETECT);
+ scoped_refptr<ConfigurationPolicyPrefStore> store(
+ new ConfigurationPolicyPrefStore(&provider));
+ VerifyProxyPrefs(*store, "", "", "", ProxyPrefs::MODE_AUTO_DETECT);
}
TEST_F(ConfigurationPolicyPrefStoreProxyTest, AutoDetectProxyModeName) {
@@ -332,8 +337,9 @@ TEST_F(ConfigurationPolicyPrefStoreProxyTest, AutoDetectProxyModeName) {
kPolicyProxyMode,
Value::CreateStringValue(ProxyPrefs::kAutoDetectProxyModeName));
- ConfigurationPolicyPrefStore store(&provider);
- VerifyProxyPrefs(store, "", "", "", ProxyPrefs::MODE_AUTO_DETECT);
+ scoped_refptr<ConfigurationPolicyPrefStore> store(
+ new ConfigurationPolicyPrefStore(&provider));
+ VerifyProxyPrefs(*store, "", "", "", ProxyPrefs::MODE_AUTO_DETECT);
}
TEST_F(ConfigurationPolicyPrefStoreProxyTest, PacScriptProxyMode) {
@@ -344,9 +350,10 @@ TEST_F(ConfigurationPolicyPrefStoreProxyTest, PacScriptProxyMode) {
kPolicyProxyMode,
Value::CreateStringValue(ProxyPrefs::kPacScriptProxyModeName));
- ConfigurationPolicyPrefStore store(&provider);
- VerifyProxyPrefs(
- store, "", "http://short.org/proxy.pac", "", ProxyPrefs::MODE_PAC_SCRIPT);
+ scoped_refptr<ConfigurationPolicyPrefStore> store(
+ new ConfigurationPolicyPrefStore(&provider));
+ VerifyProxyPrefs(*store, "", "http://short.org/proxy.pac", "",
+ ProxyPrefs::MODE_PAC_SCRIPT);
}
TEST_F(ConfigurationPolicyPrefStoreProxyTest, UseSystemProxyServerMode) {
@@ -355,8 +362,9 @@ TEST_F(ConfigurationPolicyPrefStoreProxyTest, UseSystemProxyServerMode) {
kPolicyProxyServerMode,
Value::CreateIntegerValue(kPolicyUseSystemProxyServerMode));
- ConfigurationPolicyPrefStore store(&provider);
- VerifyProxyPrefs(store, "", "", "", ProxyPrefs::MODE_SYSTEM);
+ scoped_refptr<ConfigurationPolicyPrefStore> store(
+ new ConfigurationPolicyPrefStore(&provider));
+ VerifyProxyPrefs(*store, "", "", "", ProxyPrefs::MODE_SYSTEM);
}
TEST_F(ConfigurationPolicyPrefStoreProxyTest, UseSystemProxyMode) {
@@ -365,8 +373,9 @@ TEST_F(ConfigurationPolicyPrefStoreProxyTest, UseSystemProxyMode) {
kPolicyProxyMode,
Value::CreateStringValue(ProxyPrefs::kSystemProxyModeName));
- ConfigurationPolicyPrefStore store(&provider);
- VerifyProxyPrefs(store, "", "", "", ProxyPrefs::MODE_SYSTEM);
+ scoped_refptr<ConfigurationPolicyPrefStore> store(
+ new ConfigurationPolicyPrefStore(&provider));
+ VerifyProxyPrefs(*store, "", "", "", ProxyPrefs::MODE_SYSTEM);
}
TEST_F(ConfigurationPolicyPrefStoreProxyTest,
@@ -378,8 +387,9 @@ TEST_F(ConfigurationPolicyPrefStoreProxyTest,
kPolicyProxyMode,
Value::CreateStringValue(ProxyPrefs::kAutoDetectProxyModeName));
- ConfigurationPolicyPrefStore store(&provider);
- VerifyProxyPrefs(store, "", "", "", ProxyPrefs::MODE_AUTO_DETECT);
+ scoped_refptr<ConfigurationPolicyPrefStore> store(
+ new ConfigurationPolicyPrefStore(&provider));
+ VerifyProxyPrefs(*store, "", "", "", ProxyPrefs::MODE_AUTO_DETECT);
}
TEST_F(ConfigurationPolicyPrefStoreProxyTest, ProxyInvalid) {
@@ -395,9 +405,10 @@ TEST_F(ConfigurationPolicyPrefStoreProxyTest, ProxyInvalid) {
provider.AddPolicy(kPolicyProxyServer,
Value::CreateStringValue("chromium.org"));
- ConfigurationPolicyPrefStore store(&provider);
+ scoped_refptr<ConfigurationPolicyPrefStore> store(
+ new ConfigurationPolicyPrefStore(&provider));
EXPECT_EQ(PrefStore::READ_NO_VALUE,
- store.GetValue(prefs::kProxyMode, NULL));
+ store->GetValue(prefs::kProxyMode, NULL));
}
}
@@ -414,35 +425,36 @@ TEST_F(ConfigurationPolicyPrefStoreDefaultSearchTest, MinimallyDefined) {
provider.AddPolicy(kPolicyDefaultSearchProviderSearchURL,
Value::CreateStringValue(search_url));
- ConfigurationPolicyPrefStore store(&provider);
+ scoped_refptr<ConfigurationPolicyPrefStore> store(
+ new ConfigurationPolicyPrefStore(&provider));
Value* value = NULL;
EXPECT_EQ(PrefStore::READ_OK,
- store.GetValue(prefs::kDefaultSearchProviderSearchURL, &value));
+ store->GetValue(prefs::kDefaultSearchProviderSearchURL, &value));
EXPECT_TRUE(StringValue(search_url).Equals(value));
EXPECT_EQ(PrefStore::READ_OK,
- store.GetValue(prefs::kDefaultSearchProviderName, &value));
+ store->GetValue(prefs::kDefaultSearchProviderName, &value));
EXPECT_TRUE(StringValue("test.com").Equals(value));
EXPECT_EQ(PrefStore::READ_OK,
- store.GetValue(prefs::kDefaultSearchProviderKeyword, &value));
+ store->GetValue(prefs::kDefaultSearchProviderKeyword, &value));
EXPECT_TRUE(StringValue(std::string()).Equals(value));
EXPECT_EQ(PrefStore::READ_OK,
- store.GetValue(prefs::kDefaultSearchProviderSuggestURL, &value));
+ store->GetValue(prefs::kDefaultSearchProviderSuggestURL, &value));
EXPECT_TRUE(StringValue(std::string()).Equals(value));
EXPECT_EQ(PrefStore::READ_OK,
- store.GetValue(prefs::kDefaultSearchProviderIconURL, &value));
+ store->GetValue(prefs::kDefaultSearchProviderIconURL, &value));
EXPECT_TRUE(StringValue(std::string()).Equals(value));
EXPECT_EQ(PrefStore::READ_OK,
- store.GetValue(prefs::kDefaultSearchProviderEncodings, &value));
+ store->GetValue(prefs::kDefaultSearchProviderEncodings, &value));
EXPECT_TRUE(StringValue(std::string()).Equals(value));
EXPECT_EQ(PrefStore::READ_OK,
- store.GetValue(prefs::kDefaultSearchProviderInstantURL, &value));
+ store->GetValue(prefs::kDefaultSearchProviderInstantURL, &value));
EXPECT_TRUE(StringValue(std::string()).Equals(value));
}
@@ -471,31 +483,32 @@ TEST_F(ConfigurationPolicyPrefStoreDefaultSearchTest, FullyDefined) {
provider.AddPolicy(kPolicyDefaultSearchProviderEncodings,
Value::CreateStringValue(encodings));
- ConfigurationPolicyPrefStore store(&provider);
+ scoped_refptr<ConfigurationPolicyPrefStore> store(
+ new ConfigurationPolicyPrefStore(&provider));
Value* value = NULL;
EXPECT_EQ(PrefStore::READ_OK,
- store.GetValue(prefs::kDefaultSearchProviderSearchURL, &value));
+ store->GetValue(prefs::kDefaultSearchProviderSearchURL, &value));
EXPECT_TRUE(StringValue(search_url).Equals(value));
EXPECT_EQ(PrefStore::READ_OK,
- store.GetValue(prefs::kDefaultSearchProviderName, &value));
+ store->GetValue(prefs::kDefaultSearchProviderName, &value));
EXPECT_TRUE(StringValue(name).Equals(value));
EXPECT_EQ(PrefStore::READ_OK,
- store.GetValue(prefs::kDefaultSearchProviderKeyword, &value));
+ store->GetValue(prefs::kDefaultSearchProviderKeyword, &value));
EXPECT_TRUE(StringValue(keyword).Equals(value));
EXPECT_EQ(PrefStore::READ_OK,
- store.GetValue(prefs::kDefaultSearchProviderSuggestURL, &value));
+ store->GetValue(prefs::kDefaultSearchProviderSuggestURL, &value));
EXPECT_TRUE(StringValue(suggest_url).Equals(value));
EXPECT_EQ(PrefStore::READ_OK,
- store.GetValue(prefs::kDefaultSearchProviderIconURL, &value));
+ store->GetValue(prefs::kDefaultSearchProviderIconURL, &value));
EXPECT_TRUE(StringValue(icon_url).Equals(value));
EXPECT_EQ(PrefStore::READ_OK,
- store.GetValue(prefs::kDefaultSearchProviderEncodings, &value));
+ store->GetValue(prefs::kDefaultSearchProviderEncodings, &value));
EXPECT_TRUE(StringValue(encodings).Equals(value));
}
@@ -521,20 +534,21 @@ TEST_F(ConfigurationPolicyPrefStoreDefaultSearchTest, MissingUrl) {
provider.AddPolicy(kPolicyDefaultSearchProviderEncodings,
Value::CreateStringValue(encodings));
- ConfigurationPolicyPrefStore store(&provider);
+ scoped_refptr<ConfigurationPolicyPrefStore> store(
+ new ConfigurationPolicyPrefStore(&provider));
EXPECT_EQ(PrefStore::READ_NO_VALUE,
- store.GetValue(prefs::kDefaultSearchProviderSearchURL, NULL));
+ store->GetValue(prefs::kDefaultSearchProviderSearchURL, NULL));
EXPECT_EQ(PrefStore::READ_NO_VALUE,
- store.GetValue(prefs::kDefaultSearchProviderName, NULL));
+ store->GetValue(prefs::kDefaultSearchProviderName, NULL));
EXPECT_EQ(PrefStore::READ_NO_VALUE,
- store.GetValue(prefs::kDefaultSearchProviderKeyword, NULL));
+ store->GetValue(prefs::kDefaultSearchProviderKeyword, NULL));
EXPECT_EQ(PrefStore::READ_NO_VALUE,
- store.GetValue(prefs::kDefaultSearchProviderSuggestURL, NULL));
+ store->GetValue(prefs::kDefaultSearchProviderSuggestURL, NULL));
EXPECT_EQ(PrefStore::READ_NO_VALUE,
- store.GetValue(prefs::kDefaultSearchProviderIconURL, NULL));
+ store->GetValue(prefs::kDefaultSearchProviderIconURL, NULL));
EXPECT_EQ(PrefStore::READ_NO_VALUE,
- store.GetValue(prefs::kDefaultSearchProviderEncodings, NULL));
+ store->GetValue(prefs::kDefaultSearchProviderEncodings, NULL));
}
// Checks that if the default search policy is invalid, that no elements of the
@@ -562,20 +576,21 @@ TEST_F(ConfigurationPolicyPrefStoreDefaultSearchTest, Invalid) {
provider.AddPolicy(kPolicyDefaultSearchProviderEncodings,
Value::CreateStringValue(encodings));
- ConfigurationPolicyPrefStore store(&provider);
+ scoped_refptr<ConfigurationPolicyPrefStore> store(
+ new ConfigurationPolicyPrefStore(&provider));
EXPECT_EQ(PrefStore::READ_NO_VALUE,
- store.GetValue(prefs::kDefaultSearchProviderSearchURL, NULL));
+ store->GetValue(prefs::kDefaultSearchProviderSearchURL, NULL));
EXPECT_EQ(PrefStore::READ_NO_VALUE,
- store.GetValue(prefs::kDefaultSearchProviderName, NULL));
+ store->GetValue(prefs::kDefaultSearchProviderName, NULL));
EXPECT_EQ(PrefStore::READ_NO_VALUE,
- store.GetValue(prefs::kDefaultSearchProviderKeyword, NULL));
+ store->GetValue(prefs::kDefaultSearchProviderKeyword, NULL));
EXPECT_EQ(PrefStore::READ_NO_VALUE,
- store.GetValue(prefs::kDefaultSearchProviderSuggestURL, NULL));
+ store->GetValue(prefs::kDefaultSearchProviderSuggestURL, NULL));
EXPECT_EQ(PrefStore::READ_NO_VALUE,
- store.GetValue(prefs::kDefaultSearchProviderIconURL, NULL));
+ store->GetValue(prefs::kDefaultSearchProviderIconURL, NULL));
EXPECT_EQ(PrefStore::READ_NO_VALUE,
- store.GetValue(prefs::kDefaultSearchProviderEncodings, NULL));
+ store->GetValue(prefs::kDefaultSearchProviderEncodings, NULL));
}
// Test cases for the Sync policy setting.
@@ -585,23 +600,23 @@ class ConfigurationPolicyPrefStoreSyncTest
TEST_F(ConfigurationPolicyPrefStoreSyncTest, Default) {
EXPECT_EQ(PrefStore::READ_NO_VALUE,
- store_.GetValue(prefs::kSyncManaged, NULL));
+ store_->GetValue(prefs::kSyncManaged, NULL));
}
TEST_F(ConfigurationPolicyPrefStoreSyncTest, Enabled) {
provider_.AddPolicy(kPolicySyncDisabled, Value::CreateBooleanValue(false));
- store_.OnUpdatePolicy();
+ store_->OnUpdatePolicy();
// Enabling Sync should not set the pref.
EXPECT_EQ(PrefStore::READ_NO_VALUE,
- store_.GetValue(prefs::kSyncManaged, NULL));
+ store_->GetValue(prefs::kSyncManaged, NULL));
}
TEST_F(ConfigurationPolicyPrefStoreSyncTest, Disabled) {
provider_.AddPolicy(kPolicySyncDisabled, Value::CreateBooleanValue(true));
- store_.OnUpdatePolicy();
+ store_->OnUpdatePolicy();
// Sync should be flagged as managed.
Value* value = NULL;
- EXPECT_EQ(PrefStore::READ_OK, store_.GetValue(prefs::kSyncManaged, &value));
+ EXPECT_EQ(PrefStore::READ_OK, store_->GetValue(prefs::kSyncManaged, &value));
ASSERT_TRUE(value != NULL);
EXPECT_TRUE(FundamentalValue(true).Equals(value));
}
@@ -613,24 +628,24 @@ class ConfigurationPolicyPrefStoreAutoFillTest
TEST_F(ConfigurationPolicyPrefStoreAutoFillTest, Default) {
EXPECT_EQ(PrefStore::READ_NO_VALUE,
- store_.GetValue(prefs::kSyncManaged, NULL));
+ store_->GetValue(prefs::kSyncManaged, NULL));
}
TEST_F(ConfigurationPolicyPrefStoreAutoFillTest, Enabled) {
provider_.AddPolicy(kPolicyAutoFillEnabled, Value::CreateBooleanValue(true));
- store_.OnUpdatePolicy();
+ store_->OnUpdatePolicy();
// Enabling AutoFill should not set the pref.
EXPECT_EQ(PrefStore::READ_NO_VALUE,
- store_.GetValue(prefs::kSyncManaged, NULL));
+ store_->GetValue(prefs::kSyncManaged, NULL));
}
TEST_F(ConfigurationPolicyPrefStoreAutoFillTest, Disabled) {
provider_.AddPolicy(kPolicyAutoFillEnabled, Value::CreateBooleanValue(false));
- store_.OnUpdatePolicy();
+ store_->OnUpdatePolicy();
// Disabling AutoFill should switch the pref to managed.
Value* value = NULL;
EXPECT_EQ(PrefStore::READ_OK,
- store_.GetValue(prefs::kAutoFillEnabled, &value));
+ store_->GetValue(prefs::kAutoFillEnabled, &value));
EXPECT_TRUE(FundamentalValue(false).Equals(value));
}
@@ -639,11 +654,11 @@ class ConfigurationPolicyPrefStoreRefreshTest
: public ConfigurationPolicyPrefStoreTestBase<testing::Test> {
protected:
virtual void SetUp() {
- store_.AddObserver(&observer_);
+ store_->AddObserver(&observer_);
}
virtual void TearDown() {
- store_.RemoveObserver(&observer_);
+ store_->RemoveObserver(&observer_);
}
PrefStoreObserverMock observer_;
@@ -652,40 +667,40 @@ class ConfigurationPolicyPrefStoreRefreshTest
TEST_F(ConfigurationPolicyPrefStoreRefreshTest, Refresh) {
Value* value = NULL;
EXPECT_EQ(PrefStore::READ_NO_VALUE,
- store_.GetValue(prefs::kHomePage, NULL));
+ store_->GetValue(prefs::kHomePage, NULL));
EXPECT_CALL(observer_, OnPrefValueChanged(prefs::kHomePage)).Times(1);
provider_.AddPolicy(kPolicyHomePage,
Value::CreateStringValue("http://www.chromium.org"));
- store_.OnUpdatePolicy();
+ store_->OnUpdatePolicy();
Mock::VerifyAndClearExpectations(&observer_);
EXPECT_EQ(PrefStore::READ_OK,
- store_.GetValue(prefs::kHomePage, &value));
+ store_->GetValue(prefs::kHomePage, &value));
EXPECT_TRUE(StringValue("http://www.chromium.org").Equals(value));
EXPECT_CALL(observer_, OnPrefValueChanged(_)).Times(0);
- store_.OnUpdatePolicy();
+ store_->OnUpdatePolicy();
Mock::VerifyAndClearExpectations(&observer_);
EXPECT_CALL(observer_, OnPrefValueChanged(prefs::kHomePage)).Times(1);
provider_.RemovePolicy(kPolicyHomePage);
- store_.OnUpdatePolicy();
+ store_->OnUpdatePolicy();
Mock::VerifyAndClearExpectations(&observer_);
EXPECT_EQ(PrefStore::READ_NO_VALUE,
- store_.GetValue(prefs::kHomePage, NULL));
+ store_->GetValue(prefs::kHomePage, NULL));
}
TEST_F(ConfigurationPolicyPrefStoreRefreshTest, Initialization) {
- EXPECT_FALSE(store_.IsInitializationComplete());
+ EXPECT_FALSE(store_->IsInitializationComplete());
EXPECT_CALL(observer_, OnInitializationCompleted()).Times(1);
provider_.SetInitializationComplete(true);
- EXPECT_FALSE(store_.IsInitializationComplete());
+ EXPECT_FALSE(store_->IsInitializationComplete());
- store_.OnUpdatePolicy();
+ store_->OnUpdatePolicy();
Mock::VerifyAndClearExpectations(&observer_);
- EXPECT_TRUE(store_.IsInitializationComplete());
+ EXPECT_TRUE(store_->IsInitializationComplete());
}
} // namespace policy
diff --git a/chrome/browser/prefs/command_line_pref_store_unittest.cc b/chrome/browser/prefs/command_line_pref_store_unittest.cc
index 790f52b..2518ff9 100644
--- a/chrome/browser/prefs/command_line_pref_store_unittest.cc
+++ b/chrome/browser/prefs/command_line_pref_store_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -6,6 +6,7 @@
#include "app/app_switches.h"
#include "base/command_line.h"
+#include "base/ref_counted.h"
#include "base/string_util.h"
#include "base/values.h"
#include "chrome/browser/prefs/command_line_pref_store.h"
@@ -41,11 +42,11 @@ const char unknown_string[] = "unknown_other_switch";
TEST(CommandLinePrefStoreTest, SimpleStringPref) {
CommandLine cl(CommandLine::NO_PROGRAM);
cl.AppendSwitchASCII(switches::kLang, "hi-MOM");
- CommandLinePrefStore store(&cl);
+ scoped_refptr<CommandLinePrefStore> store = new CommandLinePrefStore(&cl);
Value* actual = NULL;
EXPECT_EQ(PrefStore::READ_OK,
- store.GetValue(prefs::kApplicationLocale, &actual));
+ store->GetValue(prefs::kApplicationLocale, &actual));
std::string result;
EXPECT_TRUE(actual->GetAsString(&result));
EXPECT_EQ("hi-MOM", result);
@@ -55,9 +56,10 @@ TEST(CommandLinePrefStoreTest, SimpleStringPref) {
TEST(CommandLinePrefStoreTest, SimpleBooleanPref) {
CommandLine cl(CommandLine::NO_PROGRAM);
cl.AppendSwitch(switches::kNoProxyServer);
- TestCommandLinePrefStore store(&cl);
+ scoped_refptr<TestCommandLinePrefStore> store =
+ new TestCommandLinePrefStore(&cl);
- store.VerifyIntPref(prefs::kProxyMode, ProxyPrefs::MODE_DIRECT);
+ store->VerifyIntPref(prefs::kProxyMode, ProxyPrefs::MODE_DIRECT);
}
// Tests a command line with no recognized prefs.
@@ -65,11 +67,11 @@ TEST(CommandLinePrefStoreTest, NoPrefs) {
CommandLine cl(CommandLine::NO_PROGRAM);
cl.AppendSwitch(unknown_string);
cl.AppendSwitchASCII(unknown_bool, "a value");
- CommandLinePrefStore store(&cl);
+ scoped_refptr<CommandLinePrefStore> store = new CommandLinePrefStore(&cl);
Value* actual = NULL;
- EXPECT_EQ(PrefStore::READ_NO_VALUE, store.GetValue(unknown_bool, &actual));
- EXPECT_EQ(PrefStore::READ_NO_VALUE, store.GetValue(unknown_string, &actual));
+ EXPECT_EQ(PrefStore::READ_NO_VALUE, store->GetValue(unknown_bool, &actual));
+ EXPECT_EQ(PrefStore::READ_NO_VALUE, store->GetValue(unknown_string, &actual));
}
// Tests a complex command line with multiple known and unknown switches.
@@ -80,19 +82,20 @@ TEST(CommandLinePrefStoreTest, MultipleSwitches) {
cl.AppendSwitchASCII(switches::kProxyServer, "proxy");
cl.AppendSwitchASCII(switches::kProxyBypassList, "list");
cl.AppendSwitchASCII(unknown_bool, "a value");
- TestCommandLinePrefStore store(&cl);
+ scoped_refptr<TestCommandLinePrefStore> store =
+ new TestCommandLinePrefStore(&cl);
Value* actual = NULL;
- EXPECT_EQ(PrefStore::READ_NO_VALUE, store.GetValue(unknown_bool, &actual));
- store.VerifyIntPref(prefs::kProxyMode, ProxyPrefs::MODE_AUTO_DETECT);
+ EXPECT_EQ(PrefStore::READ_NO_VALUE, store->GetValue(unknown_bool, &actual));
+ store->VerifyIntPref(prefs::kProxyMode, ProxyPrefs::MODE_AUTO_DETECT);
- EXPECT_EQ(PrefStore::READ_NO_VALUE, store.GetValue(unknown_string, &actual));
+ EXPECT_EQ(PrefStore::READ_NO_VALUE, store->GetValue(unknown_string, &actual));
std::string string_result = "";
- ASSERT_EQ(PrefStore::READ_OK, store.GetValue(prefs::kProxyServer, &actual));
+ ASSERT_EQ(PrefStore::READ_OK, store->GetValue(prefs::kProxyServer, &actual));
EXPECT_TRUE(actual->GetAsString(&string_result));
EXPECT_EQ("proxy", string_result);
ASSERT_EQ(PrefStore::READ_OK,
- store.GetValue(prefs::kProxyBypassList, &actual));
+ store->GetValue(prefs::kProxyBypassList, &actual));
EXPECT_TRUE(actual->GetAsString(&string_result));
EXPECT_EQ("list", string_result);
}
@@ -102,18 +105,21 @@ TEST(CommandLinePrefStoreTest, ProxySwitchValidation) {
CommandLine cl(CommandLine::NO_PROGRAM);
// No switches.
- TestCommandLinePrefStore store(&cl);
- EXPECT_TRUE(store.ProxySwitchesAreValid());
+ scoped_refptr<TestCommandLinePrefStore> store =
+ new TestCommandLinePrefStore(&cl);
+ EXPECT_TRUE(store->ProxySwitchesAreValid());
// Only no-proxy.
cl.AppendSwitch(switches::kNoProxyServer);
- TestCommandLinePrefStore store2(&cl);
- EXPECT_TRUE(store2.ProxySwitchesAreValid());
+ scoped_refptr<TestCommandLinePrefStore> store2 =
+ new TestCommandLinePrefStore(&cl);
+ EXPECT_TRUE(store2->ProxySwitchesAreValid());
// Another proxy switch too.
cl.AppendSwitch(switches::kProxyAutoDetect);
- TestCommandLinePrefStore store3(&cl);
- EXPECT_FALSE(store3.ProxySwitchesAreValid());
+ scoped_refptr<TestCommandLinePrefStore> store3 =
+ new TestCommandLinePrefStore(&cl);
+ EXPECT_FALSE(store3->ProxySwitchesAreValid());
// All proxy switches except no-proxy.
CommandLine cl2(CommandLine::NO_PROGRAM);
@@ -121,19 +127,22 @@ TEST(CommandLinePrefStoreTest, ProxySwitchValidation) {
cl2.AppendSwitchASCII(switches::kProxyServer, "server");
cl2.AppendSwitchASCII(switches::kProxyPacUrl, "url");
cl2.AppendSwitchASCII(switches::kProxyBypassList, "list");
- TestCommandLinePrefStore store4(&cl2);
- EXPECT_TRUE(store4.ProxySwitchesAreValid());
+ scoped_refptr<TestCommandLinePrefStore> store4 =
+ new TestCommandLinePrefStore(&cl2);
+ EXPECT_TRUE(store4->ProxySwitchesAreValid());
}
TEST(CommandLinePrefStoreTest, ManualProxyModeInference) {
CommandLine cl1(CommandLine::NO_PROGRAM);
cl1.AppendSwitch(unknown_string);
cl1.AppendSwitchASCII(switches::kProxyServer, "proxy");
- TestCommandLinePrefStore store1(&cl1);
- store1.VerifyIntPref(prefs::kProxyMode, ProxyPrefs::MODE_FIXED_SERVERS);
+ scoped_refptr<TestCommandLinePrefStore> store1 =
+ new TestCommandLinePrefStore(&cl1);
+ store1->VerifyIntPref(prefs::kProxyMode, ProxyPrefs::MODE_FIXED_SERVERS);
CommandLine cl2(CommandLine::NO_PROGRAM);
cl2.AppendSwitchASCII(switches::kProxyPacUrl, "proxy");
- TestCommandLinePrefStore store2(&cl2);
- store2.VerifyIntPref(prefs::kProxyMode, ProxyPrefs::MODE_PAC_SCRIPT);
+ scoped_refptr<TestCommandLinePrefStore> store2 =
+ new TestCommandLinePrefStore(&cl2);
+ store2->VerifyIntPref(prefs::kProxyMode, ProxyPrefs::MODE_PAC_SCRIPT);
}
diff --git a/chrome/browser/prefs/default_pref_store.cc b/chrome/browser/prefs/default_pref_store.cc
new file mode 100644
index 0000000..cacc833
--- /dev/null
+++ b/chrome/browser/prefs/default_pref_store.cc
@@ -0,0 +1,20 @@
+// Copyright (c) 2011 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/prefs/default_pref_store.h"
+
+DefaultPrefStore::DefaultPrefStore() {}
+
+DefaultPrefStore::~DefaultPrefStore() {}
+
+void DefaultPrefStore::SetDefaultValue(const std::string& key, Value* value) {
+ CHECK(GetValue(key, NULL) == READ_NO_VALUE);
+ SetValue(key, value);
+}
+
+Value::ValueType DefaultPrefStore::GetType(const std::string& key) const {
+ Value* value;
+ return GetValue(key, &value) == READ_OK ? value->GetType()
+ : Value::TYPE_NULL;
+}
diff --git a/chrome/browser/prefs/default_pref_store.h b/chrome/browser/prefs/default_pref_store.h
index 9e2e715..79a6a0e 100644
--- a/chrome/browser/prefs/default_pref_store.h
+++ b/chrome/browser/prefs/default_pref_store.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -6,22 +6,24 @@
#define CHROME_BROWSER_PREFS_DEFAULT_PREF_STORE_H_
#pragma once
-#include <map>
+#include <string>
-#include "base/basictypes.h"
+#include "base/values.h"
#include "chrome/browser/prefs/value_map_pref_store.h"
// This PrefStore keeps track of default preference values set when a
// preference is registered with the PrefService.
class DefaultPrefStore : public ValueMapPrefStore {
public:
- DefaultPrefStore() {}
- virtual ~DefaultPrefStore() {}
+ DefaultPrefStore();
+ virtual ~DefaultPrefStore();
// Stores a new |value| for |key|. Assumes ownership of |value|.
- void SetDefaultValue(const std::string& key, Value* value) {
- SetValue(key, value);
- }
+ void SetDefaultValue(const std::string& key, Value* value);
+
+ // Returns the registered type for |key| or Value::TYPE_NULL if the |key|
+ // has not been registered.
+ Value::ValueType GetType(const std::string& key) const;
private:
DISALLOW_COPY_AND_ASSIGN(DefaultPrefStore);
diff --git a/chrome/browser/prefs/overlay_persistent_pref_store.cc b/chrome/browser/prefs/overlay_persistent_pref_store.cc
new file mode 100644
index 0000000..16c082a
--- /dev/null
+++ b/chrome/browser/prefs/overlay_persistent_pref_store.cc
@@ -0,0 +1,77 @@
+// Copyright (c) 2011 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/prefs/overlay_persistent_pref_store.h"
+
+OverlayPersistentPrefStore::OverlayPersistentPrefStore(
+ PersistentPrefStore* underlay)
+ : underlay_(underlay) {
+ underlay_->AddObserver(this);
+}
+OverlayPersistentPrefStore::~OverlayPersistentPrefStore() {
+ underlay_->RemoveObserver(this);
+}
+
+void OverlayPersistentPrefStore::AddObserver(PrefStore::Observer* observer) {
+ observers_.AddObserver(observer);
+}
+
+void OverlayPersistentPrefStore::RemoveObserver(PrefStore::Observer* observer) {
+ observers_.RemoveObserver(observer);
+}
+
+bool OverlayPersistentPrefStore::IsInitializationComplete() const {
+ return underlay_->IsInitializationComplete();
+}
+
+PrefStore::ReadResult OverlayPersistentPrefStore::GetValue(
+ const std::string& key, Value** result) const {
+ if (overlay_.GetValue(key, result))
+ return READ_OK;
+ return underlay_->GetValue(key, result);
+}
+
+void OverlayPersistentPrefStore::SetValue(const std::string& key,
+ Value* value) {
+ if (overlay_.SetValue(key, value))
+ FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key));
+}
+
+void OverlayPersistentPrefStore::SetValueSilently(const std::string& key,
+ Value* value) {
+ overlay_.SetValue(key, value);
+}
+
+void OverlayPersistentPrefStore::RemoveValue(const std::string& key) {
+ if (overlay_.RemoveValue(key))
+ FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key));
+}
+
+bool OverlayPersistentPrefStore::ReadOnly() const {
+ return false;
+}
+
+PersistentPrefStore::PrefReadError OverlayPersistentPrefStore::ReadPrefs() {
+ // We do not read intentionally.
+ return PersistentPrefStore::PREF_READ_ERROR_NONE;
+}
+
+bool OverlayPersistentPrefStore::WritePrefs() {
+ // We do not write intentionally.
+ return true;
+}
+
+void OverlayPersistentPrefStore::ScheduleWritePrefs() {
+ // We do not write intentionally.
+}
+
+void OverlayPersistentPrefStore::OnPrefValueChanged(const std::string& key) {
+ if (!overlay_.GetValue(key, NULL))
+ FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key));
+}
+
+void OverlayPersistentPrefStore::OnInitializationCompleted() {
+ FOR_EACH_OBSERVER(PrefStore::Observer, observers_,
+ OnInitializationCompleted());
+}
diff --git a/chrome/browser/prefs/overlay_persistent_pref_store.h b/chrome/browser/prefs/overlay_persistent_pref_store.h
new file mode 100644
index 0000000..dcc3161
--- /dev/null
+++ b/chrome/browser/prefs/overlay_persistent_pref_store.h
@@ -0,0 +1,54 @@
+// Copyright (c) 2011 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.
+
+#ifndef CHROME_BROWSER_PREFS_OVERLAY_PERSISTENT_PREF_STORE_H_
+#define CHROME_BROWSER_PREFS_OVERLAY_PERSISTENT_PREF_STORE_H_
+#pragma once
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/observer_list.h"
+#include "base/ref_counted.h"
+#include "chrome/browser/prefs/pref_value_map.h"
+#include "chrome/common/persistent_pref_store.h"
+
+// PersistentPrefStore that directs all write operations into a in-memory
+// PrefValueMap. Read operations are first answered by the PrefValueMap.
+// If the PrefValueMap does not contain a value for the requested key,
+// the look-up is passed on to an underlying PersistentPrefStore |underlay_|.
+class OverlayPersistentPrefStore : public PersistentPrefStore,
+ public PrefStore::Observer {
+ public:
+ explicit OverlayPersistentPrefStore(PersistentPrefStore* underlay);
+ virtual ~OverlayPersistentPrefStore();
+
+ // Methods of PrefStore.
+ virtual void AddObserver(PrefStore::Observer* observer);
+ virtual void RemoveObserver(PrefStore::Observer* observer);
+ virtual bool IsInitializationComplete() const;
+ virtual ReadResult GetValue(const std::string& key, Value** result) const;
+
+ // Methods of PersistentPrefStore.
+ virtual void SetValue(const std::string& key, Value* value);
+ virtual void SetValueSilently(const std::string& key, Value* value);
+ virtual void RemoveValue(const std::string& key);
+ virtual bool ReadOnly() const;
+ virtual PrefReadError ReadPrefs();
+ virtual bool WritePrefs();
+ virtual void ScheduleWritePrefs();
+
+ private:
+ // Methods of PrefStore::Observer.
+ virtual void OnPrefValueChanged(const std::string& key);
+ virtual void OnInitializationCompleted();
+
+ ObserverList<PrefStore::Observer, true> observers_;
+ PrefValueMap overlay_;
+ scoped_refptr<PersistentPrefStore> underlay_;
+
+ DISALLOW_COPY_AND_ASSIGN(OverlayPersistentPrefStore);
+};
+
+#endif // CHROME_BROWSER_PREFS_OVERLAY_PERSISTENT_PREF_STORE_H_
diff --git a/chrome/browser/prefs/overlay_persistent_pref_store_unittest.cc b/chrome/browser/prefs/overlay_persistent_pref_store_unittest.cc
new file mode 100644
index 0000000..7e2e0a2
--- /dev/null
+++ b/chrome/browser/prefs/overlay_persistent_pref_store_unittest.cc
@@ -0,0 +1,119 @@
+// Copyright (c) 2011 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 "base/values.h"
+#include "chrome/browser/prefs/overlay_persistent_pref_store.h"
+#include "chrome/browser/prefs/testing_pref_store.h"
+#include "chrome/common/pref_store_observer_mock.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::Mock;
+using ::testing::StrEq;
+
+const char key[] = "test.key";
+
+class OverlayPersistentPrefStoreTest : public testing::Test {
+ public:
+ OverlayPersistentPrefStoreTest()
+ : underlay_(new TestingPrefStore()),
+ overlay_(new OverlayPersistentPrefStore(underlay_.get())) {
+ }
+
+ scoped_refptr<TestingPrefStore> underlay_;
+ scoped_refptr<OverlayPersistentPrefStore> overlay_;
+};
+
+TEST_F(OverlayPersistentPrefStoreTest, Observer) {
+ PrefStoreObserverMock obs;
+ overlay_->AddObserver(&obs);
+
+ // Check that underlay first value is reported.
+ EXPECT_CALL(obs, OnPrefValueChanged(StrEq(key))).Times(1);
+ underlay_->SetValue(key, Value::CreateIntegerValue(42));
+ Mock::VerifyAndClearExpectations(&obs);
+
+ // Check that underlay overwriting is reported.
+ EXPECT_CALL(obs, OnPrefValueChanged(StrEq(key))).Times(1);
+ underlay_->SetValue(key, Value::CreateIntegerValue(43));
+ Mock::VerifyAndClearExpectations(&obs);
+
+ // Check that overwriting change in overlay is reported.
+ EXPECT_CALL(obs, OnPrefValueChanged(StrEq(key))).Times(1);
+ overlay_->SetValue(key, Value::CreateIntegerValue(44));
+ Mock::VerifyAndClearExpectations(&obs);
+
+ // Check that hidden underlay change is not reported.
+ EXPECT_CALL(obs, OnPrefValueChanged(StrEq(key))).Times(0);
+ underlay_->SetValue(key, Value::CreateIntegerValue(45));
+ Mock::VerifyAndClearExpectations(&obs);
+
+ // Check that overlay remove is reported.
+ EXPECT_CALL(obs, OnPrefValueChanged(StrEq(key))).Times(1);
+ overlay_->RemoveValue(key);
+ Mock::VerifyAndClearExpectations(&obs);
+
+ // Check that underlay remove is reported.
+ EXPECT_CALL(obs, OnPrefValueChanged(StrEq(key))).Times(1);
+ underlay_->RemoveValue(key);
+ Mock::VerifyAndClearExpectations(&obs);
+
+ // Check respecting of silence.
+ EXPECT_CALL(obs, OnPrefValueChanged(StrEq(key))).Times(0);
+ overlay_->SetValueSilently(key, Value::CreateIntegerValue(46));
+ Mock::VerifyAndClearExpectations(&obs);
+
+ overlay_->RemoveObserver(&obs);
+
+ // Check successful unsubscription.
+ EXPECT_CALL(obs, OnPrefValueChanged(StrEq(key))).Times(0);
+ underlay_->SetValue(key, Value::CreateIntegerValue(47));
+ overlay_->SetValue(key, Value::CreateIntegerValue(48));
+ Mock::VerifyAndClearExpectations(&obs);
+}
+
+TEST_F(OverlayPersistentPrefStoreTest, GetAndSet) {
+ Value* value = NULL;
+ int i = -1;
+ EXPECT_EQ(PrefStore::READ_NO_VALUE, overlay_->GetValue(key, &value));
+ EXPECT_EQ(PrefStore::READ_NO_VALUE, underlay_->GetValue(key, &value));
+
+ underlay_->SetValue(key, Value::CreateIntegerValue(42));
+
+ // Value shines through:
+ EXPECT_EQ(PrefStore::READ_OK, overlay_->GetValue(key, &value));
+ ASSERT_TRUE(value);
+ EXPECT_TRUE(value->GetAsInteger(&i));
+ EXPECT_EQ(42, i);
+
+ EXPECT_EQ(PrefStore::READ_OK, underlay_->GetValue(key, &value));
+ ASSERT_TRUE(value);
+ EXPECT_TRUE(value->GetAsInteger(&i));
+ EXPECT_EQ(42, i);
+
+ overlay_->SetValue(key, Value::CreateIntegerValue(43));
+
+ EXPECT_EQ(PrefStore::READ_OK, overlay_->GetValue(key, &value));
+ ASSERT_TRUE(value);
+ EXPECT_TRUE(value->GetAsInteger(&i));
+ EXPECT_EQ(43, i);
+
+ EXPECT_EQ(PrefStore::READ_OK, underlay_->GetValue(key, &value));
+ ASSERT_TRUE(value);
+ EXPECT_TRUE(value->GetAsInteger(&i));
+ EXPECT_EQ(42, i);
+
+ overlay_->RemoveValue(key);
+
+ // Value shines through:
+ EXPECT_EQ(PrefStore::READ_OK, overlay_->GetValue(key, &value));
+ ASSERT_TRUE(value);
+ EXPECT_TRUE(value->GetAsInteger(&i));
+ EXPECT_EQ(42, i);
+
+ EXPECT_EQ(PrefStore::READ_OK, underlay_->GetValue(key, &value));
+ ASSERT_TRUE(value);
+ EXPECT_TRUE(value->GetAsInteger(&i));
+ EXPECT_EQ(42, i);
+}
diff --git a/chrome/browser/prefs/pref_change_registrar.cc b/chrome/browser/prefs/pref_change_registrar.cc
index 5655a8e..64c60962 100644
--- a/chrome/browser/prefs/pref_change_registrar.cc
+++ b/chrome/browser/prefs/pref_change_registrar.cc
@@ -10,6 +10,10 @@
PrefChangeRegistrar::PrefChangeRegistrar() : service_(NULL) {}
PrefChangeRegistrar::~PrefChangeRegistrar() {
+ // If you see an invalid memory access in this destructor, this
+ // PrefChangeRegistrar might be subscribed to an OffTheRecordProfileImpl that
+ // has been destroyed. This should not happen any more but be warned.
+ // Feel free to contact battre@chromium.org in case this happens.
RemoveAll();
}
diff --git a/chrome/browser/prefs/pref_member.cc b/chrome/browser/prefs/pref_member.cc
index cc14384..0b38486 100644
--- a/chrome/browser/prefs/pref_member.cc
+++ b/chrome/browser/prefs/pref_member.cc
@@ -18,7 +18,7 @@ PrefMemberBase::PrefMemberBase()
}
PrefMemberBase::~PrefMemberBase() {
- if (!pref_name_.empty())
+ if (prefs_ && !pref_name_.empty())
prefs_->RemovePrefObserver(pref_name_.c_str(), this);
}
@@ -37,6 +37,13 @@ void PrefMemberBase::Init(const char* pref_name, PrefService* prefs,
prefs_->AddPrefObserver(pref_name, this);
}
+void PrefMemberBase::Destroy() {
+ if (prefs_) {
+ prefs_->RemovePrefObserver(pref_name_.c_str(), this);
+ prefs_ = NULL;
+ }
+}
+
bool PrefMemberBase::IsManaged() const {
DCHECK(!pref_name_.empty());
const PrefService::Preference* pref =
diff --git a/chrome/browser/prefs/pref_member.h b/chrome/browser/prefs/pref_member.h
index 6d1ab5a..099511a 100644
--- a/chrome/browser/prefs/pref_member.h
+++ b/chrome/browser/prefs/pref_member.h
@@ -45,6 +45,9 @@ class PrefMemberBase : public NotificationObserver {
NotificationObserver* observer);
// See PrefMember<> for description.
+ void Destroy();
+
+ // See PrefMember<> for description.
bool IsManaged() const;
// NotificationObserver
@@ -92,6 +95,12 @@ class PrefMember : public subtle::PrefMemberBase {
subtle::PrefMemberBase::Init(pref_name, prefs, observer);
}
+ // Unsubscribes the PrefMember from the PrefService. After calling this
+ // function, the PrefMember may not be used any more.
+ void Destroy() {
+ subtle::PrefMemberBase::Destroy();
+ }
+
// Check whether the pref is managed, i.e. controlled externally through
// enterprise configuration management (e.g. windows group policy). Returns
// false for unknown prefs.
diff --git a/chrome/browser/prefs/pref_service.cc b/chrome/browser/prefs/pref_service.cc
index 68edbb5..2ab04f8 100644
--- a/chrome/browser/prefs/pref_service.cc
+++ b/chrome/browser/prefs/pref_service.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -20,9 +20,11 @@
#include "base/utf_string_conversions.h"
#include "build/build_config.h"
#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/extensions/extension_pref_store.h"
#include "chrome/browser/policy/configuration_policy_pref_store.h"
#include "chrome/browser/prefs/command_line_pref_store.h"
#include "chrome/browser/prefs/default_pref_store.h"
+#include "chrome/browser/prefs/overlay_persistent_pref_store.h"
#include "chrome/browser/prefs/pref_notifier_impl.h"
#include "chrome/browser/prefs/pref_value_store.h"
#include "chrome/common/json_pref_store.h"
@@ -114,9 +116,15 @@ PrefService* PrefService::CreatePrefService(const FilePath& pref_filename,
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE));
ConfigurationPolicyPrefStore* recommended =
ConfigurationPolicyPrefStore::CreateRecommendedPolicyPrefStore();
+ DefaultPrefStore* default_pref_store = new DefaultPrefStore();
return new PrefService(managed, device_management, extension_prefs,
- command_line, user, recommended);
+ command_line, user, recommended, default_pref_store);
+}
+
+PrefService* PrefService::CreateIncognitoPrefService(
+ PrefStore* incognito_extension_prefs) {
+ return new PrefService(*this, incognito_extension_prefs);
}
PrefService::PrefService(PrefStore* managed_platform_prefs,
@@ -124,10 +132,11 @@ PrefService::PrefService(PrefStore* managed_platform_prefs,
PrefStore* extension_prefs,
PrefStore* command_line_prefs,
PersistentPrefStore* user_prefs,
- PrefStore* recommended_prefs)
- : user_pref_store_(user_prefs) {
+ PrefStore* recommended_prefs,
+ DefaultPrefStore* default_store)
+ : user_pref_store_(user_prefs),
+ default_store_(default_store) {
pref_notifier_.reset(new PrefNotifierImpl(this));
- default_store_ = new DefaultPrefStore();
pref_value_store_ =
new PrefValueStore(managed_platform_prefs,
device_management_prefs,
@@ -135,11 +144,29 @@ PrefService::PrefService(PrefStore* managed_platform_prefs,
command_line_prefs,
user_pref_store_,
recommended_prefs,
- default_store_,
+ default_store,
pref_notifier_.get());
InitFromStorage();
}
+PrefService::PrefService(const PrefService& original,
+ PrefStore* incognito_extension_prefs)
+ : user_pref_store_(
+ new OverlayPersistentPrefStore(original.user_pref_store_.get())),
+ default_store_(original.default_store_.get()){
+ pref_notifier_.reset(new PrefNotifierImpl(this));
+ pref_value_store_ = original.pref_value_store_->CloneAndSpecialize(
+ NULL, // managed_platform_prefs
+ NULL, // device_management_prefs
+ incognito_extension_prefs,
+ NULL, // command_line_prefs
+ user_pref_store_.get(),
+ NULL, // recommended_prefs
+ default_store_.get(),
+ pref_notifier_.get() );
+ InitFromStorage();
+}
+
PrefService::~PrefService() {
DCHECK(CalledOnValidThread());
STLDeleteContainerPointers(prefs_.begin(), prefs_.end());
@@ -325,15 +352,23 @@ FilePath PrefService::GetFilePath(const char* path) const {
}
bool PrefService::HasPrefPath(const char* path) const {
- return pref_value_store_->HasPrefPath(path);
+ const Preference* pref = FindPreference(path);
+ return pref && !pref->IsDefaultValue();
}
const PrefService::Preference* PrefService::FindPreference(
const char* pref_name) const {
DCHECK(CalledOnValidThread());
- Preference p(this, pref_name);
+ Preference p(this, pref_name, Value::TYPE_NULL);
PreferenceSet::const_iterator it = prefs_.find(&p);
- return it == prefs_.end() ? NULL : *it;
+ if (it != prefs_.end())
+ return *it;
+ const Value::ValueType type = default_store_->GetType(pref_name);
+ if (type == Value::TYPE_NULL)
+ return NULL;
+ Preference* new_pref = new Preference(this, pref_name, type);
+ prefs_.insert(new_pref);
+ return new_pref;
}
bool PrefService::ReadOnly() const {
@@ -346,10 +381,7 @@ PrefNotifier* PrefService::pref_notifier() const {
bool PrefService::IsManagedPreference(const char* pref_name) const {
const Preference* pref = FindPreference(pref_name);
- if (pref && pref->IsManaged()) {
- return true;
- }
- return false;
+ return pref && pref->IsManaged();
}
const DictionaryValue* PrefService::GetDictionary(const char* path) const {
@@ -405,18 +437,8 @@ void PrefService::RegisterPreference(const char* path, Value* default_value) {
DCHECK(orig_type != Value::TYPE_NULL && orig_type != Value::TYPE_BINARY) <<
"invalid preference type: " << orig_type;
- // We set the default value of dictionaries and lists to be null so it's
- // easier for callers to check for empty dict/list prefs. The PrefValueStore
- // accepts ownership of the value (null or default_value).
- if (Value::TYPE_LIST == orig_type || Value::TYPE_DICTIONARY == orig_type) {
- default_store_->SetDefaultValue(path, Value::CreateNullValue());
- } else {
- // Hand off ownership.
- default_store_->SetDefaultValue(path, scoped_value.release());
- }
-
- pref_value_store_->RegisterPreferenceType(path, orig_type);
- prefs_.insert(new Preference(this, path));
+ // Hand off ownership.
+ default_store_->SetDefaultValue(path, scoped_value.release());
}
void PrefService::ClearPref(const char* path) {
@@ -439,13 +461,7 @@ void PrefService::Set(const char* path, const Value& value) {
return;
}
- // Allow dictionary and list types to be set to null, which removes their
- // user values.
- if (value.GetType() == Value::TYPE_NULL &&
- (pref->GetType() == Value::TYPE_DICTIONARY ||
- pref->GetType() == Value::TYPE_LIST)) {
- user_pref_store_->RemoveValue(path);
- } else if (pref->GetType() != value.GetType()) {
+ if (pref->GetType() != value.GetType()) {
NOTREACHED() << "Trying to set pref " << path
<< " of type " << pref->GetType()
<< " to value of type " << value.GetType();
@@ -587,15 +603,17 @@ void PrefService::SetUserPrefValue(const char* path, Value* new_value) {
// PrefService::Preference
PrefService::Preference::Preference(const PrefService* service,
- const char* name)
+ const char* name,
+ Value::ValueType type)
: name_(name),
+ type_(type),
pref_service_(service) {
DCHECK(name);
DCHECK(service);
}
Value::ValueType PrefService::Preference::GetType() const {
- return pref_service_->pref_value_store_->GetRegisteredType(name_);
+ return type_;
}
const Value* PrefService::Preference::GetValue() const {
@@ -603,8 +621,10 @@ const Value* PrefService::Preference::GetValue() const {
"Must register pref before getting its value";
Value* found_value = NULL;
- if (pref_service_->pref_value_store_->GetValue(name_, &found_value))
+ if (pref_service_->pref_value_store_->GetValue(name_, type_, &found_value)) {
+ DCHECK(found_value->IsType(type_));
return found_value;
+ }
// Every registered preference has at least a default value.
NOTREACHED() << "no valid value found for registered pref " << name_;
diff --git a/chrome/browser/prefs/pref_service.h b/chrome/browser/prefs/pref_service.h
index f17bbbd..24b08d2 100644
--- a/chrome/browser/prefs/pref_service.h
+++ b/chrome/browser/prefs/pref_service.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -42,7 +42,8 @@ class PrefService : public base::NonThreadSafe {
// dictionary (a branch), or list. You shouldn't need to construct this on
// your own; use the PrefService::Register*Pref methods instead.
Preference(const PrefService* service,
- const char* name);
+ const char* name,
+ Value::ValueType type);
~Preference() {}
// Returns the name of the Preference (i.e., the key, e.g.,
@@ -92,6 +93,8 @@ class PrefService : public base::NonThreadSafe {
std::string name_;
+ Value::ValueType type_;
+
// Reference to the PrefService in which this pref was created.
const PrefService* pref_service_;
@@ -109,6 +112,12 @@ class PrefService : public base::NonThreadSafe {
PrefStore* extension_pref_store,
Profile* profile);
+ // Creates an incognito copy of the pref service that shares most pref stores
+ // but uses a fresh non-persistent overlay for the user pref store and an
+ // individual extension pref store (to cache the effective extension prefs for
+ // incognito windows).
+ PrefService* CreateIncognitoPrefService(PrefStore* incognito_extension_prefs);
+
virtual ~PrefService();
// Reloads the data from file. This should only be called when the importer
@@ -230,7 +239,8 @@ class PrefService : public base::NonThreadSafe {
PrefStore* extension_prefs,
PrefStore* command_line_prefs,
PersistentPrefStore* user_prefs,
- PrefStore* recommended_prefs);
+ PrefStore* recommended_prefs,
+ DefaultPrefStore* default_store);
// The PrefNotifier handles registering and notifying preference observers.
// It is created and owned by this PrefService. Subclasses may access it for
@@ -249,6 +259,11 @@ class PrefService : public base::NonThreadSafe {
friend class PrefChangeRegistrar;
friend class subtle::PrefMemberBase;
+ // Construct an incognito version of the pref service. Use
+ // CreateIncognitoPrefService() instead of calling this constructor directly.
+ PrefService(const PrefService& original,
+ PrefStore* incognito_extension_prefs);
+
// If the pref at the given path changes, we call the observer's Observe
// method with PREF_CHANGED. Note that observers should not call these methods
// directly but rather use a PrefChangeRegistrar to make sure the observer
@@ -272,14 +287,14 @@ class PrefService : public base::NonThreadSafe {
// and owned by this PrefService. Subclasses may access it for unit testing.
scoped_refptr<PrefValueStore> pref_value_store_;
- // The persistent pref store used for actual user data.
- PersistentPrefStore* user_pref_store_;
-
- // Points to the default pref store we passed to the PrefValueStore.
- DefaultPrefStore* default_store_;
+ // Pref Stores and profile that we passed to the PrefValueStore.
+ scoped_refptr<PersistentPrefStore> user_pref_store_;
+ scoped_refptr<DefaultPrefStore> default_store_;
- // A set of all the registered Preference objects.
- PreferenceSet prefs_;
+ // Local cache of registered Preference objects. The default_store_
+ // is authoritative with respect to what the types and default values
+ // of registered preferences are.
+ mutable PreferenceSet prefs_;
DISALLOW_COPY_AND_ASSIGN(PrefService);
};
diff --git a/chrome/browser/prefs/pref_service_mock_builder.cc b/chrome/browser/prefs/pref_service_mock_builder.cc
index b02a334..62f4d54 100644
--- a/chrome/browser/prefs/pref_service_mock_builder.cc
+++ b/chrome/browser/prefs/pref_service_mock_builder.cc
@@ -7,6 +7,7 @@
#include "chrome/browser/browser_thread.h"
#include "chrome/browser/policy/configuration_policy_pref_store.h"
#include "chrome/browser/prefs/command_line_pref_store.h"
+#include "chrome/browser/prefs/default_pref_store.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/prefs/testing_pref_store.h"
#include "chrome/common/json_pref_store.h"
@@ -19,87 +20,94 @@ PrefServiceMockBuilder::~PrefServiceMockBuilder() {}
PrefServiceMockBuilder&
PrefServiceMockBuilder::WithManagedPlatformPrefs(PrefStore* store) {
- managed_platform_prefs_.reset(store);
+ managed_platform_prefs_ = store;
return *this;
}
PrefServiceMockBuilder&
PrefServiceMockBuilder::WithDeviceManagementPrefs(PrefStore* store) {
- device_management_prefs_.reset(store);
+ device_management_prefs_ = store;
return *this;
}
PrefServiceMockBuilder&
PrefServiceMockBuilder::WithExtensionPrefs(PrefStore* store) {
- extension_prefs_.reset(store);
+ extension_prefs_ = store;
return *this;
}
PrefServiceMockBuilder&
PrefServiceMockBuilder::WithCommandLinePrefs(PrefStore* store) {
- command_line_prefs_.reset(store);
+ command_line_prefs_ = store;
return *this;
}
PrefServiceMockBuilder&
PrefServiceMockBuilder::WithUserPrefs(PersistentPrefStore* store) {
- user_prefs_.reset(store);
+ user_prefs_ = store;
return *this;
}
PrefServiceMockBuilder&
PrefServiceMockBuilder::WithRecommendedPrefs(PrefStore* store) {
- recommended_prefs_.reset(store);
+ recommended_prefs_ = store;
return *this;
}
PrefServiceMockBuilder&
PrefServiceMockBuilder::WithManagedPlatformProvider(
policy::ConfigurationPolicyProvider* provider) {
- managed_platform_prefs_.reset(
- new policy::ConfigurationPolicyPrefStore(provider));
+ managed_platform_prefs_ =
+ new policy::ConfigurationPolicyPrefStore(provider);
return *this;
}
PrefServiceMockBuilder&
PrefServiceMockBuilder::WithDeviceManagementProvider(
policy::ConfigurationPolicyProvider* provider) {
- device_management_prefs_.reset(
- new policy::ConfigurationPolicyPrefStore(provider));
+ device_management_prefs_ =
+ new policy::ConfigurationPolicyPrefStore(provider);
return *this;
}
PrefServiceMockBuilder&
PrefServiceMockBuilder::WithRecommendedProvider(
policy::ConfigurationPolicyProvider* provider) {
- recommended_prefs_.reset(
- new policy::ConfigurationPolicyPrefStore(provider));
+ recommended_prefs_ =
+ new policy::ConfigurationPolicyPrefStore(provider);
return *this;
}
PrefServiceMockBuilder&
PrefServiceMockBuilder::WithCommandLine(CommandLine* command_line) {
- command_line_prefs_.reset(new CommandLinePrefStore(command_line));
+ command_line_prefs_ = new CommandLinePrefStore(command_line);
return *this;
}
PrefServiceMockBuilder&
PrefServiceMockBuilder::WithUserFilePrefs(const FilePath& prefs_file) {
- user_prefs_.reset(
+ user_prefs_ =
new JsonPrefStore(prefs_file,
BrowserThread::GetMessageLoopProxyForThread(
- BrowserThread::FILE)));
+ BrowserThread::FILE));
return *this;
}
PrefService* PrefServiceMockBuilder::Create() {
PrefService* pref_service =
- new PrefService(managed_platform_prefs_.release(),
- device_management_prefs_.release(),
- extension_prefs_.release(),
- command_line_prefs_.release(),
- user_prefs_.release(),
- recommended_prefs_.release());
- user_prefs_.reset(new TestingPrefStore);
+ new PrefService(managed_platform_prefs_.get(),
+ device_management_prefs_.get(),
+ extension_prefs_.get(),
+ command_line_prefs_.get(),
+ user_prefs_.get(),
+ recommended_prefs_.get(),
+ new DefaultPrefStore());
+ managed_platform_prefs_ = NULL;
+ device_management_prefs_ = NULL;
+ extension_prefs_ = NULL;
+ command_line_prefs_ = NULL;
+ user_prefs_ = NULL;
+ recommended_prefs_ = NULL;
+ user_prefs_ = new TestingPrefStore;
return pref_service;
}
diff --git a/chrome/browser/prefs/pref_service_mock_builder.h b/chrome/browser/prefs/pref_service_mock_builder.h
index 9cc4fcc..0c4a6e8 100644
--- a/chrome/browser/prefs/pref_service_mock_builder.h
+++ b/chrome/browser/prefs/pref_service_mock_builder.h
@@ -7,7 +7,7 @@
#pragma once
#include "base/basictypes.h"
-#include "base/scoped_ptr.h"
+#include "base/ref_counted.h"
#include "chrome/common/persistent_pref_store.h"
#include "chrome/common/pref_store.h"
@@ -56,12 +56,12 @@ class PrefServiceMockBuilder {
PrefService* Create();
private:
- scoped_ptr<PrefStore> managed_platform_prefs_;
- scoped_ptr<PrefStore> device_management_prefs_;
- scoped_ptr<PrefStore> extension_prefs_;
- scoped_ptr<PrefStore> command_line_prefs_;
- scoped_ptr<PersistentPrefStore> user_prefs_;
- scoped_ptr<PrefStore> recommended_prefs_;
+ scoped_refptr<PrefStore> managed_platform_prefs_;
+ scoped_refptr<PrefStore> device_management_prefs_;
+ scoped_refptr<PrefStore> extension_prefs_;
+ scoped_refptr<PrefStore> command_line_prefs_;
+ scoped_refptr<PersistentPrefStore> user_prefs_;
+ scoped_refptr<PrefStore> recommended_prefs_;
DISALLOW_COPY_AND_ASSIGN(PrefServiceMockBuilder);
};
diff --git a/chrome/browser/prefs/pref_service_unittest.cc b/chrome/browser/prefs/pref_service_unittest.cc
index 3ead502..32ab5b7 100644
--- a/chrome/browser/prefs/pref_service_unittest.cc
+++ b/chrome/browser/prefs/pref_service_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -148,6 +148,27 @@ TEST(PrefServiceTest, Observers) {
Mock::VerifyAndClearExpectations(&obs2);
}
+// Make sure that if a preference changes type, so the wrong type is stored in
+// the user pref file, it uses the correct fallback value instead.
+TEST(PrefServiceTest, GetValueChangedType) {
+ const int kTestValue = 10;
+ TestingPrefService prefs;
+ prefs.RegisterIntegerPref(prefs::kStabilityLaunchCount, kTestValue);
+
+ // Check falling back to a recommended value.
+ prefs.SetUserPref(prefs::kStabilityLaunchCount,
+ Value::CreateStringValue("not an integer"));
+ const PrefService::Preference* pref =
+ prefs.FindPreference(prefs::kStabilityLaunchCount);
+ ASSERT_TRUE(pref);
+ const Value* value = pref->GetValue();
+ ASSERT_TRUE(value);
+ EXPECT_EQ(Value::TYPE_INTEGER, value->GetType());
+ int actual_int_value = -1;
+ EXPECT_TRUE(value->GetAsInteger(&actual_int_value));
+ EXPECT_EQ(kTestValue, actual_int_value);
+}
+
TEST(PrefServiceTest, ProxyPolicyOverridesCommandLineOptions) {
CommandLine command_line(CommandLine::NO_PROGRAM);
command_line.AppendSwitchASCII(switches::kProxyBypassList, "123");
@@ -296,11 +317,7 @@ class PrefServiceSetValueTest : public testing::Test {
static const char kName[];
static const char kValue[];
- PrefServiceSetValueTest()
- : null_value_(Value::CreateNullValue()) {}
-
TestingPrefService prefs_;
- scoped_ptr<Value> null_value_;
PrefObserverMock observer_;
};
@@ -337,10 +354,8 @@ TEST_F(PrefServiceSetValueTest, SetDictionaryValue) {
registrar.Init(&prefs_);
registrar.Add(kName, &observer_);
- // Dictionary values are special: setting one to NULL is the same as clearing
- // the user value, allowing the NULL default to take (or keep) control.
EXPECT_CALL(observer_, Observe(_, _, _)).Times(0);
- prefs_.Set(kName, *null_value_);
+ prefs_.RemoveUserPref(kName);
Mock::VerifyAndClearExpectations(&observer_);
DictionaryValue new_value;
@@ -353,8 +368,9 @@ TEST_F(PrefServiceSetValueTest, SetDictionaryValue) {
prefs_.Set(kName, new_value);
Mock::VerifyAndClearExpectations(&observer_);
- observer_.Expect(&prefs_, kName, null_value_.get());
- prefs_.Set(kName, *null_value_);
+ DictionaryValue empty;
+ observer_.Expect(&prefs_, kName, &empty);
+ prefs_.Set(kName, empty);
Mock::VerifyAndClearExpectations(&observer_);
}
@@ -364,10 +380,8 @@ TEST_F(PrefServiceSetValueTest, SetListValue) {
registrar.Init(&prefs_);
registrar.Add(kName, &observer_);
- // List values are special: setting one to NULL is the same as clearing the
- // user value, allowing the NULL default to take (or keep) control.
EXPECT_CALL(observer_, Observe(_, _, _)).Times(0);
- prefs_.Set(kName, *null_value_);
+ prefs_.RemoveUserPref(kName);
Mock::VerifyAndClearExpectations(&observer_);
ListValue new_value;
@@ -380,7 +394,8 @@ TEST_F(PrefServiceSetValueTest, SetListValue) {
prefs_.Set(kName, new_value);
Mock::VerifyAndClearExpectations(&observer_);
- observer_.Expect(&prefs_, kName, null_value_.get());
- prefs_.Set(kName, *null_value_);
+ ListValue empty;
+ observer_.Expect(&prefs_, kName, &empty);
+ prefs_.Set(kName, empty);
Mock::VerifyAndClearExpectations(&observer_);
}
diff --git a/chrome/browser/prefs/pref_value_map.cc b/chrome/browser/prefs/pref_value_map.cc
index 6e7bf79..0857f6d 100644
--- a/chrome/browser/prefs/pref_value_map.cc
+++ b/chrome/browser/prefs/pref_value_map.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -58,6 +58,22 @@ void PrefValueMap::Clear() {
prefs_.clear();
}
+PrefValueMap::iterator PrefValueMap::begin() {
+ return prefs_.begin();
+}
+
+PrefValueMap::iterator PrefValueMap::end() {
+ return prefs_.end();
+}
+
+PrefValueMap::const_iterator PrefValueMap::begin() const {
+ return prefs_.begin();
+}
+
+PrefValueMap::const_iterator PrefValueMap::end() const {
+ return prefs_.end();
+}
+
bool PrefValueMap::GetBoolean(const std::string& key,
bool* value) const {
Value* stored_value = NULL;
diff --git a/chrome/browser/prefs/pref_value_map.h b/chrome/browser/prefs/pref_value_map.h
index 0e99920..19aeb05 100644
--- a/chrome/browser/prefs/pref_value_map.h
+++ b/chrome/browser/prefs/pref_value_map.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -17,6 +17,9 @@ class Value;
// A generic string to value map used by the PrefStore implementations.
class PrefValueMap {
public:
+ typedef std::map<std::string, Value*>::iterator iterator;
+ typedef std::map<std::string, Value*>::const_iterator const_iterator;
+
PrefValueMap();
virtual ~PrefValueMap();
@@ -36,6 +39,11 @@ class PrefValueMap {
// Clears the map.
void Clear();
+ iterator begin();
+ iterator end();
+ const_iterator begin() const;
+ const_iterator end() const;
+
// Gets a boolean value for |key| and stores it in |value|. Returns true if
// the value was found and of the proper type.
bool GetBoolean(const std::string& key, bool* value) const;
diff --git a/chrome/browser/prefs/pref_value_store.cc b/chrome/browser/prefs/pref_value_store.cc
index 0fd3449..c86accd 100644
--- a/chrome/browser/prefs/pref_value_store.cc
+++ b/chrome/browser/prefs/pref_value_store.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -24,7 +24,7 @@ void PrefValueStore::PrefStoreKeeper::Initialize(
pref_store_->RemoveObserver(this);
type_ = type;
pref_value_store_ = store;
- pref_store_.reset(pref_store);
+ pref_store_ = pref_store;
if (pref_store_.get())
pref_store_->AddObserver(this);
}
@@ -60,49 +60,63 @@ PrefValueStore::PrefValueStore(PrefStore* managed_platform_prefs,
PrefValueStore::~PrefValueStore() {}
+PrefValueStore* PrefValueStore::CloneAndSpecialize(
+ PrefStore* managed_platform_prefs,
+ PrefStore* device_management_prefs,
+ PrefStore* extension_prefs,
+ PrefStore* command_line_prefs,
+ PrefStore* user_prefs,
+ PrefStore* recommended_prefs,
+ PrefStore* default_prefs,
+ PrefNotifier* pref_notifier) {
+ DCHECK(pref_notifier);
+ if (!managed_platform_prefs)
+ managed_platform_prefs = GetPrefStore(MANAGED_PLATFORM_STORE);
+ if (!device_management_prefs)
+ device_management_prefs = GetPrefStore(DEVICE_MANAGEMENT_STORE);
+ if (!extension_prefs)
+ extension_prefs = GetPrefStore(EXTENSION_STORE);
+ if (!command_line_prefs)
+ command_line_prefs = GetPrefStore(COMMAND_LINE_STORE);
+ if (!user_prefs)
+ user_prefs = GetPrefStore(USER_STORE);
+ if (!recommended_prefs)
+ recommended_prefs = GetPrefStore(RECOMMENDED_STORE);
+ if (!default_prefs)
+ default_prefs = GetPrefStore(DEFAULT_STORE);
+
+ return new PrefValueStore(
+ managed_platform_prefs, device_management_prefs, extension_prefs,
+ command_line_prefs, user_prefs, recommended_prefs, default_prefs,
+ pref_notifier);
+}
+
bool PrefValueStore::GetValue(const std::string& name,
+ Value::ValueType type,
Value** out_value) const {
+ *out_value = NULL;
// Check the |PrefStore|s in order of their priority from highest to lowest
// to find the value of the preference described by the given preference name.
for (size_t i = 0; i <= PREF_STORE_TYPE_MAX; ++i) {
if (GetValueFromStore(name.c_str(), static_cast<PrefStoreType>(i),
- out_value))
+ out_value)) {
+ if (!(*out_value)->IsType(type)) {
+ LOG(WARNING) << "Expected type for " << name << " is " << type
+ << " but got " << (*out_value)->GetType()
+ << " in store " << i;
+ continue;
+ }
return true;
+ }
}
return false;
}
-void PrefValueStore::RegisterPreferenceType(const std::string& name,
- Value::ValueType type) {
- pref_types_[name] = type;
-}
-
-Value::ValueType PrefValueStore::GetRegisteredType(
- const std::string& name) const {
- PrefTypeMap::const_iterator found = pref_types_.find(name);
- if (found == pref_types_.end())
- return Value::TYPE_NULL;
- return found->second;
-}
-
-bool PrefValueStore::HasPrefPath(const char* path) const {
- Value* tmp_value = NULL;
- const std::string name(path);
- bool rv = GetValue(name, &tmp_value);
- // Merely registering a pref doesn't count as "having" it: we require a
- // non-default value set.
- return rv && !PrefValueFromDefaultStore(path);
-}
-
void PrefValueStore::NotifyPrefChanged(
const char* path,
PrefValueStore::PrefStoreType new_store) {
DCHECK(new_store != INVALID_STORE);
- // If this pref is not registered, just discard the notification.
- if (!pref_types_.count(path))
- return;
-
bool changed = true;
// Replying that the pref has changed in case the new store is invalid may
// cause problems, but it's the safer choice.
@@ -155,24 +169,6 @@ bool PrefValueStore::PrefValueUserModifiable(const char* name) const {
effective_store == INVALID_STORE;
}
-// Returns true if the actual value is a valid type for the expected type when
-// found in the given store.
-bool PrefValueStore::IsValidType(Value::ValueType expected,
- Value::ValueType actual,
- PrefValueStore::PrefStoreType store) {
- if (expected == actual)
- return true;
-
- // Dictionaries and lists are allowed to hold TYPE_NULL values too, but only
- // in the default pref store.
- if (store == DEFAULT_STORE &&
- actual == Value::TYPE_NULL &&
- (expected == Value::TYPE_DICTIONARY || expected == Value::TYPE_LIST)) {
- return true;
- }
- return false;
-}
-
bool PrefValueStore::PrefValueInStore(
const char* name,
PrefValueStore::PrefStoreType store) const {
@@ -224,12 +220,7 @@ bool PrefValueStore::GetValueFromStore(const char* name,
}
// Fall through...
case PrefStore::READ_OK:
- if (IsValidType(GetRegisteredType(name),
- (*out_value)->GetType(),
- store_type)) {
- return true;
- }
- break;
+ return true;
case PrefStore::READ_NO_VALUE:
break;
}
@@ -257,7 +248,8 @@ void PrefValueStore::InitPrefStore(PrefValueStore::PrefStoreType type,
void PrefValueStore::CheckInitializationCompleted() {
for (size_t i = 0; i <= PREF_STORE_TYPE_MAX; ++i) {
- PrefStore* store = GetPrefStore(static_cast<PrefStoreType>(i));
+ scoped_refptr<PrefStore> store =
+ GetPrefStore(static_cast<PrefStoreType>(i));
if (store && !store->IsInitializationComplete())
return;
}
diff --git a/chrome/browser/prefs/pref_value_store.h b/chrome/browser/prefs/pref_value_store.h
index 87bf4f7..6c64b3e 100644
--- a/chrome/browser/prefs/pref_value_store.h
+++ b/chrome/browser/prefs/pref_value_store.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -13,7 +13,6 @@
#include "base/basictypes.h"
#include "base/gtest_prod_util.h"
#include "base/ref_counted.h"
-#include "base/scoped_ptr.h"
#include "base/values.h"
#include "chrome/browser/browser_thread.h"
#include "chrome/common/pref_store.h"
@@ -63,26 +62,25 @@ class PrefValueStore : public base::RefCountedThreadSafe<PrefValueStore> {
PrefNotifier* pref_notifier);
virtual ~PrefValueStore();
- // Gets the value for the given preference name that has a valid value type;
- // that is, the same type the preference was registered with, or NULL for
- // default values of Dictionaries and Lists. Returns true if a valid value
+ // Creates a clone of this PrefValueStore with PrefStores overwritten
+ // by the parameters passed, if unequal NULL.
+ PrefValueStore* CloneAndSpecialize(PrefStore* managed_platform_prefs,
+ PrefStore* device_management_prefs,
+ PrefStore* extension_prefs,
+ PrefStore* command_line_prefs,
+ PrefStore* user_prefs,
+ PrefStore* recommended_prefs,
+ PrefStore* default_prefs,
+ PrefNotifier* pref_notifier);
+
+ // Gets the value for the given preference name that has the specified value
+ // type. Values stored in a PrefStore that have the matching |name| but
+ // a non-matching |type| are silently skipped. Returns true if a valid value
// was found in any of the available PrefStores. Most callers should use
// Preference::GetValue() instead of calling this method directly.
- bool GetValue(const std::string& name, Value** out_value) const;
-
- // Adds a preference to the mapping of names to types.
- void RegisterPreferenceType(const std::string& name, Value::ValueType type);
-
- // Gets the registered value type for the given preference name. Returns
- // Value::TYPE_NULL if the preference has never been registered.
- Value::ValueType GetRegisteredType(const std::string& name) const;
-
- // Returns true if the PrefValueStore contains the given preference (i.e.,
- // it's been registered), and a value with the correct type has been actively
- // set in some pref store. The application default specified when the pref was
- // registered does not count as an "actively set" value, but another pref
- // store setting a value that happens to be equal to the default does.
- bool HasPrefPath(const char* name) const;
+ bool GetValue(const std::string& name,
+ Value::ValueType type,
+ Value** out_value) const;
// These methods return true if a preference with the given name is in the
// indicated pref store, even if that value is currently being overridden by
@@ -155,7 +153,7 @@ class PrefValueStore : public base::RefCountedThreadSafe<PrefValueStore> {
PrefValueStore* pref_value_store_;
// The PrefStore managed by this keeper.
- scoped_ptr<PrefStore> pref_store_;
+ scoped_refptr<PrefStore> pref_store_;
// Type of the pref store.
PrefStoreType type_;
@@ -172,12 +170,6 @@ class PrefValueStore : public base::RefCountedThreadSafe<PrefValueStore> {
FRIEND_TEST_ALL_PREFIXES(PrefValueStorePolicyRefreshTest,
TestConcurrentPolicyRefresh);
- // Returns true if the actual type is a valid type for the expected type when
- // found in the given store.
- static bool IsValidType(Value::ValueType expected,
- Value::ValueType actual,
- PrefStoreType store);
-
// Returns true if the preference with the given name has a value in the
// given PrefStoreType, of the same value type as the preference was
// registered with.
diff --git a/chrome/browser/prefs/pref_value_store_unittest.cc b/chrome/browser/prefs/pref_value_store_unittest.cc
index 5c0fa53..af4e85a 100644
--- a/chrome/browser/prefs/pref_value_store_unittest.cc
+++ b/chrome/browser/prefs/pref_value_store_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -109,31 +109,6 @@ class PrefValueStoreTest : public testing::Test {
recommended_pref_store_,
default_pref_store_,
&pref_notifier_);
-
- // Register prefs with the PrefValueStore.
- pref_value_store_->RegisterPreferenceType(prefs::kApplicationLocale,
- Value::TYPE_STRING);
- pref_value_store_->RegisterPreferenceType(prefs::kCurrentThemeID,
- Value::TYPE_STRING);
- pref_value_store_->RegisterPreferenceType(
- prefs::kDefaultSearchProviderName,
- Value::TYPE_STRING);
- pref_value_store_->RegisterPreferenceType(prefs::kDeleteCache,
- Value::TYPE_BOOLEAN);
- pref_value_store_->RegisterPreferenceType(prefs::kHomePage,
- Value::TYPE_STRING);
- pref_value_store_->RegisterPreferenceType(prefs::kStabilityLaunchCount,
- Value::TYPE_INTEGER);
- pref_value_store_->RegisterPreferenceType(prefs::kRecommendedPref,
- Value::TYPE_BOOLEAN);
- pref_value_store_->RegisterPreferenceType(prefs::kSampleDict,
- Value::TYPE_DICTIONARY);
- pref_value_store_->RegisterPreferenceType(prefs::kSampleList,
- Value::TYPE_LIST);
- pref_value_store_->RegisterPreferenceType(prefs::kDefaultPref,
- Value::TYPE_INTEGER);
- pref_value_store_->RegisterPreferenceType(prefs::kProxyMode,
- Value::TYPE_INTEGER);
}
// Creates a new dictionary and stores some sample user preferences
@@ -224,14 +199,13 @@ class PrefValueStoreTest : public testing::Test {
MockPrefNotifier pref_notifier_;
scoped_refptr<PrefValueStore> pref_value_store_;
- // |PrefStore|s are owned by the |PrefValueStore|.
- TestingPrefStore* managed_platform_pref_store_;
- TestingPrefStore* device_management_pref_store_;
- TestingPrefStore* extension_pref_store_;
- TestingPrefStore* command_line_pref_store_;
- TestingPrefStore* user_pref_store_;
- TestingPrefStore* recommended_pref_store_;
- TestingPrefStore* default_pref_store_;
+ scoped_refptr<TestingPrefStore> managed_platform_pref_store_;
+ scoped_refptr<TestingPrefStore> device_management_pref_store_;
+ scoped_refptr<TestingPrefStore> extension_pref_store_;
+ scoped_refptr<TestingPrefStore> command_line_pref_store_;
+ scoped_refptr<TestingPrefStore> user_pref_store_;
+ scoped_refptr<TestingPrefStore> recommended_pref_store_;
+ scoped_refptr<TestingPrefStore> default_pref_store_;
};
TEST_F(PrefValueStoreTest, GetValue) {
@@ -240,7 +214,8 @@ TEST_F(PrefValueStoreTest, GetValue) {
// Test getting a managed platform value overwriting a user-defined and
// extension-defined value.
value = NULL;
- ASSERT_TRUE(pref_value_store_->GetValue(prefs::kHomePage, &value));
+ ASSERT_TRUE(pref_value_store_->GetValue(prefs::kHomePage, Value::TYPE_STRING,
+ &value));
std::string actual_str_value;
EXPECT_TRUE(value->GetAsString(&actual_str_value));
EXPECT_EQ(managed_platform_pref::kHomepageValue, actual_str_value);
@@ -248,7 +223,7 @@ TEST_F(PrefValueStoreTest, GetValue) {
// Test getting a managed platform value overwriting a user-defined value.
value = NULL;
ASSERT_TRUE(pref_value_store_->GetValue(prefs::kDefaultSearchProviderName,
- &value));
+ Value::TYPE_STRING, &value));
EXPECT_TRUE(value->GetAsString(&actual_str_value));
EXPECT_EQ(device_management_pref::kSearchProviderNameValue,
actual_str_value);
@@ -256,19 +231,22 @@ TEST_F(PrefValueStoreTest, GetValue) {
// Test getting an extension value overwriting a user-defined and
// command-line-defined value.
value = NULL;
- ASSERT_TRUE(pref_value_store_->GetValue(prefs::kCurrentThemeID, &value));
+ ASSERT_TRUE(pref_value_store_->GetValue(prefs::kCurrentThemeID,
+ Value::TYPE_STRING, &value));
EXPECT_TRUE(value->GetAsString(&actual_str_value));
EXPECT_EQ(extension_pref::kCurrentThemeIDValue, actual_str_value);
// Test getting a command-line value overwriting a user-defined value.
value = NULL;
- ASSERT_TRUE(pref_value_store_->GetValue(prefs::kApplicationLocale, &value));
+ ASSERT_TRUE(pref_value_store_->GetValue(prefs::kApplicationLocale,
+ Value::TYPE_STRING, &value));
EXPECT_TRUE(value->GetAsString(&actual_str_value));
EXPECT_EQ(command_line_pref::kApplicationLocaleValue, actual_str_value);
// Test getting a user-set value.
value = NULL;
- ASSERT_TRUE(pref_value_store_->GetValue(prefs::kDeleteCache, &value));
+ ASSERT_TRUE(pref_value_store_->GetValue(prefs::kDeleteCache,
+ Value::TYPE_BOOLEAN, &value));
bool actual_bool_value = false;
EXPECT_TRUE(value->GetAsBoolean(&actual_bool_value));
EXPECT_EQ(user_pref::kDeleteCacheValue, actual_bool_value);
@@ -276,21 +254,23 @@ TEST_F(PrefValueStoreTest, GetValue) {
// Test getting a user set value overwriting a recommended value.
value = NULL;
ASSERT_TRUE(pref_value_store_->GetValue(prefs::kStabilityLaunchCount,
- &value));
+ Value::TYPE_INTEGER, &value));
int actual_int_value = -1;
EXPECT_TRUE(value->GetAsInteger(&actual_int_value));
EXPECT_EQ(user_pref::kStabilityLaunchCountValue, actual_int_value);
// Test getting a recommended value.
value = NULL;
- ASSERT_TRUE(pref_value_store_->GetValue(prefs::kRecommendedPref, &value));
+ ASSERT_TRUE(pref_value_store_->GetValue(prefs::kRecommendedPref,
+ Value::TYPE_BOOLEAN, &value));
actual_bool_value = false;
EXPECT_TRUE(value->GetAsBoolean(&actual_bool_value));
EXPECT_EQ(recommended_pref::kRecommendedPrefValue, actual_bool_value);
// Test getting a default value.
value = NULL;
- ASSERT_TRUE(pref_value_store_->GetValue(prefs::kDefaultPref, &value));
+ ASSERT_TRUE(pref_value_store_->GetValue(prefs::kDefaultPref,
+ Value::TYPE_INTEGER, &value));
actual_int_value = -1;
EXPECT_TRUE(value->GetAsInteger(&actual_int_value));
EXPECT_EQ(default_pref::kDefaultValue, actual_int_value);
@@ -299,78 +279,20 @@ TEST_F(PrefValueStoreTest, GetValue) {
// does not contain.
FundamentalValue tmp_dummy_value(true);
Value* v_null = &tmp_dummy_value;
- ASSERT_FALSE(pref_value_store_->GetValue(prefs::kMissingPref, &v_null));
+ ASSERT_FALSE(pref_value_store_->GetValue(prefs::kMissingPref,
+ Value::TYPE_STRING, &v_null));
ASSERT_TRUE(v_null == NULL);
}
-// Make sure that if a preference changes type, so the wrong type is stored in
-// the user pref file, it uses the correct fallback value instead.
-TEST_F(PrefValueStoreTest, GetValueChangedType) {
- EXPECT_CALL(pref_notifier_, OnPreferenceChanged(_)).Times(AnyNumber());
-
- // Check falling back to a recommended value.
- user_pref_store_->SetString(prefs::kStabilityLaunchCount,
- "not an integer");
- Value* value = NULL;
- ASSERT_TRUE(pref_value_store_->GetValue(prefs::kStabilityLaunchCount,
- &value));
- ASSERT_TRUE(value != NULL);
- ASSERT_EQ(Value::TYPE_INTEGER, value->GetType());
- int actual_int_value = -1;
- EXPECT_TRUE(value->GetAsInteger(&actual_int_value));
- EXPECT_EQ(recommended_pref::kStabilityLaunchCountValue, actual_int_value);
-
- // Check falling back multiple times, to a default string.
- default_pref_store_->SetString(prefs::kHomePage,
- default_pref::kHomepageValue);
- managed_platform_pref_store_->SetInteger(prefs::kHomePage, 1);
- device_management_pref_store_->SetInteger(prefs::kHomePage, 1);
- extension_pref_store_->SetInteger(prefs::kHomePage, 1);
- command_line_pref_store_->SetInteger(prefs::kHomePage, 1);
- user_pref_store_->SetInteger(prefs::kHomePage, 1);
- recommended_pref_store_->SetInteger(prefs::kHomePage, 1);
-
- value = NULL;
- ASSERT_TRUE(pref_value_store_->GetValue(prefs::kHomePage, &value));
- ASSERT_TRUE(value != NULL);
- ASSERT_EQ(Value::TYPE_STRING, value->GetType());
- std::string actual_str_value;
- EXPECT_TRUE(value->GetAsString(&actual_str_value));
- EXPECT_EQ(default_pref::kHomepageValue, actual_str_value);
-}
-
-TEST_F(PrefValueStoreTest, HasPrefPath) {
- // Managed Platform preference
- EXPECT_TRUE(pref_value_store_->HasPrefPath(prefs::kHomePage));
- // Device management preference
- EXPECT_TRUE(pref_value_store_->HasPrefPath(
- prefs::kDefaultSearchProviderName));
- // Extension preference
- EXPECT_TRUE(pref_value_store_->HasPrefPath(prefs::kCurrentThemeID));
- // User preference
- EXPECT_TRUE(pref_value_store_->HasPrefPath(prefs::kDeleteCache));
- // Recommended preference
- EXPECT_TRUE(pref_value_store_->HasPrefPath(prefs::kRecommendedPref));
- // Default preference
- EXPECT_FALSE(pref_value_store_->HasPrefPath(prefs::kDefaultPref));
- // Unknown preference
- EXPECT_FALSE(pref_value_store_->HasPrefPath(prefs::kMissingPref));
-}
-
TEST_F(PrefValueStoreTest, PrefChanges) {
// Setup.
EXPECT_CALL(pref_notifier_, OnPreferenceChanged(_)).Times(AnyNumber());
const char managed_platform_pref_path[] = "managed_platform_pref";
- pref_value_store_->RegisterPreferenceType(managed_platform_pref_path,
- Value::TYPE_STRING);
managed_platform_pref_store_->SetString(managed_platform_pref_path,
"managed value");
const char user_pref_path[] = "user_pref";
- pref_value_store_->RegisterPreferenceType(user_pref_path, Value::TYPE_STRING);
user_pref_store_->SetString(user_pref_path, "user value");
const char default_pref_path[] = "default_pref";
- pref_value_store_->RegisterPreferenceType(default_pref_path,
- Value::TYPE_STRING);
default_pref_store_->SetString(default_pref_path, "default value");
Mock::VerifyAndClearExpectations(&pref_notifier_);
@@ -425,99 +347,81 @@ TEST_F(PrefValueStoreTest, OnInitializationCompleted) {
TEST_F(PrefValueStoreTest, PrefValueInManagedPlatformStore) {
// Test a managed platform preference.
- ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kHomePage));
EXPECT_TRUE(pref_value_store_->PrefValueInManagedPlatformStore(
prefs::kHomePage));
// Test a device management preference.
- ASSERT_TRUE(pref_value_store_->HasPrefPath(
- prefs::kDefaultSearchProviderName));
EXPECT_TRUE(pref_value_store_->PrefValueInDeviceManagementStore(
prefs::kDefaultSearchProviderName));
// Test an extension preference.
- ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kCurrentThemeID));
EXPECT_FALSE(pref_value_store_->PrefValueInManagedPlatformStore(
prefs::kCurrentThemeID));
// Test a command-line preference.
- ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kApplicationLocale));
EXPECT_FALSE(pref_value_store_->PrefValueInManagedPlatformStore(
prefs::kApplicationLocale));
// Test a user preference.
- ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kStabilityLaunchCount));
EXPECT_FALSE(pref_value_store_->PrefValueInManagedPlatformStore(
prefs::kStabilityLaunchCount));
// Test a preference from the recommended pref store.
- ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kRecommendedPref));
EXPECT_FALSE(pref_value_store_->PrefValueInManagedPlatformStore(
prefs::kRecommendedPref));
// Test a preference from the default pref store.
- ASSERT_FALSE(pref_value_store_->HasPrefPath(prefs::kDefaultPref));
EXPECT_FALSE(pref_value_store_->PrefValueInManagedPlatformStore(
prefs::kDefaultPref));
// Test a preference for which the PrefValueStore does not contain a value.
- ASSERT_FALSE(pref_value_store_->HasPrefPath(prefs::kMissingPref));
EXPECT_FALSE(pref_value_store_->PrefValueInManagedPlatformStore(
prefs::kMissingPref));
}
TEST_F(PrefValueStoreTest, PrefValueInExtensionStore) {
// Test a managed platform preference.
- ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kHomePage));
EXPECT_TRUE(pref_value_store_->PrefValueInExtensionStore(prefs::kHomePage));
EXPECT_FALSE(pref_value_store_->PrefValueFromExtensionStore(
prefs::kHomePage));
// Test a device management preference.
- ASSERT_TRUE(pref_value_store_->HasPrefPath(
- prefs::kDefaultSearchProviderName));
EXPECT_TRUE(pref_value_store_->PrefValueInExtensionStore(
prefs::kDefaultSearchProviderName));
EXPECT_FALSE(pref_value_store_->PrefValueFromExtensionStore(
prefs::kDefaultSearchProviderName));
// Test an extension preference.
- ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kCurrentThemeID));
EXPECT_TRUE(pref_value_store_->PrefValueInExtensionStore(
prefs::kCurrentThemeID));
EXPECT_TRUE(pref_value_store_->PrefValueFromExtensionStore(
prefs::kCurrentThemeID));
// Test a command-line preference.
- ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kApplicationLocale));
EXPECT_FALSE(pref_value_store_->PrefValueInExtensionStore(
prefs::kApplicationLocale));
EXPECT_FALSE(pref_value_store_->PrefValueFromExtensionStore(
prefs::kApplicationLocale));
// Test a user preference.
- ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kStabilityLaunchCount));
EXPECT_FALSE(pref_value_store_->PrefValueInExtensionStore(
prefs::kStabilityLaunchCount));
EXPECT_FALSE(pref_value_store_->PrefValueFromExtensionStore(
prefs::kStabilityLaunchCount));
// Test a preference from the recommended pref store.
- ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kRecommendedPref));
EXPECT_FALSE(pref_value_store_->PrefValueInExtensionStore(
prefs::kRecommendedPref));
EXPECT_FALSE(pref_value_store_->PrefValueFromExtensionStore(
prefs::kRecommendedPref));
// Test a preference from the default pref store.
- ASSERT_FALSE(pref_value_store_->HasPrefPath(prefs::kDefaultPref));
EXPECT_FALSE(pref_value_store_->PrefValueInExtensionStore(
prefs::kDefaultPref));
EXPECT_FALSE(pref_value_store_->PrefValueFromExtensionStore(
prefs::kDefaultPref));
// Test a preference for which the PrefValueStore does not contain a value.
- ASSERT_FALSE(pref_value_store_->HasPrefPath(prefs::kMissingPref));
EXPECT_FALSE(pref_value_store_->PrefValueInExtensionStore(
prefs::kMissingPref));
EXPECT_FALSE(pref_value_store_->PrefValueFromExtensionStore(
@@ -526,95 +430,77 @@ TEST_F(PrefValueStoreTest, PrefValueInExtensionStore) {
TEST_F(PrefValueStoreTest, PrefValueInUserStore) {
// Test a managed platform preference.
- ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kHomePage));
EXPECT_TRUE(pref_value_store_->PrefValueInUserStore(prefs::kHomePage));
EXPECT_FALSE(pref_value_store_->PrefValueFromUserStore(prefs::kHomePage));
// Test a device management preference.
- ASSERT_TRUE(pref_value_store_->HasPrefPath(
- prefs::kDefaultSearchProviderName));
EXPECT_TRUE(pref_value_store_->PrefValueInUserStore(
prefs::kDefaultSearchProviderName));
EXPECT_FALSE(pref_value_store_->PrefValueFromUserStore(
prefs::kDefaultSearchProviderName));
// Test an extension preference.
- ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kCurrentThemeID));
EXPECT_TRUE(pref_value_store_->PrefValueInUserStore(
prefs::kCurrentThemeID));
EXPECT_FALSE(pref_value_store_->PrefValueFromUserStore(
prefs::kCurrentThemeID));
// Test a command-line preference.
- ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kApplicationLocale));
EXPECT_TRUE(pref_value_store_->PrefValueInUserStore(
prefs::kApplicationLocale));
EXPECT_FALSE(pref_value_store_->PrefValueFromUserStore(
prefs::kApplicationLocale));
// Test a user preference.
- ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kStabilityLaunchCount));
EXPECT_TRUE(pref_value_store_->PrefValueInUserStore(
prefs::kStabilityLaunchCount));
EXPECT_TRUE(pref_value_store_->PrefValueFromUserStore(
prefs::kStabilityLaunchCount));
// Test a preference from the recommended pref store.
- ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kRecommendedPref));
EXPECT_FALSE(pref_value_store_->PrefValueInUserStore(
prefs::kRecommendedPref));
EXPECT_FALSE(pref_value_store_->PrefValueFromUserStore(
prefs::kRecommendedPref));
// Test a preference from the default pref store.
- ASSERT_FALSE(pref_value_store_->HasPrefPath(prefs::kDefaultPref));
EXPECT_FALSE(pref_value_store_->PrefValueInUserStore(prefs::kDefaultPref));
EXPECT_FALSE(pref_value_store_->PrefValueFromUserStore(prefs::kDefaultPref));
// Test a preference for which the PrefValueStore does not contain a value.
- ASSERT_FALSE(pref_value_store_->HasPrefPath(prefs::kMissingPref));
EXPECT_FALSE(pref_value_store_->PrefValueInUserStore(prefs::kMissingPref));
EXPECT_FALSE(pref_value_store_->PrefValueFromUserStore(prefs::kMissingPref));
}
TEST_F(PrefValueStoreTest, PrefValueFromDefaultStore) {
// Test a managed platform preference.
- ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kHomePage));
EXPECT_FALSE(pref_value_store_->PrefValueFromDefaultStore(prefs::kHomePage));
// Test a device management preference.
- ASSERT_TRUE(pref_value_store_->HasPrefPath(
- prefs::kDefaultSearchProviderName));
EXPECT_FALSE(pref_value_store_->PrefValueFromDefaultStore(
prefs::kDefaultSearchProviderName));
// Test an extension preference.
- ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kCurrentThemeID));
EXPECT_FALSE(pref_value_store_->PrefValueFromDefaultStore(
prefs::kCurrentThemeID));
// Test a command-line preference.
- ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kApplicationLocale));
EXPECT_FALSE(pref_value_store_->PrefValueFromDefaultStore(
prefs::kApplicationLocale));
// Test a user preference.
- ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kStabilityLaunchCount));
EXPECT_FALSE(pref_value_store_->PrefValueFromDefaultStore(
prefs::kStabilityLaunchCount));
// Test a preference from the recommended pref store.
- ASSERT_TRUE(pref_value_store_->HasPrefPath(prefs::kRecommendedPref));
EXPECT_FALSE(pref_value_store_->PrefValueFromDefaultStore(
prefs::kRecommendedPref));
// Test a preference from the default pref store.
- ASSERT_FALSE(pref_value_store_->HasPrefPath(prefs::kDefaultPref));
EXPECT_TRUE(
pref_value_store_->PrefValueFromDefaultStore(prefs::kDefaultPref));
// Test a preference for which the PrefValueStore does not contain a value.
- ASSERT_FALSE(pref_value_store_->HasPrefPath(prefs::kMissingPref));
EXPECT_FALSE(
pref_value_store_->PrefValueFromDefaultStore(prefs::kMissingPref));
}
diff --git a/chrome/browser/profiles/profile.cc b/chrome/browser/profiles/profile.cc
index 488ca6e..0f5653f 100644
--- a/chrome/browser/profiles/profile.cc
+++ b/chrome/browser/profiles/profile.cc
@@ -19,10 +19,12 @@
#include "chrome/browser/chrome_blob_storage_context.h"
#include "chrome/browser/download/download_manager.h"
#include "chrome/browser/extensions/extension_message_service.h"
+#include "chrome/browser/extensions/extension_pref_store.h"
#include "chrome/browser/extensions/extension_process_manager.h"
#include "chrome/browser/file_system/browser_file_system_helper.h"
#include "chrome/browser/in_process_webkit/webkit_context.h"
#include "chrome/browser/net/chrome_url_request_context.h"
+#include "chrome/browser/net/pref_proxy_config_service.h"
#include "chrome/browser/notifications/desktop_notification_service.h"
#include "chrome/browser/ssl/ssl_host_state.h"
#include "chrome/browser/sync/profile_sync_service.h"
@@ -139,6 +141,9 @@ class OffTheRecordProfileImpl : public Profile,
explicit OffTheRecordProfileImpl(Profile* real_profile)
: profile_(real_profile),
start_time_(Time::Now()) {
+ prefs_.reset(profile_->GetPrefs()->CreateIncognitoPrefService(
+ new ExtensionPrefStore(profile_->GetExtensionPrefValueMap(), true)));
+
request_context_ = ChromeURLRequestContextGetter::CreateOffTheRecord(this);
extension_process_manager_.reset(ExtensionProcessManager::Create(this));
@@ -163,6 +168,9 @@ class OffTheRecordProfileImpl : public Profile,
&webkit_database::DatabaseTracker::DeleteIncognitoDBDirectory));
BrowserList::RemoveObserver(this);
+
+ if (pref_proxy_config_tracker_)
+ pref_proxy_config_tracker_->DetachFromPrefService();
}
virtual ProfileId GetRuntimeId() {
@@ -314,7 +322,7 @@ class OffTheRecordProfileImpl : public Profile,
}
virtual PrefService* GetPrefs() {
- return profile_->GetPrefs();
+ return prefs_.get();
}
virtual TemplateURLModel* GetTemplateURLModel() {
@@ -612,7 +620,10 @@ class OffTheRecordProfileImpl : public Profile,
#endif // defined(OS_CHROMEOS)
virtual PrefProxyConfigTracker* GetProxyConfigTracker() {
- return profile_->GetProxyConfigTracker();
+ if (!pref_proxy_config_tracker_)
+ pref_proxy_config_tracker_ = new PrefProxyConfigTracker(GetPrefs());
+
+ return pref_proxy_config_tracker_;
}
virtual PrerenderManager* GetPrerenderManager() {
@@ -622,12 +633,19 @@ class OffTheRecordProfileImpl : public Profile,
return NULL;
}
+ protected:
+ virtual ExtensionPrefValueMap* GetExtensionPrefValueMap() {
+ return profile_->GetExtensionPrefValueMap();
+ }
+
private:
NotificationRegistrar registrar_;
// The real underlying profile.
Profile* profile_;
+ scoped_ptr<PrefService> prefs_;
+
scoped_ptr<ExtensionProcessManager> extension_process_manager_;
// The context to use for requests made from this OTR session.
@@ -683,6 +701,8 @@ class OffTheRecordProfileImpl : public Profile,
// The file_system context for this profile.
scoped_refptr<fileapi::SandboxedFileSystemContext> file_system_context_;
+ scoped_refptr<PrefProxyConfigTracker> pref_proxy_config_tracker_;
+
DISALLOW_COPY_AND_ASSIGN(OffTheRecordProfileImpl);
};
diff --git a/chrome/browser/profiles/profile.h b/chrome/browser/profiles/profile.h
index e13c0b3..1ec1760 100644
--- a/chrome/browser/profiles/profile.h
+++ b/chrome/browser/profiles/profile.h
@@ -59,6 +59,7 @@ class ExtensionDevToolsManager;
class ExtensionEventRouter;
class ExtensionInfoMap;
class ExtensionMessageService;
+class ExtensionPrefValueMap;
class ExtensionProcessManager;
class ExtensionService;
class FaviconService;
@@ -546,8 +547,12 @@ class Profile {
Profile* CreateOffTheRecordProfile();
protected:
+ friend class OffTheRecordProfileImpl;
+
static URLRequestContextGetter* default_request_context_;
+ virtual ExtensionPrefValueMap* GetExtensionPrefValueMap() = 0;
+
private:
bool restored_last_session_;
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc
index e0d3429..229d377 100644
--- a/chrome/browser/profiles/profile_impl.cc
+++ b/chrome/browser/profiles/profile_impl.cc
@@ -683,10 +683,10 @@ net::TransportSecurityState*
PrefService* ProfileImpl::GetPrefs() {
if (!prefs_.get()) {
- ExtensionPrefStore* extension_pref_store = new ExtensionPrefStore;
- prefs_.reset(PrefService::CreatePrefService(GetPrefFilePath(),
- extension_pref_store,
- GetOriginalProfile()));
+ prefs_.reset(PrefService::CreatePrefService(
+ GetPrefFilePath(),
+ new ExtensionPrefStore(GetExtensionPrefValueMap(), false),
+ GetOriginalProfile()));
// The Profile class and ProfileManager class may read some prefs so
// register known prefs as soon as possible.
@@ -707,7 +707,7 @@ PrefService* ProfileImpl::GetPrefs() {
extension_prefs_.reset(new ExtensionPrefs(
prefs_.get(),
GetPath().AppendASCII(ExtensionService::kInstallDirectoryName),
- extension_pref_store));
+ GetExtensionPrefValueMap()));
DCHECK(!net_pref_observer_.get());
net_pref_observer_.reset(new NetPrefObserver(prefs_.get()));
@@ -1196,6 +1196,12 @@ void ProfileImpl::SpellCheckHostInitialized() {
Source<Profile>(this), NotificationService::NoDetails());
}
+ExtensionPrefValueMap* ProfileImpl::GetExtensionPrefValueMap() {
+ if (!extension_pref_value_map_.get())
+ extension_pref_value_map_.reset(new ExtensionPrefValueMap);
+ return extension_pref_value_map_.get();
+}
+
WebKitContext* ProfileImpl::GetWebKitContext() {
if (!webkit_context_.get())
webkit_context_ = new WebKitContext(this, clear_local_state_on_exit_);
diff --git a/chrome/browser/profiles/profile_impl.h b/chrome/browser/profiles/profile_impl.h
index 3f9e53c..bb65c8d 100644
--- a/chrome/browser/profiles/profile_impl.h
+++ b/chrome/browser/profiles/profile_impl.h
@@ -20,6 +20,7 @@
class BackgroundModeManager;
class ExtensionPrefs;
+class ExtensionPrefValueMap;
class PrefService;
#if defined(OS_CHROMEOS)
@@ -146,6 +147,9 @@ class ProfileImpl : public Profile,
// SpellCheckHostObserver implementation.
virtual void SpellCheckHostInitialized();
+ protected:
+ virtual ExtensionPrefValueMap* GetExtensionPrefValueMap();
+
private:
friend class Profile;
@@ -174,6 +178,7 @@ class ProfileImpl : public Profile,
FilePath path_;
FilePath base_cache_path_;
+ scoped_ptr<ExtensionPrefValueMap> extension_pref_value_map_;
// Keep prefs_ on top for destruction order because extension_prefs_,
// net_pref_observer_, web_resource_service_ and background_contents_service_
// store pointers to prefs_ and shall be destructed first.
diff --git a/chrome/browser/sync/glue/preference_model_associator_unittest.cc b/chrome/browser/sync/glue/preference_model_associator_unittest.cc
index b3dca08..394720a 100644
--- a/chrome/browser/sync/glue/preference_model_associator_unittest.cc
+++ b/chrome/browser/sync/glue/preference_model_associator_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -34,11 +34,6 @@ class AbstractPreferenceMergeTest : public testing::Test {
Value::CreateIntegerValue(setting));
}
- void SetPrefToNull(const std::string& pref_name) {
- scoped_ptr<Value> null_value(Value::CreateNullValue());
- pref_service_->Set(pref_name.c_str(), *null_value);
- }
-
void SetPrefToEmpty(const std::string& pref_name) {
scoped_ptr<Value> empty_value;
const PrefService::Preference* pref =
@@ -89,15 +84,6 @@ TEST_F(ListPreferenceMergeTest, NotListOrDictionary) {
EXPECT_TRUE(merged_value->Equals(server_value.get()));
}
-TEST_F(ListPreferenceMergeTest, LocalNull) {
- SetPrefToNull(prefs::kURLsToRestoreOnStartup);
- const PrefService::Preference* pref =
- pref_service_->FindPreference(prefs::kURLsToRestoreOnStartup);
- scoped_ptr<Value> merged_value(
- PreferenceModelAssociator::MergePreference(*pref, server_url_list_));
- EXPECT_TRUE(merged_value->Equals(&server_url_list_));
-}
-
TEST_F(ListPreferenceMergeTest, LocalEmpty) {
SetPrefToEmpty(prefs::kURLsToRestoreOnStartup);
const PrefService::Preference* pref =
@@ -133,16 +119,6 @@ TEST_F(ListPreferenceMergeTest, ServerEmpty) {
EXPECT_TRUE(merged_value->Equals(local_list_value));
}
-TEST_F(ListPreferenceMergeTest, BothNull) {
- SetPrefToNull(prefs::kURLsToRestoreOnStartup);
- scoped_ptr<Value> null_value(Value::CreateNullValue());
- const PrefService::Preference* pref =
- pref_service_->FindPreference(prefs::kURLsToRestoreOnStartup);
- scoped_ptr<Value> merged_value(
- PreferenceModelAssociator::MergePreference(*pref, *null_value));
- EXPECT_TRUE(merged_value->Equals(null_value.get()));
-}
-
TEST_F(ListPreferenceMergeTest, Merge) {
ListValue* local_list_value =
pref_service_->GetMutableList(prefs::kURLsToRestoreOnStartup);
@@ -219,15 +195,6 @@ class DictionaryPreferenceMergeTest : public AbstractPreferenceMergeTest {
DictionaryValue server_patterns_;
};
-TEST_F(DictionaryPreferenceMergeTest, LocalNull) {
- SetPrefToNull(prefs::kContentSettingsPatterns);
- const PrefService::Preference* pref =
- pref_service_->FindPreference(prefs::kURLsToRestoreOnStartup);
- scoped_ptr<Value> merged_value(
- PreferenceModelAssociator::MergePreference(*pref, server_patterns_));
- EXPECT_TRUE(merged_value->Equals(&server_patterns_));
-}
-
TEST_F(DictionaryPreferenceMergeTest, LocalEmpty) {
SetPrefToEmpty(prefs::kContentSettingsPatterns);
const PrefService::Preference* pref =
@@ -263,16 +230,6 @@ TEST_F(DictionaryPreferenceMergeTest, ServerEmpty) {
EXPECT_TRUE(merged_value->Equals(local_dict_value));
}
-TEST_F(DictionaryPreferenceMergeTest, BothNull) {
- scoped_ptr<Value> null_value(Value::CreateNullValue());
- SetPrefToNull(prefs::kContentSettingsPatterns);
- const PrefService::Preference* pref =
- pref_service_->FindPreference(prefs::kContentSettingsPatterns);
- scoped_ptr<Value> merged_value(
- PreferenceModelAssociator::MergePreference(*pref, *null_value));
- EXPECT_TRUE(merged_value->Equals(null_value.get()));
-}
-
TEST_F(DictionaryPreferenceMergeTest, MergeNoConflicts) {
DictionaryValue* local_dict_value =
pref_service_->GetMutableDictionary(prefs::kContentSettingsPatterns);
diff --git a/chrome/browser/translate/translate_manager.cc b/chrome/browser/translate/translate_manager.cc
index 16895b9..a07a52a 100644
--- a/chrome/browser/translate/translate_manager.cc
+++ b/chrome/browser/translate/translate_manager.cc
@@ -355,7 +355,7 @@ TranslateManager::TranslateManager()
void TranslateManager::InitiateTranslation(TabContents* tab,
const std::string& page_lang) {
- PrefService* prefs = tab->profile()->GetPrefs();
+ PrefService* prefs = tab->profile()->GetOriginalProfile()->GetPrefs();
if (!prefs->GetBoolean(prefs::kEnableTranslate))
return;
@@ -548,7 +548,7 @@ void TranslateManager::PageTranslated(TabContents* tab,
bool TranslateManager::IsAcceptLanguage(TabContents* tab,
const std::string& language) {
- PrefService* pref_service = tab->profile()->GetPrefs();
+ PrefService* pref_service = tab->profile()->GetOriginalProfile()->GetPrefs();
PrefServiceLanguagesMap::const_iterator iter =
accept_languages_.find(pref_service);
if (iter == accept_languages_.end()) {
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc
index 7352f92..b6aa9fc 100644
--- a/chrome/browser/ui/browser.cc
+++ b/chrome/browser/ui/browser.cc
@@ -285,6 +285,12 @@ Browser::~Browser() {
if (tab_restore_service)
tab_restore_service->BrowserClosed(this);
+ encoding_auto_detect_.Destroy();
+ printing_enabled_.Destroy();
+ dev_tools_disabled_.Destroy();
+ instant_enabled_.Destroy();
+ use_vertical_tabs_.Destroy();
+
if (profile_->IsOffTheRecord() &&
!BrowserList::IsOffTheRecordSessionActive()) {
// An off-the-record profile is no longer needed, this indirectly
diff --git a/chrome/browser/ui/cocoa/browser_window_controller_unittest.mm b/chrome/browser/ui/cocoa/browser_window_controller_unittest.mm
index e0a9edd..497967b 100644
--- a/chrome/browser/ui/cocoa/browser_window_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/browser_window_controller_unittest.mm
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -85,14 +85,20 @@ TEST_F(BrowserWindowControllerTest, TestSaveWindowPosition) {
ASSERT_TRUE(prefs != NULL);
// Check to make sure there is no existing pref for window placement.
- ASSERT_TRUE(prefs->GetDictionary(prefs::kBrowserWindowPlacement) == NULL);
+ const DictionaryValue* browser_window_placement =
+ prefs->GetDictionary(prefs::kBrowserWindowPlacement);
+ ASSERT_TRUE(browser_window_placement);
+ EXPECT_TRUE(browser_window_placement->empty());
// Ask the window to save its position, then check that a preference
// exists. We're technically passing in a pointer to the user prefs
// and not the local state prefs, but a PrefService* is a
// PrefService*, and this is a unittest.
[controller_ saveWindowPositionToPrefs:prefs];
- EXPECT_TRUE(prefs->GetDictionary(prefs::kBrowserWindowPlacement) != NULL);
+ browser_window_placement =
+ prefs->GetDictionary(prefs::kBrowserWindowPlacement);
+ ASSERT_TRUE(browser_window_placement);
+ EXPECT_FALSE(browser_window_placement->empty());
}
TEST_F(BrowserWindowControllerTest, TestFullScreenWindow) {
diff --git a/chrome/browser/ui/cocoa/extensions/extension_action_context_menu.h b/chrome/browser/ui/cocoa/extensions/extension_action_context_menu.h
index e40388f..9af03e1 100644
--- a/chrome/browser/ui/cocoa/extensions/extension_action_context_menu.h
+++ b/chrome/browser/ui/cocoa/extensions/extension_action_context_menu.h
@@ -21,6 +21,7 @@ class Profile;
namespace extension_action_context_menu {
class DevmodeObserver;
+class ProfileObserverBridge;
} // namespace extension_action_context_menu
@@ -42,6 +43,10 @@ class DevmodeObserver;
// The observer used to listen for pref changed notifications.
scoped_ptr<extension_action_context_menu::DevmodeObserver> observer_;
+ // The observer used to reset |observer_| when the profile is destroyed.
+ scoped_ptr<extension_action_context_menu::ProfileObserverBridge>
+ profile_observer_;
+
// Used to load the extension icon asynchronously on the I/O thread then show
// the uninstall confirmation dialog.
scoped_ptr<AsyncUninstaller> uninstaller_;
@@ -55,6 +60,10 @@ class DevmodeObserver;
// Show or hide the inspector menu item.
- (void)updateInspectorItem;
+// Notifies the ExtensionActionContextMenu that the profile is is being
+// destroyed.
+- (void)invalidateProfile;
+
@end
typedef ExtensionActionContextMenu ExtensionActionContextMenuMac;
diff --git a/chrome/browser/ui/cocoa/extensions/extension_action_context_menu.mm b/chrome/browser/ui/cocoa/extensions/extension_action_context_menu.mm
index 705276e..b8475ea 100644
--- a/chrome/browser/ui/cocoa/extensions/extension_action_context_menu.mm
+++ b/chrome/browser/ui/cocoa/extensions/extension_action_context_menu.mm
@@ -25,6 +25,7 @@
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/notification_details.h"
#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_source.h"
#include "chrome/common/notification_type.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
@@ -92,6 +93,34 @@ class DevmodeObserver : public NotificationObserver {
PrefChangeRegistrar registrar_;
};
+class ProfileObserverBridge : public NotificationObserver {
+ public:
+ ProfileObserverBridge(ExtensionActionContextMenu* owner,
+ const Profile* profile)
+ : owner_(owner),
+ profile_(profile) {
+ registrar_.Add(this, NotificationType::PROFILE_DESTROYED,
+ Source<Profile>(profile));
+ }
+
+ ~ProfileObserverBridge() {}
+
+ // Overridden from NotificationObserver
+ void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ if (type == NotificationType::PROFILE_DESTROYED &&
+ source == Source<Profile>(profile_)) {
+ [owner_ invalidateProfile];
+ }
+ }
+
+ private:
+ ExtensionActionContextMenu* owner_;
+ const Profile* profile_;
+ NotificationRegistrar registrar_;
+};
+
} // namespace extension_action_context_menu
@interface ExtensionActionContextMenu(Private)
@@ -177,6 +206,9 @@ int CurrentTabId() {
PrefService* service = profile_->GetPrefs();
observer_.reset(
new extension_action_context_menu::DevmodeObserver(self, service));
+ profile_observer_.reset(
+ new extension_action_context_menu::ProfileObserverBridge(self,
+ profile));
[self updateInspectorItem];
return self;
@@ -275,4 +307,9 @@ int CurrentTabId() {
return YES;
}
+- (void)invalidateProfile {
+ observer_.reset();
+ profile_ = NULL;
+}
+
@end
diff --git a/chrome/browser/ui/cocoa/extensions/extension_popup_controller_unittest.mm b/chrome/browser/ui/cocoa/extensions/extension_popup_controller_unittest.mm
index 992dd2c..a0b5614 100644
--- a/chrome/browser/ui/cocoa/extensions/extension_popup_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/extensions/extension_popup_controller_unittest.mm
@@ -1,10 +1,10 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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 "base/message_loop.h"
#include "base/scoped_nsobject.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/extensions/extension_process_manager.h"
#include "chrome/browser/extensions/extension_service.h"
@@ -28,10 +28,10 @@ class ExtensionTestingProfile : public TestingProfile {
DCHECK(!GetExtensionService());
manager_.reset(ExtensionProcessManager::Create(this));
- ExtensionPrefStore* pref_store = new ExtensionPrefStore;
+ extension_pref_value_map_.reset(new ExtensionPrefValueMap);
extension_prefs_.reset(new ExtensionPrefs(GetPrefs(),
GetExtensionsInstallDir(),
- pref_store));
+ extension_pref_value_map_.get()));
service_ = new ExtensionService(this,
CommandLine::ForCurrentProcess(),
GetExtensionsInstallDir(),
@@ -61,6 +61,7 @@ class ExtensionTestingProfile : public TestingProfile {
scoped_ptr<ExtensionProcessManager> manager_;
scoped_ptr<ExtensionPrefs> extension_prefs_;
scoped_refptr<ExtensionService> service_;
+ scoped_ptr<ExtensionPrefValueMap> extension_pref_value_map_;
DISALLOW_COPY_AND_ASSIGN(ExtensionTestingProfile);
};
diff --git a/chrome/browser/ui/cocoa/window_size_autosaver_unittest.mm b/chrome/browser/ui/cocoa/window_size_autosaver_unittest.mm
index c3b33ed..3b95440 100644
--- a/chrome/browser/ui/cocoa/window_size_autosaver_unittest.mm
+++ b/chrome/browser/ui/cocoa/window_size_autosaver_unittest.mm
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -44,7 +44,9 @@ TEST_F(WindowSizeAutosaverTest, RestoresAndSavesPos) {
ASSERT_TRUE(pref != NULL);
// Check to make sure there is no existing pref for window placement.
- ASSERT_TRUE(pref->GetDictionary(path_) == NULL);
+ const DictionaryValue* placement = pref->GetDictionary(path_);
+ ASSERT_TRUE(placement);
+ EXPECT_TRUE(placement->empty());
// Replace the window with one that doesn't have resize controls.
[window_ close];
@@ -109,7 +111,9 @@ TEST_F(WindowSizeAutosaverTest, RestoresAndSavesRect) {
ASSERT_TRUE(pref != NULL);
// Check to make sure there is no existing pref for window placement.
- ASSERT_TRUE(pref->GetDictionary(path_) == NULL);
+ const DictionaryValue* placement = pref->GetDictionary(path_);
+ ASSERT_TRUE(placement);
+ EXPECT_TRUE(placement->empty());
// Ask the window to save its position, then check that a preference
// exists. We're technically passing in a pointer to the user prefs
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index 484295b..06e23d4 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -480,6 +480,9 @@ BrowserView::~BrowserView() {
delete tabstrip_;
tabstrip_ = NULL;
+ // Child views maintain PrefMember attributes that point to
+ // OffTheRecordProfile's PrefService which gets deleted by ~Browser.
+ RemoveAllChildViews(true);
// Explicitly set browser_ to NULL.
browser_.reset();
}
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 4730e1f..904ea87 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1148,6 +1148,8 @@
'browser/extensions/extension_popup_api.h',
'browser/extensions/extension_pref_store.h',
'browser/extensions/extension_pref_store.cc',
+ 'browser/extensions/extension_pref_value_map.h',
+ 'browser/extensions/extension_pref_value_map.cc',
'browser/extensions/extension_prefs.cc',
'browser/extensions/extension_prefs.h',
'browser/extensions/extension_process_manager.cc',
@@ -2046,7 +2048,10 @@
'browser/prefs/browser_prefs.h',
'browser/prefs/command_line_pref_store.cc',
'browser/prefs/command_line_pref_store.h',
+ 'browser/prefs/default_pref_store.cc',
'browser/prefs/default_pref_store.h',
+ 'browser/prefs/overlay_persistent_pref_store.cc',
+ 'browser/prefs/overlay_persistent_pref_store.h',
'browser/prefs/pref_member.cc',
'browser/prefs/pref_member.h',
'browser/prefs/pref_notifier.h',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 0803406..a4a36d4 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1162,6 +1162,7 @@
'browser/extensions/extension_icon_manager_unittest.cc',
'browser/extensions/extension_info_map_unittest.cc',
'browser/extensions/extension_menu_manager_unittest.cc',
+ 'browser/extensions/extension_pref_value_map_unittest.cc',
'browser/extensions/extension_prefs_unittest.cc',
'browser/extensions/extension_process_manager_unittest.cc',
'browser/extensions/extension_omnibox_unittest.cc',
@@ -1306,6 +1307,7 @@
'browser/preferences_mock_mac.cc',
'browser/preferences_mock_mac.h',
'browser/prefs/command_line_pref_store_unittest.cc',
+ 'browser/prefs/overlay_persistent_pref_store_unittest.cc',
'browser/prefs/pref_change_registrar_unittest.cc',
'browser/prefs/pref_member_unittest.cc',
'browser/prefs/pref_notifier_impl_unittest.cc',
diff --git a/chrome/common/json_pref_store_unittest.cc b/chrome/common/json_pref_store_unittest.cc
index 2d1e1df..1b98aa9 100644
--- a/chrome/common/json_pref_store_unittest.cc
+++ b/chrome/common/json_pref_store_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -6,6 +6,7 @@
#include "base/message_loop.h"
#include "base/message_loop_proxy.h"
#include "base/path_service.h"
+#include "base/ref_counted.h"
#include "base/scoped_ptr.h"
#include "base/string_number_conversions.h"
#include "base/string_util.h"
@@ -53,10 +54,11 @@ class JsonPrefStoreTest : public testing::Test {
TEST_F(JsonPrefStoreTest, NonExistentFile) {
FilePath bogus_input_file = data_dir_.AppendASCII("read.txt");
ASSERT_FALSE(file_util::PathExists(bogus_input_file));
- JsonPrefStore pref_store(bogus_input_file, message_loop_proxy_.get());
+ scoped_refptr<JsonPrefStore> pref_store =
+ new JsonPrefStore(bogus_input_file, message_loop_proxy_.get());
EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
- pref_store.ReadPrefs());
- EXPECT_FALSE(pref_store.ReadOnly());
+ pref_store->ReadPrefs());
+ EXPECT_FALSE(pref_store->ReadOnly());
}
// Test fallback behavior for an invalid file.
@@ -64,10 +66,11 @@ TEST_F(JsonPrefStoreTest, InvalidFile) {
FilePath invalid_file_original = data_dir_.AppendASCII("invalid.json");
FilePath invalid_file = test_dir_.AppendASCII("invalid.json");
ASSERT_TRUE(file_util::CopyFile(invalid_file_original, invalid_file));
- JsonPrefStore pref_store(invalid_file, message_loop_proxy_.get());
+ scoped_refptr<JsonPrefStore> pref_store =
+ new JsonPrefStore(invalid_file, message_loop_proxy_.get());
EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_JSON_PARSE,
- pref_store.ReadPrefs());
- EXPECT_FALSE(pref_store.ReadOnly());
+ pref_store->ReadPrefs());
+ EXPECT_FALSE(pref_store->ReadOnly());
// The file should have been moved aside.
EXPECT_FALSE(file_util::PathExists(invalid_file));
@@ -84,9 +87,10 @@ TEST_F(JsonPrefStoreTest, Basic) {
// Test that the persistent value can be loaded.
FilePath input_file = test_dir_.AppendASCII("write.json");
ASSERT_TRUE(file_util::PathExists(input_file));
- JsonPrefStore pref_store(input_file, message_loop_proxy_.get());
- ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store.ReadPrefs());
- ASSERT_FALSE(pref_store.ReadOnly());
+ scoped_refptr<JsonPrefStore> pref_store =
+ new JsonPrefStore(input_file, message_loop_proxy_.get());
+ ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs());
+ ASSERT_FALSE(pref_store->ReadOnly());
// The JSON file looks like this:
// {
@@ -106,52 +110,52 @@ TEST_F(JsonPrefStoreTest, Basic) {
Value* actual;
EXPECT_EQ(PrefStore::READ_OK,
- pref_store.GetValue(prefs::kHomePage, &actual));
+ pref_store->GetValue(prefs::kHomePage, &actual));
std::string string_value;
EXPECT_TRUE(actual->GetAsString(&string_value));
EXPECT_EQ(cnn, string_value);
const char kSomeDirectory[] = "some_directory";
- EXPECT_EQ(PrefStore::READ_OK, pref_store.GetValue(kSomeDirectory, &actual));
+ EXPECT_EQ(PrefStore::READ_OK, pref_store->GetValue(kSomeDirectory, &actual));
FilePath::StringType path;
EXPECT_TRUE(actual->GetAsString(&path));
EXPECT_EQ(FilePath::StringType(FILE_PATH_LITERAL("/usr/local/")), path);
FilePath some_path(FILE_PATH_LITERAL("/usr/sbin/"));
- pref_store.SetValue(kSomeDirectory,
- Value::CreateStringValue(some_path.value()));
- EXPECT_EQ(PrefStore::READ_OK, pref_store.GetValue(kSomeDirectory, &actual));
+ pref_store->SetValue(kSomeDirectory,
+ Value::CreateStringValue(some_path.value()));
+ EXPECT_EQ(PrefStore::READ_OK, pref_store->GetValue(kSomeDirectory, &actual));
EXPECT_TRUE(actual->GetAsString(&path));
EXPECT_EQ(some_path.value(), path);
// Test reading some other data types from sub-dictionaries.
EXPECT_EQ(PrefStore::READ_OK,
- pref_store.GetValue(kNewWindowsInTabs, &actual));
+ pref_store->GetValue(kNewWindowsInTabs, &actual));
bool boolean = false;
EXPECT_TRUE(actual->GetAsBoolean(&boolean));
EXPECT_TRUE(boolean);
- pref_store.SetValue(kNewWindowsInTabs,
+ pref_store->SetValue(kNewWindowsInTabs,
Value::CreateBooleanValue(false));
EXPECT_EQ(PrefStore::READ_OK,
- pref_store.GetValue(kNewWindowsInTabs, &actual));
+ pref_store->GetValue(kNewWindowsInTabs, &actual));
EXPECT_TRUE(actual->GetAsBoolean(&boolean));
EXPECT_FALSE(boolean);
- EXPECT_EQ(PrefStore::READ_OK, pref_store.GetValue(kMaxTabs, &actual));
+ EXPECT_EQ(PrefStore::READ_OK, pref_store->GetValue(kMaxTabs, &actual));
int integer = 0;
EXPECT_TRUE(actual->GetAsInteger(&integer));
EXPECT_EQ(20, integer);
- pref_store.SetValue(kMaxTabs, Value::CreateIntegerValue(10));
- EXPECT_EQ(PrefStore::READ_OK, pref_store.GetValue(kMaxTabs, &actual));
+ pref_store->SetValue(kMaxTabs, Value::CreateIntegerValue(10));
+ EXPECT_EQ(PrefStore::READ_OK, pref_store->GetValue(kMaxTabs, &actual));
EXPECT_TRUE(actual->GetAsInteger(&integer));
EXPECT_EQ(10, integer);
- pref_store.SetValue(kLongIntPref,
+ pref_store->SetValue(kLongIntPref,
Value::CreateStringValue(
base::Int64ToString(214748364842LL)));
- EXPECT_EQ(PrefStore::READ_OK, pref_store.GetValue(kLongIntPref, &actual));
+ EXPECT_EQ(PrefStore::READ_OK, pref_store->GetValue(kLongIntPref, &actual));
EXPECT_TRUE(actual->GetAsString(&string_value));
int64 value;
base::StringToInt64(string_value, &value);
@@ -161,7 +165,7 @@ TEST_F(JsonPrefStoreTest, Basic) {
FilePath output_file = input_file;
FilePath golden_output_file = data_dir_.AppendASCII("write.golden.json");
ASSERT_TRUE(file_util::PathExists(golden_output_file));
- ASSERT_TRUE(pref_store.WritePrefs());
+ ASSERT_TRUE(pref_store->WritePrefs());
MessageLoop::current()->RunAllPending();
EXPECT_TRUE(file_util::TextContentsEqual(golden_output_file, output_file));
ASSERT_TRUE(file_util::Delete(output_file, false));
diff --git a/chrome/common/persistent_pref_store.h b/chrome/common/persistent_pref_store.h
index 9e2fb0a..e0eb8dc 100644
--- a/chrome/common/persistent_pref_store.h
+++ b/chrome/common/persistent_pref_store.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -11,7 +11,7 @@
#include <chrome/common/pref_store.h>
// This interface is complementary to the PrefStore interface, declaring
-// additional functionatliy that adds support for setting values and persisting
+// additional functionality that adds support for setting values and persisting
// the data to some backing store.
class PersistentPrefStore : public PrefStore {
public:
diff --git a/chrome/common/pref_store.h b/chrome/common/pref_store.h
index 35818a0..819a764 100644
--- a/chrome/common/pref_store.h
+++ b/chrome/common/pref_store.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -9,6 +9,7 @@
#include <string>
#include "base/basictypes.h"
+#include "base/ref_counted.h"
class Value;
@@ -19,7 +20,7 @@ class Value;
// CommandLinePrefStore, which bridges command line options to preferences and
// ConfigurationPolicyPrefStore, which is used for hooking up configuration
// policy with the preference subsystem.
-class PrefStore {
+class PrefStore : public base::RefCounted<PrefStore> {
public:
// Observer interface for monitoring PrefStore.
class Observer {
@@ -43,7 +44,6 @@ class PrefStore {
};
PrefStore() {}
- virtual ~PrefStore() {}
// Add and remove observers.
virtual void AddObserver(Observer* observer) {}
@@ -57,6 +57,11 @@ class PrefStore {
// |result| value remains with the PrefStore.
virtual ReadResult GetValue(const std::string& key, Value** result) const = 0;
+ protected:
+ friend class base::RefCounted<PrefStore>;
+ virtual ~PrefStore() {}
+
+ private:
DISALLOW_COPY_AND_ASSIGN(PrefStore);
};
diff --git a/chrome/test/testing_pref_service.cc b/chrome/test/testing_pref_service.cc
index acb4be2..afcb1c5 100644
--- a/chrome/test/testing_pref_service.cc
+++ b/chrome/test/testing_pref_service.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -6,59 +6,76 @@
#include "chrome/browser/policy/configuration_policy_pref_store.h"
#include "chrome/browser/prefs/command_line_pref_store.h"
+#include "chrome/browser/prefs/default_pref_store.h"
#include "chrome/browser/prefs/pref_notifier.h"
#include "chrome/browser/prefs/pref_value_store.h"
#include "chrome/browser/prefs/testing_pref_store.h"
-// TODO(pamg): Instantiate no PrefStores by default. Allow callers to specify
-// which they want, and expand usage of this class to more unit tests.
-TestingPrefService::TestingPrefService()
- : PrefService(
- managed_platform_prefs_ = new TestingPrefStore(),
- device_management_prefs_ = new TestingPrefStore(),
- NULL,
- NULL,
- user_prefs_ = new TestingPrefStore(),
- NULL) {
+TestingPrefServiceBase::TestingPrefServiceBase(
+ TestingPrefStore* managed_platform_prefs,
+ TestingPrefStore* device_management_prefs,
+ TestingPrefStore* user_prefs)
+ : PrefService(managed_platform_prefs,
+ device_management_prefs,
+ NULL,
+ NULL,
+ user_prefs,
+ NULL,
+ new DefaultPrefStore()),
+ managed_platform_prefs_(managed_platform_prefs),
+ device_management_prefs_(device_management_prefs),
+ user_prefs_(user_prefs) {
+}
+
+TestingPrefServiceBase::~TestingPrefServiceBase() {
}
-const Value* TestingPrefService::GetManagedPref(const char* path) const {
+const Value* TestingPrefServiceBase::GetManagedPref(const char* path) const {
return GetPref(managed_platform_prefs_, path);
}
-void TestingPrefService::SetManagedPref(const char* path, Value* value) {
+void TestingPrefServiceBase::SetManagedPref(const char* path, Value* value) {
SetPref(managed_platform_prefs_, path, value);
}
-void TestingPrefService::RemoveManagedPref(const char* path) {
+void TestingPrefServiceBase::RemoveManagedPref(const char* path) {
RemovePref(managed_platform_prefs_, path);
}
-const Value* TestingPrefService::GetUserPref(const char* path) const {
+const Value* TestingPrefServiceBase::GetUserPref(const char* path) const {
return GetPref(user_prefs_, path);
}
-void TestingPrefService::SetUserPref(const char* path, Value* value) {
+void TestingPrefServiceBase::SetUserPref(const char* path, Value* value) {
SetPref(user_prefs_, path, value);
}
-void TestingPrefService::RemoveUserPref(const char* path) {
+void TestingPrefServiceBase::RemoveUserPref(const char* path) {
RemovePref(user_prefs_, path);
}
-const Value* TestingPrefService::GetPref(TestingPrefStore* pref_store,
- const char* path) const {
+const Value* TestingPrefServiceBase::GetPref(TestingPrefStore* pref_store,
+ const char* path) const {
Value* res;
return pref_store->GetValue(path, &res) == PrefStore::READ_OK ? res : NULL;
}
-void TestingPrefService::SetPref(TestingPrefStore* pref_store,
- const char* path,
- Value* value) {
+void TestingPrefServiceBase::SetPref(TestingPrefStore* pref_store,
+ const char* path,
+ Value* value) {
pref_store->SetValue(path, value);
}
-void TestingPrefService::RemovePref(TestingPrefStore* pref_store,
- const char* path) {
+void TestingPrefServiceBase::RemovePref(TestingPrefStore* pref_store,
+ const char* path) {
pref_store->RemoveValue(path);
}
+
+TestingPrefService::TestingPrefService()
+ : TestingPrefServiceBase(new TestingPrefStore(),
+ new TestingPrefStore(),
+ new TestingPrefStore()) {
+}
+
+TestingPrefService::~TestingPrefService() {
+}
diff --git a/chrome/test/testing_pref_service.h b/chrome/test/testing_pref_service.h
index 25349b6..7429145 100644
--- a/chrome/test/testing_pref_service.h
+++ b/chrome/test/testing_pref_service.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -6,6 +6,7 @@
#define CHROME_TEST_TESTING_PREF_SERVICE_H_
#pragma once
+#include "base/ref_counted.h"
#include "chrome/browser/prefs/pref_service.h"
class TestingPrefStore;
@@ -13,11 +14,9 @@ class TestingPrefStore;
// A PrefService subclass for testing. It operates totally in memory and
// provides additional API for manipulating preferences at the different levels
// (managed, extension, user) conveniently.
-class TestingPrefService : public PrefService {
+class TestingPrefServiceBase : public PrefService {
public:
- // Create an empty instance.
- TestingPrefService();
- virtual ~TestingPrefService() {}
+ virtual ~TestingPrefServiceBase();
// Read the value of a preference from the managed layer. Returns NULL if the
// preference is not defined at the managed layer.
@@ -36,6 +35,12 @@ class TestingPrefService : public PrefService {
void SetUserPref(const char* path, Value* value);
void RemoveUserPref(const char* path);
+ protected:
+ TestingPrefServiceBase(
+ TestingPrefStore* managed_platform_prefs,
+ TestingPrefStore* device_management_prefs,
+ TestingPrefStore* user_prefs);
+
private:
// Reads the value of the preference indicated by |path| from |pref_store|.
// Returns NULL if the preference was not found.
@@ -48,10 +53,20 @@ class TestingPrefService : public PrefService {
void RemovePref(TestingPrefStore* pref_store, const char* path);
// Pointers to the pref stores our value store uses.
- TestingPrefStore* managed_platform_prefs_; // weak
- TestingPrefStore* device_management_prefs_; // weak
- TestingPrefStore* user_prefs_; // weak
+ scoped_refptr<TestingPrefStore> managed_platform_prefs_;
+ scoped_refptr<TestingPrefStore> device_management_prefs_;
+ scoped_refptr<TestingPrefStore> user_prefs_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestingPrefServiceBase);
+};
+// Class for simplified construction of TestPrefServiceBase objects.
+class TestingPrefService : public TestingPrefServiceBase {
+ public:
+ TestingPrefService();
+ virtual ~TestingPrefService();
+
+ private:
DISALLOW_COPY_AND_ASSIGN(TestingPrefService);
};
diff --git a/chrome/test/testing_profile.cc b/chrome/test/testing_profile.cc
index 4f3b40b..6b584af 100644
--- a/chrome/test/testing_profile.cc
+++ b/chrome/test/testing_profile.cc
@@ -17,8 +17,8 @@
#include "chrome/browser/browser_thread.h"
#include "chrome/browser/content_settings/host_content_settings_map.h"
#include "chrome/browser/dom_ui/ntp_resource_cache.h"
-#include "chrome/browser/extensions/extension_pref_store.h"
#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/extension_pref_value_map.h"
#include "chrome/browser/favicon_service.h"
#include "chrome/browser/geolocation/geolocation_content_settings_map.h"
#include "chrome/browser/geolocation/geolocation_permission_context.h"
@@ -30,6 +30,7 @@
#include "chrome/browser/net/pref_proxy_config_service.h"
#include "chrome/browser/notifications/desktop_notification_service.h"
#include "chrome/browser/prefs/browser_prefs.h"
+#include "chrome/browser/prefs/testing_pref_store.h"
#include "chrome/browser/search_engines/template_url_fetcher.h"
#include "chrome/browser/search_engines/template_url_model.h"
#include "chrome/browser/sessions/session_service.h"
@@ -48,7 +49,6 @@
#include "net/url_request/url_request_unittest.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "webkit/database/database_tracker.h"
-
#if defined(OS_LINUX) && !defined(TOOLKIT_VIEWS)
#include "chrome/browser/ui/gtk/gtk_theme_provider.h"
#endif
@@ -326,18 +326,25 @@ void TestingProfile::UseThemeProvider(BrowserThemeProvider* theme_provider) {
theme_provider_.reset(theme_provider);
}
-scoped_refptr<ExtensionService> TestingProfile::CreateExtensionService(
+ExtensionService* TestingProfile::CreateExtensionService(
const CommandLine* command_line,
const FilePath& install_directory) {
- extension_pref_store_.reset(new ExtensionPrefStore);
- extension_prefs_.reset(new ExtensionPrefs(GetPrefs(),
- install_directory,
- extension_pref_store_.get()));
+ // Extension pref store, created for use by |extension_prefs_|.
+
+ extension_pref_value_map_.reset(new ExtensionPrefValueMap);
+ // Note that the GetPrefs() creates a TestingPrefService, therefore
+ // the extension controlled pref values set in extension_prefs_
+ // are not reflected in the pref service. One would need to
+ // inject a new ExtensionPrefStore(extension_pref_value_map_.get(), false).
+ extension_prefs_.reset(
+ new ExtensionPrefs(GetPrefs(),
+ install_directory,
+ extension_pref_value_map_.get()));
extensions_service_ = new ExtensionService(this,
- command_line,
- install_directory,
- extension_prefs_.get(),
- false);
+ command_line,
+ install_directory,
+ extension_prefs_.get(),
+ false);
return extensions_service_;
}
diff --git a/chrome/test/testing_profile.h b/chrome/test/testing_profile.h
index 181e375..e1e5d8b 100644
--- a/chrome/test/testing_profile.h
+++ b/chrome/test/testing_profile.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -25,8 +25,9 @@ class BookmarkModel;
class BrowserThemeProvider;
class CommandLine;
class DesktopNotificationService;
-class ExtensionPrefStore;
class ExtensionPrefs;
+class ExtensionPrefStore;
+class ExtensionPrefValueMap;
class FaviconService;
class FindBarState;
class GeolocationContentSettingsMap;
@@ -115,9 +116,8 @@ class TestingProfile : public Profile {
// returns it. The profile keeps its own copy of a scoped_refptr to the
// ExtensionService to make sure that is still alive to be notified when the
// profile is destroyed.
- scoped_refptr<ExtensionService> CreateExtensionService(
- const CommandLine* command_line,
- const FilePath& install_directory);
+ ExtensionService* CreateExtensionService(const CommandLine* command_line,
+ const FilePath& install_directory);
TestingPrefService* GetTestingPrefService();
@@ -322,6 +322,10 @@ class TestingProfile : public Profile {
virtual PrerenderManager* GetPrerenderManager() { return NULL; }
protected:
+ virtual ExtensionPrefValueMap* GetExtensionPrefValueMap() {
+ return extension_pref_value_map_.get();
+ }
+
base::Time start_time_;
scoped_ptr<PrefService> prefs_;
// ref only for right type, lifecycle is managed by prefs_
@@ -411,9 +415,6 @@ class TestingProfile : public Profile {
FilePath last_selected_directory_;
scoped_refptr<history::TopSites> top_sites_; // For history and thumbnails.
- // Extension pref store, created for use by |extension_prefs_|.
- scoped_ptr<ExtensionPrefStore> extension_pref_store_;
-
// The Extension Preferences. Only created if CreateExtensionService is
// invoked.
scoped_ptr<ExtensionPrefs> extension_prefs_;
@@ -422,6 +423,8 @@ class TestingProfile : public Profile {
// is disposed.
scoped_refptr<ExtensionService> extensions_service_;
+ scoped_ptr<ExtensionPrefValueMap> extension_pref_value_map_;
+
// The proxy prefs tracker.
scoped_refptr<PrefProxyConfigTracker> pref_proxy_config_tracker_;
diff --git a/net/base/network_config_watcher_mac.cc b/net/base/network_config_watcher_mac.cc
index 5cc41b1..bd3528a 100644
--- a/net/base/network_config_watcher_mac.cc
+++ b/net/base/network_config_watcher_mac.cc
@@ -10,8 +10,8 @@
#include "base/compiler_specific.h"
#include "base/threading/thread.h"
-#include "base/mac/scoped_cftyperef.h"
#include "base/threading/thread_restrictions.h"
+#include "base/mac/scoped_cftyperef.h"
namespace net {
diff --git a/net/proxy/proxy_config_service_linux.cc b/net/proxy/proxy_config_service_linux.cc
index 3867df1..893a8e5 100644
--- a/net/proxy/proxy_config_service_linux.cc
+++ b/net/proxy/proxy_config_service_linux.cc
@@ -26,6 +26,7 @@
#include "base/string_tokenizer.h"
#include "base/string_util.h"
#include "base/task.h"
+#include "base/threading/thread_restrictions.h"
#include "base/timer.h"
#include "base/nix/xdg_util.h"
#include "googleurl/src/url_canon.h"
@@ -435,6 +436,9 @@ class GConfSettingGetterImplKDE
: inotify_fd_(-1), notify_delegate_(NULL), indirect_manual_(false),
auto_no_pac_(false), reversed_bypass_list_(false),
env_var_getter_(env_var_getter), file_loop_(NULL) {
+ // This has to be called on the UI thread (http://crbug.com/69057).
+ base::ThreadRestrictions::ScopedAllowIO allow_io;
+
// Derive the location of the kde config dir from the environment.
std::string home;
if (env_var_getter->GetVar("KDEHOME", &home) && !home.empty()) {
@@ -502,6 +506,8 @@ class GConfSettingGetterImplKDE
virtual bool Init(MessageLoop* glib_default_loop,
MessageLoopForIO* file_loop) {
+ // This has to be called on the UI thread (http://crbug.com/69057).
+ base::ThreadRestrictions::ScopedAllowIO allow_io;
DCHECK(inotify_fd_ < 0);
inotify_fd_ = inotify_init();
if (inotify_fd_ < 0) {