OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "chrome/browser/browsing_data_remover.h" | |
6 | |
7 #include <map> | |
8 #include <set> | |
9 | |
10 #include "base/bind.h" | |
11 #include "base/bind_helpers.h" | |
12 #include "base/callback.h" | |
13 #include "base/file_util.h" | |
14 #include "base/logging.h" | |
15 #include "base/platform_file.h" | |
16 #include "chrome/browser/autofill/personal_data_manager.h" | |
17 #include "chrome/browser/autofill/personal_data_manager_factory.h" | |
18 #include "chrome/browser/browser_process.h" | |
19 #include "chrome/browser/browsing_data_helper.h" | |
20 #include "chrome/browser/download/download_service.h" | |
21 #include "chrome/browser/download/download_service_factory.h" | |
22 #include "chrome/browser/extensions/extension_service.h" | |
23 #include "chrome/browser/extensions/extension_special_storage_policy.h" | |
24 #include "chrome/browser/history/history.h" | |
25 #include "chrome/browser/history/history_service_factory.h" | |
26 #include "chrome/browser/io_thread.h" | |
27 #include "chrome/browser/nacl_host/nacl_browser.h" | |
28 #include "chrome/browser/net/chrome_url_request_context.h" | |
29 #include "chrome/browser/net/predictor.h" | |
30 #include "chrome/browser/password_manager/password_store.h" | |
31 #include "chrome/browser/password_manager/password_store_factory.h" | |
32 #include "chrome/browser/prefs/pref_member.h" | |
33 #include "chrome/browser/prerender/prerender_manager.h" | |
34 #include "chrome/browser/prerender/prerender_manager_factory.h" | |
35 #include "chrome/browser/profiles/profile.h" | |
36 #include "chrome/browser/renderer_host/web_cache_manager.h" | |
37 #include "chrome/browser/safe_browsing/safe_browsing_service.h" | |
38 #include "chrome/browser/search_engines/template_url_service.h" | |
39 #include "chrome/browser/search_engines/template_url_service_factory.h" | |
40 #include "chrome/browser/sessions/session_service.h" | |
41 #include "chrome/browser/sessions/session_service_factory.h" | |
42 #include "chrome/browser/sessions/tab_restore_service.h" | |
43 #include "chrome/browser/sessions/tab_restore_service_factory.h" | |
44 #include "chrome/browser/webdata/web_data_service.h" | |
45 #include "chrome/browser/webdata/web_data_service_factory.h" | |
46 #include "chrome/common/chrome_notification_types.h" | |
47 #include "chrome/common/pref_names.h" | |
48 #include "chrome/common/url_constants.h" | |
49 #include "content/public/browser/browser_thread.h" | |
50 #include "content/public/browser/dom_storage_context.h" | |
51 #include "content/public/browser/download_manager.h" | |
52 #include "content/public/browser/notification_service.h" | |
53 #include "content/public/browser/plugin_data_remover.h" | |
54 #include "content/public/browser/user_metrics.h" | |
55 #include "net/base/net_errors.h" | |
56 #include "net/base/server_bound_cert_service.h" | |
57 #include "net/base/server_bound_cert_store.h" | |
58 #include "net/base/transport_security_state.h" | |
59 #include "net/cookies/cookie_store.h" | |
60 #include "net/disk_cache/disk_cache.h" | |
61 #include "net/http/http_cache.h" | |
62 #include "net/url_request/url_request_context.h" | |
63 #include "net/url_request/url_request_context_getter.h" | |
64 #include "webkit/dom_storage/dom_storage_context.h" | |
65 #include "webkit/quota/quota_manager.h" | |
66 #include "webkit/quota/quota_types.h" | |
67 #include "webkit/quota/special_storage_policy.h" | |
68 | |
69 using content::BrowserContext; | |
70 using content::BrowserThread; | |
71 using content::DOMStorageContext; | |
72 using content::DownloadManager; | |
73 using content::UserMetricsAction; | |
74 | |
75 bool BrowsingDataRemover::removing_ = false; | |
76 | |
77 BrowsingDataRemover::NotificationDetails::NotificationDetails() | |
78 : removal_begin(base::Time()), | |
79 removal_mask(-1), | |
80 origin_set_mask(-1) { | |
81 } | |
82 | |
83 BrowsingDataRemover::NotificationDetails::NotificationDetails( | |
84 const BrowsingDataRemover::NotificationDetails& details) | |
85 : removal_begin(details.removal_begin), | |
86 removal_mask(details.removal_mask), | |
87 origin_set_mask(details.origin_set_mask) { | |
88 } | |
89 | |
90 BrowsingDataRemover::NotificationDetails::NotificationDetails( | |
91 base::Time removal_begin, | |
92 int removal_mask, | |
93 int origin_set_mask) | |
94 : removal_begin(removal_begin), | |
95 removal_mask(removal_mask), | |
96 origin_set_mask(origin_set_mask) { | |
97 } | |
98 | |
99 BrowsingDataRemover::NotificationDetails::~NotificationDetails() {} | |
100 | |
101 // TODO(mkwst): We should have one constructor, not two. http://crbug.com/130732 | |
102 BrowsingDataRemover::BrowsingDataRemover(Profile* profile, | |
103 base::Time delete_begin, | |
104 base::Time delete_end) | |
105 : profile_(profile), | |
106 quota_manager_(NULL), | |
107 dom_storage_context_(NULL), | |
108 special_storage_policy_(profile->GetExtensionSpecialStoragePolicy()), | |
109 delete_begin_(delete_begin), | |
110 delete_end_(delete_end), | |
111 next_cache_state_(STATE_NONE), | |
112 cache_(NULL), | |
113 main_context_getter_(profile->GetRequestContext()), | |
114 media_context_getter_(profile->GetRequestContextForMedia()), | |
115 deauthorize_content_licenses_request_id_(0), | |
116 waiting_for_clear_cache_(false), | |
117 waiting_for_clear_nacl_cache_(false), | |
118 waiting_for_clear_cookies_count_(0), | |
119 waiting_for_clear_history_(false), | |
120 waiting_for_clear_local_storage_(false), | |
121 waiting_for_clear_networking_history_(false), | |
122 waiting_for_clear_server_bound_certs_(false), | |
123 waiting_for_clear_plugin_data_(false), | |
124 waiting_for_clear_quota_managed_data_(false), | |
125 waiting_for_clear_content_licenses_(false), | |
126 remove_mask_(0), | |
127 remove_origin_(GURL()), | |
128 origin_set_mask_(0) { | |
129 DCHECK(profile); | |
130 } | |
131 | |
132 BrowsingDataRemover::BrowsingDataRemover(Profile* profile, | |
133 TimePeriod time_period, | |
134 base::Time delete_end) | |
135 : profile_(profile), | |
136 quota_manager_(NULL), | |
137 dom_storage_context_(NULL), | |
138 special_storage_policy_(profile->GetExtensionSpecialStoragePolicy()), | |
139 delete_begin_(CalculateBeginDeleteTime(time_period)), | |
140 delete_end_(delete_end), | |
141 next_cache_state_(STATE_NONE), | |
142 cache_(NULL), | |
143 main_context_getter_(profile->GetRequestContext()), | |
144 media_context_getter_(profile->GetRequestContextForMedia()), | |
145 deauthorize_content_licenses_request_id_(0), | |
146 waiting_for_clear_cache_(false), | |
147 waiting_for_clear_nacl_cache_(false), | |
148 waiting_for_clear_cookies_count_(0), | |
149 waiting_for_clear_history_(false), | |
150 waiting_for_clear_local_storage_(false), | |
151 waiting_for_clear_networking_history_(false), | |
152 waiting_for_clear_server_bound_certs_(false), | |
153 waiting_for_clear_plugin_data_(false), | |
154 waiting_for_clear_quota_managed_data_(false), | |
155 waiting_for_clear_content_licenses_(false), | |
156 remove_mask_(0), | |
157 remove_origin_(GURL()), | |
158 origin_set_mask_(0) { | |
159 DCHECK(profile); | |
160 } | |
161 | |
162 BrowsingDataRemover::~BrowsingDataRemover() { | |
163 DCHECK(AllDone()); | |
164 } | |
165 | |
166 // Static. | |
167 void BrowsingDataRemover::set_removing(bool removing) { | |
168 DCHECK(removing_ != removing); | |
169 removing_ = removing; | |
170 } | |
171 | |
172 // Static. | |
173 int BrowsingDataRemover::GenerateQuotaClientMask(int remove_mask) { | |
174 int quota_client_mask = 0; | |
175 if (remove_mask & BrowsingDataRemover::REMOVE_FILE_SYSTEMS) | |
176 quota_client_mask |= quota::QuotaClient::kFileSystem; | |
177 if (remove_mask & BrowsingDataRemover::REMOVE_WEBSQL) | |
178 quota_client_mask |= quota::QuotaClient::kDatabase; | |
179 if (remove_mask & BrowsingDataRemover::REMOVE_APPCACHE) | |
180 quota_client_mask |= quota::QuotaClient::kAppcache; | |
181 if (remove_mask & BrowsingDataRemover::REMOVE_INDEXEDDB) | |
182 quota_client_mask |= quota::QuotaClient::kIndexedDatabase; | |
183 | |
184 return quota_client_mask; | |
185 } | |
186 | |
187 void BrowsingDataRemover::Remove(int remove_mask, int origin_set_mask) { | |
188 RemoveImpl(remove_mask, GURL(), origin_set_mask); | |
189 } | |
190 | |
191 void BrowsingDataRemover::RemoveImpl(int remove_mask, | |
192 const GURL& origin, | |
193 int origin_set_mask) { | |
194 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
195 set_removing(true); | |
196 remove_mask_ = remove_mask; | |
197 remove_origin_ = origin; | |
198 origin_set_mask_ = origin_set_mask; | |
199 | |
200 if (origin_set_mask_ & BrowsingDataHelper::UNPROTECTED_WEB) { | |
201 content::RecordAction( | |
202 UserMetricsAction("ClearBrowsingData_MaskContainsUnprotectedWeb")); | |
203 } | |
204 if (origin_set_mask_ & BrowsingDataHelper::PROTECTED_WEB) { | |
205 content::RecordAction( | |
206 UserMetricsAction("ClearBrowsingData_MaskContainsProtectedWeb")); | |
207 } | |
208 if (origin_set_mask_ & BrowsingDataHelper::EXTENSION) { | |
209 content::RecordAction( | |
210 UserMetricsAction("ClearBrowsingData_MaskContainsExtension")); | |
211 } | |
212 // If this fires, we added a new BrowsingDataHelper::OriginSetMask without | |
213 // updating the user metrics above. | |
214 COMPILE_ASSERT( | |
215 BrowsingDataHelper::ALL == (BrowsingDataHelper::UNPROTECTED_WEB | | |
216 BrowsingDataHelper::PROTECTED_WEB | | |
217 BrowsingDataHelper::EXTENSION), | |
218 forgotten_to_add_origin_mask_type); | |
219 | |
220 if (remove_mask & REMOVE_HISTORY) { | |
221 HistoryService* history_service = HistoryServiceFactory::GetForProfile( | |
222 profile_, Profile::EXPLICIT_ACCESS); | |
223 if (history_service) { | |
224 std::set<GURL> restrict_urls; | |
225 if (!remove_origin_.is_empty()) | |
226 restrict_urls.insert(remove_origin_); | |
227 content::RecordAction(UserMetricsAction("ClearBrowsingData_History")); | |
228 waiting_for_clear_history_ = true; | |
229 history_service->ExpireHistoryBetween(restrict_urls, | |
230 delete_begin_, delete_end_, | |
231 &request_consumer_, | |
232 base::Bind(&BrowsingDataRemover::OnHistoryDeletionDone, | |
233 base::Unretained(this))); | |
234 } | |
235 | |
236 // Need to clear the host cache and accumulated speculative data, as it also | |
237 // reveals some history: we have no mechanism to track when these items were | |
238 // created, so we'll clear them all. Better safe than sorry. | |
239 if (g_browser_process->io_thread()) { | |
240 waiting_for_clear_networking_history_ = true; | |
241 BrowserThread::PostTask( | |
242 BrowserThread::IO, FROM_HERE, | |
243 base::Bind(&BrowsingDataRemover::ClearNetworkingHistory, | |
244 base::Unretained(this), g_browser_process->io_thread())); | |
245 } | |
246 | |
247 // As part of history deletion we also delete the auto-generated keywords. | |
248 TemplateURLService* keywords_model = | |
249 TemplateURLServiceFactory::GetForProfile(profile_); | |
250 if (keywords_model && !keywords_model->loaded()) { | |
251 registrar_.Add(this, chrome::NOTIFICATION_TEMPLATE_URL_SERVICE_LOADED, | |
252 content::Source<TemplateURLService>(keywords_model)); | |
253 keywords_model->Load(); | |
254 } else if (keywords_model) { | |
255 keywords_model->RemoveAutoGeneratedForOriginBetween(remove_origin_, | |
256 delete_begin_, delete_end_); | |
257 } | |
258 | |
259 // The PrerenderManager keeps history of prerendered pages, so clear that. | |
260 // It also may have a prerendered page. If so, the page could be | |
261 // considered to have a small amount of historical information, so delete | |
262 // it, too. | |
263 prerender::PrerenderManager* prerender_manager = | |
264 prerender::PrerenderManagerFactory::GetForProfile(profile_); | |
265 if (prerender_manager) { | |
266 prerender_manager->ClearData( | |
267 prerender::PrerenderManager::CLEAR_PRERENDER_CONTENTS | | |
268 prerender::PrerenderManager::CLEAR_PRERENDER_HISTORY); | |
269 } | |
270 | |
271 // If the caller is removing history for all hosts, then clear ancillary | |
272 // historical information. | |
273 if (remove_origin_.is_empty()) { | |
274 // We also delete the list of recently closed tabs. Since these expire, | |
275 // they can't be more than a day old, so we can simply clear them all. | |
276 TabRestoreService* tab_service = | |
277 TabRestoreServiceFactory::GetForProfile(profile_); | |
278 if (tab_service) { | |
279 tab_service->ClearEntries(); | |
280 tab_service->DeleteLastSession(); | |
281 } | |
282 | |
283 #if defined(ENABLE_SESSION_SERVICE) | |
284 // We also delete the last session when we delete the history. | |
285 SessionService* session_service = | |
286 SessionServiceFactory::GetForProfile(profile_); | |
287 if (session_service) | |
288 session_service->DeleteLastSession(); | |
289 #endif | |
290 } | |
291 } | |
292 | |
293 if (remove_mask & REMOVE_DOWNLOADS) { | |
294 content::RecordAction(UserMetricsAction("ClearBrowsingData_Downloads")); | |
295 DownloadManager* download_manager = | |
296 BrowserContext::GetDownloadManager(profile_); | |
297 download_manager->RemoveDownloadsBetween(delete_begin_, delete_end_); | |
298 download_manager->ClearLastDownloadPath(); | |
299 } | |
300 | |
301 // We ignore the REMOVE_COOKIES request if UNPROTECTED_WEB is not set, | |
302 // so that callers who request REMOVE_SITE_DATA with PROTECTED_WEB | |
303 // don't accidentally remove the cookies that are associated with the | |
304 // UNPROTECTED_WEB origin. This is necessary because cookies are not separated | |
305 // between UNPROTECTED_WEB and PROTECTED_WEB. | |
306 if (remove_mask & REMOVE_COOKIES && | |
307 origin_set_mask_ & BrowsingDataHelper::UNPROTECTED_WEB) { | |
308 content::RecordAction(UserMetricsAction("ClearBrowsingData_Cookies")); | |
309 // Since we are running on the UI thread don't call GetURLRequestContext(). | |
310 net::URLRequestContextGetter* rq_context = profile_->GetRequestContext(); | |
311 if (rq_context) { | |
312 ++waiting_for_clear_cookies_count_; | |
313 BrowserThread::PostTask( | |
314 BrowserThread::IO, FROM_HERE, | |
315 base::Bind(&BrowsingDataRemover::ClearCookiesOnIOThread, | |
316 base::Unretained(this), base::Unretained(rq_context))); | |
317 } | |
318 | |
319 #if defined(ENABLE_SAFE_BROWSING) | |
320 // Clear the safebrowsing cookies only if time period is for "all time". It | |
321 // doesn't make sense to apply the time period of deleting in the last X | |
322 // hours/days to the safebrowsing cookies since they aren't the result of | |
323 // any user action. | |
324 if (delete_begin_ == base::Time()) { | |
325 SafeBrowsingService* sb_service = | |
326 g_browser_process->safe_browsing_service(); | |
327 if (sb_service) { | |
328 net::URLRequestContextGetter* sb_context = | |
329 sb_service->url_request_context(); | |
330 ++waiting_for_clear_cookies_count_; | |
331 BrowserThread::PostTask( | |
332 BrowserThread::IO, FROM_HERE, | |
333 base::Bind(&BrowsingDataRemover::ClearCookiesOnIOThread, | |
334 base::Unretained(this), base::Unretained(sb_context))); | |
335 } | |
336 } | |
337 #endif | |
338 } | |
339 | |
340 // Server bound certs are not separated for protected and unprotected web | |
341 // origins. We check the origin_set_mask_ to prevent unintended deletion. | |
342 if (remove_mask & REMOVE_SERVER_BOUND_CERTS && | |
343 origin_set_mask_ & BrowsingDataHelper::UNPROTECTED_WEB) { | |
344 content::RecordAction( | |
345 UserMetricsAction("ClearBrowsingData_ServerBoundCerts")); | |
346 // Since we are running on the UI thread don't call GetURLRequestContext(). | |
347 net::URLRequestContextGetter* rq_context = profile_->GetRequestContext(); | |
348 if (rq_context) { | |
349 waiting_for_clear_server_bound_certs_ = true; | |
350 BrowserThread::PostTask( | |
351 BrowserThread::IO, FROM_HERE, | |
352 base::Bind(&BrowsingDataRemover::ClearServerBoundCertsOnIOThread, | |
353 base::Unretained(this), base::Unretained(rq_context))); | |
354 } | |
355 } | |
356 | |
357 if (remove_mask & REMOVE_LOCAL_STORAGE) { | |
358 waiting_for_clear_local_storage_ = true; | |
359 if (!dom_storage_context_) | |
360 dom_storage_context_ = | |
361 BrowserContext::GetDefaultDOMStorageContext(profile_); | |
362 ClearLocalStorageOnUIThread(); | |
363 } | |
364 | |
365 if (remove_mask & REMOVE_INDEXEDDB || remove_mask & REMOVE_WEBSQL || | |
366 remove_mask & REMOVE_APPCACHE || remove_mask & REMOVE_FILE_SYSTEMS) { | |
367 if (!quota_manager_) | |
368 quota_manager_ = content::BrowserContext::GetQuotaManager(profile_); | |
369 waiting_for_clear_quota_managed_data_ = true; | |
370 BrowserThread::PostTask( | |
371 BrowserThread::IO, FROM_HERE, | |
372 base::Bind(&BrowsingDataRemover::ClearQuotaManagedDataOnIOThread, | |
373 base::Unretained(this))); | |
374 } | |
375 | |
376 // Plugin is data not separated for protected and unprotected web origins. We | |
377 // check the origin_set_mask_ to prevent unintended deletion. | |
378 if (remove_mask & REMOVE_PLUGIN_DATA && | |
379 origin_set_mask_ & BrowsingDataHelper::UNPROTECTED_WEB) { | |
380 content::RecordAction(UserMetricsAction("ClearBrowsingData_LSOData")); | |
381 | |
382 waiting_for_clear_plugin_data_ = true; | |
383 if (!plugin_data_remover_.get()) | |
384 plugin_data_remover_.reset(content::PluginDataRemover::Create(profile_)); | |
385 base::WaitableEvent* event = | |
386 plugin_data_remover_->StartRemoving(delete_begin_); | |
387 watcher_.StartWatching(event, this); | |
388 } | |
389 | |
390 if (remove_mask & REMOVE_PASSWORDS) { | |
391 content::RecordAction(UserMetricsAction("ClearBrowsingData_Passwords")); | |
392 PasswordStore* password_store = PasswordStoreFactory::GetForProfile( | |
393 profile_, Profile::EXPLICIT_ACCESS); | |
394 | |
395 if (password_store) | |
396 password_store->RemoveLoginsCreatedBetween(delete_begin_, delete_end_); | |
397 } | |
398 | |
399 if (remove_mask & REMOVE_FORM_DATA) { | |
400 content::RecordAction(UserMetricsAction("ClearBrowsingData_Autofill")); | |
401 scoped_refptr<WebDataService> web_data_service = | |
402 WebDataServiceFactory::GetForProfile(profile_, | |
403 Profile::EXPLICIT_ACCESS); | |
404 | |
405 if (web_data_service.get()) { | |
406 web_data_service->RemoveFormElementsAddedBetween(delete_begin_, | |
407 delete_end_); | |
408 web_data_service->RemoveAutofillProfilesAndCreditCardsModifiedBetween( | |
409 delete_begin_, delete_end_); | |
410 PersonalDataManager* data_manager = | |
411 PersonalDataManagerFactory::GetForProfile(profile_); | |
412 if (data_manager) { | |
413 data_manager->Refresh(); | |
414 } | |
415 } | |
416 } | |
417 | |
418 if (remove_mask & REMOVE_CACHE) { | |
419 // Tell the renderers to clear their cache. | |
420 WebCacheManager::GetInstance()->ClearCache(); | |
421 | |
422 // Invoke DoClearCache on the IO thread. | |
423 waiting_for_clear_cache_ = true; | |
424 content::RecordAction(UserMetricsAction("ClearBrowsingData_Cache")); | |
425 | |
426 BrowserThread::PostTask( | |
427 BrowserThread::IO, FROM_HERE, | |
428 base::Bind(&BrowsingDataRemover::ClearCacheOnIOThread, | |
429 base::Unretained(this))); | |
430 | |
431 #if !defined(DISABLE_NACL) | |
432 waiting_for_clear_nacl_cache_ = true; | |
433 | |
434 BrowserThread::PostTask( | |
435 BrowserThread::IO, FROM_HERE, | |
436 base::Bind(&BrowsingDataRemover::ClearNaClCacheOnIOThread, | |
437 base::Unretained(this))); | |
438 #endif | |
439 | |
440 // The PrerenderManager may have a page actively being prerendered, which | |
441 // is essentially a preemptively cached page. | |
442 prerender::PrerenderManager* prerender_manager = | |
443 prerender::PrerenderManagerFactory::GetForProfile(profile_); | |
444 if (prerender_manager) { | |
445 prerender_manager->ClearData( | |
446 prerender::PrerenderManager::CLEAR_PRERENDER_CONTENTS); | |
447 } | |
448 } | |
449 | |
450 if (remove_mask & REMOVE_CONTENT_LICENSES) { | |
451 content::RecordAction( | |
452 UserMetricsAction("ClearBrowsingData_ContentLicenses")); | |
453 | |
454 waiting_for_clear_content_licenses_ = true; | |
455 if (!pepper_flash_settings_manager_.get()) { | |
456 pepper_flash_settings_manager_.reset( | |
457 new PepperFlashSettingsManager(this, profile_)); | |
458 } | |
459 deauthorize_content_licenses_request_id_ = | |
460 pepper_flash_settings_manager_->DeauthorizeContentLicenses(); | |
461 } | |
462 | |
463 // Also delete cached network related data (like TransportSecurityState, | |
464 // HttpServerProperties data). | |
465 profile_->ClearNetworkingHistorySince(delete_begin_); | |
466 | |
467 NotifyAndDeleteIfDone(); | |
468 } | |
469 | |
470 void BrowsingDataRemover::AddObserver(Observer* observer) { | |
471 observer_list_.AddObserver(observer); | |
472 } | |
473 | |
474 void BrowsingDataRemover::RemoveObserver(Observer* observer) { | |
475 observer_list_.RemoveObserver(observer); | |
476 } | |
477 | |
478 void BrowsingDataRemover::OnHistoryDeletionDone() { | |
479 waiting_for_clear_history_ = false; | |
480 NotifyAndDeleteIfDone(); | |
481 } | |
482 | |
483 void BrowsingDataRemover::OverrideQuotaManagerForTesting( | |
484 quota::QuotaManager* quota_manager) { | |
485 quota_manager_ = quota_manager; | |
486 } | |
487 | |
488 base::Time BrowsingDataRemover::CalculateBeginDeleteTime( | |
489 TimePeriod time_period) { | |
490 base::TimeDelta diff; | |
491 base::Time delete_begin_time = base::Time::Now(); | |
492 switch (time_period) { | |
493 case LAST_HOUR: | |
494 diff = base::TimeDelta::FromHours(1); | |
495 break; | |
496 case LAST_DAY: | |
497 diff = base::TimeDelta::FromHours(24); | |
498 break; | |
499 case LAST_WEEK: | |
500 diff = base::TimeDelta::FromHours(7*24); | |
501 break; | |
502 case FOUR_WEEKS: | |
503 diff = base::TimeDelta::FromHours(4*7*24); | |
504 break; | |
505 case EVERYTHING: | |
506 delete_begin_time = base::Time(); | |
507 break; | |
508 default: | |
509 NOTREACHED() << L"Missing item"; | |
510 break; | |
511 } | |
512 return delete_begin_time - diff; | |
513 } | |
514 | |
515 bool BrowsingDataRemover::AllDone() { | |
516 return registrar_.IsEmpty() && | |
517 !waiting_for_clear_cache_ && | |
518 !waiting_for_clear_nacl_cache_ && | |
519 !waiting_for_clear_cookies_count_&& | |
520 !waiting_for_clear_history_ && | |
521 !waiting_for_clear_local_storage_ && | |
522 !waiting_for_clear_networking_history_ && | |
523 !waiting_for_clear_server_bound_certs_ && | |
524 !waiting_for_clear_plugin_data_ && | |
525 !waiting_for_clear_quota_managed_data_ && | |
526 !waiting_for_clear_content_licenses_; | |
527 } | |
528 | |
529 void BrowsingDataRemover::Observe(int type, | |
530 const content::NotificationSource& source, | |
531 const content::NotificationDetails& details) { | |
532 // TODO(brettw) bug 1139736: This should also observe session | |
533 // clearing (what about other things such as passwords, etc.?) and wait for | |
534 // them to complete before continuing. | |
535 DCHECK(type == chrome::NOTIFICATION_TEMPLATE_URL_SERVICE_LOADED); | |
536 TemplateURLService* model = content::Source<TemplateURLService>(source).ptr(); | |
537 if (model->profile() == profile_) { | |
538 registrar_.RemoveAll(); | |
539 model->RemoveAutoGeneratedBetween(delete_begin_, delete_end_); | |
540 NotifyAndDeleteIfDone(); | |
541 } | |
542 } | |
543 | |
544 void BrowsingDataRemover::NotifyAndDeleteIfDone() { | |
545 // TODO(brettw) bug 1139736: see TODO in Observe() above. | |
546 if (!AllDone()) | |
547 return; | |
548 | |
549 set_removing(false); | |
550 | |
551 // Send global notification, then notify any explicit observers. | |
552 BrowsingDataRemover::NotificationDetails details(delete_begin_, remove_mask_, | |
553 origin_set_mask_); | |
554 content::NotificationService::current()->Notify( | |
555 chrome::NOTIFICATION_BROWSING_DATA_REMOVED, | |
556 content::Source<Profile>(profile_), | |
557 content::Details<BrowsingDataRemover::NotificationDetails>(&details)); | |
558 | |
559 FOR_EACH_OBSERVER(Observer, observer_list_, OnBrowsingDataRemoverDone()); | |
560 | |
561 // History requests aren't happy if you delete yourself from the callback. | |
562 // As such, we do a delete later. | |
563 MessageLoop::current()->DeleteSoon(FROM_HERE, this); | |
564 } | |
565 | |
566 void BrowsingDataRemover::ClearedNetworkHistory() { | |
567 waiting_for_clear_networking_history_ = false; | |
568 | |
569 NotifyAndDeleteIfDone(); | |
570 } | |
571 | |
572 void BrowsingDataRemover::ClearNetworkingHistory(IOThread* io_thread) { | |
573 // This function should be called on the IO thread. | |
574 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
575 | |
576 io_thread->ClearHostCache(); | |
577 | |
578 chrome_browser_net::Predictor* predictor = profile_->GetNetworkPredictor(); | |
579 if (predictor) { | |
580 predictor->DiscardInitialNavigationHistory(); | |
581 predictor->DiscardAllResults(); | |
582 } | |
583 | |
584 // Notify the UI thread that we are done. | |
585 BrowserThread::PostTask( | |
586 BrowserThread::UI, FROM_HERE, | |
587 base::Bind(&BrowsingDataRemover::ClearedNetworkHistory, | |
588 base::Unretained(this))); | |
589 } | |
590 | |
591 void BrowsingDataRemover::ClearedCache() { | |
592 waiting_for_clear_cache_ = false; | |
593 | |
594 NotifyAndDeleteIfDone(); | |
595 } | |
596 | |
597 void BrowsingDataRemover::ClearCacheOnIOThread() { | |
598 // This function should be called on the IO thread. | |
599 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
600 DCHECK_EQ(STATE_NONE, next_cache_state_); | |
601 DCHECK(main_context_getter_); | |
602 DCHECK(media_context_getter_); | |
603 | |
604 next_cache_state_ = STATE_CREATE_MAIN; | |
605 DoClearCache(net::OK); | |
606 } | |
607 | |
608 // The expected state sequence is STATE_NONE --> STATE_CREATE_MAIN --> | |
609 // STATE_DELETE_MAIN --> STATE_CREATE_MEDIA --> STATE_DELETE_MEDIA --> | |
610 // STATE_DONE, and any errors are ignored. | |
611 void BrowsingDataRemover::DoClearCache(int rv) { | |
612 DCHECK_NE(STATE_NONE, next_cache_state_); | |
613 | |
614 while (rv != net::ERR_IO_PENDING && next_cache_state_ != STATE_NONE) { | |
615 switch (next_cache_state_) { | |
616 case STATE_CREATE_MAIN: | |
617 case STATE_CREATE_MEDIA: { | |
618 // Get a pointer to the cache. | |
619 net::URLRequestContextGetter* getter = | |
620 (next_cache_state_ == STATE_CREATE_MAIN) ? | |
621 main_context_getter_ : media_context_getter_; | |
622 net::HttpTransactionFactory* factory = | |
623 getter->GetURLRequestContext()->http_transaction_factory(); | |
624 | |
625 rv = factory->GetCache()->GetBackend( | |
626 &cache_, base::Bind(&BrowsingDataRemover::DoClearCache, | |
627 base::Unretained(this))); | |
628 next_cache_state_ = (next_cache_state_ == STATE_CREATE_MAIN) ? | |
629 STATE_DELETE_MAIN : STATE_DELETE_MEDIA; | |
630 break; | |
631 } | |
632 case STATE_DELETE_MAIN: | |
633 case STATE_DELETE_MEDIA: { | |
634 // |cache_| can be null if it cannot be initialized. | |
635 if (cache_) { | |
636 if (delete_begin_.is_null()) { | |
637 rv = cache_->DoomAllEntries( | |
638 base::Bind(&BrowsingDataRemover::DoClearCache, | |
639 base::Unretained(this))); | |
640 } else { | |
641 rv = cache_->DoomEntriesBetween( | |
642 delete_begin_, delete_end_, | |
643 base::Bind(&BrowsingDataRemover::DoClearCache, | |
644 base::Unretained(this))); | |
645 } | |
646 cache_ = NULL; | |
647 } | |
648 next_cache_state_ = (next_cache_state_ == STATE_DELETE_MAIN) ? | |
649 STATE_CREATE_MEDIA : STATE_DONE; | |
650 break; | |
651 } | |
652 case STATE_DONE: { | |
653 cache_ = NULL; | |
654 | |
655 // Notify the UI thread that we are done. | |
656 BrowserThread::PostTask( | |
657 BrowserThread::UI, FROM_HERE, | |
658 base::Bind(&BrowsingDataRemover::ClearedCache, | |
659 base::Unretained(this))); | |
660 | |
661 next_cache_state_ = STATE_NONE; | |
662 break; | |
663 } | |
664 default: { | |
665 NOTREACHED() << "bad state"; | |
666 next_cache_state_ = STATE_NONE; // Stop looping. | |
667 break; | |
668 } | |
669 } | |
670 } | |
671 } | |
672 | |
673 #if !defined(DISABLE_NACL) | |
674 void BrowsingDataRemover::ClearedNaClCache() { | |
675 // This function should be called on the UI thread. | |
676 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
677 | |
678 waiting_for_clear_nacl_cache_ = false; | |
679 | |
680 NotifyAndDeleteIfDone(); | |
681 } | |
682 | |
683 void BrowsingDataRemover::ClearedNaClCacheOnIOThread() { | |
684 // This function should be called on the IO thread. | |
685 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
686 | |
687 // Notify the UI thread that we are done. | |
688 BrowserThread::PostTask( | |
689 BrowserThread::UI, FROM_HERE, | |
690 base::Bind(&BrowsingDataRemover::ClearedNaClCache, | |
691 base::Unretained(this))); | |
692 } | |
693 | |
694 void BrowsingDataRemover::ClearNaClCacheOnIOThread() { | |
695 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
696 | |
697 NaClBrowser::GetInstance()->ClearValidationCache( | |
698 base::Bind(&BrowsingDataRemover::ClearedNaClCacheOnIOThread, | |
699 base::Unretained(this))); | |
700 } | |
701 #endif | |
702 | |
703 void BrowsingDataRemover::ClearLocalStorageOnUIThread() { | |
704 DCHECK(waiting_for_clear_local_storage_); | |
705 | |
706 dom_storage_context_->GetUsageInfo( | |
707 base::Bind(&BrowsingDataRemover::OnGotLocalStorageUsageInfo, | |
708 base::Unretained(this))); | |
709 } | |
710 | |
711 void BrowsingDataRemover::OnGotLocalStorageUsageInfo( | |
712 const std::vector<dom_storage::DomStorageContext::UsageInfo>& infos) { | |
713 DCHECK(waiting_for_clear_local_storage_); | |
714 | |
715 for (size_t i = 0; i < infos.size(); ++i) { | |
716 if (!BrowsingDataHelper::DoesOriginMatchMask(infos[i].origin, | |
717 origin_set_mask_, | |
718 special_storage_policy_)) | |
719 continue; | |
720 | |
721 if (infos[i].last_modified >= delete_begin_ && | |
722 infos[i].last_modified <= delete_end_) | |
723 dom_storage_context_->DeleteOrigin(infos[i].origin); | |
724 } | |
725 BrowserThread::PostTask( | |
726 BrowserThread::UI, FROM_HERE, | |
727 base::Bind(&BrowsingDataRemover::OnLocalStorageCleared, | |
728 base::Unretained(this))); | |
729 } | |
730 | |
731 void BrowsingDataRemover::OnLocalStorageCleared() { | |
732 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
733 DCHECK(waiting_for_clear_local_storage_); | |
734 waiting_for_clear_local_storage_ = false; | |
735 NotifyAndDeleteIfDone(); | |
736 } | |
737 | |
738 void BrowsingDataRemover::ClearQuotaManagedDataOnIOThread() { | |
739 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
740 | |
741 // Ask the QuotaManager for all origins with temporary quota modified within | |
742 // the user-specified timeframe, and deal with the resulting set in | |
743 // OnGotQuotaManagedOrigins(). | |
744 quota_managed_origins_to_delete_count_ = 0; | |
745 quota_managed_storage_types_to_delete_count_ = 0; | |
746 | |
747 if (delete_begin_ == base::Time() || | |
748 origin_set_mask_ & | |
749 (BrowsingDataHelper::PROTECTED_WEB | BrowsingDataHelper::EXTENSION)) { | |
750 // If we're deleting since the beginning of time, or we're removing | |
751 // protected origins, then ask the QuotaManager for all origins with | |
752 // persistent quota modified within the user-specified timeframe, and deal | |
753 // with the resulting set in OnGotQuotaManagedOrigins. | |
754 ++quota_managed_storage_types_to_delete_count_; | |
755 quota_manager_->GetOriginsModifiedSince( | |
756 quota::kStorageTypePersistent, delete_begin_, | |
757 base::Bind(&BrowsingDataRemover::OnGotQuotaManagedOrigins, | |
758 base::Unretained(this))); | |
759 } | |
760 | |
761 // Do the same for temporary quota. | |
762 ++quota_managed_storage_types_to_delete_count_; | |
763 quota_manager_->GetOriginsModifiedSince( | |
764 quota::kStorageTypeTemporary, delete_begin_, | |
765 base::Bind(&BrowsingDataRemover::OnGotQuotaManagedOrigins, | |
766 base::Unretained(this))); | |
767 } | |
768 | |
769 void BrowsingDataRemover::OnGotQuotaManagedOrigins( | |
770 const std::set<GURL>& origins, quota::StorageType type) { | |
771 DCHECK_GT(quota_managed_storage_types_to_delete_count_, 0); | |
772 // Walk through the origins passed in, delete quota of |type| from each that | |
773 // matches the |origin_set_mask_|. | |
774 std::set<GURL>::const_iterator origin; | |
775 for (origin = origins.begin(); origin != origins.end(); ++origin) { | |
776 // TODO(mkwst): Clean this up, it's slow. http://crbug.com/130746 | |
777 if (!remove_origin_.is_empty() && remove_origin_ != origin->GetOrigin()) | |
778 continue; | |
779 | |
780 if (!BrowsingDataHelper::DoesOriginMatchMask(origin->GetOrigin(), | |
781 origin_set_mask_, | |
782 special_storage_policy_)) | |
783 continue; | |
784 | |
785 ++quota_managed_origins_to_delete_count_; | |
786 quota_manager_->DeleteOriginData( | |
787 origin->GetOrigin(), type, | |
788 BrowsingDataRemover::GenerateQuotaClientMask(remove_mask_), | |
789 base::Bind(&BrowsingDataRemover::OnQuotaManagedOriginDeletion, | |
790 base::Unretained(this), origin->GetOrigin(), type)); | |
791 } | |
792 | |
793 --quota_managed_storage_types_to_delete_count_; | |
794 CheckQuotaManagedDataDeletionStatus(); | |
795 } | |
796 | |
797 void BrowsingDataRemover::OnQuotaManagedOriginDeletion( | |
798 const GURL& origin, | |
799 quota::StorageType type, | |
800 quota::QuotaStatusCode status) { | |
801 DCHECK_GT(quota_managed_origins_to_delete_count_, 0); | |
802 if (status != quota::kQuotaStatusOk) { | |
803 DLOG(ERROR) << "Couldn't remove data of type " << type << " for origin " | |
804 << origin << ". Status: " << status; | |
805 } | |
806 | |
807 --quota_managed_origins_to_delete_count_; | |
808 CheckQuotaManagedDataDeletionStatus(); | |
809 } | |
810 | |
811 void BrowsingDataRemover::CheckQuotaManagedDataDeletionStatus() { | |
812 if (quota_managed_storage_types_to_delete_count_ != 0 || | |
813 quota_managed_origins_to_delete_count_ != 0) { | |
814 return; | |
815 } | |
816 | |
817 BrowserThread::PostTask( | |
818 BrowserThread::UI, FROM_HERE, | |
819 base::Bind(&BrowsingDataRemover::OnQuotaManagedDataDeleted, | |
820 base::Unretained(this))); | |
821 } | |
822 | |
823 void BrowsingDataRemover::OnQuotaManagedDataDeleted() { | |
824 DCHECK(waiting_for_clear_quota_managed_data_); | |
825 waiting_for_clear_quota_managed_data_ = false; | |
826 NotifyAndDeleteIfDone(); | |
827 } | |
828 | |
829 void BrowsingDataRemover::OnWaitableEventSignaled( | |
830 base::WaitableEvent* waitable_event) { | |
831 waiting_for_clear_plugin_data_ = false; | |
832 NotifyAndDeleteIfDone(); | |
833 } | |
834 | |
835 void BrowsingDataRemover::OnDeauthorizeContentLicensesCompleted( | |
836 uint32 request_id, | |
837 bool /* success */) { | |
838 DCHECK(waiting_for_clear_content_licenses_); | |
839 DCHECK_EQ(request_id, deauthorize_content_licenses_request_id_); | |
840 | |
841 waiting_for_clear_content_licenses_ = false; | |
842 NotifyAndDeleteIfDone(); | |
843 } | |
844 | |
845 void BrowsingDataRemover::OnClearedCookies(int num_deleted) { | |
846 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | |
847 BrowserThread::PostTask( | |
848 BrowserThread::UI, FROM_HERE, | |
849 base::Bind(&BrowsingDataRemover::OnClearedCookies, | |
850 base::Unretained(this), num_deleted)); | |
851 return; | |
852 } | |
853 | |
854 DCHECK(waiting_for_clear_cookies_count_ > 0); | |
855 --waiting_for_clear_cookies_count_; | |
856 NotifyAndDeleteIfDone(); | |
857 } | |
858 | |
859 void BrowsingDataRemover::ClearCookiesOnIOThread( | |
860 net::URLRequestContextGetter* rq_context) { | |
861 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
862 net::CookieStore* cookie_store = rq_context-> | |
863 GetURLRequestContext()->cookie_store(); | |
864 cookie_store->DeleteAllCreatedBetweenAsync( | |
865 delete_begin_, delete_end_, | |
866 base::Bind(&BrowsingDataRemover::OnClearedCookies, | |
867 base::Unretained(this))); | |
868 } | |
869 | |
870 void BrowsingDataRemover::ClearServerBoundCertsOnIOThread( | |
871 net::URLRequestContextGetter* rq_context) { | |
872 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
873 net::ServerBoundCertService* server_bound_cert_service = | |
874 rq_context->GetURLRequestContext()->server_bound_cert_service(); | |
875 server_bound_cert_service->GetCertStore()->DeleteAllCreatedBetween( | |
876 delete_begin_, delete_end_); | |
877 BrowserThread::PostTask( | |
878 BrowserThread::UI, FROM_HERE, | |
879 base::Bind(&BrowsingDataRemover::OnClearedServerBoundCerts, | |
880 base::Unretained(this))); | |
881 } | |
882 | |
883 void BrowsingDataRemover::OnClearedServerBoundCerts() { | |
884 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
885 waiting_for_clear_server_bound_certs_ = false; | |
886 NotifyAndDeleteIfDone(); | |
887 } | |
OLD | NEW |