Remove ProfileStatistics calculation on Startup and Shutdown

In order to reduce the latency on shutdown and possibly also on
startup, ProfileStatistics will not be precalculated and stored in
ProfileAttributesStorage anymore but calculated when the removal of a
profile is requested.
This requires the profile to be loaded if it isn't already loaded.

BUG=716267
[email protected]

Review-Url: https://codereview.chromium.org/2909053002
Cr-Commit-Position: refs/heads/master@{#477257}
diff --git a/chrome/browser/profiles/profile_attributes_entry.cc b/chrome/browser/profiles/profile_attributes_entry.cc
index 193f85ce..5165629 100644
--- a/chrome/browser/profiles/profile_attributes_entry.cc
+++ b/chrome/browser/profiles/profile_attributes_entry.cc
@@ -134,44 +134,6 @@
       profile_index());
 }
 
-bool ProfileAttributesEntry::HasStatsBrowsingHistory() const {
-  return profile_info_cache_->HasStatsBrowsingHistoryOfProfileAtIndex(
-      profile_index());
-}
-
-int ProfileAttributesEntry::GetStatsBrowsingHistory() const {
-  return profile_info_cache_->GetStatsBrowsingHistoryOfProfileAtIndex(
-      profile_index());
-}
-
-bool ProfileAttributesEntry::HasStatsPasswords() const {
-  return profile_info_cache_->HasStatsPasswordsOfProfileAtIndex(
-      profile_index());
-}
-
-int ProfileAttributesEntry::GetStatsPasswords() const {
-  return profile_info_cache_->GetStatsPasswordsOfProfileAtIndex(
-      profile_index());
-}
-
-bool ProfileAttributesEntry::HasStatsBookmarks() const {
-  return profile_info_cache_->HasStatsBookmarksOfProfileAtIndex(
-      profile_index());
-}
-
-int ProfileAttributesEntry::GetStatsBookmarks() const {
-  return profile_info_cache_->GetStatsBookmarksOfProfileAtIndex(
-      profile_index());
-}
-
-bool ProfileAttributesEntry::HasStatsSettings() const {
-  return profile_info_cache_->HasStatsSettingsOfProfileAtIndex(profile_index());
-}
-
-int ProfileAttributesEntry::GetStatsSettings() const {
-  return profile_info_cache_->GetStatsSettingsOfProfileAtIndex(profile_index());
-}
-
 void ProfileAttributesEntry::SetName(const base::string16& name) {
   profile_info_cache_->SetNameOfProfileAtIndex(profile_index(), name);
 }
@@ -262,25 +224,6 @@
       profile_index(), icon_index);
 }
 
