• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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