Reinitialize LocalState's CommandLinePrefStore after about_flags updates the command line. Otherwise flags set in about:flags are ignored by the LocalState.

BUG=none
TEST=none
Review URL: https://chromiumcodereview.appspot.com/9251026

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@118926 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index 1f464969..a9d09107 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -58,7 +58,6 @@
 #include "chrome/browser/notifications/desktop_notification_service.h"
 #include "chrome/browser/notifications/desktop_notification_service_factory.h"
 #include "chrome/browser/plugin_prefs.h"
-#include "chrome/browser/policy/browser_policy_connector.h"
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/prefs/pref_value_store.h"
 #include "chrome/browser/prerender/prerender_field_trial.h"
@@ -466,7 +465,7 @@
 
 #if defined(OS_MACOSX)
 OSStatus KeychainCallback(SecKeychainEvent keychain_event,
-                          SecKeychainCallbackInfo *info, void *context) {
+                          SecKeychainCallbackInfo* info, void* context) {
   return noErr;
 }
 #endif
@@ -1263,6 +1262,7 @@
   // Convert active labs into switches. Modifies the current command line.
   about_flags::ConvertFlagsToSwitches(local_state_,
                                       CommandLine::ForCurrentProcess());
+  local_state_->UpdateCommandLinePrefStore(CommandLine::ForCurrentProcess());
 
   // Reset the command line in the crash report details, since we may have
   // just changed it to include experiments.
diff --git a/chrome/browser/policy/configuration_policy_pref_store.cc b/chrome/browser/policy/configuration_policy_pref_store.cc
index 711de52..dd9bb5c 100644
--- a/chrome/browser/policy/configuration_policy_pref_store.cc
+++ b/chrome/browser/policy/configuration_policy_pref_store.cc
@@ -65,6 +65,10 @@
   observers_.RemoveObserver(observer);
 }
 
+size_t ConfigurationPolicyPrefStore::NumberOfObservers() const {
+  return observers_.size();
+}
+
 bool ConfigurationPolicyPrefStore::IsInitializationComplete() const {
   return initialization_complete_;
 }
diff --git a/chrome/browser/policy/configuration_policy_pref_store.h b/chrome/browser/policy/configuration_policy_pref_store.h
index 237e2ac8..37e997a8 100644
--- a/chrome/browser/policy/configuration_policy_pref_store.h
+++ b/chrome/browser/policy/configuration_policy_pref_store.h
@@ -6,6 +6,8 @@
 #define CHROME_BROWSER_POLICY_CONFIGURATION_POLICY_PREF_STORE_H_
 #pragma once
 
+#include <string>
+
 #include "base/basictypes.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/observer_list.h"
@@ -31,6 +33,7 @@
   // PrefStore methods:
   virtual void AddObserver(PrefStore::Observer* observer) OVERRIDE;
   virtual void RemoveObserver(PrefStore::Observer* observer) OVERRIDE;
+  virtual size_t NumberOfObservers() const OVERRIDE;
   virtual bool IsInitializationComplete() const OVERRIDE;
   virtual ReadResult GetValue(const std::string& key,
                               const Value** result) const OVERRIDE;
diff --git a/chrome/browser/prefs/overlay_user_pref_store.cc b/chrome/browser/prefs/overlay_user_pref_store.cc
index c230cc8e..5849c80 100644
--- a/chrome/browser/prefs/overlay_user_pref_store.cc
+++ b/chrome/browser/prefs/overlay_user_pref_store.cc
@@ -29,6 +29,10 @@
   observers_.RemoveObserver(observer);
 }
 
+size_t OverlayUserPrefStore::NumberOfObservers() const {
+  return observers_.size();
+}
+
 bool OverlayUserPrefStore::IsInitializationComplete() const {
   return underlay_->IsInitializationComplete();
 }
diff --git a/chrome/browser/prefs/overlay_user_pref_store.h b/chrome/browser/prefs/overlay_user_pref_store.h
index 5964d886..7e95c45c 100644
--- a/chrome/browser/prefs/overlay_user_pref_store.h
+++ b/chrome/browser/prefs/overlay_user_pref_store.h
@@ -33,6 +33,7 @@
   // Methods of PrefStore.
   virtual void AddObserver(PrefStore::Observer* observer) OVERRIDE;
   virtual void RemoveObserver(PrefStore::Observer* observer) OVERRIDE;
+  virtual size_t NumberOfObservers() const OVERRIDE;
   virtual bool IsInitializationComplete() const OVERRIDE;
   virtual ReadResult GetValue(const std::string& key,
                               const base::Value** result) const OVERRIDE;
