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