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