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