| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 
|  | 2 // Use of this source code is governed by a BSD-style license that can be | 
|  | 3 // found in the LICENSE file. | 
|  | 4 | 
|  | 5 #include "chrome/browser/profiles/profile_statistics.h" | 
|  | 6 | 
|  | 7 #include "base/bind.h" | 
|  | 8 #include "base/memory/ref_counted.h" | 
|  | 9 #include "base/prefs/pref_service.h" | 
|  | 10 #include "base/task_runner.h" | 
|  | 11 #include "base/time/time.h" | 
|  | 12 #include "chrome/browser/bookmarks/bookmark_model_factory.h" | 
|  | 13 #include "chrome/browser/history/history_service_factory.h" | 
|  | 14 #include "chrome/browser/password_manager/password_store_factory.h" | 
|  | 15 #include "components/bookmarks/browser/bookmark_model.h" | 
|  | 16 #include "components/history/core/browser/history_service.h" | 
|  | 17 #include "components/password_manager/core/browser/password_store.h" | 
|  | 18 #include "components/password_manager/core/browser/password_store_consumer.h" | 
|  | 19 #include "content/public/browser/browser_thread.h" | 
|  | 20 | 
|  | 21 using content::BrowserThread; | 
|  | 22 | 
|  | 23 namespace { | 
|  | 24 | 
|  | 25 struct ProfileStatValue { | 
|  | 26   int count; | 
|  | 27   bool success; // false means the statistics failed to load | 
|  | 28 }; | 
|  | 29 | 
|  | 30 int CountBookmarksFromNode(const bookmarks::BookmarkNode* node) { | 
|  | 31   int count = 0; | 
|  | 32   if (node->is_url()) { | 
|  | 33     ++count; | 
|  | 34   } else { | 
|  | 35     for (int i = 0; i < node->child_count(); ++i) | 
|  | 36       count += CountBookmarksFromNode(node->GetChild(i)); | 
|  | 37   } | 
|  | 38   return count; | 
|  | 39 } | 
|  | 40 | 
|  | 41 class ProfileStatisticsAggregator | 
|  | 42     : public base::RefCountedThreadSafe<ProfileStatisticsAggregator> { | 
|  | 43   // This class collects statistical information about the profile and returns | 
|  | 44   // the information via a callback function. Currently bookmarks, history, | 
|  | 45   // logins and preferences are counted. | 
|  | 46   // | 
|  | 47   // The class is RefCounted because this is needed for CancelableTaskTracker | 
|  | 48   // to function properly. Once all tasks are run (or cancelled) the instance is | 
|  | 49   // automatically destructed. | 
|  | 50   // | 
|  | 51   // The class is used internally by GetProfileStatistics function. | 
|  | 52 | 
|  | 53  public: | 
|  | 54   explicit ProfileStatisticsAggregator(Profile* profile, | 
|  | 55       const profiles::ProfileStatisticsCallback& callback, | 
|  | 56       base::CancelableTaskTracker* tracker); | 
|  | 57 | 
|  | 58  private: | 
|  | 59   friend class base::RefCountedThreadSafe<ProfileStatisticsAggregator>; | 
|  | 60   ~ProfileStatisticsAggregator() {} | 
|  | 61 | 
|  | 62   void Init(); | 
|  | 63 | 
|  | 64   // Callback functions | 
|  | 65   // Normal callback. Appends result to |profile_category_stats_|, and then call | 
|  | 66   // the external callback. All other callbacks call this function. | 
|  | 67   void StatisticsCallback(const char* category, ProfileStatValue result); | 
|  | 68   // Callback for reporting success. | 
|  | 69   void StatisticsCallbackSuccess(const char* category, int count); | 
|  | 70   // Callback for reporting failure. | 
|  | 71   void StatisticsCallbackFailure(const char* category); | 
|  | 72   // Callback for history. | 
|  | 73   void StatisticsCallbackHistory(history::HistoryCountResult result); | 
|  | 74 | 
|  | 75   // Bookmark counting. | 
|  | 76   ProfileStatValue CountBookmarks() const; | 
|  | 77 | 
|  | 78   // Preference counting. | 
|  | 79   ProfileStatValue CountPrefs() const; | 
|  | 80 | 
|  | 81   Profile* profile_; | 
|  | 82   profiles::ProfileCategoryStats profile_category_stats_; | 
|  | 83 | 
|  | 84   // Callback function to be called when results arrive. Will be called | 
|  | 85   // multiple times (once for each statistics). | 
|  | 86   const profiles::ProfileStatisticsCallback callback_; | 
|  | 87 | 
|  | 88   base::CancelableTaskTracker* tracker_; | 
|  | 89 | 
|  | 90   // Password counting. | 
|  | 91   class PasswordStoreConsumerHelper | 
|  | 92       : public password_manager::PasswordStoreConsumer { | 
|  | 93    public: | 
|  | 94     explicit PasswordStoreConsumerHelper(ProfileStatisticsAggregator* parent) | 
|  | 95         : parent_(parent) {} | 
|  | 96 | 
|  | 97     void OnGetPasswordStoreResults( | 
|  | 98         ScopedVector<autofill::PasswordForm> results) override { | 
|  | 99       parent_->StatisticsCallbackSuccess(profiles::kProfileStatisticsPasswords, | 
|  | 100                                          results.size()); | 
|  | 101     } | 
|  | 102 | 
|  | 103    private: | 
|  | 104     ProfileStatisticsAggregator* parent_ = nullptr; | 
|  | 105 | 
|  | 106     DISALLOW_COPY_AND_ASSIGN(PasswordStoreConsumerHelper); | 
|  | 107   }; | 
|  | 108   PasswordStoreConsumerHelper password_store_consumer_helper_; | 
|  | 109 | 
|  | 110   DISALLOW_COPY_AND_ASSIGN(ProfileStatisticsAggregator); | 
|  | 111 }; | 
|  | 112 | 
|  | 113 ProfileStatisticsAggregator::ProfileStatisticsAggregator( | 
|  | 114     Profile* profile, | 
|  | 115     const profiles::ProfileStatisticsCallback& callback, | 
|  | 116     base::CancelableTaskTracker* tracker) | 
|  | 117     : profile_(profile), | 
|  | 118       callback_(callback), | 
|  | 119       tracker_(tracker), | 
|  | 120       password_store_consumer_helper_(this) { | 
|  | 121   Init(); | 
|  | 122 } | 
|  | 123 | 
|  | 124 void ProfileStatisticsAggregator::Init() { | 
|  | 125   // Initiate bookmark counting (async). Post to UI thread. | 
|  | 126   tracker_->PostTaskAndReplyWithResult( | 
|  | 127       BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI).get(), | 
|  | 128           FROM_HERE, | 
|  | 129           base::Bind(&ProfileStatisticsAggregator::CountBookmarks, this), | 
|  | 130           base::Bind(&ProfileStatisticsAggregator::StatisticsCallback, | 
|  | 131                      this, profiles::kProfileStatisticsBookmarks)); | 
|  | 132 | 
|  | 133   // Initiate history counting (async). | 
|  | 134   history::HistoryService* history_service = | 
|  | 135       HistoryServiceFactory::GetForProfileWithoutCreating(profile_); | 
|  | 136 | 
|  | 137   if (history_service) { | 
|  | 138     history_service->GetHistoryCount( | 
|  | 139         base::Time(), | 
|  | 140         base::Time::Max(), | 
|  | 141         base::Bind(&ProfileStatisticsAggregator::StatisticsCallbackHistory, | 
|  | 142                    this), | 
|  | 143         tracker_); | 
|  | 144   } else { | 
|  | 145     StatisticsCallbackFailure(profiles::kProfileStatisticsBrowsingHistory); | 
|  | 146   } | 
|  | 147 | 
|  | 148   // Initiate stored password counting (async). | 
|  | 149   // TODO(anthonyvd): make password task cancellable. | 
|  | 150   scoped_refptr<password_manager::PasswordStore> password_store = | 
|  | 151       PasswordStoreFactory::GetForProfile( | 
|  | 152           profile_, ServiceAccessType::EXPLICIT_ACCESS); | 
|  | 153   if (password_store) { | 
|  | 154     password_store->GetAutofillableLogins(&password_store_consumer_helper_); | 
|  | 155   } else { | 
|  | 156     StatisticsCallbackFailure(profiles::kProfileStatisticsPasswords); | 
|  | 157   } | 
|  | 158 | 
|  | 159   // Initiate preference counting (async). Post to UI thread. | 
|  | 160   tracker_->PostTaskAndReplyWithResult( | 
|  | 161       BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI).get(), | 
|  | 162           FROM_HERE, | 
|  | 163           base::Bind(&ProfileStatisticsAggregator::CountPrefs, this), | 
|  | 164           base::Bind(&ProfileStatisticsAggregator::StatisticsCallback, | 
|  | 165                      this, profiles::kProfileStatisticsSettings)); | 
|  | 166 } | 
|  | 167 | 
|  | 168 void ProfileStatisticsAggregator::StatisticsCallback( | 
|  | 169     const char* category, ProfileStatValue result) { | 
|  | 170   profiles::ProfileCategoryStat datum; | 
|  | 171   datum.category = category; | 
|  | 172   datum.count = result.count; | 
|  | 173   datum.success = result.success; | 
|  | 174   profile_category_stats_.push_back(datum); | 
|  | 175   callback_.Run(profile_category_stats_); | 
|  | 176 } | 
|  | 177 | 
|  | 178 void ProfileStatisticsAggregator::StatisticsCallbackSuccess( | 
|  | 179     const char* category, int count) { | 
|  | 180   ProfileStatValue result; | 
|  | 181   result.count = count; | 
|  | 182   result.success = true; | 
|  | 183   StatisticsCallback(category, result); | 
|  | 184 } | 
|  | 185 | 
|  | 186 void ProfileStatisticsAggregator::StatisticsCallbackFailure( | 
|  | 187     const char* category) { | 
|  | 188   ProfileStatValue result; | 
|  | 189   result.count = 0; | 
|  | 190   result.success = false; | 
|  | 191   StatisticsCallback(category, result); | 
|  | 192 } | 
|  | 193 | 
|  | 194 void ProfileStatisticsAggregator::StatisticsCallbackHistory( | 
|  | 195     history::HistoryCountResult result) { | 
|  | 196   ProfileStatValue result_converted; | 
|  | 197   result_converted.count = result.count; | 
|  | 198   result_converted.success = result.success; | 
|  | 199   StatisticsCallback(profiles::kProfileStatisticsBrowsingHistory, | 
|  | 200                      result_converted); | 
|  | 201 } | 
|  | 202 | 
|  | 203 ProfileStatValue ProfileStatisticsAggregator::CountBookmarks() const { | 
|  | 204   bookmarks::BookmarkModel* bookmark_model = | 
|  | 205       BookmarkModelFactory::GetForProfileIfExists(profile_); | 
|  | 206 | 
|  | 207   ProfileStatValue result; | 
|  | 208   if (bookmark_model) { | 
|  | 209     result.count = CountBookmarksFromNode(bookmark_model->bookmark_bar_node()) + | 
|  | 210                    CountBookmarksFromNode(bookmark_model->other_node()) + | 
|  | 211                    CountBookmarksFromNode(bookmark_model->mobile_node()); | 
|  | 212     result.success = true; | 
|  | 213   } else { | 
|  | 214     result.count = 0; | 
|  | 215     result.success = false; | 
|  | 216   } | 
|  | 217   return result; | 
|  | 218 } | 
|  | 219 | 
|  | 220 ProfileStatValue ProfileStatisticsAggregator::CountPrefs() const { | 
|  | 221   const PrefService* pref_service = profile_->GetPrefs(); | 
|  | 222 | 
|  | 223   ProfileStatValue result; | 
|  | 224   if (pref_service) { | 
|  | 225     scoped_ptr<base::DictionaryValue> prefs = | 
|  | 226         pref_service->GetPreferenceValuesWithoutPathExpansion(); | 
|  | 227 | 
|  | 228     int count = 0; | 
|  | 229     for (base::DictionaryValue::Iterator it(*(prefs.get())); | 
|  | 230          !it.IsAtEnd(); it.Advance()) { | 
|  | 231       const PrefService::Preference* pref = pref_service-> | 
|  | 232                                                 FindPreference(it.key()); | 
|  | 233       // Skip all dictionaries (which must be empty by the function call above). | 
|  | 234       if (it.value().GetType() != base::Value::TYPE_DICTIONARY && | 
|  | 235         pref && pref->IsUserControlled() && !pref->IsDefaultValue()) { | 
|  | 236         ++count; | 
|  | 237       } | 
|  | 238     } | 
|  | 239 | 
|  | 240     result.count = count; | 
|  | 241     result.success = true; | 
|  | 242   } else { | 
|  | 243     result.count = 0; | 
|  | 244     result.success = false; | 
|  | 245   } | 
|  | 246   return result; | 
|  | 247 } | 
|  | 248 | 
|  | 249 }  // namespace | 
|  | 250 | 
|  | 251 namespace profiles { | 
|  | 252 | 
|  | 253 // Constants for the categories in ProfileCategoryStats | 
|  | 254 const char kProfileStatisticsBrowsingHistory[] = "BrowsingHistory"; | 
|  | 255 const char kProfileStatisticsPasswords[] = "Passwords"; | 
|  | 256 const char kProfileStatisticsBookmarks[] = "Bookmarks"; | 
|  | 257 const char kProfileStatisticsSettings[] = "Settings"; | 
|  | 258 | 
|  | 259 void GetProfileStatistics(Profile* profile, | 
|  | 260     const ProfileStatisticsCallback& callback, | 
|  | 261     base::CancelableTaskTracker* tracker) { | 
|  | 262   scoped_refptr<ProfileStatisticsAggregator> aggregator = | 
|  | 263       new ProfileStatisticsAggregator(profile, callback, tracker); | 
|  | 264 } | 
|  | 265 | 
|  | 266 }  // namespace profiles | 
| OLD | NEW | 
|---|