-void ProfileAttributesEntry::SetStatsBrowsingHistory(int value) {
-  profile_info_cache_->SetStatsBrowsingHistoryOfProfileAtIndex(profile_index(),
-                                                               value);
-}
-
-void ProfileAttributesEntry::SetStatsPasswords(int value) {
-  profile_info_cache_->SetStatsPasswordsOfProfileAtIndex(profile_index(),
-                                                         value);
-}
-
-void ProfileAttributesEntry::SetStatsBookmarks(int value) {
-  profile_info_cache_->SetStatsBookmarksOfProfileAtIndex(profile_index(),
-                                                         value);
-}
-
-void ProfileAttributesEntry::SetStatsSettings(int value) {
-  profile_info_cache_->SetStatsSettingsOfProfileAtIndex(profile_index(), value);
-}
-
 void ProfileAttributesEntry::SetAuthInfo(
     const std::string& gaia_id, const base::string16& user_name) {
   profile_info_cache_->SetAuthInfoOfProfileAtIndex(
diff --git a/chrome/browser/profiles/profile_attributes_entry.h b/chrome/browser/profiles/profile_attributes_entry.h
index 19e2380..3c98b9992 100644
--- a/chrome/browser/profiles/profile_attributes_entry.h
+++ b/chrome/browser/profiles/profile_attributes_entry.h
@@ -87,16 +87,6 @@
   // Returns the index of the default icon used by the profile.
   size_t GetAvatarIconIndex() const;
 
-  // Browsing statistics of the profile.
-  bool HasStatsBrowsingHistory() const;
-  int GetStatsBrowsingHistory() const;
-  bool HasStatsPasswords() const;
-  int GetStatsPasswords() const;
-  bool HasStatsBookmarks() const;
-  int GetStatsBookmarks() const;
-  bool HasStatsSettings() const;
-  int GetStatsSettings() const;
-
   void SetName(const base::string16& name);
   void SetShortcutName(const base::string16& name);
   void SetActiveTimeToNow();
@@ -116,12 +106,6 @@
   void SetIsAuthError(bool value);
   void SetAvatarIconIndex(size_t icon_index);
 
-  // Get the statistics of the profile.
-  void SetStatsBrowsingHistory(int value);
-  void SetStatsPasswords(int value);
-  void SetStatsBookmarks(int value);
-  void SetStatsSettings(int value);
-
   void SetAuthInfo(const std::string& gaia_id, const base::string16& user_name);
 
   // Lock/Unlock the profile, should be called only if force-sign-in is enabled.
diff --git a/chrome/browser/profiles/profile_attributes_storage_unittest.cc b/chrome/browser/profiles/profile_attributes_storage_unittest.cc
index 403a401..55c58da 100644
--- a/chrome/browser/profiles/profile_attributes_storage_unittest.cc
+++ b/chrome/browser/profiles/profile_attributes_storage_unittest.cc
@@ -267,11 +267,6 @@
   TEST_BOOL_ACCESSORS(ProfileAttributesEntry, entry, IsUsingDefaultName);
   TEST_BOOL_ACCESSORS(ProfileAttributesEntry, entry, IsUsingDefaultAvatar);
   TEST_BOOL_ACCESSORS(ProfileAttributesEntry, entry, IsAuthError);
-
-  TEST_STAT_ACCESSORS(ProfileAttributesEntry, entry, StatsBrowsingHistory);
-  TEST_STAT_ACCESSORS(ProfileAttributesEntry, entry, StatsBookmarks);
-  TEST_STAT_ACCESSORS(ProfileAttributesEntry, entry, StatsPasswords);
-  TEST_STAT_ACCESSORS(ProfileAttributesEntry, entry, StatsSettings);
 }
 
 TEST_F(ProfileAttributesStorageTest, AuthInfo) {
diff --git a/chrome/browser/profiles/profile_info_cache.cc b/chrome/browser/profiles/profile_info_cache.cc
index c816c9b..2078c029 100644
--- a/chrome/browser/profiles/profile_info_cache.cc
+++ b/chrome/browser/profiles/profile_info_cache.cc
@@ -63,10 +63,12 @@
 const char kProfileIsEphemeral[] = "is_ephemeral";
 const char kActiveTimeKey[] = "active_time";
 const char kIsAuthErrorKey[] = "is_auth_error";
-const char kStatsBrowsingHistoryKey[] = "stats_browsing_history";
-const char kStatsPasswordsKey[] = "stats_passwords";
-const char kStatsBookmarksKey[] = "stats_bookmarks";
-const char kStatsSettingsKey[] = "stats_settings";
+
+// TODO(dullweber): Remove these constants after the stored data is removed.
+const char kStatsBrowsingHistoryKeyDeprecated[] = "stats_browsing_history";
+const char kStatsPasswordsKeyDeprecated[] = "stats_passwords";
+const char kStatsBookmarksKeyDeprecated[] = "stats_bookmarks";
+const char kStatsSettingsKeyDeprecated[] = "stats_settings";
 
 typedef std::vector<unsigned char> ImageData;
 
@@ -171,6 +173,8 @@
   // profile names.
   if (!disable_avatar_download_for_testing_)
     MigrateLegacyProfileNamesAndDownloadAvatars();
+
+  RemoveDeprecatedStatistics();
 }
 
 ProfileInfoCache::~ProfileInfoCache() {
@@ -478,55 +482,6 @@
   return icon_index;
 }
 
-bool ProfileInfoCache::HasStatsBrowsingHistoryOfProfileAtIndex(size_t index)
-    const {
-  int value = 0;
-  return GetInfoForProfileAtIndex(index)->GetInteger(kStatsBrowsingHistoryKey,
-                                                     &value);
-}
-
-int ProfileInfoCache::GetStatsBrowsingHistoryOfProfileAtIndex(size_t index)
-    const {
-  int value = 0;
-  GetInfoForProfileAtIndex(index)->GetInteger(kStatsBrowsingHistoryKey, &value);
-  return value;
-}
-
-bool ProfileInfoCache::HasStatsPasswordsOfProfileAtIndex(size_t index) const {
-  int value = 0;
-  return GetInfoForProfileAtIndex(index)->GetInteger(kStatsPasswordsKey,
-                                                     &value);
-}
-
-int ProfileInfoCache::GetStatsPasswordsOfProfileAtIndex(size_t index) const {
-  int value = 0;
-  GetInfoForProfileAtIndex(index)->GetInteger(kStatsPasswordsKey, &value);
-  return value;
-}
-
-bool ProfileInfoCache::HasStatsBookmarksOfProfileAtIndex(size_t index) const {
-  int value = 0;
-  return GetInfoForProfileAtIndex(index)->GetInteger(kStatsBookmarksKey,
-                                                     &value);
-}
-
-int ProfileInfoCache::GetStatsBookmarksOfProfileAtIndex(size_t index) const {
-  int value = 0;
-  GetInfoForProfileAtIndex(index)->GetInteger(kStatsBookmarksKey, &value);
-  return value;
-}
-
-bool ProfileInfoCache::HasStatsSettingsOfProfileAtIndex(size_t index) const {
-  int value = 0;
-  return GetInfoForProfileAtIndex(index)->GetInteger(kStatsSettingsKey, &value);
-}
-
-int ProfileInfoCache::GetStatsSettingsOfProfileAtIndex(size_t index) const {
-  int value = 0;
-  GetInfoForProfileAtIndex(index)->GetInteger(kStatsSettingsKey, &value);
-  return value;
-}
-
 void ProfileInfoCache::SetProfileActiveTimeAtIndex(size_t index) {
   if (base::Time::Now() - GetProfileActiveTimeAtIndex(index) <
       base::TimeDelta::FromHours(1)) {
@@ -832,38 +787,6 @@
   SetInfoForProfileAtIndex(index, std::move(info));
 }
 
-void ProfileInfoCache::SetStatsBrowsingHistoryOfProfileAtIndex(size_t index,
-                                                               int value) {
-  std::unique_ptr<base::DictionaryValue> info(
-      GetInfoForProfileAtIndex(index)->DeepCopy());
-  info->SetInteger(kStatsBrowsingHistoryKey, value);
-  SetInfoForProfileAtIndex(index, std::move(info));
-}
-
-void ProfileInfoCache::SetStatsPasswordsOfProfileAtIndex(size_t index,
-                                                         int value) {
-  std::unique_ptr<base::DictionaryValue> info(
-      GetInfoForProfileAtIndex(index)->DeepCopy());
-  info->SetInteger(kStatsPasswordsKey, value);
-  SetInfoForProfileAtIndex(index, std::move(info));
-}
-
-void ProfileInfoCache::SetStatsBookmarksOfProfileAtIndex(size_t index,
-                                                         int value) {
-  std::unique_ptr<base::DictionaryValue> info(
-      GetInfoForProfileAtIndex(index)->DeepCopy());
-  info->SetInteger(kStatsBookmarksKey, value);
-  SetInfoForProfileAtIndex(index, std::move(info));
-}
-
-void ProfileInfoCache::SetStatsSettingsOfProfileAtIndex(size_t index,
-                                                        int value) {
-  std::unique_ptr<base::DictionaryValue> info(
-      GetInfoForProfileAtIndex(index)->DeepCopy());
-  info->SetInteger(kStatsSettingsKey, value);
-  SetInfoForProfileAtIndex(index, std::move(info));
-}
-
 void ProfileInfoCache::NotifyIsSigninRequiredChanged(
     const base::FilePath& profile_path) {
   for (auto& observer : observer_list_)
@@ -1174,6 +1097,19 @@
 #endif
 }
 
+void ProfileInfoCache::RemoveDeprecatedStatistics() {
+  for (size_t i = 0; i < GetNumberOfProfiles(); i++) {
+    if (GetInfoForProfileAtIndex(i)->HasKey(kStatsBookmarksKeyDeprecated)) {
+      auto info = GetInfoForProfileAtIndex(i)->CreateDeepCopy();
+      info->Remove(kStatsBookmarksKeyDeprecated, nullptr);
+      info->Remove(kStatsBrowsingHistoryKeyDeprecated, nullptr);
+      info->Remove(kStatsPasswordsKeyDeprecated, nullptr);
+      info->Remove(kStatsSettingsKeyDeprecated, nullptr);
+      SetInfoForProfileAtIndex(i, std::move(info));
+    }
+  }
+}
+
 void ProfileInfoCache::AddProfile(
     const base::FilePath& profile_path,
     const base::string16& name,
diff --git a/chrome/browser/profiles/profile_info_cache.h b/chrome/browser/profiles/profile_info_cache.h
index 3d3374c..4a0e2aed 100644
--- a/chrome/browser/profiles/profile_info_cache.h
+++ b/chrome/browser/profiles/profile_info_cache.h
@@ -108,16 +108,6 @@
 
   size_t GetAvatarIconIndexOfProfileAtIndex(size_t index) const;
 
-  // Statistics
-  bool HasStatsBrowsingHistoryOfProfileAtIndex(size_t index) const;
-  int GetStatsBrowsingHistoryOfProfileAtIndex(size_t index) const;
-  bool HasStatsPasswordsOfProfileAtIndex(size_t index) const;
-  int GetStatsPasswordsOfProfileAtIndex(size_t index) const;
-  bool HasStatsBookmarksOfProfileAtIndex(size_t index) const;
-  int GetStatsBookmarksOfProfileAtIndex(size_t index) const;
-  bool HasStatsSettingsOfProfileAtIndex(size_t index) const;
-  int GetStatsSettingsOfProfileAtIndex(size_t index) const;
-
   void SetProfileActiveTimeAtIndex(size_t index);
   // Warning: This will re-sort profiles and thus may change indices!
   void SetNameOfProfileAtIndex(size_t index, const base::string16& name);
@@ -148,12 +138,6 @@
   void SetProfileIsUsingDefaultAvatarAtIndex(size_t index, bool value);
   void SetProfileIsAuthErrorAtIndex(size_t index, bool value);
 
-  // Statistics
-  void SetStatsBrowsingHistoryOfProfileAtIndex(size_t index, int value);
-  void SetStatsPasswordsOfProfileAtIndex(size_t index, int value);
-  void SetStatsBookmarksOfProfileAtIndex(size_t index, int value);
-  void SetStatsSettingsOfProfileAtIndex(size_t index, int value);
-
   // Notify IsSignedInRequired to all observer
   void NotifyIsSigninRequiredChanged(const base::FilePath& profile_path);
 
@@ -246,6 +230,10 @@
   // used by the profiles.
   void MigrateLegacyProfileNamesAndDownloadAvatars();
 
+  // Remove statistics values that have previously been stored and are not used
+  // anymore.
+  void RemoveDeprecatedStatistics();
+
   std::vector<std::string> sorted_keys_;
 
   mutable base::ObserverList<ProfileInfoCacheObserver> observer_list_;
diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc
index 5f2317b7..037d7068 100644
--- a/chrome/browser/profiles/profile_manager.cc
+++ b/chrome/browser/profiles/profile_manager.cc
@@ -506,7 +506,12 @@
                                  bool incognito,
                                  const ProfileLoadedCallback& callback) {
   const base::FilePath profile_path = user_data_dir().AppendASCII(profile_name);
+  return LoadProfileByPath(profile_path, incognito, callback);
+}
 
+bool ProfileManager::LoadProfileByPath(const base::FilePath& profile_path,
+                                       bool incognito,
+                                       const ProfileLoadedCallback& callback) {
   ProfileAttributesEntry* entry = nullptr;
   if (!GetProfileAttributesStorage().GetProfileAttributesWithPath(profile_path,
                                                                   &entry)) {
@@ -1188,17 +1193,6 @@
       chrome::NOTIFICATION_PROFILE_ADDED,
       content::Source<Profile>(profile),
       content::NotificationService::NoDetails());
-
-#if !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_CHROMEOS)
-  // Record statistics to ProfileInfoCache if statistics were not recorded
-  // during shutdown, i.e. the last shutdown was a system shutdown or a crash.
-  if (!profile->IsGuestSession() && !profile->IsSystemProfile() &&
-      !profile->IsNewProfile() && !go_off_the_record &&
-      profile->GetLastSessionExitType() != Profile::EXIT_NORMAL) {
-    ProfileStatisticsFactory::GetForProfile(profile)->GatherStatistics(
-        profiles::ProfileStatisticsCallback());
-  }
-#endif
 }
 
 void ProfileManager::DoFinalInitForServices(Profile* profile,
@@ -1694,16 +1688,6 @@
     // Delete if the profile is an ephemeral profile.
     g_browser_process->profile_manager()
         ->ScheduleForcedEphemeralProfileForDeletion(path);
-  } else {
-#if !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_CHROMEOS)
-    // Gather statistics and store into ProfileInfoCache. For incognito profile
-    // we gather the statistics of its parent profile instead, because a window
-    // of the parent profile was open.
-    if (!profile->IsSystemProfile() && !original_profile->IsSystemProfile()) {
-      ProfileStatisticsFactory::GetForProfile(original_profile)->
-          GatherStatistics(profiles::ProfileStatisticsCallback());
-    }
-#endif
   }
 }
 
diff --git a/chrome/browser/profiles/profile_manager.h b/chrome/browser/profiles/profile_manager.h
index 083970a..607736e 100644
--- a/chrome/browser/profiles/profile_manager.h
+++ b/chrome/browser/profiles/profile_manager.h
@@ -104,6 +104,9 @@
   bool LoadProfile(const std::string& profile_name,
                    bool incognito,
                    const ProfileLoadedCallback& callback);
+  bool LoadProfileByPath(const base::FilePath& profile_path,
+                         bool incognito,
+                         const ProfileLoadedCallback& callback);
 
   // Explicit asynchronous creation of a profile located at |profile_path|.
   // If the profile has already been created then callback is called
diff --git a/chrome/browser/profiles/profile_statistics.cc b/chrome/browser/profiles/profile_statistics.cc
index 72808da6..284b34d4 100644
--- a/chrome/browser/profiles/profile_statistics.cc
+++ b/chrome/browser/profiles/profile_statistics.cc
@@ -35,80 +35,7 @@
   aggregator_->AddCallbackAndStartAggregator(callback);
 }
 
