Move creation of the PrefStores into the PrefValueStore, to reduce the knowledge the PrefService has of its two-levels-deep implementation.

Create a TestingPrefService::TestingPrefValueStore to allow tests to set the PrefStores directly, as they used to be able to do.

BUG=50722
TEST=covered by unit tests
Review URL: http://codereview.chromium.org/3032058

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@55202 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/extensions/extension_pref_store_unittest.cc b/chrome/browser/extensions/extension_pref_store_unittest.cc
index b538bc9..55d300e2 100644
--- a/chrome/browser/extensions/extension_pref_store_unittest.cc
+++ b/chrome/browser/extensions/extension_pref_store_unittest.cc
@@ -14,6 +14,7 @@
 #include "chrome/browser/pref_service.h"
 #include "chrome/browser/pref_value_store.h"
 #include "chrome/common/extensions/extension.h"
+#include "chrome/test/testing_pref_service.h"
 
 namespace {
 
@@ -321,7 +322,8 @@
   // The PrefValueStore takes ownership of the PrefStores; in this case, that's
   // only an ExtensionPrefStore. Likewise, the PrefService takes ownership of
   // the PrefValueStore.
-  PrefValueStore* value_store = new PrefValueStore(NULL, eps, NULL, NULL, NULL);
+  PrefValueStore* value_store = new TestingPrefService::TestingPrefValueStore(
+      NULL, eps, NULL, NULL, NULL);
   scoped_ptr<MockPrefService> pref_service(new MockPrefService(value_store));
   eps->SetPrefService(pref_service.get());
   pref_service->RegisterStringPref(kPref1, std::string());
diff --git a/chrome/browser/net/chrome_url_request_context_unittest.cc b/chrome/browser/net/chrome_url_request_context_unittest.cc
index eaaddf5..af67e576 100644
--- a/chrome/browser/net/chrome_url_request_context_unittest.cc
+++ b/chrome/browser/net/chrome_url_request_context_unittest.cc
@@ -9,6 +9,7 @@
 #include "chrome/browser/configuration_policy_pref_store.h"
 #include "chrome/browser/pref_value_store.h"
 #include "chrome/common/chrome_switches.h"
+#include "chrome/test/testing_pref_service.h"
 #include "net/proxy/proxy_config.h"
 #include "net/proxy/proxy_config_service_common_unittest.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -157,7 +158,7 @@
     SCOPED_TRACE(StringPrintf("Test[%" PRIuS "] %s", i,
                               tests[i].description.c_str()));
     CommandLine command_line(tests[i].command_line);
-    PrefService prefs(new PrefValueStore(
+    PrefService prefs(new TestingPrefService::TestingPrefValueStore(
         new ConfigurationPolicyPrefStore(&command_line, NULL),
         NULL, NULL, NULL, NULL));  // Only configuration-policy prefs.
     ChromeURLRequestContextGetter::RegisterUserPrefs(&prefs);
diff --git a/chrome/browser/pref_service.cc b/chrome/browser/pref_service.cc
index c02dd34..fa2d004 100644
--- a/chrome/browser/pref_service.cc
+++ b/chrome/browser/pref_service.cc
@@ -19,11 +19,8 @@
 #include "base/utf_string_conversions.h"
 #include "build/build_config.h"
 #include "chrome/browser/chrome_thread.h"
-#include "chrome/browser/profile.h"
-#include "chrome/browser/command_line_pref_store.h"
 #include "chrome/browser/configuration_policy_pref_store.h"
-#include "chrome/browser/extensions/extension_pref_store.h"
-#include "chrome/common/json_pref_store.h"
+#include "chrome/browser/profile.h"
 #include "chrome/common/notification_service.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
@@ -83,37 +80,14 @@
 // static
 PrefService* PrefService::CreatePrefService(const FilePath& pref_filename,
                                             Profile* profile) {
-  ExtensionPrefStore* extension_prefs = new ExtensionPrefStore(profile);
-  CommandLinePrefStore* command_line_prefs = new CommandLinePrefStore(
-      CommandLine::ForCurrentProcess());
-  PrefStore* local_prefs = new JsonPrefStore(
-      pref_filename,
-      ChromeThread::GetMessageLoopProxyForThread(ChromeThread::FILE));
-
-  // The PrefValueStore takes ownership of the PrefStores.
-  PrefValueStore* value_store = new PrefValueStore(
-      ConfigurationPolicyPrefStore::CreateManagedPolicyPrefStore(),
-      extension_prefs,
-      command_line_prefs,
-      local_prefs,
-      ConfigurationPolicyPrefStore::CreateRecommendedPolicyPrefStore());
-
-  return new PrefService(value_store);
+  return new PrefService(
+      PrefValueStore::CreatePrefValueStore(pref_filename, profile, false));
 }
 
 // static
-PrefService* PrefService::CreateUserPrefService(
-    const FilePath& pref_filename) {
-  PrefValueStore* value_store = new PrefValueStore(
-      NULL, /* no enforced prefs */
-      NULL, /* no extension prefs */
-      NULL, /* no command-line prefs */
-      new JsonPrefStore(
-          pref_filename,
-          ChromeThread::GetMessageLoopProxyForThread(ChromeThread::FILE)),
-          /* user prefs */
-      NULL /* no advised prefs */);
-  return new PrefService(value_store);
+PrefService* PrefService::CreateUserPrefService(const FilePath& pref_filename) {
+  return new PrefService(
+      PrefValueStore::CreatePrefValueStore(pref_filename, NULL, true));
 }
 
 PrefService::PrefService(PrefValueStore* pref_value_store)
diff --git a/chrome/browser/pref_service.h b/chrome/browser/pref_service.h
index 90e4004..e15c5f55 100644
--- a/chrome/browser/pref_service.h
+++ b/chrome/browser/pref_service.h
@@ -101,8 +101,8 @@
     DISALLOW_COPY_AND_ASSIGN(Preference);
   };
 
-  // Factory method that creates a new instance of a |PrefService| with
-  // all platform-applicable PrefStores (managed, extension, user, etc.).
+  // Factory method that creates a new instance of a PrefService with
+  // a PrefValueStore containing all platform-applicable PrefStores.
   // The |pref_filename| points to the user preference file. The |profile| is
   // the one to which these preferences apply; it may be NULL if we're dealing
   // with the local state. This is the usual way to create a new PrefService.
diff --git a/chrome/browser/pref_value_store.cc b/chrome/browser/pref_value_store.cc
index ab976aa2..7fae719 100644
--- a/chrome/browser/pref_value_store.cc
+++ b/chrome/browser/pref_value_store.cc
@@ -3,21 +3,43 @@
 // found in the LICENSE file.
 
 #include "chrome/browser/pref_value_store.h"
+
+#include "chrome/browser/chrome_thread.h"
+#include "chrome/browser/command_line_pref_store.h"
+#include "chrome/browser/configuration_policy_pref_store.h"
+#include "chrome/browser/extensions/extension_pref_store.h"
+#include "chrome/common/json_pref_store.h"
 #include "chrome/common/notification_service.h"
 
-PrefValueStore::PrefValueStore(PrefStore* managed_prefs,
-                               PrefStore* extension_prefs,
-                               PrefStore* command_line_prefs,
-                               PrefStore* user_prefs,
-                               PrefStore* recommended_prefs) {
-  pref_stores_[MANAGED].reset(managed_prefs);
-  pref_stores_[EXTENSION].reset(extension_prefs);
-  pref_stores_[COMMAND_LINE].reset(command_line_prefs);
-  pref_stores_[USER].reset(user_prefs);
-  pref_stores_[RECOMMENDED].reset(recommended_prefs);
+// static
+PrefValueStore* PrefValueStore::CreatePrefValueStore(
+    const FilePath& pref_filename,
+    Profile* profile,
+    bool user_only) {
+  ConfigurationPolicyPrefStore* managed = NULL;
+  ExtensionPrefStore* extension = NULL;
+  CommandLinePrefStore* command_line = NULL;
+  JsonPrefStore* user = NULL;
+  ConfigurationPolicyPrefStore* recommended = NULL;
+
+  if (!pref_filename.empty()) {
+    user = new JsonPrefStore(
+        pref_filename,
+        ChromeThread::GetMessageLoopProxyForThread(ChromeThread::FILE));
+  }
+
+  if (!user_only) {
+    managed = ConfigurationPolicyPrefStore::CreateManagedPolicyPrefStore();
+    extension = new ExtensionPrefStore(profile);
+    command_line = new CommandLinePrefStore(CommandLine::ForCurrentProcess());
+    recommended =
+        ConfigurationPolicyPrefStore::CreateRecommendedPolicyPrefStore();
+  }
+  return new PrefValueStore(managed, extension, command_line, user,
+      recommended);
 }
 
-PrefValueStore::~PrefValueStore() { }
+PrefValueStore::~PrefValueStore() {}
 
 bool PrefValueStore::GetValue(const std::wstring& name,
                               Value** out_value) const {
@@ -211,3 +233,15 @@
                         new_recommended_pref_store,
                         callback));
 }
+
+PrefValueStore::PrefValueStore(PrefStore* managed_prefs,
+                               PrefStore* extension_prefs,
+                               PrefStore* command_line_prefs,
+                               PrefStore* user_prefs,
+                               PrefStore* recommended_prefs) {
+  pref_stores_[MANAGED].reset(managed_prefs);
+  pref_stores_[EXTENSION].reset(extension_prefs);
+  pref_stores_[COMMAND_LINE].reset(command_line_prefs);
+  pref_stores_[USER].reset(user_prefs);
+  pref_stores_[RECOMMENDED].reset(recommended_prefs);
+}
diff --git a/chrome/browser/pref_value_store.h b/chrome/browser/pref_value_store.h
index addb580..ff277a0 100644
--- a/chrome/browser/pref_value_store.h
+++ b/chrome/browser/pref_value_store.h
@@ -21,6 +21,7 @@
 #include "chrome/common/pref_store.h"
 
 class PrefStore;
+class Profile;
 
 // The class PrefValueStore provides values for preferences. Each Preference
 // has a unique name. This name is used to retrieve the value of a Preference.
@@ -38,18 +39,17 @@
 // be called on the UI thread.
 class PrefValueStore : public base::RefCountedThreadSafe<PrefValueStore> {
  public:
-  // In decreasing order of precedence:
-  //   |managed_prefs| contains all managed (policy) preference values.
-  //   |extension_prefs| contains preference values set by extensions.
-  //   |command_line_prefs| contains preference values set by command-line
-  //        switches.
-  //   |user_prefs| contains all user-set preference values.
-  //   |recommended_prefs| contains all recommended (policy) preference values.
-  PrefValueStore(PrefStore* managed_prefs,
-                 PrefStore* extension_prefs,
-                 PrefStore* command_line_prefs,
-                 PrefStore* user_prefs,
-                 PrefStore* recommended_prefs);
+  // Returns a new PrefValueStore with all applicable PrefStores. The
+  // |pref_filename| points to the user preference file. The |profile| is the
+  // one to which these preferences apply; it may be NULL if we're dealing
+  // with the local state. If |pref_filename| is empty, the user PrefStore will
+  // not be created. If |user_only| is true, no PrefStores will be created
+  // other than the user PrefStore (if |pref_filename| is not empty). This
+  // should not normally be called directly: the usual way to create a
+  // PrefValueStore is by creating a PrefService.
+  static PrefValueStore* CreatePrefValueStore(const FilePath& pref_filename,
+                                              Profile* profile,
+                                              bool user_only);
 
   ~PrefValueStore();
 
@@ -127,6 +127,24 @@
                           PrefStore* recommended_pref_store,
                           AfterRefreshCallback callback);
 
+ protected:
+  // In decreasing order of precedence:
+  //   |managed_prefs| contains all managed (policy) preference values.
+  //   |extension_prefs| contains preference values set by extensions.
+  //   |command_line_prefs| contains preference values set by command-line
+  //        switches.
+  //   |user_prefs| contains all user-set preference values.
+  //   |recommended_prefs| contains all recommended (policy) preference values.
+  //
+  // This constructor should only be used internally, or by subclasses in
+  // testing. The usual way to create a PrefValueStore is by creating a
+  // PrefService.
+  PrefValueStore(PrefStore* managed_prefs,
+                 PrefStore* extension_prefs,
+                 PrefStore* command_line_prefs,
+                 PrefStore* user_prefs,
+                 PrefStore* recommended_prefs);
+
  private:
   friend class PrefValueStoreTest;
   FRIEND_TEST_ALL_PREFIXES(PrefValueStoreTest,
diff --git a/chrome/browser/pref_value_store_unittest.cc b/chrome/browser/pref_value_store_unittest.cc
index ae14598..55982d9c 100644
--- a/chrome/browser/pref_value_store_unittest.cc
+++ b/chrome/browser/pref_value_store_unittest.cc
@@ -6,8 +6,10 @@
 #include "base/utf_string_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/configuration_policy_pref_store.h"
+#include "chrome/browser/chrome_thread.h"
 #include "chrome/browser/dummy_pref_store.h"
 #include "chrome/browser/pref_value_store.h"
+#include "chrome/test/testing_pref_service.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -85,11 +87,12 @@
     recommended_pref_store_->set_prefs(recommended_prefs_);
 
     // Create a new pref-value-store.
-    pref_value_store_ = new PrefValueStore(enforced_pref_store_,
-                                           extension_pref_store_,
-                                           command_line_pref_store_,
-                                           user_pref_store_,
-                                           recommended_pref_store_);
+    pref_value_store_ = new TestingPrefService::TestingPrefValueStore(
+        enforced_pref_store_,
+        extension_pref_store_,
+        command_line_pref_store_,
+        user_pref_store_,
+        recommended_pref_store_);
 
     ui_thread_.reset(new ChromeThread(ChromeThread::UI, &loop_));
     file_thread_.reset(new ChromeThread(ChromeThread::FILE, &loop_));
@@ -176,7 +179,7 @@
 
   MessageLoop loop_;
 
-  scoped_refptr<PrefValueStore> pref_value_store_;
+  scoped_refptr<TestingPrefService::TestingPrefValueStore> pref_value_store_;
 
   // |PrefStore|s are owned by the |PrefValueStore|.
   DummyPrefStore* enforced_pref_store_;
diff --git a/chrome/test/testing_pref_service.cc b/chrome/test/testing_pref_service.cc
index e6dde83..067b8b9 100644
--- a/chrome/test/testing_pref_service.cc
+++ b/chrome/test/testing_pref_service.cc
@@ -7,8 +7,20 @@
 #include "chrome/browser/dummy_pref_store.h"
 #include "chrome/browser/pref_value_store.h"
 
+TestingPrefService::TestingPrefValueStore::TestingPrefValueStore(
+    PrefStore* managed_prefs,
+    PrefStore* extension_prefs,
+    PrefStore* command_line_prefs,
+    PrefStore* user_prefs,
+    PrefStore* recommended_prefs)
+    : PrefValueStore(managed_prefs, extension_prefs, command_line_prefs,
+      user_prefs, recommended_prefs) {
+}
+
+// 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(new PrefValueStore(
+    : PrefService(new TestingPrefValueStore(
           managed_prefs_ = new DummyPrefStore(),
           NULL,
           NULL,
diff --git a/chrome/test/testing_pref_service.h b/chrome/test/testing_pref_service.h
index d4512d9..e08c6d1 100644
--- a/chrome/test/testing_pref_service.h
+++ b/chrome/test/testing_pref_service.h
@@ -8,11 +8,23 @@
 
 #include <chrome/browser/pref_service.h>
 
+class PrefStore;
+
 // 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 {
  public:
+  // Subclass to allow directly setting PrefStores.
+  class TestingPrefValueStore : public PrefValueStore {
+   public:
+    TestingPrefValueStore(PrefStore* managed_prefs,
+                          PrefStore* extension_prefs,
+                          PrefStore* command_line_prefs,
+                          PrefStore* user_prefs,
+                          PrefStore* recommended_prefs);
+  };
+
   // Create an empty instance.
   TestingPrefService();