1 // Copyright 2016 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 "components/browsing_data/core/browsing_data_utils.h"
6
7 #include <string>
8 #include <vector>
9
10 #include "base/macros.h"
11 #include "base/metrics/histogram_macros.h"
12 #include "base/metrics/user_metrics.h"
13 #include "base/no_destructor.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "components/browsing_data/core/counters/autofill_counter.h"
16 #include "components/browsing_data/core/counters/history_counter.h"
17 #include "components/browsing_data/core/counters/passwords_counter.h"
18 #include "components/browsing_data/core/pref_names.h"
19 #include "components/prefs/pref_service.h"
20 #include "components/strings/grit/components_strings.h"
21 #include "ui/base/l10n/l10n_util.h"
22
23 namespace browsing_data {
24
25 // Creates a string like "for a.com, b.com, and 4 more".
CreateDomainExamples(int password_count,const std::vector<std::string> domain_examples)26 base::string16 CreateDomainExamples(
27 int password_count,
28 const std::vector<std::string> domain_examples) {
29 DCHECK_GE(password_count,
30 base::checked_cast<browsing_data::BrowsingDataCounter::ResultInt>(
31 domain_examples.size()));
32 DCHECK_EQ(domain_examples.empty(), password_count == 0);
33 std::vector<base::string16> replacements;
34
35 replacements.emplace_back(base::UTF8ToUTF16(domain_examples[0]));
36 if (domain_examples.size() > 1) {
37 replacements.emplace_back(base::UTF8ToUTF16(domain_examples[1]));
38 }
39 if (password_count > 2 && domain_examples.size() > 1) {
40 replacements.emplace_back(l10n_util::GetPluralStringFUTF16(
41 IDS_DEL_PASSWORDS_COUNTER_AND_X_MORE, password_count - 2));
42 }
43 base::string16 domains_list = base::ReplaceStringPlaceholders(
44 l10n_util::GetPluralStringFUTF16(IDS_DEL_PASSWORDS_DOMAINS_DISPLAY,
45 (domain_examples.size() > 1)
46 ? password_count
47 : domain_examples.size()),
48 replacements, nullptr);
49 return domains_list;
50 }
51
CalculateBeginDeleteTime(TimePeriod time_period)52 base::Time CalculateBeginDeleteTime(TimePeriod time_period) {
53 base::TimeDelta diff;
54 base::Time delete_begin_time = base::Time::Now();
55 switch (time_period) {
56 case TimePeriod::LAST_HOUR:
57 diff = base::TimeDelta::FromHours(1);
58 break;
59 case TimePeriod::LAST_DAY:
60 diff = base::TimeDelta::FromHours(24);
61 break;
62 case TimePeriod::LAST_WEEK:
63 diff = base::TimeDelta::FromHours(7 * 24);
64 break;
65 case TimePeriod::FOUR_WEEKS:
66 diff = base::TimeDelta::FromHours(4 * 7 * 24);
67 break;
68 case TimePeriod::ALL_TIME:
69 case TimePeriod::OLDER_THAN_30_DAYS:
70 delete_begin_time = base::Time();
71 break;
72 }
73 return delete_begin_time - diff;
74 }
75
CalculateEndDeleteTime(TimePeriod time_period)76 base::Time CalculateEndDeleteTime(TimePeriod time_period) {
77 if (time_period == TimePeriod::OLDER_THAN_30_DAYS) {
78 return base::Time::Now() - base::TimeDelta::FromDays(30);
79 }
80 return base::Time::Max();
81 }
82
RecordDeletionForPeriod(TimePeriod period)83 void RecordDeletionForPeriod(TimePeriod period) {
84 switch (period) {
85 case TimePeriod::LAST_HOUR:
86 base::RecordAction(base::UserMetricsAction("ClearBrowsingData_LastHour"));
87 break;
88 case TimePeriod::LAST_DAY:
89 base::RecordAction(base::UserMetricsAction("ClearBrowsingData_LastDay"));
90 break;
91 case TimePeriod::LAST_WEEK:
92 base::RecordAction(base::UserMetricsAction("ClearBrowsingData_LastWeek"));
93 break;
94 case TimePeriod::FOUR_WEEKS:
95 base::RecordAction(
96 base::UserMetricsAction("ClearBrowsingData_LastMonth"));
97 break;
98 case TimePeriod::ALL_TIME:
99 base::RecordAction(
100 base::UserMetricsAction("ClearBrowsingData_Everything"));
101 break;
102 case TimePeriod::OLDER_THAN_30_DAYS:
103 base::RecordAction(
104 base::UserMetricsAction("ClearBrowsingData_OlderThan30Days"));
105 break;
106 }
107 }
108
RecordTimePeriodChange(TimePeriod period)109 void RecordTimePeriodChange(TimePeriod period) {
110 switch (period) {
111 case TimePeriod::LAST_HOUR:
112 base::RecordAction(base::UserMetricsAction(
113 "ClearBrowsingData_TimePeriodChanged_LastHour"));
114 break;
115 case TimePeriod::LAST_DAY:
116 base::RecordAction(base::UserMetricsAction(
117 "ClearBrowsingData_TimePeriodChanged_LastDay"));
118 break;
119 case TimePeriod::LAST_WEEK:
120 base::RecordAction(base::UserMetricsAction(
121 "ClearBrowsingData_TimePeriodChanged_LastWeek"));
122 break;
123 case TimePeriod::FOUR_WEEKS:
124 base::RecordAction(base::UserMetricsAction(
125 "ClearBrowsingData_TimePeriodChanged_LastMonth"));
126 break;
127 case TimePeriod::ALL_TIME:
128 base::RecordAction(base::UserMetricsAction(
129 "ClearBrowsingData_TimePeriodChanged_Everything"));
130 break;
131 case TimePeriod::OLDER_THAN_30_DAYS:
132 base::RecordAction(base::UserMetricsAction(
133 "ClearBrowsingData_TimePeriodChanged_OlderThan30Days"));
134 break;
135 }
136 }
137
GetCounterTextFromResult(const BrowsingDataCounter::Result * result)138 base::string16 GetCounterTextFromResult(
139 const BrowsingDataCounter::Result* result) {
140 std::string pref_name = result->source()->GetPrefName();
141
142 if (!result->Finished()) {
143 // The counter is still counting.
144 return l10n_util::GetStringUTF16(IDS_CLEAR_BROWSING_DATA_CALCULATING);
145 }
146
147 if (pref_name == prefs::kDeletePasswords) {
148 const PasswordsCounter::PasswordsResult* password_result =
149 static_cast<const PasswordsCounter::PasswordsResult*>(result);
150
151 std::vector<base::string16> parts;
152 BrowsingDataCounter::ResultInt profile_passwords = password_result->Value();
153
154 if (profile_passwords) {
155 parts.emplace_back(base::ReplaceStringPlaceholders(
156 l10n_util::GetPluralStringFUTF16(
157 password_result->is_sync_enabled()
158 ? IDS_DEL_PASSWORDS_COUNTER_SYNCED
159 : IDS_DEL_PASSWORDS_COUNTER,
160 profile_passwords),
161 {CreateDomainExamples(profile_passwords,
162 password_result->domain_examples())},
163 nullptr));
164 }
165
166 if (password_result->account_passwords()) {
167 parts.emplace_back(base::ReplaceStringPlaceholders(
168 l10n_util::GetPluralStringFUTF16(
169 IDS_DEL_ACCOUNT_PASSWORDS_COUNTER,
170 password_result->account_passwords()),
171 {CreateDomainExamples(password_result->account_passwords(),
172 password_result->account_domain_examples())},
173 nullptr));
174 }
175
176 switch (parts.size()) {
177 case 0:
178 return l10n_util::GetStringUTF16(
179 IDS_DEL_PASSWORDS_AND_SIGNIN_DATA_COUNTER_NONE);
180 case 1:
181 return parts[0];
182 case 2:
183 return l10n_util::GetStringFUTF16(
184 IDS_DEL_PASSWORDS_AND_SIGNIN_DATA_COUNTER_COMBINATION, parts[0],
185 parts[1]);
186 default:
187 NOTREACHED();
188 }
189 }
190
191 if (pref_name == prefs::kDeleteDownloadHistory) {
192 BrowsingDataCounter::ResultInt count =
193 static_cast<const BrowsingDataCounter::FinishedResult*>(result)
194 ->Value();
195 return l10n_util::GetPluralStringFUTF16(IDS_DEL_DOWNLOADS_COUNTER, count);
196 }
197
198 if (pref_name == prefs::kDeleteSiteSettings) {
199 BrowsingDataCounter::ResultInt count =
200 static_cast<const BrowsingDataCounter::FinishedResult*>(result)
201 ->Value();
202 return l10n_util::GetPluralStringFUTF16(IDS_DEL_SITE_SETTINGS_COUNTER,
203 count);
204 }
205
206 if (pref_name == prefs::kDeleteBrowsingHistoryBasic) {
207 // The basic tab doesn't show history counter results.
208 NOTREACHED();
209 }
210
211 if (pref_name == prefs::kDeleteBrowsingHistory) {
212 // History counter.
213 const HistoryCounter::HistoryResult* history_result =
214 static_cast<const HistoryCounter::HistoryResult*>(result);
215 BrowsingDataCounter::ResultInt local_item_count = history_result->Value();
216 bool has_synced_visits = history_result->has_synced_visits();
217 return has_synced_visits
218 ? l10n_util::GetPluralStringFUTF16(
219 IDS_DEL_BROWSING_HISTORY_COUNTER_SYNCED, local_item_count)
220 : l10n_util::GetPluralStringFUTF16(
221 IDS_DEL_BROWSING_HISTORY_COUNTER, local_item_count);
222 }
223
224 if (pref_name == prefs::kDeleteFormData) {
225 // Autofill counter.
226 const AutofillCounter::AutofillResult* autofill_result =
227 static_cast<const AutofillCounter::AutofillResult*>(result);
228 AutofillCounter::ResultInt num_suggestions = autofill_result->Value();
229 AutofillCounter::ResultInt num_credit_cards =
230 autofill_result->num_credit_cards();
231 AutofillCounter::ResultInt num_addresses = autofill_result->num_addresses();
232
233 std::vector<base::string16> displayed_strings;
234
235 if (num_credit_cards) {
236 displayed_strings.push_back(l10n_util::GetPluralStringFUTF16(
237 IDS_DEL_AUTOFILL_COUNTER_CREDIT_CARDS, num_credit_cards));
238 }
239 if (num_addresses) {
240 displayed_strings.push_back(l10n_util::GetPluralStringFUTF16(
241 IDS_DEL_AUTOFILL_COUNTER_ADDRESSES, num_addresses));
242 }
243 if (num_suggestions) {
244 // We use a different wording for autocomplete suggestions based on the
245 // length of the entire string.
246 switch (displayed_strings.size()) {
247 case 0:
248 displayed_strings.push_back(l10n_util::GetPluralStringFUTF16(
249 IDS_DEL_AUTOFILL_COUNTER_SUGGESTIONS, num_suggestions));
250 break;
251 case 1:
252 displayed_strings.push_back(l10n_util::GetPluralStringFUTF16(
253 IDS_DEL_AUTOFILL_COUNTER_SUGGESTIONS_LONG, num_suggestions));
254 break;
255 case 2:
256 displayed_strings.push_back(l10n_util::GetPluralStringFUTF16(
257 IDS_DEL_AUTOFILL_COUNTER_SUGGESTIONS_SHORT, num_suggestions));
258 break;
259 default:
260 NOTREACHED();
261 }
262 }
263
264 bool synced = autofill_result->is_sync_enabled();
265
266 // Construct the resulting string from the sections in |displayed_strings|.
267 switch (displayed_strings.size()) {
268 case 0:
269 return l10n_util::GetStringUTF16(IDS_DEL_AUTOFILL_COUNTER_EMPTY);
270 break;
271 case 1:
272 return synced ? l10n_util::GetStringFUTF16(
273 IDS_DEL_AUTOFILL_COUNTER_ONE_TYPE_SYNCED,
274 displayed_strings[0])
275 : displayed_strings[0];
276 break;
277 case 2:
278 return l10n_util::GetStringFUTF16(
279 synced ? IDS_DEL_AUTOFILL_COUNTER_TWO_TYPES_SYNCED
280 : IDS_DEL_AUTOFILL_COUNTER_TWO_TYPES,
281 displayed_strings[0], displayed_strings[1]);
282 break;
283 case 3:
284 return l10n_util::GetStringFUTF16(
285 synced ? IDS_DEL_AUTOFILL_COUNTER_THREE_TYPES_SYNCED
286 : IDS_DEL_AUTOFILL_COUNTER_THREE_TYPES,
287 displayed_strings[0], displayed_strings[1], displayed_strings[2]);
288 break;
289 default:
290 NOTREACHED();
291 }
292 }
293
294 NOTREACHED();
295 return base::string16();
296 }
297
GetTimePeriodPreferenceName(ClearBrowsingDataTab clear_browsing_data_tab)298 const char* GetTimePeriodPreferenceName(
299 ClearBrowsingDataTab clear_browsing_data_tab) {
300 return clear_browsing_data_tab == ClearBrowsingDataTab::BASIC
301 ? prefs::kDeleteTimePeriodBasic
302 : prefs::kDeleteTimePeriod;
303 }
304
GetDeletionPreferenceFromDataType(BrowsingDataType data_type,ClearBrowsingDataTab clear_browsing_data_tab,std::string * out_pref)305 bool GetDeletionPreferenceFromDataType(
306 BrowsingDataType data_type,
307 ClearBrowsingDataTab clear_browsing_data_tab,
308 std::string* out_pref) {
309 if (clear_browsing_data_tab == ClearBrowsingDataTab::BASIC) {
310 switch (data_type) {
311 case BrowsingDataType::HISTORY:
312 *out_pref = prefs::kDeleteBrowsingHistoryBasic;
313 return true;
314 case BrowsingDataType::CACHE:
315 *out_pref = prefs::kDeleteCacheBasic;
316 return true;
317 case BrowsingDataType::COOKIES:
318 *out_pref = prefs::kDeleteCookiesBasic;
319 return true;
320 case BrowsingDataType::PASSWORDS:
321 case BrowsingDataType::FORM_DATA:
322 case BrowsingDataType::BOOKMARKS:
323 case BrowsingDataType::SITE_SETTINGS:
324 case BrowsingDataType::DOWNLOADS:
325 case BrowsingDataType::HOSTED_APPS_DATA:
326 return false; // No corresponding preference on basic tab.
327 case BrowsingDataType::NUM_TYPES:
328 // This is not an actual type.
329 NOTREACHED();
330 return false;
331 }
332 }
333 switch (data_type) {
334 case BrowsingDataType::HISTORY:
335 *out_pref = prefs::kDeleteBrowsingHistory;
336 return true;
337 case BrowsingDataType::CACHE:
338 *out_pref = prefs::kDeleteCache;
339 return true;
340 case BrowsingDataType::COOKIES:
341 *out_pref = prefs::kDeleteCookies;
342 return true;
343 case BrowsingDataType::PASSWORDS:
344 *out_pref = prefs::kDeletePasswords;
345 return true;
346 case BrowsingDataType::FORM_DATA:
347 *out_pref = prefs::kDeleteFormData;
348 return true;
349 case BrowsingDataType::BOOKMARKS:
350 // Bookmarks are deleted on the Android side. No corresponding deletion
351 // preference. Not implemented on Desktop.
352 return false;
353 case BrowsingDataType::SITE_SETTINGS:
354 *out_pref = prefs::kDeleteSiteSettings;
355 return true;
356 case BrowsingDataType::DOWNLOADS:
357 *out_pref = prefs::kDeleteDownloadHistory;
358 return true;
359 case BrowsingDataType::HOSTED_APPS_DATA:
360 *out_pref = prefs::kDeleteHostedAppsData;
361 return true;
362 case BrowsingDataType::NUM_TYPES:
363 NOTREACHED(); // This is not an actual type.
364 return false;
365 }
366 NOTREACHED();
367 return false;
368 }
369
GetDataTypeFromDeletionPreference(const std::string & pref_name)370 BrowsingDataType GetDataTypeFromDeletionPreference(
371 const std::string& pref_name) {
372 using DataTypeMap = base::flat_map<std::string, BrowsingDataType>;
373 static base::NoDestructor<DataTypeMap> preference_to_datatype(
374 std::initializer_list<DataTypeMap::value_type>{
375 {prefs::kDeleteBrowsingHistory, BrowsingDataType::HISTORY},
376 {prefs::kDeleteBrowsingHistoryBasic, BrowsingDataType::HISTORY},
377 {prefs::kDeleteCache, BrowsingDataType::CACHE},
378 {prefs::kDeleteCacheBasic, BrowsingDataType::CACHE},
379 {prefs::kDeleteCookies, BrowsingDataType::COOKIES},
380 {prefs::kDeleteCookiesBasic, BrowsingDataType::COOKIES},
381 {prefs::kDeletePasswords, BrowsingDataType::PASSWORDS},
382 {prefs::kDeleteFormData, BrowsingDataType::FORM_DATA},
383 {prefs::kDeleteSiteSettings, BrowsingDataType::SITE_SETTINGS},
384 {prefs::kDeleteDownloadHistory, BrowsingDataType::DOWNLOADS},
385 {prefs::kDeleteHostedAppsData, BrowsingDataType::HOSTED_APPS_DATA},
386 });
387
388 auto iter = preference_to_datatype->find(pref_name);
389 DCHECK(iter != preference_to_datatype->end());
390 return iter->second;
391 }
392
393 } // namespace browsing_data
394