Adds async interface method, which is used by JsonPrefStore. Also see the bug description for more info.

BUG=chromium-os:14289
TEST=JsonPrefStoreTest.*

Review URL: http://codereview.chromium.org/6894020

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@84962 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/browser_main.cc b/chrome/browser/browser_main.cc
index 68da6cb4..f80a813 100644
--- a/chrome/browser/browser_main.cc
+++ b/chrome/browser/browser_main.cc
@@ -793,7 +793,7 @@
     FilePath parent_profile =
         parsed_command_line.GetSwitchValuePath(switches::kParentProfile);
     scoped_ptr<PrefService> parent_local_state(
-        PrefService::CreatePrefService(parent_profile, NULL, NULL));
+        PrefService::CreatePrefService(parent_profile, NULL, NULL, false));
     parent_local_state->RegisterStringPref(prefs::kApplicationLocale,
                                            std::string());
     // Right now, we only inherit the locale setting from the parent profile.
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc
index f2c276e..d1e43d6 100644
--- a/chrome/browser/browser_process_impl.cc
+++ b/chrome/browser/browser_process_impl.cc
@@ -881,7 +881,7 @@
   FilePath local_state_path;
   PathService::Get(chrome::FILE_LOCAL_STATE, &local_state_path);
   local_state_.reset(
-      PrefService::CreatePrefService(local_state_path, NULL, NULL));
+      PrefService::CreatePrefService(local_state_path, NULL, NULL, false));
 
   // Initialize the prefs of the local state.
   browser::RegisterLocalState(local_state_.get());
diff --git a/chrome/browser/chromeos/login/signed_settings_temp_storage_unittest.cc b/chrome/browser/chromeos/login/signed_settings_temp_storage_unittest.cc
index e196ea6..b6273eb 100644
--- a/chrome/browser/chromeos/login/signed_settings_temp_storage_unittest.cc
+++ b/chrome/browser/chromeos/login/signed_settings_temp_storage_unittest.cc
@@ -30,7 +30,8 @@
     FilePath temp_file;
     ASSERT_TRUE(
         file_util::CreateTemporaryFileInDir(temp_dir_.path(), &temp_file));
-    local_state_.reset(PrefService::CreatePrefService(temp_file, NULL, NULL));
+    local_state_.reset(
+        PrefService::CreatePrefService(temp_file, NULL, NULL, false));
     ASSERT_TRUE(NULL != local_state_.get());
     SignedSettingsTempStorage::RegisterPrefs(local_state_.get());
   }
diff --git a/chrome/browser/content_settings/content_settings_pref_provider_unittest.cc b/chrome/browser/content_settings/content_settings_pref_provider_unittest.cc
index 105cb96..c6f7f2d 100644
--- a/chrome/browser/content_settings/content_settings_pref_provider_unittest.cc
+++ b/chrome/browser/content_settings/content_settings_pref_provider_unittest.cc
@@ -36,7 +36,7 @@
       : PrefService(
           managed_platform_prefs, managed_cloud_prefs, extension_prefs,
           command_line_prefs, user_prefs, recommended_platform_prefs,
-          recommended_cloud_prefs, default_store, NULL) {}
+          recommended_cloud_prefs, default_store, false) {}
   virtual ~ContentSettingsPrefService() {}
 };
 }
diff --git a/chrome/browser/policy/configuration_policy_pref_store.cc b/chrome/browser/policy/configuration_policy_pref_store.cc
index 68fe0d0..96dfb2e 100644
--- a/chrome/browser/policy/configuration_policy_pref_store.cc
+++ b/chrome/browser/policy/configuration_policy_pref_store.cc
@@ -1039,7 +1039,7 @@
       provider_->IsInitializationComplete()) {
     initialization_complete_ = true;
     FOR_EACH_OBSERVER(PrefStore::Observer, observers_,
-                      OnInitializationCompleted());
+                      OnInitializationCompleted(true));
   }
 }
 
diff --git a/chrome/browser/policy/configuration_policy_pref_store_unittest.cc b/chrome/browser/policy/configuration_policy_pref_store_unittest.cc
index 07eed39..478c0cce 100644
--- a/chrome/browser/policy/configuration_policy_pref_store_unittest.cc
+++ b/chrome/browser/policy/configuration_policy_pref_store_unittest.cc
@@ -819,7 +819,7 @@
 TEST_F(ConfigurationPolicyPrefStoreRefreshTest, Initialization) {
   EXPECT_FALSE(store_->IsInitializationComplete());
 
-  EXPECT_CALL(observer_, OnInitializationCompleted()).Times(1);
+  EXPECT_CALL(observer_, OnInitializationCompleted(true)).Times(1);
 
   provider_.SetInitializationComplete(true);
   EXPECT_FALSE(store_->IsInitializationComplete());
diff --git a/chrome/browser/prefs/overlay_persistent_pref_store.cc b/chrome/browser/prefs/overlay_persistent_pref_store.cc
index e75fbc66..13c51bb3 100644
--- a/chrome/browser/prefs/overlay_persistent_pref_store.cc
+++ b/chrome/browser/prefs/overlay_persistent_pref_store.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/prefs/overlay_persistent_pref_store.h"
 
+#include "base/memory/scoped_ptr.h"
 #include "base/values.h"
 
 OverlayPersistentPrefStore::OverlayPersistentPrefStore(
@@ -80,9 +81,17 @@
 
 PersistentPrefStore::PrefReadError OverlayPersistentPrefStore::ReadPrefs() {
   // We do not read intentionally.
+  OnInitializationCompleted(true);
   return PersistentPrefStore::PREF_READ_ERROR_NONE;
 }
 
+void OverlayPersistentPrefStore::ReadPrefsAsync(
+    ReadErrorDelegate* error_delegate_raw) {
+  scoped_ptr<ReadErrorDelegate> error_delegate(error_delegate_raw);
+  // We do not read intentionally.
+  OnInitializationCompleted(true);
+}
+
 bool OverlayPersistentPrefStore::WritePrefs() {
   // We do not write intentionally.
   return true;
@@ -105,7 +114,7 @@
     FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key));
 }
 
-void OverlayPersistentPrefStore::OnInitializationCompleted() {
+void OverlayPersistentPrefStore::OnInitializationCompleted(bool succeeded) {
   FOR_EACH_OBSERVER(PrefStore::Observer, observers_,
-                    OnInitializationCompleted());
+                    OnInitializationCompleted(succeeded));
 }
diff --git a/chrome/browser/prefs/overlay_persistent_pref_store.h b/chrome/browser/prefs/overlay_persistent_pref_store.h
index bbb85c3..57ffe8d7 100644
--- a/chrome/browser/prefs/overlay_persistent_pref_store.h
+++ b/chrome/browser/prefs/overlay_persistent_pref_store.h
@@ -43,6 +43,7 @@
   virtual void RemoveValue(const std::string& key);
   virtual bool ReadOnly() const;
   virtual PrefReadError ReadPrefs();
+  virtual void ReadPrefsAsync(ReadErrorDelegate* delegate);
   virtual bool WritePrefs();
   virtual void ScheduleWritePrefs();
   virtual void CommitPendingWrite();