-bool ProfileStatistics::HasAggregator() const {
-  return aggregator_ != nullptr;
-}
-
-ProfileStatisticsAggregator* ProfileStatistics::GetAggregator() const {
-  return aggregator_.get();
-}
-
 void ProfileStatistics::DeregisterAggregator() {
   aggregator_ = nullptr;
 }
 
-// static
-profiles::ProfileCategoryStats
-    ProfileStatistics::GetProfileStatisticsFromAttributesStorage(
-        const base::FilePath& profile_path) {
-  ProfileAttributesEntry* entry = nullptr;
-  bool has_entry = g_browser_process->profile_manager()->
-      GetProfileAttributesStorage().
-      GetProfileAttributesWithPath(profile_path, &entry);
-
-  profiles::ProfileCategoryStats stats;
-  profiles::ProfileCategoryStat stat;
-
-  stat.category = profiles::kProfileStatisticsBrowsingHistory;
-  stat.success = has_entry ? entry->HasStatsBrowsingHistory() : false;
-  stat.count = stat.success ? entry->GetStatsBrowsingHistory() : 0;
-  stats.push_back(stat);
-
-  stat.category = profiles::kProfileStatisticsPasswords;
-  stat.success = has_entry ? entry->HasStatsPasswords() : false;
-  stat.count = stat.success ? entry->GetStatsPasswords() : 0;
-  stats.push_back(stat);
-
-  stat.category = profiles::kProfileStatisticsBookmarks;
-  stat.success = has_entry ? entry->HasStatsBookmarks() : false;
-  stat.count = stat.success ? entry->GetStatsBookmarks() : 0;
-  stats.push_back(stat);
-
-  stat.category = profiles::kProfileStatisticsSettings;
-  stat.success = has_entry ? entry->HasStatsSettings() : false;
-  stat.count = stat.success ? entry->GetStatsSettings() : 0;
-  stats.push_back(stat);
-
-  return stats;
-}
-
-// static
-void ProfileStatistics::SetProfileStatisticsToAttributesStorage(
-    const base::FilePath& profile_path,
-    const std::string& category,
-    int count) {
-  // |profile_manager()| may return a null pointer.
-  ProfileManager* profile_manager = g_browser_process->profile_manager();
-  if (!profile_manager)
-    return;
-
-  ProfileAttributesEntry* entry = nullptr;
-  if (!profile_manager->GetProfileAttributesStorage().
-          GetProfileAttributesWithPath(profile_path, &entry)) {
-    // It is possible to have the profile attributes entry absent, e.g. the
-    // profile is scheduled for deletion during the async statistics task.
-    return;
-  }
-
-  if (category == profiles::kProfileStatisticsBrowsingHistory) {
-    entry->SetStatsBrowsingHistory(count);
-  } else if (category == profiles::kProfileStatisticsPasswords) {
-    entry->SetStatsPasswords(count);
-  } else if (category == profiles::kProfileStatisticsBookmarks) {
-    entry->SetStatsBookmarks(count);
-  } else if (category == profiles::kProfileStatisticsSettings) {
-    entry->SetStatsSettings(count);
-  } else {
-    NOTREACHED();
-  }
-}
diff --git a/chrome/browser/profiles/profile_statistics.h b/chrome/browser/profiles/profile_statistics.h
index 7f254f10..76918c5 100644
--- a/chrome/browser/profiles/profile_statistics.h
+++ b/chrome/browser/profiles/profile_statistics.h
@@ -11,9 +11,6 @@
 #include "chrome/browser/profiles/profile_statistics_common.h"
 #include "components/keyed_service/core/keyed_service.h"
 
