1 // Copyright (c) 2011 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/callback.h"
11 #include "chrome/browser/autofill/personal_data_manager.h"
12 #include "chrome/browser/browser_process.h"
13 #include "chrome/browser/download/download_manager.h"
14 #include "chrome/browser/extensions/extension_service.h"
15 #include "chrome/browser/extensions/extension_special_storage_policy.h"
16 #include "chrome/browser/history/history.h"
17 #include "chrome/browser/io_thread.h"
18 #include "chrome/browser/metrics/user_metrics.h"
19 #include "chrome/browser/net/chrome_net_log.h"
20 #include "chrome/browser/net/chrome_url_request_context.h"
21 #include "chrome/browser/password_manager/password_store.h"
22 #include "chrome/browser/plugin_data_remover.h"
23 #include "chrome/browser/profiles/profile.h"
24 #include "chrome/browser/renderer_host/web_cache_manager.h"
25 #include "chrome/browser/search_engines/template_url_model.h"
26 #include "chrome/browser/sessions/session_service.h"
27 #include "chrome/browser/sessions/tab_restore_service.h"
28 #include "chrome/browser/webdata/web_data_service.h"
29 #include "chrome/common/url_constants.h"
30 #include "content/browser/browser_thread.h"
31 #include "content/browser/in_process_webkit/webkit_context.h"
32 #include "content/common/notification_source.h"
33 #include "net/base/cookie_monster.h"
34 #include "net/base/net_errors.h"
35 #include "net/base/transport_security_state.h"
36 #include "net/disk_cache/disk_cache.h"
37 #include "net/http/http_cache.h"
38 #include "net/url_request/url_request_context.h"
39 #include "net/url_request/url_request_context_getter.h"
40 #include "webkit/database/database_tracker.h"
41 #include "webkit/database/database_util.h"
42
43 // Done so that we can use PostTask on BrowsingDataRemovers and not have
44 // BrowsingDataRemover implement RefCounted.
45 DISABLE_RUNNABLE_METHOD_REFCOUNT(BrowsingDataRemover);
46
47 bool BrowsingDataRemover::removing_ = false;
48
BrowsingDataRemover(Profile * profile,base::Time delete_begin,base::Time delete_end)49 BrowsingDataRemover::BrowsingDataRemover(Profile* profile,
50 base::Time delete_begin,
51 base::Time delete_end)
52 : profile_(profile),
53 special_storage_policy_(profile->GetExtensionSpecialStoragePolicy()),
54 delete_begin_(delete_begin),
55 delete_end_(delete_end),
56 ALLOW_THIS_IN_INITIALIZER_LIST(database_cleared_callback_(
57 this, &BrowsingDataRemover::OnClearedDatabases)),
58 ALLOW_THIS_IN_INITIALIZER_LIST(cache_callback_(
59 this, &BrowsingDataRemover::DoClearCache)),
60 ALLOW_THIS_IN_INITIALIZER_LIST(appcache_got_info_callback_(
61 this, &BrowsingDataRemover::OnGotAppCacheInfo)),
62 ALLOW_THIS_IN_INITIALIZER_LIST(appcache_deleted_callback_(
63 this, &BrowsingDataRemover::OnAppCacheDeleted)),
64 appcaches_to_be_deleted_count_(0),
65 next_cache_state_(STATE_NONE),
66 cache_(NULL),
67 main_context_getter_(profile->GetRequestContext()),
68 media_context_getter_(profile->GetRequestContextForMedia()),
69 waiting_for_clear_databases_(false),
70 waiting_for_clear_history_(false),
71 waiting_for_clear_networking_history_(false),
72 waiting_for_clear_cache_(false),
73 waiting_for_clear_appcache_(false) {
74 DCHECK(profile);
75 }
76
BrowsingDataRemover(Profile * profile,TimePeriod time_period,base::Time delete_end)77 BrowsingDataRemover::BrowsingDataRemover(Profile* profile,
78 TimePeriod time_period,
79 base::Time delete_end)
80 : profile_(profile),
81 special_storage_policy_(profile->GetExtensionSpecialStoragePolicy()),
82 delete_begin_(CalculateBeginDeleteTime(time_period)),
83 delete_end_(delete_end),
84 ALLOW_THIS_IN_INITIALIZER_LIST(database_cleared_callback_(
85 this, &BrowsingDataRemover::OnClearedDatabases)),
86 ALLOW_THIS_IN_INITIALIZER_LIST(cache_callback_(
87 this, &BrowsingDataRemover::DoClearCache)),
88 ALLOW_THIS_IN_INITIALIZER_LIST(appcache_got_info_callback_(
89 this, &BrowsingDataRemover::OnGotAppCacheInfo)),
90 ALLOW_THIS_IN_INITIALIZER_LIST(appcache_deleted_callback_(
91 this, &BrowsingDataRemover::OnAppCacheDeleted)),
92 appcaches_to_be_deleted_count_(0),
93 next_cache_state_(STATE_NONE),
94 cache_(NULL),
95 main_context_getter_(profile->GetRequestContext()),
96 media_context_getter_(profile->GetRequestContextForMedia()),
97 waiting_for_clear_databases_(false),
98 waiting_for_clear_history_(false),
99 waiting_for_clear_networking_history_(false),
100 waiting_for_clear_cache_(false),
101 waiting_for_clear_appcache_(false),
102 waiting_for_clear_lso_data_(false) {
103 DCHECK(profile);
104 }
105
~BrowsingDataRemover()106 BrowsingDataRemover::~BrowsingDataRemover() {
107 DCHECK(all_done());
108 }
109
Remove(int remove_mask)110 void BrowsingDataRemover::Remove(int remove_mask) {
111 DCHECK(!removing_);
112 removing_ = true;
113
114 if (remove_mask & REMOVE_HISTORY) {
115 HistoryService* history_service =
116 profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
117 if (history_service) {
118 std::set<GURL> restrict_urls;
119 UserMetrics::RecordAction(UserMetricsAction("ClearBrowsingData_History"),
120 profile_);
121 waiting_for_clear_history_ = true;
122 history_service->ExpireHistoryBetween(restrict_urls,
123 delete_begin_, delete_end_,
124 &request_consumer_,
125 NewCallback(this, &BrowsingDataRemover::OnHistoryDeletionDone));
126 }
127
128 // Need to clear the host cache and accumulated speculative data, as it also
129 // reveals some history.
130 waiting_for_clear_networking_history_ = true;
131 BrowserThread::PostTask(
132 BrowserThread::IO, FROM_HERE,
133 NewRunnableMethod(
134 this,
135 &BrowsingDataRemover::ClearNetworkingHistory,
136 g_browser_process->io_thread()));
137
138 // As part of history deletion we also delete the auto-generated keywords.
139 TemplateURLModel* keywords_model = profile_->GetTemplateURLModel();
140 if (keywords_model && !keywords_model->loaded()) {
141 registrar_.Add(this, NotificationType::TEMPLATE_URL_MODEL_LOADED,
142 Source<TemplateURLModel>(keywords_model));
143 keywords_model->Load();
144 } else if (keywords_model) {
145 keywords_model->RemoveAutoGeneratedBetween(delete_begin_, delete_end_);
146 }
147
148 // We also delete the list of recently closed tabs. Since these expire,
149 // they can't be more than a day old, so we can simply clear them all.
150 TabRestoreService* tab_service = profile_->GetTabRestoreService();
151 if (tab_service) {
152 tab_service->ClearEntries();
153 tab_service->DeleteLastSession();
154 }
155
156 // We also delete the last session when we delete the history.
157 SessionService* session_service = profile_->GetSessionService();
158 if (session_service)
159 session_service->DeleteLastSession();
160 }
161
162 if (remove_mask & REMOVE_DOWNLOADS) {
163 UserMetrics::RecordAction(UserMetricsAction("ClearBrowsingData_Downloads"),
164 profile_);
165 DownloadManager* download_manager = profile_->GetDownloadManager();
166 download_manager->RemoveDownloadsBetween(delete_begin_, delete_end_);
167 download_manager->ClearLastDownloadPath();
168 }
169
170 if (remove_mask & REMOVE_COOKIES) {
171 UserMetrics::RecordAction(UserMetricsAction("ClearBrowsingData_Cookies"),
172 profile_);
173 // Since we are running on the UI thread don't call GetURLRequestContext().
174 net::CookieMonster* cookie_monster =
175 profile_->GetRequestContext()->DONTUSEME_GetCookieStore()->
176 GetCookieMonster();
177 if (cookie_monster)
178 cookie_monster->DeleteAllCreatedBetween(delete_begin_, delete_end_, true);
179
180 // REMOVE_COOKIES is actually "cookies and other site data" so we make sure
181 // to remove other data such local databases, STS state, etc.
182 // We assume the end time is now.
183
184 profile_->GetWebKitContext()->DeleteDataModifiedSince(delete_begin_);
185
186 database_tracker_ = profile_->GetDatabaseTracker();
187 if (database_tracker_.get()) {
188 waiting_for_clear_databases_ = true;
189 BrowserThread::PostTask(
190 BrowserThread::FILE, FROM_HERE,
191 NewRunnableMethod(
192 this,
193 &BrowsingDataRemover::ClearDatabasesOnFILEThread));
194 }
195
196 waiting_for_clear_appcache_ = true;
197 BrowserThread::PostTask(
198 BrowserThread::IO, FROM_HERE,
199 NewRunnableMethod(
200 this,
201 &BrowsingDataRemover::ClearAppCacheOnIOThread));
202
203 // TODO(michaeln): delete temporary file system data too
204
205 BrowserThread::PostTask(
206 BrowserThread::IO, FROM_HERE,
207 NewRunnableMethod(
208 profile_->GetTransportSecurityState(),
209 &net::TransportSecurityState::DeleteSince,
210 delete_begin_));
211 }
212
213 if (remove_mask & REMOVE_PASSWORDS) {
214 UserMetrics::RecordAction(UserMetricsAction("ClearBrowsingData_Passwords"),
215 profile_);
216 PasswordStore* password_store =
217 profile_->GetPasswordStore(Profile::EXPLICIT_ACCESS);
218
219 if (password_store)
220 password_store->RemoveLoginsCreatedBetween(delete_begin_, delete_end_);
221 }
222
223 if (remove_mask & REMOVE_FORM_DATA) {
224 UserMetrics::RecordAction(UserMetricsAction("ClearBrowsingData_Autofill"),
225 profile_);
226 WebDataService* web_data_service =
227 profile_->GetWebDataService(Profile::EXPLICIT_ACCESS);
228
229 if (web_data_service) {
230 web_data_service->RemoveFormElementsAddedBetween(delete_begin_,
231 delete_end_);
232 web_data_service->RemoveAutofillProfilesAndCreditCardsModifiedBetween(
233 delete_begin_, delete_end_);
234 PersonalDataManager* data_manager = profile_->GetPersonalDataManager();
235 if (data_manager) {
236 data_manager->Refresh();
237 }
238 }
239 }
240
241 if (remove_mask & REMOVE_CACHE) {
242 // Tell the renderers to clear their cache.
243 WebCacheManager::GetInstance()->ClearCache();
244
245 // Invoke DoClearCache on the IO thread.
246 waiting_for_clear_cache_ = true;
247 UserMetrics::RecordAction(UserMetricsAction("ClearBrowsingData_Cache"),
248 profile_);
249
250 BrowserThread::PostTask(
251 BrowserThread::IO, FROM_HERE,
252 NewRunnableMethod(this, &BrowsingDataRemover::ClearCacheOnIOThread));
253 }
254
255 if (remove_mask & REMOVE_LSO_DATA) {
256 UserMetrics::RecordAction(UserMetricsAction("ClearBrowsingData_LSOData"));
257
258 waiting_for_clear_lso_data_ = true;
259 if (!plugin_data_remover_.get())
260 plugin_data_remover_ = new PluginDataRemover();
261 base::WaitableEvent* event =
262 plugin_data_remover_->StartRemoving(delete_begin_);
263 watcher_.StartWatching(event, this);
264 }
265
266 NotifyAndDeleteIfDone();
267 }
268
AddObserver(Observer * observer)269 void BrowsingDataRemover::AddObserver(Observer* observer) {
270 observer_list_.AddObserver(observer);
271 }
272
RemoveObserver(Observer * observer)273 void BrowsingDataRemover::RemoveObserver(Observer* observer) {
274 observer_list_.RemoveObserver(observer);
275 }
276
OnHistoryDeletionDone()277 void BrowsingDataRemover::OnHistoryDeletionDone() {
278 waiting_for_clear_history_ = false;
279 NotifyAndDeleteIfDone();
280 }
281
CalculateBeginDeleteTime(TimePeriod time_period)282 base::Time BrowsingDataRemover::CalculateBeginDeleteTime(
283 TimePeriod time_period) {
284 base::TimeDelta diff;
285 base::Time delete_begin_time = base::Time::Now();
286 switch (time_period) {
287 case LAST_HOUR:
288 diff = base::TimeDelta::FromHours(1);
289 break;
290 case LAST_DAY:
291 diff = base::TimeDelta::FromHours(24);
292 break;
293 case LAST_WEEK:
294 diff = base::TimeDelta::FromHours(7*24);
295 break;
296 case FOUR_WEEKS:
297 diff = base::TimeDelta::FromHours(4*7*24);
298 break;
299 case EVERYTHING:
300 delete_begin_time = base::Time();
301 break;
302 default:
303 NOTREACHED() << L"Missing item";
304 break;
305 }
306 return delete_begin_time - diff;
307 }
308
Observe(NotificationType type,const NotificationSource & source,const NotificationDetails & details)309 void BrowsingDataRemover::Observe(NotificationType type,
310 const NotificationSource& source,
311 const NotificationDetails& details) {
312 // TODO(brettw) bug 1139736: This should also observe session
313 // clearing (what about other things such as passwords, etc.?) and wait for
314 // them to complete before continuing.
315 DCHECK(type == NotificationType::TEMPLATE_URL_MODEL_LOADED);
316 TemplateURLModel* model = Source<TemplateURLModel>(source).ptr();
317 if (model->profile() == profile_->GetOriginalProfile()) {
318 registrar_.RemoveAll();
319 model->RemoveAutoGeneratedBetween(delete_begin_, delete_end_);
320 NotifyAndDeleteIfDone();
321 }
322 }
323
NotifyAndDeleteIfDone()324 void BrowsingDataRemover::NotifyAndDeleteIfDone() {
325 // TODO(brettw) bug 1139736: see TODO in Observe() above.
326 if (!all_done())
327 return;
328
329 // The NetLog contains download history, but may also contain form data,
330 // cookies and passwords. Simplest just to always clear it. Must be cleared
331 // after the cache, as cleaning up the disk cache exposes some of the history
332 // in the NetLog.
333 g_browser_process->net_log()->ClearAllPassivelyCapturedEvents();
334
335 removing_ = false;
336 FOR_EACH_OBSERVER(Observer, observer_list_, OnBrowsingDataRemoverDone());
337
338 // History requests aren't happy if you delete yourself from the callback.
339 // As such, we do a delete later.
340 MessageLoop::current()->DeleteSoon(FROM_HERE, this);
341 }
342
ClearedNetworkHistory()343 void BrowsingDataRemover::ClearedNetworkHistory() {
344 waiting_for_clear_networking_history_ = false;
345
346 NotifyAndDeleteIfDone();
347 }
348
ClearNetworkingHistory(IOThread * io_thread)349 void BrowsingDataRemover::ClearNetworkingHistory(IOThread* io_thread) {
350 // This function should be called on the IO thread.
351 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
352
353 io_thread->ClearNetworkingHistory();
354
355 // Notify the UI thread that we are done.
356 BrowserThread::PostTask(
357 BrowserThread::UI, FROM_HERE,
358 NewRunnableMethod(this, &BrowsingDataRemover::ClearedNetworkHistory));
359 }
360
ClearedCache()361 void BrowsingDataRemover::ClearedCache() {
362 waiting_for_clear_cache_ = false;
363
364 NotifyAndDeleteIfDone();
365 }
366
ClearCacheOnIOThread()367 void BrowsingDataRemover::ClearCacheOnIOThread() {
368 // This function should be called on the IO thread.
369 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
370 DCHECK_EQ(STATE_NONE, next_cache_state_);
371 DCHECK(main_context_getter_);
372 DCHECK(media_context_getter_);
373
374 next_cache_state_ = STATE_CREATE_MAIN;
375 DoClearCache(net::OK);
376 }
377
378 // The expected state sequence is STATE_NONE --> STATE_CREATE_MAIN -->
379 // STATE_DELETE_MAIN --> STATE_CREATE_MEDIA --> STATE_DELETE_MEDIA -->
380 // STATE_DONE, and any errors are ignored.
DoClearCache(int rv)381 void BrowsingDataRemover::DoClearCache(int rv) {
382 DCHECK_NE(STATE_NONE, next_cache_state_);
383
384 while (rv != net::ERR_IO_PENDING && next_cache_state_ != STATE_NONE) {
385 switch (next_cache_state_) {
386 case STATE_CREATE_MAIN:
387 case STATE_CREATE_MEDIA: {
388 // Get a pointer to the cache.
389 net::URLRequestContextGetter* getter =
390 (next_cache_state_ == STATE_CREATE_MAIN) ?
391 main_context_getter_ : media_context_getter_;
392 net::HttpTransactionFactory* factory =
393 getter->GetURLRequestContext()->http_transaction_factory();
394
395 rv = factory->GetCache()->GetBackend(&cache_, &cache_callback_);
396 next_cache_state_ = (next_cache_state_ == STATE_CREATE_MAIN) ?
397 STATE_DELETE_MAIN : STATE_DELETE_MEDIA;
398 break;
399 }
400 case STATE_DELETE_MAIN:
401 case STATE_DELETE_MEDIA: {
402 // |cache_| can be null if it cannot be initialized.
403 if (cache_) {
404 if (delete_begin_.is_null()) {
405 rv = cache_->DoomAllEntries(&cache_callback_);
406 } else {
407 rv = cache_->DoomEntriesBetween(delete_begin_, delete_end_,
408 &cache_callback_);
409 }
410 cache_ = NULL;
411 }
412 next_cache_state_ = (next_cache_state_ == STATE_DELETE_MAIN) ?
413 STATE_CREATE_MEDIA : STATE_DONE;
414 break;
415 }
416 case STATE_DONE: {
417 cache_ = NULL;
418
419 // Notify the UI thread that we are done.
420 BrowserThread::PostTask(
421 BrowserThread::UI, FROM_HERE,
422 NewRunnableMethod(this, &BrowsingDataRemover::ClearedCache));
423
424 next_cache_state_ = STATE_NONE;
425 break;
426 }
427 default: {
428 NOTREACHED() << "bad state";
429 next_cache_state_ = STATE_NONE; // Stop looping.
430 break;
431 }
432 }
433 }
434 }
435
OnClearedDatabases(int rv)436 void BrowsingDataRemover::OnClearedDatabases(int rv) {
437 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
438 bool result = BrowserThread::PostTask(
439 BrowserThread::UI, FROM_HERE,
440 NewRunnableMethod(this, &BrowsingDataRemover::OnClearedDatabases, rv));
441 DCHECK(result);
442 return;
443 }
444 // Notify the UI thread that we are done.
445 database_tracker_ = NULL;
446 waiting_for_clear_databases_ = false;
447
448 NotifyAndDeleteIfDone();
449 }
450
ClearDatabasesOnFILEThread()451 void BrowsingDataRemover::ClearDatabasesOnFILEThread() {
452 // This function should be called on the FILE thread.
453 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
454 int rv = database_tracker_->DeleteDataModifiedSince(
455 delete_begin_, &database_cleared_callback_);
456 if (rv != net::ERR_IO_PENDING)
457 OnClearedDatabases(rv);
458 }
459
OnClearedAppCache()460 void BrowsingDataRemover::OnClearedAppCache() {
461 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
462 bool result = BrowserThread::PostTask(
463 BrowserThread::UI, FROM_HERE,
464 NewRunnableMethod(this, &BrowsingDataRemover::OnClearedAppCache));
465 DCHECK(result);
466 return;
467 }
468 waiting_for_clear_appcache_ = false;
469 NotifyAndDeleteIfDone();
470 }
471
ClearAppCacheOnIOThread()472 void BrowsingDataRemover::ClearAppCacheOnIOThread() {
473 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
474 DCHECK(waiting_for_clear_appcache_);
475 appcache_info_ = new appcache::AppCacheInfoCollection;
476 GetAppCacheService()->GetAllAppCacheInfo(
477 appcache_info_, &appcache_got_info_callback_);
478 // continues in OnGotAppCacheInfo
479 }
480
OnGotAppCacheInfo(int rv)481 void BrowsingDataRemover::OnGotAppCacheInfo(int rv) {
482 using appcache::AppCacheInfoVector;
483 typedef std::map<GURL, AppCacheInfoVector> InfoByOrigin;
484
485 for (InfoByOrigin::const_iterator origin =
486 appcache_info_->infos_by_origin.begin();
487 origin != appcache_info_->infos_by_origin.end(); ++origin) {
488 if (special_storage_policy_->IsStorageProtected(origin->first))
489 continue;
490 for (AppCacheInfoVector::const_iterator info = origin->second.begin();
491 info != origin->second.end(); ++info) {
492 if (info->creation_time > delete_begin_) {
493 ++appcaches_to_be_deleted_count_;
494 GetAppCacheService()->DeleteAppCacheGroup(
495 info->manifest_url, &appcache_deleted_callback_);
496 }
497 }
498 }
499
500 if (!appcaches_to_be_deleted_count_)
501 OnClearedAppCache();
502 // else continues in OnAppCacheDeleted
503 }
504
OnAppCacheDeleted(int rv)505 void BrowsingDataRemover::OnAppCacheDeleted(int rv) {
506 --appcaches_to_be_deleted_count_;
507 if (!appcaches_to_be_deleted_count_)
508 OnClearedAppCache();
509 }
510
GetAppCacheService()511 ChromeAppCacheService* BrowsingDataRemover::GetAppCacheService() {
512 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
513 ChromeURLRequestContext* request_context =
514 reinterpret_cast<ChromeURLRequestContext*>(
515 main_context_getter_->GetURLRequestContext());
516 return request_context ? request_context->appcache_service()
517 : NULL;
518 }
519
OnWaitableEventSignaled(base::WaitableEvent * waitable_event)520 void BrowsingDataRemover::OnWaitableEventSignaled(
521 base::WaitableEvent* waitable_event) {
522 waiting_for_clear_lso_data_ = false;
523 NotifyAndDeleteIfDone();
524 }
525