@@ -51,7 +52,7 @@
  private:
   // Methods of PrefStore::Observer.
   virtual void OnPrefValueChanged(const std::string& key);
-  virtual void OnInitializationCompleted();
+  virtual void OnInitializationCompleted(bool succeeded);
 
   ObserverList<PrefStore::Observer, true> observers_;
   PrefValueMap overlay_;
diff --git a/chrome/browser/prefs/pref_notifier.h b/chrome/browser/prefs/pref_notifier.h
index f2d9c52..f4d3a5a 100644
--- a/chrome/browser/prefs/pref_notifier.h
+++ b/chrome/browser/prefs/pref_notifier.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.
 
@@ -21,7 +21,7 @@
   virtual void OnPreferenceChanged(const std::string& pref_name) = 0;
 
   // Broadcasts the intialization completed notification.
-  virtual void OnInitializationCompleted() = 0;
+  virtual void OnInitializationCompleted(bool succeeded) = 0;
 };
 
 #endif  // CHROME_BROWSER_PREFS_PREF_NOTIFIER_H_
diff --git a/chrome/browser/prefs/pref_notifier_impl.cc b/chrome/browser/prefs/pref_notifier_impl.cc
index d5ad24c..6d1dd2a 100644
--- a/chrome/browser/prefs/pref_notifier_impl.cc
+++ b/chrome/browser/prefs/pref_notifier_impl.cc
@@ -74,13 +74,13 @@
   FireObservers(path);
 }
 
-void PrefNotifierImpl::OnInitializationCompleted() {
+void PrefNotifierImpl::OnInitializationCompleted(bool succeeded) {
   DCHECK(CalledOnValidThread());
 
   NotificationService::current()->Notify(
       NotificationType::PREF_INITIALIZATION_COMPLETED,
       Source<PrefService>(pref_service_),
-      NotificationService::NoDetails());
+      Details<bool>(&succeeded));
 }
 
 void PrefNotifierImpl::FireObservers(const std::string& path) {
diff --git a/chrome/browser/prefs/pref_notifier_impl.h b/chrome/browser/prefs/pref_notifier_impl.h
index 085e547..8323fcbe 100644
--- a/chrome/browser/prefs/pref_notifier_impl.h
+++ b/chrome/browser/prefs/pref_notifier_impl.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.
 
@@ -30,7 +30,7 @@
 
   // PrefNotifier overrides.
   virtual void OnPreferenceChanged(const std::string& pref_name);
-  virtual void OnInitializationCompleted();
+  virtual void OnInitializationCompleted(bool succeeded);
 
  protected:
   // A map from pref names to a list of observers. Observers get fired in the
diff --git a/chrome/browser/prefs/pref_notifier_impl_unittest.cc b/chrome/browser/prefs/pref_notifier_impl_unittest.cc
index 096b625..c413e32 100644
--- a/chrome/browser/prefs/pref_notifier_impl_unittest.cc
+++ b/chrome/browser/prefs/pref_notifier_impl_unittest.cc
@@ -86,8 +86,8 @@
       Field(&NotificationType::value,
             NotificationType::PREF_INITIALIZATION_COMPLETED),
       Source<PrefService>(&pref_service_),
-      NotificationService::NoDetails()));
-  notifier.OnInitializationCompleted();
+      Property(&Details<bool>::ptr, testing::Pointee(true))));
+  notifier.OnInitializationCompleted(true);
 }
 
 TEST_F(PrefNotifierTest, AddAndRemovePrefObservers) {
diff --git a/chrome/browser/prefs/pref_service.cc b/chrome/browser/prefs/pref_service.cc
index 5096d1d7..5614bbf 100644
--- a/chrome/browser/prefs/pref_service.cc
+++ b/chrome/browser/prefs/pref_service.cc
@@ -79,25 +79,41 @@
 
 // Forwards a notification after a PostMessage so that we can wait for the
 // MessageLoop to run.
-void NotifyReadError(PrefService* pref, int message_id) {
+void NotifyReadError(int message_id) {
   ShowProfileErrorDialog(message_id);
 }
 
+// Shows notifications which correspond to PersistentPrefStore's reading errors.
+class ReadErrorHandler : public PersistentPrefStore::ReadErrorDelegate {
+ public:
+  virtual void OnError(PersistentPrefStore::PrefReadError error) {
+    if (error != PersistentPrefStore::PREF_READ_ERROR_NONE) {
+      // Failing to load prefs on startup is a bad thing(TM). See bug 38352 for
+      // an example problem that this can cause.
+      // Do some diagnosis and try to avoid losing data.
+      int message_id = 0;
+      if (error <= PersistentPrefStore::PREF_READ_ERROR_JSON_TYPE) {
+        message_id = IDS_PREFERENCES_CORRUPT_ERROR;
+      } else if (error != PersistentPrefStore::PREF_READ_ERROR_NO_FILE) {
+        message_id = IDS_PREFERENCES_UNREADABLE_ERROR;
+      }
+
+      if (message_id) {
+        BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+            NewRunnableFunction(&NotifyReadError, message_id));
+      }
+      UMA_HISTOGRAM_ENUMERATION("PrefService.ReadError", error, 20);
+    }
+  }
+};
+
 }  // namespace
 
 // static
 PrefService* PrefService::CreatePrefService(const FilePath& pref_filename,
                                             PrefStore* extension_prefs,
-                                            Profile* profile) {
-  return CreatePrefServiceAsync(pref_filename, extension_prefs, profile, NULL);
-}
-
-// static
-PrefService* PrefService::CreatePrefServiceAsync(
-    const FilePath& pref_filename,
-    PrefStore* extension_prefs,
-    Profile* profile,
-    PrefServiceDelegate* delegate) {
+                                            Profile* profile,
+                                            bool async) {
   using policy::ConfigurationPolicyPrefStore;
 
 #if defined(OS_LINUX)
@@ -129,9 +145,10 @@
           profile);
   DefaultPrefStore* default_pref_store = new DefaultPrefStore();
 
-  return new PrefService(managed_platform, managed_cloud, extension_prefs,
-                         command_line, user, recommended_platform,
-                         recommended_cloud, default_pref_store, delegate);
+  return new PrefService(
+      managed_platform, managed_cloud, extension_prefs,
+      command_line, user, recommended_platform,
+      recommended_cloud, default_pref_store, async);
 }
 
 PrefService* PrefService::CreateIncognitoPrefService(
@@ -147,10 +164,9 @@
                          PrefStore* recommended_platform_prefs,
                          PrefStore* recommended_cloud_prefs,
                          DefaultPrefStore* default_store,
-                         PrefServiceDelegate* delegate)
+                         bool async)
     : user_pref_store_(user_prefs),
-      default_store_(default_store),
-      delegate_(delegate) {
+      default_store_(default_store) {
   pref_sync_associator_.reset(new PrefModelAssociator(this));
   pref_notifier_.reset(new PrefNotifierImpl(this));
   pref_value_store_.reset(
@@ -164,15 +180,14 @@
                          default_store,
                          pref_sync_associator_.get(),
                          pref_notifier_.get()));
-  InitFromStorage();
+  InitFromStorage(async);
 }
 
 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()),