-namespace base {
-class FilePath;
-}  // namespace base
 class Profile;
 class ProfileStatisticsAggregator;
 
@@ -24,30 +21,12 @@
   // Profile Statistics --------------------------------------------------------
 
   // This function collects statistical information about |profile|, also
-  // returns the information via |callback| if |callback| is not null. The
-  // statistical information is also copied to ProfileAttributesStorage.
+  // returns the information via |callback| if |callback| is not null.
   // Currently bookmarks, history, logins and preferences are counted. The
   // callback function will probably be called more than once, so binding
-  // parameters with bind::Passed() is prohibited. Most of the async tasks
-  // involved in this function can be cancelled if |tracker| is not null.
+  // parameters with bind::Passed() is prohibited.
   void GatherStatistics(const profiles::ProfileStatisticsCallback& callback);
 
-  bool HasAggregator() const;
-  ProfileStatisticsAggregator* GetAggregator() const;
-
-  // ProfileAttributesStorage --------------------------------------------------
-
-  // Gets statistical information from the profiles attributes storage.
-  static profiles::ProfileCategoryStats
-      GetProfileStatisticsFromAttributesStorage(
-           const base::FilePath& profile_path);
-
-  // Sets an individual statistic to the profiles attributes storage.
-  static void SetProfileStatisticsToAttributesStorage(
-      const base::FilePath& profile_path,
-      const std::string& category,
-      int count);
-
  private:
   friend class ProfileStatisticsFactory;
 
