Home | History | Annotate | Download | only in browser
      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 
     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 
     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 
    106 BrowsingDataRemover::~BrowsingDataRemover() {
    107   DCHECK(all_done());
    108 }
    109 
    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 
    269 void BrowsingDataRemover::AddObserver(Observer* observer) {
    270   observer_list_.AddObserver(observer);
    271 }
    272 
    273 void BrowsingDataRemover::RemoveObserver(Observer* observer) {
    274   observer_list_.RemoveObserver(observer);
    275 }
    276 
    277 void BrowsingDataRemover::OnHistoryDeletionDone() {
    278   waiting_for_clear_history_ = false;
    279   NotifyAndDeleteIfDone();
    280 }
    281 
    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 
    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 
    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 
    343 void BrowsingDataRemover::ClearedNetworkHistory() {
    344   waiting_for_clear_networking_history_ = false;
    345 
    346   NotifyAndDeleteIfDone();
    347 }
    348 
    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 
    361 void BrowsingDataRemover::ClearedCache() {
    362   waiting_for_clear_cache_ = false;
    363 
    364   NotifyAndDeleteIfDone();
    365 }
    366 
    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.
    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 
    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 
    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 
    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 
    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 
    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 
    505 void BrowsingDataRemover::OnAppCacheDeleted(int rv) {
    506   --appcaches_to_be_deleted_count_;
    507   if (!appcaches_to_be_deleted_count_)
    508     OnClearedAppCache();
    509 }
    510 
    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 
    520 void BrowsingDataRemover::OnWaitableEventSignaled(
    521     base::WaitableEvent* waitable_event) {
    522   waiting_for_clear_lso_data_ = false;
    523   NotifyAndDeleteIfDone();
    524 }
    525