-        delegate_(NULL) {
+        default_store_(original.default_store_.get()) {
   // Incognito mode doesn't sync, so no need to create PrefModelAssociator.
   pref_notifier_.reset(new PrefNotifierImpl(this));
   pref_value_store_.reset(original.pref_value_store_->CloneAndSpecialize(
@@ -186,7 +201,6 @@
       default_store_.get(),
       NULL, // pref_sync_associator_
       pref_notifier_.get()));
-  InitFromStorage();
 }
 
 PrefService::~PrefService() {
@@ -203,47 +217,17 @@
   pref_sync_associator_.reset();
 }
 
-void PrefService::OnPrefsRead(PersistentPrefStore::PrefReadError error,
-                              bool no_dir) {
-  if (no_dir) {
-    // Bad news. When profile is created, the process that creates the directory
-    // is explicitly started. So if directory is missing it probably means that
-    // Chromium hasn't sufficient privileges.
-    CHECK(delegate_);
-    delegate_->OnPrefsLoaded(this, false);
-    return;
-  }
-
-  if (error != PersistentPrefStore::PREF_READ_ERROR_NONE) {
-    // Failing to load prefs on startup is a bad thing(TM). See bug 38352 for
-    // an example problem that this can cause.
-    // Do some diagnosis and try to avoid losing data.
-    int message_id = 0;
-    if (error <= PersistentPrefStore::PREF_READ_ERROR_JSON_TYPE) {
-      message_id = IDS_PREFERENCES_CORRUPT_ERROR;
-    } else if (error != PersistentPrefStore::PREF_READ_ERROR_NO_FILE) {
-      message_id = IDS_PREFERENCES_UNREADABLE_ERROR;
-    }
-
-    if (message_id) {
-      BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-          NewRunnableFunction(&NotifyReadError, this, message_id));
-    }
-    UMA_HISTOGRAM_ENUMERATION("PrefService.ReadError", error, 20);
-  }
-
-  if (delegate_)
-    delegate_->OnPrefsLoaded(this, true);
-}
-
-void PrefService::InitFromStorage() {
-  if (!delegate_) {
-    const PersistentPrefStore::PrefReadError error =
-        user_pref_store_->ReadPrefs();
-    OnPrefsRead(error, false);
+void PrefService::InitFromStorage(bool async) {
+  if (!async) {
+    ReadErrorHandler error_handler;
+    error_handler.OnError(user_pref_store_->ReadPrefs());
   } else {
-    // todo(altimofeev): move this method to PersistentPrefStore interface.
-    (static_cast<JsonPrefStore*>(user_pref_store_.get()))->ReadPrefs(this);
+    // Guarantee that initialization happens after this function returned.
+    MessageLoop::current()->PostTask(
+        FROM_HERE,
+        NewRunnableMethod(user_pref_store_.get(),
+                          &PersistentPrefStore::ReadPrefsAsync,
+                          new ReadErrorHandler()));
   }
 }
 
diff --git a/chrome/browser/prefs/pref_service.h b/chrome/browser/prefs/pref_service.h
index 3990d5a..0a98c4c 100644
--- a/chrome/browser/prefs/pref_service.h
+++ b/chrome/browser/prefs/pref_service.h
@@ -36,13 +36,7 @@
 
 class PrefService;
 
-class PrefServiceDelegate {
- public:
-  virtual void OnPrefsLoaded(PrefService* prefs, bool success) = 0;
-};
-
-class PrefService : public base::NonThreadSafe,
-                    public JsonPrefStore::Delegate {
+class PrefService : public base::NonThreadSafe {
  public:
   // Enum used when registering preferences to determine if it should be synced
   // or not. This is only used for profile prefs, not local state prefs.
@@ -129,26 +123,21 @@
     DISALLOW_COPY_AND_ASSIGN(Preference);
   };
 
-  // JsonPrefStore::Delegate implementaion.
-  virtual void OnPrefsRead(PersistentPrefStore::PrefReadError error,
-                           bool no_dir);
-
   // Factory method that creates a new instance of a PrefService with the
   // 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. |extension_pref_store| is used as the source for
   // extension-controlled preferences and may be NULL. The PrefService takes
-  // ownership of |extension_pref_store|.
+  // ownership of |extension_pref_store|. If |async| is true, asynchronous
+  // version is used. Notifies using PREF_INITIALIZATION_COMPLETED in the end.
+  // Details is set to the created PrefService or NULL if creation has failed.
+  // Note, it is guaranteed that in asynchronous version initialization happens
+  // after this function returned.
   static PrefService* CreatePrefService(const FilePath& pref_filename,
                                         PrefStore* extension_pref_store,
-                                        Profile* profile);
-
-  // Same as above, but with async initialization.
-  static PrefService* CreatePrefServiceAsync(const FilePath& pref_filename,
-                                             PrefStore* extension_pref_store,
-                                             Profile* profile,
-                                             PrefServiceDelegate* delegate);
+                                        Profile* profile,
+                                        bool async);
 
   // 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
@@ -316,7 +305,7 @@
               PrefStore* recommended_platform_prefs,
               PrefStore* recommended_cloud_prefs,
               DefaultPrefStore* default_store,
-              PrefServiceDelegate* delegate);
+              bool async);
 
   // The PrefNotifier handles registering and notifying preference observers.
   // It is created and owned by this PrefService. Subclasses may access it for
@@ -376,7 +365,7 @@
 
   // Load preferences from storage, attempting to diagnose and handle errors.
   // This should only be called from the constructor.
-  void InitFromStorage();
+  void InitFromStorage(bool async);
 
   // Used to set the value of dictionary or list values in the user pref store.
   // This will create a dictionary or list if one does not exist in the user
@@ -400,10 +389,6 @@
   // of registered preferences are.
   mutable PreferenceSet prefs_;
 
-  // Holds delegator to be called after initialization, if async version
-  // is used.
-  PrefServiceDelegate* delegate_;
-
   // The model associator that maintains the links with the sync db.
   scoped_ptr<PrefModelAssociator> pref_sync_associator_;
 
diff --git a/chrome/browser/prefs/pref_service_mock_builder.cc b/chrome/browser/prefs/pref_service_mock_builder.cc
index 1de0403..66e3e99 100644
--- a/chrome/browser/prefs/pref_service_mock_builder.cc
+++ b/chrome/browser/prefs/pref_service_mock_builder.cc
@@ -114,7 +114,7 @@
                       recommended_platform_prefs_.get(),
                       recommended_cloud_prefs_.get(),
                       new DefaultPrefStore(),
-                      NULL);
+                      false);
   managed_platform_prefs_ = NULL;
   managed_cloud_prefs_ = NULL;
   extension_prefs_ = NULL;
diff --git a/chrome/browser/prefs/pref_value_store.cc b/chrome/browser/prefs/pref_value_store.cc
index dbb29aebd..44b526f 100644
--- a/chrome/browser/prefs/pref_value_store.cc
+++ b/chrome/browser/prefs/pref_value_store.cc
@@ -38,8 +38,9 @@
   pref_value_store_->OnPrefValueChanged(type_, key);
 }
 