diff --git a/chrome/browser/profiles/profile_statistics_aggregator.cc b/chrome/browser/profiles/profile_statistics_aggregator.cc
index 60513ec..c61688c 100644
--- a/chrome/browser/profiles/profile_statistics_aggregator.cc
+++ b/chrome/browser/profiles/profile_statistics_aggregator.cc
@@ -28,9 +28,6 @@
 
 namespace {
 
-// Number of statistic categories calculated by StartAggregator.
-const int kProfileStatisticCategories = 4;
-
 // Callback for each pref. Every one that should be counted as a changed
 // user pref will cause *count to be incremented.
 void AccumulatePrefStats(const PrefService* pref_service,
@@ -83,40 +80,26 @@
   // Try to cancel tasks.
   tracker_.TryCancelAll();
   counters_.clear();
-
   // Initiate bookmark counting.
   bookmarks::BookmarkModel* bookmark_model =
-      BookmarkModelFactory::GetForBrowserContextIfExists(profile_);
-  if (bookmark_model) {
-    AddCounter(
-        base::MakeUnique<browsing_data::BookmarkCounter>(bookmark_model));
-  } else {
-    StatisticsCallbackFailure(profiles::kProfileStatisticsBookmarks);
-  }
+      BookmarkModelFactory::GetForBrowserContext(profile_);
+  AddCounter(base::MakeUnique<browsing_data::BookmarkCounter>(bookmark_model));
 
   // Initiate history counting.
   history::HistoryService* history_service =
-      HistoryServiceFactory::GetForProfileWithoutCreating(profile_);
-
-  if (history_service) {
-    AddCounter(base::MakeUnique<browsing_data::HistoryCounter>(
-        history_service,
-        browsing_data::HistoryCounter::GetUpdatedWebHistoryServiceCallback(),
-        /*sync_service=*/nullptr));
-  } else {
-    StatisticsCallbackFailure(profiles::kProfileStatisticsBrowsingHistory);
-  }
+      HistoryServiceFactory::GetForProfile(profile_,
+                                           ServiceAccessType::EXPLICIT_ACCESS);
+  AddCounter(base::MakeUnique<browsing_data::HistoryCounter>(
+      history_service,
+      browsing_data::HistoryCounter::GetUpdatedWebHistoryServiceCallback(),
+      /*sync_service=*/nullptr));
 
   // Initiate stored password counting.
   scoped_refptr<password_manager::PasswordStore> password_store =
       PasswordStoreFactory::GetForProfile(
           profile_, ServiceAccessType::EXPLICIT_ACCESS);
-  if (password_store) {
-    AddCounter(base::MakeUnique<browsing_data::PasswordsCounter>(
-        password_store, /*sync_service=*/nullptr));
-  } else {
-    StatisticsCallbackFailure(profiles::kProfileStatisticsPasswords);
-  }
+  AddCounter(base::MakeUnique<browsing_data::PasswordsCounter>(
+      password_store, /*sync_service=*/nullptr));
 
   // Initiate preference counting (async).
   tracker_.PostTaskAndReplyWithResult(
@@ -160,11 +143,8 @@
     stats_callback.Run(profile_category_stats_);
   }
 
-  if (result.success) {
-    ProfileStatistics::SetProfileStatisticsToAttributesStorage(
-        profile_path_, datum.category, result.count);
-  }
-  if (profile_category_stats_.size() == kProfileStatisticCategories) {
+  if (profile_category_stats_.size() ==
+      profiles::kProfileStatisticsCategories.size()) {
     if (done_callback_)
       done_callback_.Run();
   }
diff --git a/chrome/browser/profiles/profile_statistics_browsertest.cc b/chrome/browser/profiles/profile_statistics_browsertest.cc
index c7dc5a64..835f2ad 100644
--- a/chrome/browser/profiles/profile_statistics_browsertest.cc
+++ b/chrome/browser/profiles/profile_statistics_browsertest.cc
@@ -188,12 +188,9 @@
       ProfileStatisticsFactory::GetForProfile(profile);
 
   ProfileStatisticsAggregatorState state;
-  EXPECT_FALSE(profile_stat->HasAggregator());
   profile_stat->GatherStatistics(
       base::Bind(&ProfileStatisticsAggregatorState::StatsCallback,
                  base::Unretained(&state)));
-  ASSERT_TRUE(profile_stat->HasAggregator());
-  EXPECT_EQ(1u, profile_stat->GetAggregator()->GetCallbackCount());
   state.WaitForStats();
 
   EXPECT_EQ(0, state.GetNumOfFails());
@@ -203,10 +200,6 @@
     if (stat.category != profiles::kProfileStatisticsSettings)
       EXPECT_EQ(0, stat.count);
   }
-
-  EXPECT_PRED_FORMAT2(AssertionProfileCategoryStatsEqual, stats,
-      ProfileStatistics::GetProfileStatisticsFromAttributesStorage(
-          profile->GetPath()));
 }
 
 IN_PROC_BROWSER_TEST_F(ProfileStatisticsBrowserTest,
@@ -219,24 +212,16 @@
   ProfileStatisticsAggregatorState state1(1u);
   ProfileStatisticsAggregatorState state2;
 
-  EXPECT_FALSE(profile_stat->HasAggregator());
   profile_stat->GatherStatistics(
       base::Bind(&ProfileStatisticsAggregatorState::StatsCallback,
                  base::Unretained(&state1)));
-  ASSERT_TRUE(profile_stat->HasAggregator());
-  EXPECT_EQ(1u, profile_stat->GetAggregator()->GetCallbackCount());
   state1.WaitForStats();
 
-  ASSERT_TRUE(profile_stat->HasAggregator());
-  EXPECT_EQ(1u, profile_stat->GetAggregator()->GetCallbackCount());
-
   state1.SetRequiredStatCountAndCreateRunLoop(stats_categories().size());
 
   profile_stat->GatherStatistics(
       base::Bind(&ProfileStatisticsAggregatorState::StatsCallback,
                  base::Unretained(&state2)));
-  ASSERT_TRUE(profile_stat->HasAggregator());
-  EXPECT_EQ(2u, profile_stat->GetAggregator()->GetCallbackCount());
   state1.WaitForStats();
   state2.WaitForStats();
 
@@ -245,32 +230,3 @@
   EXPECT_PRED_FORMAT2(AssertionProfileCategoryStatsEqual,
       state1.GetStats(), state2.GetStats());
 }
-
-IN_PROC_BROWSER_TEST_F(ProfileStatisticsBrowserTest, CloseBrowser) {
-  Profile* profile = ProfileManager::GetActiveUserProfile();
-  ASSERT_TRUE(profile);
-  ProfileStatistics* profile_stat =
-      ProfileStatisticsFactory::GetForProfile(profile);
-
-  EXPECT_FALSE(profile_stat->HasAggregator());
-  CloseBrowserSynchronously(browser());
-  // The statistics task should be either running or finished.
-  if (profile_stat->HasAggregator()) {
-    EXPECT_EQ(0u, profile_stat->GetAggregator()->GetCallbackCount());
-  } else {
-    // Some of the statistics (e.g. settings) do always succeed. If all the
-    // statistics "failed", it means nothing is stored in profile attributes
-    // storage, and the statistics task was not run.
-    profiles::ProfileCategoryStats stats =
-        ProfileStatistics::GetProfileStatisticsFromAttributesStorage(
-            profile->GetPath());
-    bool has_stats = false;
-    for (const profiles::ProfileCategoryStat& stat : stats) {
-      if (stat.success) {
-        has_stats = true;
-        break;
-      }
-    }
-    EXPECT_TRUE(has_stats);
-  }
-}
diff --git a/chrome/browser/profiles/profile_statistics_common.cc b/chrome/browser/profiles/profile_statistics_common.cc
index ffa09b6..8eeca9b 100644
--- a/chrome/browser/profiles/profile_statistics_common.cc
+++ b/chrome/browser/profiles/profile_statistics_common.cc
@@ -5,9 +5,13 @@
 #include "chrome/browser/profiles/profile_statistics_common.h"
 
 namespace profiles {
-// Constants for the categories in ProfileCategoryStats
 const char kProfileStatisticsBrowsingHistory[] = "BrowsingHistory";
 const char kProfileStatisticsPasswords[] = "Passwords";
 const char kProfileStatisticsBookmarks[] = "Bookmarks";
 const char kProfileStatisticsSettings[] = "Settings";
+
+const std::array<const char*, 4> kProfileStatisticsCategories = {
+    {kProfileStatisticsBrowsingHistory, kProfileStatisticsPasswords,
+     kProfileStatisticsBookmarks, kProfileStatisticsSettings}};
+
 }  // namespace profiles
diff --git a/chrome/browser/profiles/profile_statistics_common.h b/chrome/browser/profiles/profile_statistics_common.h
index 122e886a..5fad9cc 100644
--- a/chrome/browser/profiles/profile_statistics_common.h
+++ b/chrome/browser/profiles/profile_statistics_common.h
@@ -5,18 +5,21 @@
 #ifndef CHROME_BROWSER_PROFILES_PROFILE_STATISTICS_COMMON_H_
 #define CHROME_BROWSER_PROFILES_PROFILE_STATISTICS_COMMON_H_
 
+#include <array>
 #include <string>
 #include <vector>
 
 #include "base/callback_forward.h"
 
 namespace profiles {
-// Constants for the categories in ProfileCategoryStats
+// Constants for the categories in ProfileCategoryStats.
 extern const char kProfileStatisticsBrowsingHistory[];
 extern const char kProfileStatisticsPasswords[];
 extern const char kProfileStatisticsBookmarks[];
 extern const char kProfileStatisticsSettings[];
 
+extern const std::array<const char*, 4> kProfileStatisticsCategories;
+
 // Definition of a single return value of |ProfileStatisticsCallback|. If
 // |success| is false, the statistics failed to load and |count| is undefined.
 // The data look like these: {"BrowsingHistory", 912, true},
diff --git a/chrome/browser/profiles/profile_statistics_unittest.cc b/chrome/browser/profiles/profile_statistics_unittest.cc
index 72c7334a..9f607aa 100644
--- a/chrome/browser/profiles/profile_statistics_unittest.cc
+++ b/chrome/browser/profiles/profile_statistics_unittest.cc
@@ -16,6 +16,7 @@
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "chrome/browser/bookmarks/chrome_bookmark_client.h"
 #include "chrome/browser/bookmarks/managed_bookmark_service_factory.h"
+#include "chrome/browser/password_manager/password_store_factory.h"
 #include "chrome/browser/profiles/profile_statistics_aggregator.h"
 #include "chrome/browser/profiles/profile_statistics_common.h"
 #include "chrome/browser/profiles/profile_statistics_factory.h"
@@ -24,6 +25,8 @@
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/testing_profile_manager.h"
 #include "components/bookmarks/browser/bookmark_model.h"
+#include "components/password_manager/core/browser/password_manager_test_utils.h"
+#include "components/password_manager/core/browser/test_password_store.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/test/test_browser_thread_bundle.h"
@@ -69,24 +72,6 @@
   base::Closure quit_closure_;
   int num_of_times_called_;
 };
-
-void VerifyStatisticsCache(const base::FilePath& profile_path,
-    const std::map<std::string, int>& expected,
-    const std::vector<std::string>& categories_to_check) {
-  const profiles::ProfileCategoryStats actual =
-      ProfileStatistics::GetProfileStatisticsFromAttributesStorage(
-          profile_path);
-
-  EXPECT_EQ(categories_to_check.size(), actual.size());
-
-  std::set<std::string> checked;
-  for (const auto& stat : actual) {
-    bool has_category = expected.count(stat.category);
-    EXPECT_EQ(has_category, stat.success);
-    EXPECT_EQ(has_category ? expected.at(stat.category) : 0, stat.count);
-    EXPECT_TRUE(checked.insert(stat.category).second);
-  }
-}
 }  // namespace
 
 class ProfileStatisticsTest : public testing::Test {
@@ -109,40 +94,15 @@
   TestingProfileManager manager_;
 };
 