diff --git a/chrome/browser/prefs/pref_service.cc b/chrome/browser/prefs/pref_service.cc
index 6802462..a562f01b 100644
--- a/chrome/browser/prefs/pref_service.cc
+++ b/chrome/browser/prefs/pref_service.cc
@@ -180,6 +180,7 @@
 
 PrefService* PrefService::CreateIncognitoPrefService(
     PrefStore* incognito_extension_prefs) {
+  pref_service_forked_ = true;
   PrefNotifierImpl* pref_notifier = new PrefNotifierImpl();
   OverlayUserPrefStore* incognito_pref_store =
       new OverlayUserPrefStore(user_pref_store_.get());
@@ -187,15 +188,15 @@
   return new PrefService(
       pref_notifier,
       pref_value_store_->CloneAndSpecialize(
-          NULL, // managed_platform_prefs
-          NULL, // managed_cloud_prefs
+          NULL,  // managed_platform_prefs
+          NULL,  // managed_cloud_prefs
           incognito_extension_prefs,
-          NULL, // command_line_prefs
+          NULL,  // command_line_prefs
           incognito_pref_store,
-          NULL, // recommended_platform_prefs
-          NULL, // recommended_cloud_prefs
+          NULL,  // recommended_platform_prefs
+          NULL,  // recommended_cloud_prefs
           default_store_.get(),
-          NULL, // pref_sync_associator
+          NULL,  // pref_sync_associator
           pref_notifier),
       incognito_pref_store,
       default_store_.get(),
@@ -204,6 +205,7 @@
 }
 
 PrefService* PrefService::CreatePrefServiceWithPerTabPrefStore() {
+  pref_service_forked_ = true;
   PrefNotifierImpl* pref_notifier = new PrefNotifierImpl();
   OverlayUserPrefStore* per_tab_pref_store =
       new OverlayUserPrefStore(user_pref_store_.get());
@@ -212,13 +214,13 @@
   return new PrefService(
       pref_notifier,
       pref_value_store_->CloneAndSpecialize(
-          NULL, // managed_platform_prefs
-          NULL, // managed_cloud_prefs
-          NULL, // extension_prefs
-          NULL, // command_line_prefs
+          NULL,  // managed_platform_prefs
+          NULL,  // managed_cloud_prefs
+          NULL,  // extension_prefs
+          NULL,  // command_line_prefs
           per_tab_pref_store,
-          NULL, // recommended_platform_prefs
-          NULL, // recommended_cloud_prefs
+          NULL,  // recommended_platform_prefs
+          NULL,  // recommended_cloud_prefs
           default_store,
           NULL,
           pref_notifier),
@@ -238,7 +240,8 @@
       pref_value_store_(pref_value_store),
       user_pref_store_(user_prefs),
       default_store_(default_store),
-      pref_sync_associator_(pref_sync_associator) {
+      pref_sync_associator_(pref_sync_associator),
+      pref_service_forked_(false) {
   pref_notifier_->SetPrefService(this);
   if (pref_sync_associator_.get())
     pref_sync_associator_->SetPrefService(this);
@@ -284,14 +287,14 @@
 namespace {
 
 // If there's no g_browser_process or no local state, return true (for testing).
-bool IsLocalStatePrefService(PrefService* prefs){
+bool IsLocalStatePrefService(PrefService* prefs) {
   return (!g_browser_process ||
           !g_browser_process->local_state() ||
           g_browser_process->local_state() == prefs);
 }
 
 // If there's no g_browser_process, return true (for testing).
-bool IsProfilePrefService(PrefService* prefs){
+bool IsProfilePrefService(PrefService* prefs) {
   // TODO(zea): uncomment this once all preferences are only ever registered
   // with either the local_state's pref service or the profile's pref service.
   // return (!g_browser_process || g_browser_process->local_state() != prefs);
@@ -519,7 +522,7 @@
   DCHECK(IsProfilePrefService(this));
   RegisterPreference(
       path,
-      CreateLocaleDefaultValue(Value::TYPE_BOOLEAN,locale_default_message_id),
+      CreateLocaleDefaultValue(Value::TYPE_BOOLEAN, locale_default_message_id),
       sync_status);
 }
 
@@ -883,6 +886,14 @@
   return pref_sync_associator_.get();
 }
 
+void PrefService::UpdateCommandLinePrefStore(CommandLine* command_line) {
+  // If |pref_service_forked_| is true, then this PrefService and the forked
+  // copies will be out of sync.
+  DCHECK(!pref_service_forked_);
+  pref_value_store_->UpdateCommandLinePrefStore(
+      new CommandLinePrefStore(command_line));
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // PrefService::Preference
 
diff --git a/chrome/browser/prefs/pref_service.h b/chrome/browser/prefs/pref_service.h
index f0ed120..1768597 100644
--- a/chrome/browser/prefs/pref_service.h
+++ b/chrome/browser/prefs/pref_service.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -17,6 +17,7 @@
 #include "base/values.h"
 #include "chrome/common/json_pref_store.h"
 
+class CommandLine;
 class DefaultPrefStore;
 class FilePath;
 class PersistentPrefStore;
@@ -52,7 +53,6 @@
   // A helper class to store all the information associated with a preference.
   class Preference {
    public:
-
     // The type of the preference is determined by the type with which it is
     // registered. This type needs to be a boolean, integer, double, string,
     // dictionary (a branch), or list.  You shouldn't need to construct this on
@@ -297,6 +297,10 @@
   // TODO(zea): Have PrefService implement SyncableService directly.
   SyncableService* GetSyncableService();
 
+  // Tell our PrefValueStore to update itself using |command_line|.
+  // Do not call this after having derived an incognito or per tab pref service.
+  void UpdateCommandLinePrefStore(CommandLine* command_line);
+
  protected:
   // Construct a new pref service. This constructor is what
   // factory methods end up calling and what is used for unit tests.
@@ -390,6 +394,11 @@
   // The model associator that maintains the links with the sync db.
   scoped_ptr<PrefModelAssociator> pref_sync_associator_;
 
+  // Whether CreateIncognitoPrefService() or
+  // CreatePrefServiceWithPerTabPrefStore() have been called to create a
+  // "forked" PrefService.
+  bool pref_service_forked_;
+
   DISALLOW_COPY_AND_ASSIGN(PrefService);
 };
 
diff --git a/chrome/browser/prefs/pref_service_unittest.cc b/chrome/browser/prefs/pref_service_unittest.cc
index de2060d..3c04dd2 100644
--- a/chrome/browser/prefs/pref_service_unittest.cc
+++ b/chrome/browser/prefs/pref_service_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -22,7 +22,6 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "chrome/test/base/testing_pref_service.h"
-#include "chrome/test/base/testing_pref_service.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/browser/tab_contents/test_tab_contents.h"
 #include "content/test/test_browser_thread.h"
@@ -150,6 +149,37 @@
   EXPECT_EQ(kTestValue, actual_int_value);
 }
 
+TEST(PrefServiceTest, UpdateCommandLinePrefStore) {
+  TestingPrefService prefs;
+  prefs.RegisterBooleanPref(prefs::kCloudPrintProxyEnabled, false);
+
+  // Check to make sure the value is as expected.
+  const PrefService::Preference* pref =
+      prefs.FindPreference(prefs::kCloudPrintProxyEnabled);
+  ASSERT_TRUE(pref);
+  const Value* value = pref->GetValue();
+  ASSERT_TRUE(value);
+  EXPECT_EQ(Value::TYPE_BOOLEAN, value->GetType());
+  bool actual_bool_value = true;
+  EXPECT_TRUE(value->GetAsBoolean(&actual_bool_value));
+  EXPECT_EQ(false, actual_bool_value);
+
+  // Change the command line.
+  CommandLine cmd_line(CommandLine::NO_PROGRAM);
+  cmd_line.AppendSwitch(switches::kEnableCloudPrintProxy);
+
+  // Call UpdateCommandLinePrefStore and check to see if the value has changed.
+  prefs.UpdateCommandLinePrefStore(&cmd_line);
+  pref = prefs.FindPreference(prefs::kCloudPrintProxyEnabled);
+  ASSERT_TRUE(pref);
+  value = pref->GetValue();
+  ASSERT_TRUE(value);
+  EXPECT_EQ(Value::TYPE_BOOLEAN, value->GetType());
+  actual_bool_value = false;
+  EXPECT_TRUE(value->GetAsBoolean(&actual_bool_value));
+  EXPECT_EQ(true, actual_bool_value);
+}
+
 class PrefServiceSetValueTest : public testing::Test {
  protected:
   static const char kName[];
diff --git a/chrome/browser/prefs/pref_value_store.cc b/chrome/browser/prefs/pref_value_store.cc
index 44e4f64..6772483 100644
--- a/chrome/browser/prefs/pref_value_store.cc
+++ b/chrome/browser/prefs/pref_value_store.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -25,8 +25,10 @@
     PrefValueStore* store,
     PrefStore* pref_store,
     PrefValueStore::PrefStoreType type) {
-  if (pref_store_.get())
+  if (pref_store_.get()) {
     pref_store_->RemoveObserver(this);
+    DCHECK_EQ(0U, pref_store_->NumberOfObservers());
+  }
   type_ = type;
   pref_value_store_ = store;
   pref_store_ = pref_store;
@@ -185,6 +187,10 @@
          effective_store == INVALID_STORE;
 }
 
+void PrefValueStore::UpdateCommandLinePrefStore(PrefStore* command_line_prefs) {
+  InitPrefStore(COMMAND_LINE_STORE, command_line_prefs);
+}
+
 bool PrefValueStore::PrefValueInStore(
     const char* name,
     PrefValueStore::PrefStoreType store) const {
diff --git a/chrome/browser/prefs/pref_value_store.h b/chrome/browser/prefs/pref_value_store.h
index 804da08..8f4cabd9 100644
--- a/chrome/browser/prefs/pref_value_store.h
+++ b/chrome/browser/prefs/pref_value_store.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -105,6 +105,9 @@
   // whether there is no higher-priority source controlling it.
   bool PrefValueExtensionModifiable(const char* name) const;
 
+  // Update the command line PrefStore with |command_line_prefs|.
+  void UpdateCommandLinePrefStore(PrefStore* command_line_prefs);
+
  private:
   // PrefStores must be listed here in order from highest to lowest priority.
   //   MANAGED_PLATFORM contains all managed preference values that are
diff --git a/chrome/browser/prefs/testing_pref_store.cc b/chrome/browser/prefs/testing_pref_store.cc
index 3c6b631..3780a46 100644
--- a/chrome/browser/prefs/testing_pref_store.cc
+++ b/chrome/browser/prefs/testing_pref_store.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -31,6 +31,10 @@
   observers_.RemoveObserver(observer);
 }
 
+size_t TestingPrefStore::NumberOfObservers() const {
+  return observers_.size();
+}
+
 bool TestingPrefStore::IsInitializationComplete() const {
   return init_complete_;
 }
diff --git a/chrome/browser/prefs/testing_pref_store.h b/chrome/browser/prefs/testing_pref_store.h
index 2651f67..27250af1 100644
--- a/chrome/browser/prefs/testing_pref_store.h
+++ b/chrome/browser/prefs/testing_pref_store.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,6 +6,8 @@
 #define CHROME_BROWSER_PREFS_TESTING_PREF_STORE_H_
 #pragma once
 
+#include <string>
+
 #include "base/basictypes.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/observer_list.h"
@@ -25,6 +27,7 @@
                               const base::Value** result) const OVERRIDE;
   virtual void AddObserver(PrefStore::Observer* observer) OVERRIDE;
   virtual void RemoveObserver(PrefStore::Observer* observer) OVERRIDE;
+  virtual size_t NumberOfObservers() const OVERRIDE;
   virtual bool IsInitializationComplete() const OVERRIDE;
 
   // PersistentPrefStore overrides:
diff --git a/chrome/browser/prefs/value_map_pref_store.cc b/chrome/browser/prefs/value_map_pref_store.cc
index 6eeb79b0..6bb1decd 100644
--- a/chrome/browser/prefs/value_map_pref_store.cc
+++ b/chrome/browser/prefs/value_map_pref_store.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -26,6 +26,10 @@
   observers_.RemoveObserver(observer);
 }
 
+size_t ValueMapPrefStore::NumberOfObservers() const {
+  return observers_.size();
+}
+
 void ValueMapPrefStore::SetValue(const std::string& key, Value* value) {
   if (prefs_.SetValue(key, value))
     FOR_EACH_OBSERVER(Observer, observers_, OnPrefValueChanged(key));
diff --git a/chrome/browser/prefs/value_map_pref_store.h b/chrome/browser/prefs/value_map_pref_store.h
index 0981a6fd..b440ba1 100644
--- a/chrome/browser/prefs/value_map_pref_store.h
+++ b/chrome/browser/prefs/value_map_pref_store.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,6 +6,9 @@
 #define CHROME_BROWSER_PREFS_VALUE_MAP_PREF_STORE_H_
 #pragma once
 
+#include <map>
+#include <string>
+
 #include "base/basictypes.h"
 #include "base/observer_list.h"
 #include "chrome/browser/prefs/pref_value_map.h"
@@ -26,6 +29,7 @@
                               const base::Value** value) const OVERRIDE;
   virtual void AddObserver(PrefStore::Observer* observer) OVERRIDE;
   virtual void RemoveObserver(PrefStore::Observer* observer) OVERRIDE;
+  virtual size_t NumberOfObservers() const OVERRIDE;
 
   iterator begin();
   iterator end();