-void PrefValueStore::PrefStoreKeeper::OnInitializationCompleted() {
-  pref_value_store_->OnInitializationCompleted(type_);
+void PrefValueStore::PrefStoreKeeper::OnInitializationCompleted(
+    bool succeeded) {
+  pref_value_store_->OnInitializationCompleted(type_, succeeded);
 }
 
 PrefValueStore::PrefValueStore(PrefStore* managed_platform_prefs,
@@ -53,7 +54,8 @@
                                PrefModelAssociator* pref_sync_associator,
                                PrefNotifier* pref_notifier)
     : pref_sync_associator_(pref_sync_associator),
-      pref_notifier_(pref_notifier) {
+      pref_notifier_(pref_notifier),
+      initialization_failed_(false) {
   InitPrefStore(MANAGED_PLATFORM_STORE, managed_platform_prefs);
   InitPrefStore(MANAGED_CLOUD_STORE, managed_cloud_prefs);
   InitPrefStore(EXTENSION_STORE, extension_prefs);
@@ -245,7 +247,14 @@
 }
 
 void PrefValueStore::OnInitializationCompleted(
-    PrefValueStore::PrefStoreType type) {
+    PrefValueStore::PrefStoreType type, bool succeeded) {
+  if (initialization_failed_)
+    return;
+  if (!succeeded) {
+    initialization_failed_ = true;
+    pref_notifier_->OnInitializationCompleted(false);
+    return;
+  }
   CheckInitializationCompleted();
 }
 
@@ -255,11 +264,13 @@
 }
 
 void PrefValueStore::CheckInitializationCompleted() {
+  if (initialization_failed_)
+    return;
   for (size_t i = 0; i <= PREF_STORE_TYPE_MAX; ++i) {
     scoped_refptr<PrefStore> store =
         GetPrefStore(static_cast<PrefStoreType>(i));
     if (store && !store->IsInitializationComplete())
       return;
   }
-  pref_notifier_->OnInitializationCompleted();
+  pref_notifier_->OnInitializationCompleted(true);
 }
diff --git a/chrome/browser/prefs/pref_value_store.h b/chrome/browser/prefs/pref_value_store.h
index 07a5b61..5d3d5bb7 100644
--- a/chrome/browser/prefs/pref_value_store.h
+++ b/chrome/browser/prefs/pref_value_store.h
@@ -155,7 +155,7 @@
    private:
     // PrefStore::Observer implementation.
     virtual void OnPrefValueChanged(const std::string& key);
-    virtual void OnInitializationCompleted();
+    virtual void OnInitializationCompleted(bool succeeded);
 
     // PrefValueStore this keeper is part of.
     PrefValueStore* pref_value_store_;
@@ -214,7 +214,7 @@
   void OnPrefValueChanged(PrefStoreType type, const std::string& key);
 
   // Handle the event that the store for |type| has completed initialization.
-  void OnInitializationCompleted(PrefStoreType type);
+  void OnInitializationCompleted(PrefStoreType type, bool succeeded);
 
   // Initializes a pref store keeper. Sets up a PrefStoreKeeper that will take
   // ownership of the passed |pref_store|.
@@ -247,6 +247,9 @@
   // A mapping of preference names to their registered types.
   PrefTypeMap pref_types_;
 
+  // True if not all of the PrefStores were initialized successfully.
+  bool initialization_failed_;
+
   DISALLOW_COPY_AND_ASSIGN(PrefValueStore);
 };
 
diff --git a/chrome/browser/prefs/pref_value_store_unittest.cc b/chrome/browser/prefs/pref_value_store_unittest.cc
index 17d939c..b5eaff0 100644
--- a/chrome/browser/prefs/pref_value_store_unittest.cc
+++ b/chrome/browser/prefs/pref_value_store_unittest.cc
@@ -29,7 +29,7 @@
 class MockPrefNotifier : public PrefNotifier {
  public:
   MOCK_METHOD1(OnPreferenceChanged, void(const std::string&));
-  MOCK_METHOD0(OnInitializationCompleted, void());
+  MOCK_METHOD1(OnInitializationCompleted, void(bool));
 };
 
 // Allows to capture sync model associator interaction.
@@ -494,7 +494,7 @@
 }
 
 TEST_F(PrefValueStoreTest, OnInitializationCompleted) {
-  EXPECT_CALL(pref_notifier_, OnInitializationCompleted()).Times(0);
+  EXPECT_CALL(pref_notifier_, OnInitializationCompleted(true)).Times(0);
   managed_platform_pref_store_->SetInitializationCompleted();
   managed_cloud_pref_store_->SetInitializationCompleted();
   extension_pref_store_->SetInitializationCompleted();
@@ -505,7 +505,7 @@
   Mock::VerifyAndClearExpectations(&pref_notifier_);
 
   // The notification should only be triggered after the last store is done.
-  EXPECT_CALL(pref_notifier_, OnInitializationCompleted()).Times(1);
+  EXPECT_CALL(pref_notifier_, OnInitializationCompleted(true)).Times(1);
   user_pref_store_->SetInitializationCompleted();
   Mock::VerifyAndClearExpectations(&pref_notifier_);
 }
diff --git a/chrome/browser/prefs/testing_pref_store.cc b/chrome/browser/prefs/testing_pref_store.cc
index e85a836..d080169 100644
--- a/chrome/browser/prefs/testing_pref_store.cc
+++ b/chrome/browser/prefs/testing_pref_store.cc
@@ -55,9 +55,16 @@
 
 PersistentPrefStore::PrefReadError TestingPrefStore::ReadPrefs() {
   prefs_.Clear();
+  NotifyInitializationCompleted();
   return PersistentPrefStore::PREF_READ_ERROR_NONE;
 }
 