-TEST_F(ProfileStatisticsTest, ProfileAttributesStorage) {
-  TestingProfile* profile = manager()->CreateTestingProfile("Test 1");
-  ASSERT_TRUE(profile);
-  base::FilePath profile_path = profile->GetPath();
-
-  std::vector<std::string> categories_to_check;
-  categories_to_check.push_back(profiles::kProfileStatisticsBrowsingHistory);
-  categories_to_check.push_back(profiles::kProfileStatisticsPasswords);
-  categories_to_check.push_back(profiles::kProfileStatisticsBookmarks);
-  categories_to_check.push_back(profiles::kProfileStatisticsSettings);
-
-  std::vector<std::pair<std::string, int>> insertions;
-  int num = 3;
-  // Insert for the first round, overwrite for the second round.
-  for (int i = 0; i < 2; i++) {
-    for (const auto& category : categories_to_check)
-      insertions.push_back(std::make_pair(category, num++));
-  }
-
-  std::map<std::string, int> expected;
-  // Now no keys are set.
-  VerifyStatisticsCache(profile_path, expected, categories_to_check);
-  // Insert items and test after each insert.
-  for (const auto& item : insertions) {
-    ProfileStatistics::SetProfileStatisticsToAttributesStorage(
-        profile_path, item.first, item.second);
-    expected[item.first] = item.second;
-    VerifyStatisticsCache(profile_path, expected, categories_to_check);
-  }
-}
-
 TEST_F(ProfileStatisticsTest, WaitOrCountBookmarks) {
   TestingProfile* profile = manager()->CreateTestingProfile("Test 1");
   ASSERT_TRUE(profile);
+  // We need a history service and a password store for the test to succeed.
+  ASSERT_TRUE(profile->CreateHistoryService(true, false));
+  PasswordStoreFactory::GetInstance()->SetTestingFactory(
+      profile,
+      password_manager::BuildPasswordStore<
+          content::BrowserContext, password_manager::TestPasswordStore>);
 
   bookmarks::BookmarkModel* bookmark_model =
       CreateBookmarkModelWithoutLoad(profile);
diff --git a/chrome/browser/ui/webui/settings/profile_info_handler.cc b/chrome/browser/ui/webui/settings/profile_info_handler.cc
index bac2e49..97830eb 100644
--- a/chrome/browser/ui/webui/settings/profile_info_handler.cc
+++ b/chrome/browser/ui/webui/settings/profile_info_handler.cc
@@ -131,9 +131,6 @@
 void ProfileInfoHandler::HandleGetProfileStats(const base::ListValue* args) {
   AllowJavascript();
 
-  // Because there is open browser window for the current profile, statistics
-  // from the ProfileAttributesStorage may not be up-to-date or may be missing
-  // (e.g., |item.success| is false). Therefore, query the actual statistics.
   ProfileStatisticsFactory::GetForProfile(profile_)->GatherStatistics(
       base::Bind(&ProfileInfoHandler::PushProfileStatsCount,
                  callback_weak_ptr_factory_.GetWeakPtr()));
diff --git a/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc b/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc
index 7436f8ab..d608631 100644
--- a/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc
+++ b/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc
@@ -13,6 +13,7 @@
 #include "base/feature_list.h"
 #include "base/location.h"
 #include "base/macros.h"
+#include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
 #include "base/profiler/scoped_tracker.h"
 #include "base/single_thread_task_runner.h"
@@ -597,6 +598,7 @@
   if (!args->Get(0, &profile_path_value))
     return;
 
+  base::Time start_time = base::Time::Now();
   base::FilePath profile_path;
 
   if (!base::GetValueAsFilePath(*profile_path_value, &profile_path))
@@ -606,44 +608,29 @@
   Profile* profile = g_browser_process->profile_manager()->
       GetProfileByPath(profile_path);
 
-  if (!profile)
-    return;
-
-  if (!chrome::FindAnyBrowser(profile, true)) {
-    // If no windows are open for that profile, the statistics in
-    // ProfileAttributesStorage are up to date. The statistics in
-    // ProfileAttributesStorage are returned because the copy in user_pod_row.js
-    // may be outdated. However, if some statistics are missing in
-    // ProfileAttributesStorage (i.e. |item.success| is false), then the actual
-    // statistics are queried instead.
-    base::DictionaryValue return_value;
-    profiles::ProfileCategoryStats stats =
-        ProfileStatistics::GetProfileStatisticsFromAttributesStorage(
-            profile_path);
-    bool stats_success = true;
-    for (const auto& item : stats) {
-      std::unique_ptr<base::DictionaryValue> stat(new base::DictionaryValue);
-      stat->SetIntegerWithoutPathExpansion("count", item.count);
-      stat->SetBooleanWithoutPathExpansion("success", item.success);
-      return_value.SetWithoutPathExpansion(item.category, std::move(stat));
-      stats_success &= item.success;
-    }
-    if (stats_success) {
-      web_ui()->CallJavascriptFunctionUnsafe("updateRemoveWarningDialog",
-                                             base::Value(profile_path.value()),
-                                             return_value);
-      return;
-    }
+  if (profile) {
+    GatherStatistics(start_time, profile);
+  } else {
+    g_browser_process->profile_manager()->LoadProfileByPath(
+        profile_path, false,
+        base::Bind(&UserManagerScreenHandler::GatherStatistics,
+                   weak_ptr_factory_.GetWeakPtr(), start_time));
   }
+}
 
-  ProfileStatisticsFactory::GetForProfile(profile)->GatherStatistics(
-      base::Bind(
-          &UserManagerScreenHandler::RemoveUserDialogLoadStatsCallback,
-          weak_ptr_factory_.GetWeakPtr(), profile_path));
+void UserManagerScreenHandler::GatherStatistics(base::Time start_time,
+                                                Profile* profile) {
+  if (profile) {
+    ProfileStatisticsFactory::GetForProfile(profile)->GatherStatistics(
+        base::Bind(&UserManagerScreenHandler::RemoveUserDialogLoadStatsCallback,
+                   weak_ptr_factory_.GetWeakPtr(), profile->GetPath(),
+                   start_time));
+  }
 }
 
 void UserManagerScreenHandler::RemoveUserDialogLoadStatsCallback(
     base::FilePath profile_path,
+    base::Time start_time,
     profiles::ProfileCategoryStats result) {
   // Copy result into return_value.
   base::DictionaryValue return_value;
@@ -653,6 +640,11 @@
     stat->SetBooleanWithoutPathExpansion("success", item.success);
     return_value.SetWithoutPathExpansion(item.category, std::move(stat));
   }
+  if (result.size() == profiles::kProfileStatisticsCategories.size()) {
+    // All categories are finished.
+    UMA_HISTOGRAM_TIMES("Profile.RemoveUserWarningStatsTime",
+                        base::Time::Now() - start_time);
+  }
   web_ui()->CallJavascriptFunctionUnsafe("updateRemoveWarningDialog",
                                          base::Value(profile_path.value()),
                                          return_value);
@@ -927,8 +919,7 @@
     if (entry->IsOmitted())
       continue;
 
-    std::unique_ptr<base::DictionaryValue> profile_value(
-        new base::DictionaryValue());
+    auto profile_value = base::MakeUnique<base::DictionaryValue>();
     base::FilePath profile_path = entry->GetPath();
 
     profile_value->SetString(kKeyUsername, entry->GetUserName());
@@ -949,20 +940,17 @@
     profile_value->SetBoolean(kKeyIsDesktop, true);
     profile_value->SetString(kKeyAvatarUrl, GetAvatarImage(entry));
 
-    profiles::ProfileCategoryStats stats =
-        ProfileStatistics::GetProfileStatisticsFromAttributesStorage(
-            profile_path);
-    std::unique_ptr<base::DictionaryValue> stats_dict(
-        new base::DictionaryValue);
-    for (const auto& item : stats) {
-      std::unique_ptr<base::DictionaryValue> stat(new base::DictionaryValue);
-      stat->SetIntegerWithoutPathExpansion("count", item.count);
-      stat->SetBooleanWithoutPathExpansion("success", item.success);
-      stats_dict->SetWithoutPathExpansion(item.category, std::move(stat));
+    // Add statistics dictionary (the actual statistics will be populated
+    // once they are retrieved from the profile).
+    auto stats_dict = base::MakeUnique<base::DictionaryValue>();
+    for (const char* category : profiles::kProfileStatisticsCategories) {
+      auto stat = base::MakeUnique<base::DictionaryValue>();
+      stat->SetIntegerWithoutPathExpansion("count", 0);
+      stat->SetBooleanWithoutPathExpansion("success", false);
+      stats_dict->SetWithoutPathExpansion(category, std::move(stat));
     }
     profile_value->SetWithoutPathExpansion(kKeyStatistics,
                                            std::move(stats_dict));
-
     // GetProfileByPath returns a pointer if the profile is fully loaded, NULL
     // otherwise.
     Profile* profile =
diff --git a/chrome/browser/ui/webui/signin/user_manager_screen_handler.h b/chrome/browser/ui/webui/signin/user_manager_screen_handler.h
index 52273793..6cd26ef 100644
--- a/chrome/browser/ui/webui/signin/user_manager_screen_handler.h
+++ b/chrome/browser/ui/webui/signin/user_manager_screen_handler.h
@@ -86,10 +86,13 @@
   void HandleRemoveUserWarningLoadStats(const base::ListValue* args);
   void HandleGetRemoveWarningDialogMessage(const base::ListValue* args);
 
+  // Function used to gather statistics from a profile.
+  void GatherStatistics(base::Time start_time, Profile* profile);
+
   // Callback function used by HandleRemoveUserWarningLoadStats
-  void RemoveUserDialogLoadStatsCallback(
-      base::FilePath profile_path,
-      profiles::ProfileCategoryStats result);
+  void RemoveUserDialogLoadStatsCallback(base::FilePath profile_path,
+                                         base::Time start_time,
+                                         profiles::ProfileCategoryStats result);
 
   // Handle GAIA auth results.
   void OnGetTokenInfoResponse(
diff --git a/components/browsing_data/core/counters/history_counter.cc b/components/browsing_data/core/counters/history_counter.cc
index 7bfd7cf..0c2b45c 100644
--- a/components/browsing_data/core/counters/history_counter.cc
+++ b/components/browsing_data/core/counters/history_counter.cc
@@ -28,7 +28,9 @@
       local_counting_finished_(false),
       web_counting_finished_(false),
       history_sync_enabled_(false),
-      weak_ptr_factory_(this) {}
+      weak_ptr_factory_(this) {
+  DCHECK(history_service_);
+}
 
 HistoryCounter::~HistoryCounter() {
   if (sync_service_)
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 7027dce..ba8bf977 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -58212,6 +58212,13 @@
   </summary>
 </histogram>
 
+<histogram name="Profile.RemoveUserWarningStatsTime" units="ms">
+  <owner>[email protected]</owner>
+  <summary>
+    The amount of time that elapsed during profile statistics calculation.
+  </summary>
+</histogram>
+
 <histogram name="Profile.SupervisedProfileCreateError"
     enum="GoogleServiceAuthError">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>