Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / extensions / api / browsing_data / browsing_data_api.cc
blob049d8b73cea7fdd5346a8da194568b39fc26b228
1 // Copyright (c) 2012 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.
5 // Defines the Chrome Extensions BrowsingData API functions, which entail
6 // clearing browsing data, and clearing the browser's cache (which, let's be
7 // honest, are the same thing), as specified in the extension API JSON.
9 #include "chrome/browser/extensions/api/browsing_data/browsing_data_api.h"
11 #include <string>
13 #include "base/strings/stringprintf.h"
14 #include "base/values.h"
15 #include "chrome/browser/browsing_data/browsing_data_helper.h"
16 #include "chrome/browser/browsing_data/browsing_data_remover.h"
17 #include "chrome/browser/plugins/plugin_data_remover_helper.h"
18 #include "chrome/browser/plugins/plugin_prefs.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/browser/ui/browser.h"
21 #include "chrome/common/pref_names.h"
22 #include "content/public/browser/browser_thread.h"
23 #include "extensions/common/error_utils.h"
24 #include "extensions/common/extension.h"
26 using content::BrowserThread;
28 namespace extension_browsing_data_api_constants {
30 // Parameter name keys.
31 const char kDataRemovalPermittedKey[] = "dataRemovalPermitted";
32 const char kDataToRemoveKey[] = "dataToRemove";
33 const char kOptionsKey[] = "options";
35 // Type keys.
36 const char kAppCacheKey[] = "appcache";
37 const char kCacheKey[] = "cache";
38 const char kChannelIDsKey[] = "serverBoundCertificates";
39 const char kCookiesKey[] = "cookies";
40 const char kDownloadsKey[] = "downloads";
41 const char kFileSystemsKey[] = "fileSystems";
42 const char kFormDataKey[] = "formData";
43 const char kHistoryKey[] = "history";
44 const char kIndexedDBKey[] = "indexedDB";
45 const char kLocalStorageKey[] = "localStorage";
46 const char kPasswordsKey[] = "passwords";
47 const char kPluginDataKey[] = "pluginData";
48 const char kServiceWorkersKey[] = "serviceWorkers";
49 const char kWebSQLKey[] = "webSQL";
51 // Option keys.
52 const char kExtensionsKey[] = "extension";
53 const char kOriginTypesKey[] = "originTypes";
54 const char kProtectedWebKey[] = "protectedWeb";
55 const char kSinceKey[] = "since";
56 const char kUnprotectedWebKey[] = "unprotectedWeb";
58 // Errors!
59 // The placeholder will be filled by the name of the affected data type (e.g.,
60 // "history").
61 const char kBadDataTypeDetails[] = "Invalid value for data type '%s'.";
62 const char kDeleteProhibitedError[] = "Browsing history and downloads are not "
63 "permitted to be removed.";
64 const char kOneAtATimeError[] = "Only one 'browsingData' API call can run at "
65 "a time.";
67 } // namespace extension_browsing_data_api_constants
69 namespace {
70 int MaskForKey(const char* key) {
71 if (strcmp(key, extension_browsing_data_api_constants::kAppCacheKey) == 0)
72 return BrowsingDataRemover::REMOVE_APPCACHE;
73 if (strcmp(key, extension_browsing_data_api_constants::kCacheKey) == 0)
74 return BrowsingDataRemover::REMOVE_CACHE;
75 if (strcmp(key, extension_browsing_data_api_constants::kCookiesKey) == 0) {
76 return BrowsingDataRemover::REMOVE_COOKIES |
77 BrowsingDataRemover::REMOVE_WEBRTC_IDENTITY;
79 if (strcmp(key, extension_browsing_data_api_constants::kDownloadsKey) == 0)
80 return BrowsingDataRemover::REMOVE_DOWNLOADS;
81 if (strcmp(key, extension_browsing_data_api_constants::kFileSystemsKey) == 0)
82 return BrowsingDataRemover::REMOVE_FILE_SYSTEMS;
83 if (strcmp(key, extension_browsing_data_api_constants::kFormDataKey) == 0)
84 return BrowsingDataRemover::REMOVE_FORM_DATA;
85 if (strcmp(key, extension_browsing_data_api_constants::kHistoryKey) == 0)
86 return BrowsingDataRemover::REMOVE_HISTORY;
87 if (strcmp(key, extension_browsing_data_api_constants::kIndexedDBKey) == 0)
88 return BrowsingDataRemover::REMOVE_INDEXEDDB;
89 if (strcmp(key, extension_browsing_data_api_constants::kLocalStorageKey) == 0)
90 return BrowsingDataRemover::REMOVE_LOCAL_STORAGE;
91 if (strcmp(key,
92 extension_browsing_data_api_constants::kChannelIDsKey) == 0)
93 return BrowsingDataRemover::REMOVE_CHANNEL_IDS;
94 if (strcmp(key, extension_browsing_data_api_constants::kPasswordsKey) == 0)
95 return BrowsingDataRemover::REMOVE_PASSWORDS;
96 if (strcmp(key, extension_browsing_data_api_constants::kPluginDataKey) == 0)
97 return BrowsingDataRemover::REMOVE_PLUGIN_DATA;
98 if (strcmp(key, extension_browsing_data_api_constants::kServiceWorkersKey) ==
100 return BrowsingDataRemover::REMOVE_SERVICE_WORKERS;
101 if (strcmp(key, extension_browsing_data_api_constants::kWebSQLKey) == 0)
102 return BrowsingDataRemover::REMOVE_WEBSQL;
104 return 0;
107 // Returns false if any of the selected data types are not allowed to be
108 // deleted.
109 bool IsRemovalPermitted(int removal_mask, PrefService* prefs) {
110 // Enterprise policy or user preference might prohibit deleting browser or
111 // download history.
112 if ((removal_mask & BrowsingDataRemover::REMOVE_HISTORY) ||
113 (removal_mask & BrowsingDataRemover::REMOVE_DOWNLOADS)) {
114 return prefs->GetBoolean(prefs::kAllowDeletingBrowserHistory);
116 return true;
119 } // namespace
121 bool BrowsingDataSettingsFunction::RunSync() {
122 PrefService* prefs = GetProfile()->GetPrefs();
124 // Fill origin types.
125 // The "cookies" and "hosted apps" UI checkboxes both map to
126 // REMOVE_SITE_DATA in browsing_data_remover.h, the former for the unprotected
127 // web, the latter for protected web data. There is no UI control for
128 // extension data.
129 scoped_ptr<base::DictionaryValue> origin_types(new base::DictionaryValue);
130 origin_types->SetBoolean(
131 extension_browsing_data_api_constants::kUnprotectedWebKey,
132 prefs->GetBoolean(prefs::kDeleteCookies));
133 origin_types->SetBoolean(
134 extension_browsing_data_api_constants::kProtectedWebKey,
135 prefs->GetBoolean(prefs::kDeleteHostedAppsData));
136 origin_types->SetBoolean(
137 extension_browsing_data_api_constants::kExtensionsKey, false);
139 // Fill deletion time period.
140 int period_pref = prefs->GetInteger(prefs::kDeleteTimePeriod);
141 BrowsingDataRemover::TimePeriod period =
142 static_cast<BrowsingDataRemover::TimePeriod>(period_pref);
143 double since = 0;
144 if (period != BrowsingDataRemover::EVERYTHING) {
145 base::Time time = BrowsingDataRemover::CalculateBeginDeleteTime(period);
146 since = time.ToJsTime();
149 scoped_ptr<base::DictionaryValue> options(new base::DictionaryValue);
150 options->Set(extension_browsing_data_api_constants::kOriginTypesKey,
151 origin_types.release());
152 options->SetDouble(extension_browsing_data_api_constants::kSinceKey, since);
154 // Fill dataToRemove and dataRemovalPermitted.
155 scoped_ptr<base::DictionaryValue> selected(new base::DictionaryValue);
156 scoped_ptr<base::DictionaryValue> permitted(new base::DictionaryValue);
158 bool delete_site_data = prefs->GetBoolean(prefs::kDeleteCookies) ||
159 prefs->GetBoolean(prefs::kDeleteHostedAppsData);
161 SetDetails(selected.get(), permitted.get(),
162 extension_browsing_data_api_constants::kAppCacheKey,
163 delete_site_data);
164 SetDetails(selected.get(), permitted.get(),
165 extension_browsing_data_api_constants::kCookiesKey,
166 delete_site_data);
167 SetDetails(selected.get(), permitted.get(),
168 extension_browsing_data_api_constants::kFileSystemsKey,
169 delete_site_data);
170 SetDetails(selected.get(), permitted.get(),
171 extension_browsing_data_api_constants::kIndexedDBKey,
172 delete_site_data);
173 SetDetails(selected.get(), permitted.get(),
174 extension_browsing_data_api_constants::kLocalStorageKey,
175 delete_site_data);
176 SetDetails(selected.get(), permitted.get(),
177 extension_browsing_data_api_constants::kWebSQLKey,
178 delete_site_data);
179 SetDetails(selected.get(), permitted.get(),
180 extension_browsing_data_api_constants::kChannelIDsKey,
181 delete_site_data);
182 SetDetails(selected.get(), permitted.get(),
183 extension_browsing_data_api_constants::kServiceWorkersKey,
184 delete_site_data);
186 SetDetails(selected.get(), permitted.get(),
187 extension_browsing_data_api_constants::kPluginDataKey,
188 delete_site_data && prefs->GetBoolean(prefs::kClearPluginLSODataEnabled));
190 SetDetails(selected.get(), permitted.get(),
191 extension_browsing_data_api_constants::kHistoryKey,
192 prefs->GetBoolean(prefs::kDeleteBrowsingHistory));
193 SetDetails(selected.get(), permitted.get(),
194 extension_browsing_data_api_constants::kDownloadsKey,
195 prefs->GetBoolean(prefs::kDeleteDownloadHistory));
196 SetDetails(selected.get(), permitted.get(),
197 extension_browsing_data_api_constants::kCacheKey,
198 prefs->GetBoolean(prefs::kDeleteCache));
199 SetDetails(selected.get(), permitted.get(),
200 extension_browsing_data_api_constants::kFormDataKey,
201 prefs->GetBoolean(prefs::kDeleteFormData));
202 SetDetails(selected.get(), permitted.get(),
203 extension_browsing_data_api_constants::kPasswordsKey,
204 prefs->GetBoolean(prefs::kDeletePasswords));
206 scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue);
207 result->Set(extension_browsing_data_api_constants::kOptionsKey,
208 options.release());
209 result->Set(extension_browsing_data_api_constants::kDataToRemoveKey,
210 selected.release());
211 result->Set(extension_browsing_data_api_constants::kDataRemovalPermittedKey,
212 permitted.release());
213 SetResult(result.release());
214 return true;
217 void BrowsingDataSettingsFunction::SetDetails(
218 base::DictionaryValue* selected_dict,
219 base::DictionaryValue* permitted_dict,
220 const char* data_type,
221 bool is_selected) {
222 bool is_permitted =
223 IsRemovalPermitted(MaskForKey(data_type), GetProfile()->GetPrefs());
224 selected_dict->SetBoolean(data_type, is_selected && is_permitted);
225 permitted_dict->SetBoolean(data_type, is_permitted);
228 void BrowsingDataRemoverFunction::OnBrowsingDataRemoverDone() {
229 DCHECK_CURRENTLY_ON(BrowserThread::UI);
230 this->SendResponse(true);
232 Release(); // Balanced in RunAsync.
235 bool BrowsingDataRemoverFunction::RunAsync() {
236 // If we don't have a profile, something's pretty wrong.
237 DCHECK(GetProfile());
239 // Grab the initial |options| parameter, and parse out the arguments.
240 base::DictionaryValue* options;
241 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &options));
242 DCHECK(options);
244 origin_type_mask_ = ParseOriginTypeMask(*options);
246 // If |ms_since_epoch| isn't set, default it to 0.
247 double ms_since_epoch;
248 if (!options->GetDouble(extension_browsing_data_api_constants::kSinceKey,
249 &ms_since_epoch))
250 ms_since_epoch = 0;
252 // base::Time takes a double that represents seconds since epoch. JavaScript
253 // gives developers milliseconds, so do a quick conversion before populating
254 // the object. Also, Time::FromDoubleT converts double time 0 to empty Time
255 // object. So we need to do special handling here.
256 remove_since_ = (ms_since_epoch == 0) ?
257 base::Time::UnixEpoch() :
258 base::Time::FromDoubleT(ms_since_epoch / 1000.0);
260 removal_mask_ = GetRemovalMask();
261 if (bad_message_)
262 return false;
264 // Check for prohibited data types.
265 if (!IsRemovalPermitted(removal_mask_, GetProfile()->GetPrefs())) {
266 error_ = extension_browsing_data_api_constants::kDeleteProhibitedError;
267 return false;
270 if (removal_mask_ & BrowsingDataRemover::REMOVE_PLUGIN_DATA) {
271 // If we're being asked to remove plugin data, check whether it's actually
272 // supported.
273 BrowserThread::PostTask(
274 BrowserThread::FILE,
275 FROM_HERE,
276 base::Bind(
277 &BrowsingDataRemoverFunction::CheckRemovingPluginDataSupported,
278 this,
279 PluginPrefs::GetForProfile(GetProfile())));
280 } else {
281 StartRemoving();
284 // Will finish asynchronously.
285 return true;
288 void BrowsingDataRemoverFunction::CheckRemovingPluginDataSupported(
289 scoped_refptr<PluginPrefs> plugin_prefs) {
290 if (!PluginDataRemoverHelper::IsSupported(plugin_prefs.get()))
291 removal_mask_ &= ~BrowsingDataRemover::REMOVE_PLUGIN_DATA;
293 BrowserThread::PostTask(
294 BrowserThread::UI, FROM_HERE,
295 base::Bind(&BrowsingDataRemoverFunction::StartRemoving, this));
298 void BrowsingDataRemoverFunction::StartRemoving() {
299 if (BrowsingDataRemover::is_removing()) {
300 error_ = extension_browsing_data_api_constants::kOneAtATimeError;
301 SendResponse(false);
302 return;
305 // If we're good to go, add a ref (Balanced in OnBrowsingDataRemoverDone)
306 AddRef();
308 // Create a BrowsingDataRemover, set the current object as an observer (so
309 // that we're notified after removal) and call remove() with the arguments
310 // we've generated above. We can use a raw pointer here, as the browsing data
311 // remover is responsible for deleting itself once data removal is complete.
312 BrowsingDataRemover* remover = BrowsingDataRemover::CreateForRange(
313 GetProfile(), remove_since_, base::Time::Max());
314 remover->AddObserver(this);
315 remover->Remove(removal_mask_, origin_type_mask_);
318 int BrowsingDataRemoverFunction::ParseOriginTypeMask(
319 const base::DictionaryValue& options) {
320 // Parse the |options| dictionary to generate the origin set mask. Default to
321 // UNPROTECTED_WEB if the developer doesn't specify anything.
322 int mask = BrowsingDataHelper::UNPROTECTED_WEB;
324 const base::DictionaryValue* d = NULL;
325 if (options.HasKey(extension_browsing_data_api_constants::kOriginTypesKey)) {
326 EXTENSION_FUNCTION_VALIDATE(options.GetDictionary(
327 extension_browsing_data_api_constants::kOriginTypesKey, &d));
328 bool value;
330 // The developer specified something! Reset to 0 and parse the dictionary.
331 mask = 0;
333 // Unprotected web.
334 if (d->HasKey(extension_browsing_data_api_constants::kUnprotectedWebKey)) {
335 EXTENSION_FUNCTION_VALIDATE(d->GetBoolean(
336 extension_browsing_data_api_constants::kUnprotectedWebKey, &value));
337 mask |= value ? BrowsingDataHelper::UNPROTECTED_WEB : 0;
340 // Protected web.
341 if (d->HasKey(extension_browsing_data_api_constants::kProtectedWebKey)) {
342 EXTENSION_FUNCTION_VALIDATE(d->GetBoolean(
343 extension_browsing_data_api_constants::kProtectedWebKey, &value));
344 mask |= value ? BrowsingDataHelper::PROTECTED_WEB : 0;
347 // Extensions.
348 if (d->HasKey(extension_browsing_data_api_constants::kExtensionsKey)) {
349 EXTENSION_FUNCTION_VALIDATE(d->GetBoolean(
350 extension_browsing_data_api_constants::kExtensionsKey, &value));
351 mask |= value ? BrowsingDataHelper::EXTENSION : 0;
355 return mask;
358 // Parses the |dataToRemove| argument to generate the removal mask. Sets
359 // |bad_message_| (like EXTENSION_FUNCTION_VALIDATE would if this were a bool
360 // method) if 'dataToRemove' is not present or any data-type keys don't have
361 // supported (boolean) values.
362 int BrowsingDataRemoveFunction::GetRemovalMask() {
363 base::DictionaryValue* data_to_remove;
364 if (!args_->GetDictionary(1, &data_to_remove)) {
365 bad_message_ = true;
366 return 0;
369 int removal_mask = 0;
371 for (base::DictionaryValue::Iterator i(*data_to_remove);
372 !i.IsAtEnd();
373 i.Advance()) {
374 bool selected = false;
375 if (!i.value().GetAsBoolean(&selected)) {
376 bad_message_ = true;
377 return 0;
379 if (selected)
380 removal_mask |= MaskForKey(i.key().c_str());
383 return removal_mask;
386 int BrowsingDataRemoveAppcacheFunction::GetRemovalMask() {
387 return BrowsingDataRemover::REMOVE_APPCACHE;
390 int BrowsingDataRemoveCacheFunction::GetRemovalMask() {
391 return BrowsingDataRemover::REMOVE_CACHE;
394 int BrowsingDataRemoveCookiesFunction::GetRemovalMask() {
395 return BrowsingDataRemover::REMOVE_COOKIES |
396 BrowsingDataRemover::REMOVE_CHANNEL_IDS |
397 BrowsingDataRemover::REMOVE_WEBRTC_IDENTITY;
400 int BrowsingDataRemoveDownloadsFunction::GetRemovalMask() {
401 return BrowsingDataRemover::REMOVE_DOWNLOADS;
404 int BrowsingDataRemoveFileSystemsFunction::GetRemovalMask() {
405 return BrowsingDataRemover::REMOVE_FILE_SYSTEMS;
408 int BrowsingDataRemoveFormDataFunction::GetRemovalMask() {
409 return BrowsingDataRemover::REMOVE_FORM_DATA;
412 int BrowsingDataRemoveHistoryFunction::GetRemovalMask() {
413 return BrowsingDataRemover::REMOVE_HISTORY;
416 int BrowsingDataRemoveIndexedDBFunction::GetRemovalMask() {
417 return BrowsingDataRemover::REMOVE_INDEXEDDB;
420 int BrowsingDataRemoveLocalStorageFunction::GetRemovalMask() {
421 return BrowsingDataRemover::REMOVE_LOCAL_STORAGE;
424 int BrowsingDataRemovePluginDataFunction::GetRemovalMask() {
425 return BrowsingDataRemover::REMOVE_PLUGIN_DATA;
428 int BrowsingDataRemovePasswordsFunction::GetRemovalMask() {
429 return BrowsingDataRemover::REMOVE_PASSWORDS;
432 int BrowsingDataRemoveServiceWorkersFunction::GetRemovalMask() {
433 return BrowsingDataRemover::REMOVE_SERVICE_WORKERS;
436 int BrowsingDataRemoveWebSQLFunction::GetRemovalMask() {
437 return BrowsingDataRemover::REMOVE_WEBSQL;