+void TestingPrefStore::ReadPrefsAsync(ReadErrorDelegate* error_delegate_raw) {
+  scoped_ptr<ReadErrorDelegate> error_delegate(error_delegate_raw);
+  prefs_.Clear();
+  NotifyInitializationCompleted();
+}
+
 bool TestingPrefStore::WritePrefs() {
   prefs_written_ = true;
   return prefs_written_;
@@ -73,7 +80,7 @@
 }
 
 void TestingPrefStore::NotifyInitializationCompleted() {
-  FOR_EACH_OBSERVER(Observer, observers_, OnInitializationCompleted());
+  FOR_EACH_OBSERVER(Observer, observers_, OnInitializationCompleted(true));
 }
 
 void TestingPrefStore::ReportValueChanged(const std::string& key) {
diff --git a/chrome/browser/prefs/testing_pref_store.h b/chrome/browser/prefs/testing_pref_store.h
index 048dcc7..ff6dc00 100644
--- a/chrome/browser/prefs/testing_pref_store.h
+++ b/chrome/browser/prefs/testing_pref_store.h
@@ -37,6 +37,7 @@
   virtual void RemoveValue(const std::string& key);
   virtual bool ReadOnly() const;
   virtual PersistentPrefStore::PrefReadError ReadPrefs();
+  virtual void ReadPrefsAsync(ReadErrorDelegate* error_delegate);
   virtual bool WritePrefs();
   virtual void ScheduleWritePrefs() {}
   virtual void CommitPendingWrite() {}
diff --git a/chrome/browser/prefs/value_map_pref_store.cc b/chrome/browser/prefs/value_map_pref_store.cc
index 4d2c8ca5..39ee3a1 100644
--- a/chrome/browser/prefs/value_map_pref_store.cc
+++ b/chrome/browser/prefs/value_map_pref_store.cc
@@ -37,7 +37,7 @@
 }
 
 void ValueMapPrefStore::NotifyInitializationCompleted() {
-  FOR_EACH_OBSERVER(Observer, observers_, OnInitializationCompleted());
+  FOR_EACH_OBSERVER(Observer, observers_, OnInitializationCompleted(true));
 }
 
 ValueMapPrefStore::iterator ValueMapPrefStore::begin() {
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc
index e168882..7b73fe5 100644
--- a/chrome/browser/profiles/profile_impl.cc
+++ b/chrome/browser/profiles/profile_impl.cc
@@ -292,18 +292,23 @@
       &ProfileImpl::EnsureSessionServiceCreated);
 
   if (delegate_) {
-    prefs_.reset(PrefService::CreatePrefServiceAsync(
+    prefs_.reset(PrefService::CreatePrefService(
         GetPrefFilePath(),
         new ExtensionPrefStore(GetExtensionPrefValueMap(), false),
         GetOriginalProfile(),
-        this));  // Ask to notify us in the end.
+        true));
+    // Wait for the notifcation that prefs has been loaded (successfully or
+    // not).
+    registrar_.Add(this, NotificationType::PREF_INITIALIZATION_COMPLETED,
+                   Source<PrefService>(prefs_.get()));
   } else {
     // Load prefs synchronously.
     prefs_.reset(PrefService::CreatePrefService(
         GetPrefFilePath(),
         new ExtensionPrefStore(GetExtensionPrefValueMap(), false),
-        GetOriginalProfile()));
-    OnPrefsLoaded(prefs_.get(), true);
+        GetOriginalProfile(),
+        false));
+    OnPrefsLoaded(true);
   }
 }
 
@@ -803,9 +808,7 @@
   return transport_security_state_.get();
 }
 
