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. 45DISABLE_RUNNABLE_METHOD_REFCOUNT(BrowsingDataRemover); 46 47bool BrowsingDataRemover::removing_ = false; 48 49BrowsingDataRemover::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 77BrowsingDataRemover::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 106BrowsingDataRemover::~BrowsingDataRemover() { 107 DCHECK(all_done()); 108} 109 110void 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 269void BrowsingDataRemover::AddObserver(Observer* observer) { 270 observer_list_.AddObserver(observer); 271} 272 273void BrowsingDataRemover::RemoveObserver(Observer* observer) { 274 observer_list_.RemoveObserver(observer); 275} 276 277void BrowsingDataRemover::OnHistoryDeletionDone() { 278 waiting_for_clear_history_ = false; 279 NotifyAndDeleteIfDone(); 280} 281 282base::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 309void 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 324void 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 343void BrowsingDataRemover::ClearedNetworkHistory() { 344 waiting_for_clear_networking_history_ = false; 345 346 NotifyAndDeleteIfDone(); 347} 348 349void 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 361void BrowsingDataRemover::ClearedCache() { 362 waiting_for_clear_cache_ = false; 363 364 NotifyAndDeleteIfDone(); 365} 366 367void 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. 381void 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 436void 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 451void 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 460void 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 472void 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 481void 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 505void BrowsingDataRemover::OnAppCacheDeleted(int rv) { 506 --appcaches_to_be_deleted_count_; 507 if (!appcaches_to_be_deleted_count_) 508 OnClearedAppCache(); 509} 510 511ChromeAppCacheService* 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 520void BrowsingDataRemover::OnWaitableEventSignaled( 521 base::WaitableEvent* waitable_event) { 522 waiting_for_clear_lso_data_ = false; 523 NotifyAndDeleteIfDone(); 524} 525