-void ProfileImpl::OnPrefsLoaded(PrefService* prefs, bool success) {
-  DCHECK(prefs == prefs_.get());
-
+void ProfileImpl::OnPrefsLoaded(bool success) {
   if (!success) {
     DCHECK(delegate_);
     delegate_->OnProfileCreated(this, false);
@@ -1319,39 +1322,55 @@
 void ProfileImpl::Observe(NotificationType type,
                           const NotificationSource& source,
                           const NotificationDetails& details) {
-  if (NotificationType::PREF_CHANGED == type) {
-    std::string* pref_name_in = Details<std::string>(details).ptr();
-    PrefService* prefs = Source<PrefService>(source).ptr();
-    DCHECK(pref_name_in && prefs);
-    if (*pref_name_in == prefs::kSpellCheckDictionary ||
-        *pref_name_in == prefs::kEnableSpellCheck) {
-      ReinitializeSpellCheckHost(true);
-    } else if (*pref_name_in == prefs::kEnableAutoSpellCorrect) {
-      bool enabled = prefs->GetBoolean(prefs::kEnableAutoSpellCorrect);
-      for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator());
-           !i.IsAtEnd(); i.Advance()) {
-        RenderProcessHost* process = i.GetCurrentValue();
-        process->Send(new SpellCheckMsg_EnableAutoSpellCorrect(enabled));
-      }
-    } else if (*pref_name_in == prefs::kClearSiteDataOnExit) {
-      clear_local_state_on_exit_ =
-          prefs->GetBoolean(prefs::kClearSiteDataOnExit);
-      if (webkit_context_) {
-        webkit_context_->set_clear_local_state_on_exit(
-            clear_local_state_on_exit_);
-      }
-      if (appcache_service_) {
-        appcache_service_->SetClearLocalStateOnExit(
-            clear_local_state_on_exit_);
-      }
-    } else if (*pref_name_in == prefs::kGoogleServicesUsername) {
-      ProfileManager* profile_manager = g_browser_process->profile_manager();
-      profile_manager->RegisterProfileName(this);
+  switch (type.value) {
+    case NotificationType::PREF_INITIALIZATION_COMPLETED: {
+      bool* succeeded = Details<bool>(details).ptr();
+      PrefService *prefs = Source<PrefService>(source).ptr();
+      DCHECK(prefs == prefs_.get());
+      registrar_.Remove(this, NotificationType::PREF_INITIALIZATION_COMPLETED,
+                        Source<PrefService>(prefs));
+      OnPrefsLoaded(*succeeded);
+      break;
     }
-  } else if (NotificationType::BOOKMARK_MODEL_LOADED == type) {
-    GetProfileSyncService();  // Causes lazy-load if sync is enabled.
-    registrar_.Remove(this, NotificationType::BOOKMARK_MODEL_LOADED,
-                      Source<Profile>(this));
+    case NotificationType::PREF_CHANGED: {
+      std::string* pref_name_in = Details<std::string>(details).ptr();
+      PrefService* prefs = Source<PrefService>(source).ptr();
+      DCHECK(pref_name_in && prefs);
+      if (*pref_name_in == prefs::kSpellCheckDictionary ||
+          *pref_name_in == prefs::kEnableSpellCheck) {
+        ReinitializeSpellCheckHost(true);
+      } else if (*pref_name_in == prefs::kEnableAutoSpellCorrect) {
+        bool enabled = prefs->GetBoolean(prefs::kEnableAutoSpellCorrect);
+        for (RenderProcessHost::iterator
+             i(RenderProcessHost::AllHostsIterator());
+             !i.IsAtEnd(); i.Advance()) {
+          RenderProcessHost* process = i.GetCurrentValue();
+          process->Send(new SpellCheckMsg_EnableAutoSpellCorrect(enabled));
+        }
+      } else if (*pref_name_in == prefs::kClearSiteDataOnExit) {
+        clear_local_state_on_exit_ =
+            prefs->GetBoolean(prefs::kClearSiteDataOnExit);
+        if (webkit_context_) {
+          webkit_context_->set_clear_local_state_on_exit(
+              clear_local_state_on_exit_);
+        }
+        if (appcache_service_) {
+          appcache_service_->SetClearLocalStateOnExit(
+              clear_local_state_on_exit_);
+        }
+      } else if (*pref_name_in == prefs::kGoogleServicesUsername) {
+        ProfileManager* profile_manager = g_browser_process->profile_manager();
+        profile_manager->RegisterProfileName(this);
+      }
+      break;
+    }
+    case NotificationType::BOOKMARK_MODEL_LOADED:
+      GetProfileSyncService();  // Causes lazy-load if sync is enabled.
+      registrar_.Remove(this, NotificationType::BOOKMARK_MODEL_LOADED,
+                        Source<Profile>(this));
+      break;
+    default:
+      NOTREACHED();
   }
 }
 
diff --git a/chrome/browser/profiles/profile_impl.h b/chrome/browser/profiles/profile_impl.h
index 0809482..f5eb627 100644
--- a/chrome/browser/profiles/profile_impl.h
+++ b/chrome/browser/profiles/profile_impl.h
@@ -36,8 +36,7 @@
 // The default profile implementation.
 class ProfileImpl : public Profile,
                     public SpellCheckHostObserver,
-                    public NotificationObserver,
-                    public PrefServiceDelegate {
+                    public NotificationObserver {
  public:
   virtual ~ProfileImpl();
 
@@ -158,9 +157,8 @@
   // Does final initialization. Should be called after prefs were loaded.
   void DoFinalInit();
 
-  // PrefServiceDelegate implementation. Does final prefs initialization and
-  // calls Init().
-  virtual void OnPrefsLoaded(PrefService* prefs, bool success);
+  // Does final prefs initialization and calls Init().
+  void OnPrefsLoaded(bool success);
 
   void CreateWebDataService();
   FilePath GetPrefFilePath();
diff --git a/chrome/common/json_pref_store.cc b/chrome/common/json_pref_store.cc
index f8b054f..f391225 100644
--- a/chrome/common/json_pref_store.cc
+++ b/chrome/common/json_pref_store.cc
@@ -10,8 +10,8 @@
 #include "base/callback.h"
 #include "base/file_util.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop_proxy.h"
 #include "base/values.h"
-#include "content/browser/browser_thread.h"
 #include "content/common/json_value_serializer.h"
 
 namespace {
@@ -19,47 +19,54 @@
 // Some extensions we'll tack on to copies of the Preferences files.
 const FilePath::CharType* kBadExtension = FILE_PATH_LITERAL("bad");
 
-// Differentiates file loading between UI and FILE threads.
+// Differentiates file loading between origin thread and passed
+// (aka file) thread.
 class FileThreadDeserializer
     : public base::RefCountedThreadSafe<FileThreadDeserializer> {
  public:
-  explicit FileThreadDeserializer(JsonPrefStore* delegate)
-      : delegate_(delegate) {
+  explicit FileThreadDeserializer(JsonPrefStore* delegate,
+                                  base::MessageLoopProxy* file_loop_proxy)
+      : delegate_(delegate),
+        file_loop_proxy_(file_loop_proxy),
+        origin_loop_proxy_(base::MessageLoopProxy::CreateForCurrentThread()) {
   }
 
   void Start(const FilePath& path) {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-    BrowserThread::PostTask(
-        BrowserThread::FILE,
+    DCHECK(origin_loop_proxy_->BelongsToCurrentThread());
+    file_loop_proxy_->PostTask(
         FROM_HERE,
         NewRunnableMethod(this,
                           &FileThreadDeserializer::ReadFileAndReport,
                           path));
   }
 
-  // Deserializes JSON on the FILE thread.
+  // Deserializes JSON on the file thread.
   void ReadFileAndReport(const FilePath& path) {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+    DCHECK(file_loop_proxy_->BelongsToCurrentThread());
 
+    value_.reset(DoReading(path, &error_, &no_dir_));
+
+    origin_loop_proxy_->PostTask(
+        FROM_HERE,
+        NewRunnableMethod(this, &FileThreadDeserializer::ReportOnOriginThread));
+  }
+
+  // Reports deserialization result on the origin thread.
+  void ReportOnOriginThread() {
+    DCHECK(origin_loop_proxy_->BelongsToCurrentThread());
+    delegate_->OnFileRead(value_.release(), error_, no_dir_);
+  }
+
+  static Value* DoReading(const FilePath& path,
+                          PersistentPrefStore::PrefReadError* error,
+                          bool* no_dir) {
     int error_code;
     std::string error_msg;
     JSONFileValueSerializer serializer(path);
-    value_.reset(serializer.Deserialize(&error_code, &error_msg));
-
-    HandleErrors(value_.get(), path, error_code, error_msg, &error_);
-
-    no_dir_ = !file_util::PathExists(path.DirName());
-
-    BrowserThread::PostTask(
-        BrowserThread::UI,
-        FROM_HERE,
-        NewRunnableMethod(this, &FileThreadDeserializer::ReportOnUIThread));
-  }
-
-  // Reports deserialization result on the UI thread.
-  void ReportOnUIThread() {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-    delegate_->OnFileRead(value_.release(), error_, no_dir_);
+    Value* value = serializer.Deserialize(&error_code, &error_msg);
+    HandleErrors(value, path, error_code, error_msg, error);
+    *no_dir = !file_util::PathExists(path.DirName());
+    return value;
   }
 
   static void HandleErrors(const Value* value,
@@ -75,6 +82,8 @@
   PersistentPrefStore::PrefReadError error_;
   scoped_ptr<Value> value_;
   scoped_refptr<JsonPrefStore> delegate_;
+  scoped_refptr<base::MessageLoopProxy> file_loop_proxy_;
+  scoped_refptr<base::MessageLoopProxy> origin_loop_proxy_;
 };
 
 // static
@@ -128,9 +137,12 @@
 JsonPrefStore::JsonPrefStore(const FilePath& filename,
                              base::MessageLoopProxy* file_message_loop_proxy)
     : path_(filename),
+      file_message_loop_proxy_(file_message_loop_proxy),
       prefs_(new DictionaryValue()),
       read_only_(false),
-      writer_(filename, file_message_loop_proxy) {
+      writer_(filename, file_message_loop_proxy),
+      error_delegate_(NULL),
+      initialized_(false) {
 }
 
 JsonPrefStore::~JsonPrefStore() {
@@ -155,6 +167,10 @@
   observers_.RemoveObserver(observer);
 }
 
+bool JsonPrefStore::IsInitializationComplete() const {
+  return initialized_;
+}
+
 PrefStore::ReadResult JsonPrefStore::GetMutableValue(const std::string& key,
                                                      Value** result) {
   return prefs_->Get(key, result) ? READ_OK : READ_NO_VALUE;
@@ -194,11 +210,21 @@
                                PersistentPrefStore::PrefReadError error,
                                bool no_dir) {
   scoped_ptr<Value> value(value_owned);
+  initialized_ = true;
+
+  if (no_dir) {
+    FOR_EACH_OBSERVER(PrefStore::Observer,
+                      observers_,
+                      OnInitializationCompleted(false));
+    return;
+  }
+
   switch (error) {
     case PREF_READ_ERROR_ACCESS_DENIED:
     case PREF_READ_ERROR_FILE_OTHER:
     case PREF_READ_ERROR_FILE_LOCKED:
     case PREF_READ_ERROR_JSON_TYPE:
+    case PREF_READ_ERROR_FILE_NOT_SPECIFIED:
       read_only_ = true;
       break;
     case PREF_READ_ERROR_NONE:
@@ -216,53 +242,39 @@
       NOTREACHED() << "Unknown error: " << error;
   }
 
-  if (delegate_)
-    delegate_->OnPrefsRead(error, no_dir);
+  if (error_delegate_.get() && error != PREF_READ_ERROR_NONE)
+    error_delegate_->OnError(error);
+
+  FOR_EACH_OBSERVER(PrefStore::Observer,
+                    observers_,
+                    OnInitializationCompleted(true));
 }
 
-void JsonPrefStore::ReadPrefs(Delegate* delegate) {
-  DCHECK(delegate);
-  delegate_ = delegate;
-
+void JsonPrefStore::ReadPrefsAsync(ReadErrorDelegate *error_delegate) {
+  initialized_ = false;
+  error_delegate_.reset(error_delegate);
   if (path_.empty()) {
-    read_only_ = true;
-    delegate_->OnPrefsRead(PREF_READ_ERROR_FILE_NOT_SPECIFIED, false);
+    OnFileRead(NULL, PREF_READ_ERROR_FILE_NOT_SPECIFIED, false);
     return;
   }
 
-  // This guarantees that class will not be deleted while JSON is readed.
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
   // Start async reading of the preferences file. It will delete itself
   // in the end.
   scoped_refptr<FileThreadDeserializer> deserializer(
-      new FileThreadDeserializer(this));
+      new FileThreadDeserializer(this, file_message_loop_proxy_.get()));
   deserializer->Start(path_);
 }
 
 PersistentPrefStore::PrefReadError JsonPrefStore::ReadPrefs() {
-  delegate_ = NULL;
-
   if (path_.empty()) {
-    read_only_ = true;
+    OnFileRead(NULL, PREF_READ_ERROR_FILE_NOT_SPECIFIED, false);
     return PREF_READ_ERROR_FILE_NOT_SPECIFIED;
   }
 
-  int error_code = 0;
-  std::string error_msg;
-
-  JSONFileValueSerializer serializer(path_);
-  scoped_ptr<Value> value(serializer.Deserialize(&error_code, &error_msg));
-
-  PersistentPrefStore::PrefReadError error;
-  FileThreadDeserializer::HandleErrors(value.get(),
-                                       path_,
-                                       error_code,
-                                       error_msg,
-                                       &error);
-
-  OnFileRead(value.release(), error, false);
-
+  PrefReadError error;
+  bool no_dir;
+  Value* value = FileThreadDeserializer::DoReading(path_, &error, &no_dir);
+  OnFileRead(value, error, no_dir);
   return error;
 }
 
diff --git a/chrome/common/json_pref_store.h b/chrome/common/json_pref_store.h
index d8da37d0..8291a02 100644
--- a/chrome/common/json_pref_store.h
+++ b/chrome/common/json_pref_store.h
@@ -27,11 +27,6 @@
 class JsonPrefStore : public PersistentPrefStore,
                       public ImportantFileWriter::DataSerializer {
  public:
-  class Delegate {
-   public:
-    virtual void OnPrefsRead(PrefReadError error, bool no_dir) = 0;
-  };
-
   // |file_message_loop_proxy| is the MessageLoopProxy for a thread on which
   // file I/O can be done.
   JsonPrefStore(const FilePath& pref_filename,
@@ -43,6 +38,7 @@
                               const Value** result) const;
   virtual void AddObserver(PrefStore::Observer* observer);
   virtual void RemoveObserver(PrefStore::Observer* observer);
+  virtual bool IsInitializationComplete() const;
 
   // PersistentPrefStore overrides:
   virtual ReadResult GetMutableValue(const std::string& key, Value** result);
@@ -51,15 +47,16 @@
   virtual void RemoveValue(const std::string& key);
   virtual bool ReadOnly() const;
   virtual PrefReadError ReadPrefs();
-  // todo(altimofeev): move it to the PersistentPrefStore inteface.
-  void ReadPrefs(Delegate* delegate);
+  virtual void ReadPrefsAsync(ReadErrorDelegate* error_delegate);
   virtual bool WritePrefs();
   virtual void ScheduleWritePrefs();
   virtual void CommitPendingWrite();
   virtual void ReportValueChanged(const std::string& key);
 
   // This method is called after JSON file has been read. Method takes
-  // ownership of the |value| pointer.
+  // ownership of the |value| pointer. Note, this method is used with
+  // asynchronous file reading, so class exposes it only for the internal needs.
+  // (read: do not call it manually).
   void OnFileRead(Value* value_owned, PrefReadError error, bool no_dir);
 
  private:
@@ -67,6 +64,7 @@
   virtual bool SerializeData(std::string* output);
 
   FilePath path_;
+  scoped_refptr<base::MessageLoopProxy> file_message_loop_proxy_;
 
   scoped_ptr<DictionaryValue> prefs_;
 
@@ -77,7 +75,9 @@
 
   ObserverList<PrefStore::Observer, true> observers_;
 
-  Delegate* delegate_;
+  scoped_ptr<ReadErrorDelegate> error_delegate_;
+
+  bool initialized_;
 
   DISALLOW_COPY_AND_ASSIGN(JsonPrefStore);
 };
diff --git a/chrome/common/json_pref_store_unittest.cc b/chrome/common/json_pref_store_unittest.cc
index e7f34f52..d46f4328 100644
--- a/chrome/common/json_pref_store_unittest.cc
+++ b/chrome/common/json_pref_store_unittest.cc
@@ -5,6 +5,7 @@
 #include "base/file_util.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_temp_dir.h"
 #include "base/message_loop.h"
 #include "base/message_loop_proxy.h"
 #include "base/path_service.h"
@@ -13,12 +14,27 @@
 #include "base/threading/thread.h"
 #include "base/utf_string_conversions.h"
 #include "base/values.h"
-#include "base/memory/scoped_temp_dir.h"
-#include "chrome/common/json_pref_store.h"
 #include "chrome/common/chrome_paths.h"
+#include "chrome/common/json_pref_store.h"
 #include "chrome/common/pref_names.h"
+#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+namespace {
+
+class MockPrefStoreObserver : public PrefStore::Observer {
+ public:
+  MOCK_METHOD1(OnPrefValueChanged, void (const std::string&));
+  MOCK_METHOD1(OnInitializationCompleted, void (bool));
+};
+
+class MockReadErrorDelegate : public PersistentPrefStore::ReadErrorDelegate {
+ public:
+  MOCK_METHOD1(OnError, void(PersistentPrefStore::PrefReadError));
+};
+
+}  // namespace
+
 class JsonPrefStoreTest : public testing::Test {
  protected:
   virtual void SetUp() {
@@ -70,28 +86,11 @@
                                            moved_aside));
 }
 
-TEST_F(JsonPrefStoreTest, Basic) {
-  ASSERT_TRUE(file_util::CopyFile(data_dir_.AppendASCII("read.json"),
-                                  temp_dir_.path().AppendASCII("write.json")));
-
-  // Test that the persistent value can be loaded.
-  FilePath input_file = temp_dir_.path().AppendASCII("write.json");
-  ASSERT_TRUE(file_util::PathExists(input_file));
-  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:
-  // {
-  //   "homepage": "http://www.cnn.com",
-  //   "some_directory": "/usr/local/",
-  //   "tabs": {
-  //     "new_windows_in_tabs": true,
-  //     "max_tabs": 20
-  //   }
-  // }
-
+// This function is used to avoid code duplication while testing synchronous and
+// asynchronous version of the JsonPrefStore loading.
+void RunBasicJsonPrefStoreTest(JsonPrefStore *pref_store,
+                               const FilePath& output_file,
+                               const FilePath& golden_output_file) {
   const char kNewWindowsInTabs[] = "tabs.new_windows_in_tabs";
   const char kMaxTabs[] = "tabs.max_tabs";
   const char kLongIntPref[] = "long_int.pref";
@@ -152,11 +151,96 @@
   EXPECT_EQ(214748364842LL, value);
 
   // Serialize and compare to expected output.
-  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());
   MessageLoop::current()->RunAllPending();
   EXPECT_TRUE(file_util::TextContentsEqual(golden_output_file, output_file));
   ASSERT_TRUE(file_util::Delete(output_file, false));
 }
+
+TEST_F(JsonPrefStoreTest, Basic) {
+  ASSERT_TRUE(file_util::CopyFile(data_dir_.AppendASCII("read.json"),
+                                  temp_dir_.path().AppendASCII("write.json")));
+
+  // Test that the persistent value can be loaded.
+  FilePath input_file = temp_dir_.path().AppendASCII("write.json");
+  ASSERT_TRUE(file_util::PathExists(input_file));
+  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:
+  // {
+  //   "homepage": "http://www.cnn.com",
+  //   "some_directory": "/usr/local/",
+  //   "tabs": {
+  //     "new_windows_in_tabs": true,
+  //     "max_tabs": 20
+  //   }
+  // }
+
+  RunBasicJsonPrefStoreTest(pref_store,
+                            input_file,
+                            data_dir_.AppendASCII("write.golden.json"));
+}
+
+TEST_F(JsonPrefStoreTest, BasicAsync) {
+  ASSERT_TRUE(file_util::CopyFile(data_dir_.AppendASCII("read.json"),
+                                  temp_dir_.path().AppendASCII("write.json")));
+
+  // Test that the persistent value can be loaded.
+  FilePath input_file = temp_dir_.path().AppendASCII("write.json");
+  ASSERT_TRUE(file_util::PathExists(input_file));
+  scoped_refptr<JsonPrefStore> pref_store =
+      new JsonPrefStore(input_file, message_loop_proxy_.get());
+
+  MockPrefStoreObserver mock_observer;
+  pref_store->AddObserver(&mock_observer);
+
+  MockReadErrorDelegate *mock_error_delegate = new MockReadErrorDelegate;
+  pref_store->ReadPrefsAsync(mock_error_delegate);
+
+  EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1);
+  EXPECT_CALL(*mock_error_delegate,
+              OnError(PersistentPrefStore::PREF_READ_ERROR_NONE)).Times(0);
+  message_loop_.RunAllPending();
+  pref_store->RemoveObserver(&mock_observer);
+
+  ASSERT_FALSE(pref_store->ReadOnly());
+
+  // The JSON file looks like this:
+  // {
+  //   "homepage": "http://www.cnn.com",
+  //   "some_directory": "/usr/local/",
+  //   "tabs": {
+  //     "new_windows_in_tabs": true,
+  //     "max_tabs": 20
+  //   }
+  // }
+
+  RunBasicJsonPrefStoreTest(pref_store,
+                            input_file,
+                            data_dir_.AppendASCII("write.golden.json"));
+}
+
+// Tests asynchronous reading of the file when there is no file.
+TEST_F(JsonPrefStoreTest, AsyncNonExistingFile) {
+  FilePath bogus_input_file = data_dir_.AppendASCII("read.txt");
+  ASSERT_FALSE(file_util::PathExists(bogus_input_file));
+  scoped_refptr<JsonPrefStore> pref_store =
+      new JsonPrefStore(bogus_input_file, message_loop_proxy_.get());
+  MockPrefStoreObserver mock_observer;
+  pref_store->AddObserver(&mock_observer);
+
+  MockReadErrorDelegate *mock_error_delegate = new MockReadErrorDelegate;
+  pref_store->ReadPrefsAsync(mock_error_delegate);
+
+  EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1);
+  EXPECT_CALL(*mock_error_delegate,
+              OnError(PersistentPrefStore::PREF_READ_ERROR_NO_FILE)).Times(1);
+  message_loop_.RunAllPending();
+  pref_store->RemoveObserver(&mock_observer);
+
+  EXPECT_FALSE(pref_store->ReadOnly());
+}
diff --git a/chrome/common/persistent_pref_store.h b/chrome/common/persistent_pref_store.h
index 620fee8..0f007c5a 100644
--- a/chrome/common/persistent_pref_store.h
+++ b/chrome/common/persistent_pref_store.h
@@ -34,6 +34,13 @@
     PREF_READ_ERROR_FILE_NOT_SPECIFIED
   };
 
+  class ReadErrorDelegate {
+   public:
+    virtual ~ReadErrorDelegate() {}
+
+    virtual void OnError(PrefReadError error) = 0;
+  };
+
   // Equivalent to PrefStore::GetValue but returns a mutable value.
   virtual ReadResult GetMutableValue(const std::string& key,
                                      Value** result) = 0;
@@ -62,9 +69,16 @@
   // read errors during startup.
   virtual bool ReadOnly() const = 0;
 
-  // Reads the preferences from disk.
+  // Reads the preferences from disk. Notifies observers via
+  // "PrefStore::OnInitializationCompleted" when done.
   virtual PrefReadError ReadPrefs() = 0;
 
+  // Reads the preferences from disk asynchronously. Notifies observers via
+  // "PrefStore::OnInitializationCompleted" when done. Also it fires
+  // |error_delegate| if it is not NULL and reading error has occurred.
+  // Owns |error_delegate|.
+  virtual void ReadPrefsAsync(ReadErrorDelegate* error_delegate) = 0;
+
   // Writes the preferences to disk immediately.
   virtual bool WritePrefs() = 0;
 
diff --git a/chrome/common/pref_store.h b/chrome/common/pref_store.h
index 48b51a3..eec74e9 100644
--- a/chrome/common/pref_store.h
+++ b/chrome/common/pref_store.h
@@ -30,7 +30,7 @@
     // Called when the value for the given |key| in the store changes.
     virtual void OnPrefValueChanged(const std::string& key) = 0;
     // Notification about the PrefStore being fully initialized.
-    virtual void OnInitializationCompleted() = 0;
+    virtual void OnInitializationCompleted(bool succeeded) = 0;
   };
 
   // Return values for GetValue().
diff --git a/chrome/common/pref_store_observer_mock.h b/chrome/common/pref_store_observer_mock.h
index 3aadf342..0218d339 100644
--- a/chrome/common/pref_store_observer_mock.h
+++ b/chrome/common/pref_store_observer_mock.h
@@ -17,7 +17,7 @@
   virtual ~PrefStoreObserverMock();
 
   MOCK_METHOD1(OnPrefValueChanged, void(const std::string&));
-  MOCK_METHOD0(OnInitializationCompleted, void());
+  MOCK_METHOD1(OnInitializationCompleted, void(bool));
 
  private:
   DISALLOW_COPY_AND_ASSIGN(PrefStoreObserverMock);
diff --git a/chrome/test/testing_pref_service.cc b/chrome/test/testing_pref_service.cc
index 6d792b9..79e98cc 100644
--- a/chrome/test/testing_pref_service.cc
+++ b/chrome/test/testing_pref_service.cc
@@ -26,7 +26,7 @@
                   recommended_platform_prefs,
                   NULL,
                   new DefaultPrefStore(),
-                  NULL),
+                  false),
       managed_platform_prefs_(managed_platform_prefs),
       user_prefs_(user_prefs),
       recommended_platform_prefs_(recommended_platform_prefs) {
@@ -111,4 +111,3 @@
   EXPECT_EQ(&local_state_, browser_process_->local_state());
   browser_process_->SetLocalState(NULL);
 }
-