// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/browsing_data/browsing_data_remover.h" #include #include #include #include "base/bind.h" #include "base/bind_helpers.h" #include "base/callback.h" #include "base/logging.h" #include "base/metrics/histogram_macros.h" #include "build/build_config.h" #include "chrome/browser/autofill/personal_data_manager_factory.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browsing_data/browsing_data_helper.h" #include "chrome/browser/browsing_data/browsing_data_remover_factory.h" #include "chrome/browser/browsing_data/origin_filter_builder.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/domain_reliability/service_factory.h" #include "chrome/browser/download/download_prefs.h" #include "chrome/browser/history/history_service_factory.h" #include "chrome/browser/history/web_history_service_factory.h" #include "chrome/browser/io_thread.h" #include "chrome/browser/media/media_device_id_salt.h" #include "chrome/browser/net/predictor.h" #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings.h" #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings_factory.h" #include "chrome/browser/password_manager/password_store_factory.h" #include "chrome/browser/prerender/prerender_manager.h" #include "chrome/browser/prerender/prerender_manager_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/safe_browsing/safe_browsing_service.h" #include "chrome/browser/search_engines/template_url_service_factory.h" #include "chrome/browser/sessions/tab_restore_service_factory.h" #include "chrome/browser/web_data_service_factory.h" #include "chrome/common/features.h" #include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" #include "components/autofill/core/browser/personal_data_manager.h" #include "components/autofill/core/browser/webdata/autofill_webdata_service.h" #include "components/browsing_data/storage_partition_http_cache_data_remover.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h" #include "components/domain_reliability/service.h" #include "components/history/core/browser/history_service.h" #include "components/nacl/browser/nacl_browser.h" #include "components/nacl/browser/pnacl_host.h" #include "components/omnibox/browser/omnibox_pref_names.h" #include "components/password_manager/core/browser/password_store.h" #include "components/power/origin_power_map.h" #include "components/power/origin_power_map_factory.h" #include "components/prefs/pref_service.h" #include "components/search_engines/template_url_service.h" #include "components/sessions/core/tab_restore_service.h" #include "components/web_cache/browser/web_cache_manager.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/download_manager.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/plugin_data_remover.h" #include "content/public/browser/ssl_host_state_delegate.h" #include "content/public/browser/storage_partition.h" #include "content/public/browser/user_metrics.h" #include "net/base/net_errors.h" #include "net/cookies/cookie_store.h" #include "net/http/transport_security_state.h" #include "net/ssl/channel_id_service.h" #include "net/ssl/channel_id_store.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context_getter.h" #include "storage/browser/quota/special_storage_policy.h" #include "url/origin.h" #if BUILDFLAG(ANDROID_JAVA_UI) #include "chrome/browser/android/offline_pages/offline_page_model_factory.h" #include "chrome/browser/android/webapps/webapp_registry.h" #include "chrome/browser/precache/precache_manager_factory.h" #include "components/offline_pages/offline_page_feature.h" #include "components/offline_pages/offline_page_model.h" #include "components/precache/content/precache_manager.h" #endif #if defined(OS_CHROMEOS) #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chromeos/attestation/attestation_constants.h" #include "chromeos/cryptohome/cryptohome_parameters.h" #include "chromeos/dbus/cryptohome_client.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "components/user_manager/user.h" #endif #if defined(ENABLE_EXTENSIONS) #include "chrome/browser/extensions/activity_log/activity_log.h" #include "extensions/browser/extension_prefs.h" #endif #if defined(ENABLE_SESSION_SERVICE) #include "chrome/browser/sessions/session_service.h" #include "chrome/browser/sessions/session_service_factory.h" #endif #if defined(ENABLE_WEBRTC) #include "chrome/browser/media/webrtc_log_list.h" #include "chrome/browser/media/webrtc_log_util.h" #endif using base::UserMetricsAction; using content::BrowserContext; using content::BrowserThread; using content::DOMStorageContext; namespace { using CallbackList = base::CallbackList; // Contains all registered callbacks for browsing data removed notifications. CallbackList* g_on_browsing_data_removed_callbacks = nullptr; // Accessor for |*g_on_browsing_data_removed_callbacks|. Creates a new object // the first time so that it always returns a valid object. CallbackList* GetOnBrowsingDataRemovedCallbacks() { if (!g_on_browsing_data_removed_callbacks) g_on_browsing_data_removed_callbacks = new CallbackList(); return g_on_browsing_data_removed_callbacks; } void UIThreadTrampolineHelper(const base::Closure& callback) { BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback); } // Convenience method to create a callback that can be run on any thread and // will post the given |callback| back to the UI thread. base::Closure UIThreadTrampoline(const base::Closure& callback) { // We could directly bind &BrowserThread::PostTask, but that would require // evaluating FROM_HERE when this method is called, as opposed to when the // task is actually posted. return base::Bind(&UIThreadTrampolineHelper, callback); } template void IgnoreArgumentHelper(const base::Closure& callback, T unused_argument) { callback.Run(); } // Another convenience method to turn a callback without arguments into one that // accepts (and ignores) a single argument. template base::Callback IgnoreArgument(const base::Closure& callback) { return base::Bind(&IgnoreArgumentHelper, callback); } // Helper to create callback for BrowsingDataRemover::DoesOriginMatchMask. bool DoesOriginMatchMask( int origin_type_mask, const GURL& origin, storage::SpecialStoragePolicy* special_storage_policy) { return BrowsingDataHelper::DoesOriginMatchMask( origin, origin_type_mask, special_storage_policy); } void ClearHostnameResolutionCacheOnIOThread(IOThread* io_thread) { DCHECK_CURRENTLY_ON(BrowserThread::IO); io_thread->ClearHostCache(); } void ClearNetworkPredictorOnIOThread(chrome_browser_net::Predictor* predictor) { DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(predictor); predictor->DiscardInitialNavigationHistory(); predictor->DiscardAllResults(); } #if !defined(DISABLE_NACL) void ClearNaClCacheOnIOThread(const base::Closure& callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); nacl::NaClBrowser::GetInstance()->ClearValidationCache(callback); } void ClearPnaclCacheOnIOThread(base::Time begin, base::Time end, const base::Closure& callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); pnacl::PnaclHost::GetInstance()->ClearTranslationCacheEntriesBetween( begin, end, callback); } #endif void ClearCookiesOnIOThread(base::Time delete_begin, base::Time delete_end, net::URLRequestContextGetter* rq_context, const base::Closure& callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); net::CookieStore* cookie_store = rq_context->GetURLRequestContext()->cookie_store(); cookie_store->DeleteAllCreatedBetweenAsync(delete_begin, delete_end, IgnoreArgument(callback)); } void OnClearedChannelIDsOnIOThread(net::URLRequestContextGetter* rq_context, const base::Closure& callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); // Need to close open SSL connections which may be using the channel ids we // are deleting. // TODO(mattm): http://crbug.com/166069 Make the server bound cert // service/store have observers that can notify relevant things directly. rq_context->GetURLRequestContext() ->ssl_config_service() ->NotifySSLConfigChange(); BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback); } void ClearChannelIDsOnIOThread( base::Time delete_begin, base::Time delete_end, scoped_refptr rq_context, const base::Closure& callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); net::ChannelIDService* channel_id_service = rq_context->GetURLRequestContext()->channel_id_service(); channel_id_service->GetChannelIDStore()->DeleteAllCreatedBetween( delete_begin, delete_end, base::Bind(&OnClearedChannelIDsOnIOThread, base::RetainedRef(std::move(rq_context)), callback)); } } // namespace BrowsingDataRemover::CompletionInhibitor* BrowsingDataRemover::completion_inhibitor_ = nullptr; BrowsingDataRemover::NotificationDetails::NotificationDetails() : removal_begin(base::Time()), removal_mask(-1), origin_type_mask(-1) { } BrowsingDataRemover::NotificationDetails::NotificationDetails( const BrowsingDataRemover::NotificationDetails& details) : removal_begin(details.removal_begin), removal_mask(details.removal_mask), origin_type_mask(details.origin_type_mask) { } BrowsingDataRemover::NotificationDetails::NotificationDetails( base::Time removal_begin, int removal_mask, int origin_type_mask) : removal_begin(removal_begin), removal_mask(removal_mask), origin_type_mask(origin_type_mask) { } BrowsingDataRemover::NotificationDetails::~NotificationDetails() {} // static BrowsingDataRemover::TimeRange BrowsingDataRemover::Unbounded() { return TimeRange(base::Time(), base::Time::Max()); } // static BrowsingDataRemover::TimeRange BrowsingDataRemover::Period(TimePeriod period) { switch (period) { case LAST_HOUR: content::RecordAction( UserMetricsAction("ClearBrowsingData_LastHour")); break; case LAST_DAY: content::RecordAction( UserMetricsAction("ClearBrowsingData_LastDay")); break; case LAST_WEEK: content::RecordAction( UserMetricsAction("ClearBrowsingData_LastWeek")); break; case FOUR_WEEKS: content::RecordAction( UserMetricsAction("ClearBrowsingData_LastMonth")); break; case EVERYTHING: content::RecordAction( UserMetricsAction("ClearBrowsingData_Everything")); break; } return TimeRange(CalculateBeginDeleteTime(period), base::Time::Max()); } BrowsingDataRemover::BrowsingDataRemover( content::BrowserContext* browser_context) : profile_(Profile::FromBrowserContext(browser_context)), is_removing_(false), main_context_getter_(browser_context->GetRequestContext()), media_context_getter_(browser_context->GetMediaRequestContext()), #if BUILDFLAG(ANDROID_JAVA_UI) webapp_registry_(new WebappRegistry()), #endif weak_ptr_factory_(this) { DCHECK(browser_context); } BrowsingDataRemover::~BrowsingDataRemover() { // If we are still removing data, notify observers so they can remove // themselves from the observer list. // TODO(bauerb): If it becomes a problem that browsing data might not actually // be fully cleared when an observer is notified, add a success flag. if (is_removing_) Notify(); } void BrowsingDataRemover::Shutdown() { history_task_tracker_.TryCancelAll(); template_url_sub_.reset(); } void BrowsingDataRemover::SetRemoving(bool is_removing) { DCHECK_NE(is_removing_, is_removing); is_removing_ = is_removing; } void BrowsingDataRemover::Remove(const TimeRange& time_range, int remove_mask, int origin_type_mask) { RemoveImpl(time_range, remove_mask, GURL(), origin_type_mask); } void BrowsingDataRemover::RemoveImpl(const TimeRange& time_range, int remove_mask, const GURL& remove_url, int origin_type_mask) { DCHECK_CURRENTLY_ON(BrowserThread::UI); // crbug.com/140910: Many places were calling this with base::Time() as // delete_end, even though they should've used base::Time::Max(). DCHECK_NE(base::Time(), time_range.end); SetRemoving(true); delete_begin_ = time_range.begin; delete_end_ = time_range.end; remove_mask_ = remove_mask; origin_type_mask_ = origin_type_mask; // TODO(msramek): Replace |remove_origin| with |filter| in all backends. const url::Origin remove_origin(remove_url); OriginFilterBuilder builder(OriginFilterBuilder::BLACKLIST); if (!remove_url.is_empty()) { // Make sure that only URLs representing origins, with no extra components, // are passed to this class. DCHECK_EQ(remove_url, remove_url.GetOrigin()); builder.SetMode(OriginFilterBuilder::WHITELIST); builder.AddOrigin(url::Origin(remove_origin)); } base::Callback same_origin_filter = builder.BuildSameOriginFilter(); PrefService* prefs = profile_->GetPrefs(); bool may_delete_history = prefs->GetBoolean( prefs::kAllowDeletingBrowserHistory); // All the UI entry points into the BrowsingDataRemover should be disabled, // but this will fire if something was missed or added. DCHECK(may_delete_history || (remove_mask & REMOVE_NOCHECKS) || (!(remove_mask & REMOVE_HISTORY) && !(remove_mask & REMOVE_DOWNLOADS))); if (origin_type_mask_ & BrowsingDataHelper::UNPROTECTED_WEB) { content::RecordAction( UserMetricsAction("ClearBrowsingData_MaskContainsUnprotectedWeb")); } if (origin_type_mask_ & BrowsingDataHelper::PROTECTED_WEB) { content::RecordAction( UserMetricsAction("ClearBrowsingData_MaskContainsProtectedWeb")); } if (origin_type_mask_ & BrowsingDataHelper::EXTENSION) { content::RecordAction( UserMetricsAction("ClearBrowsingData_MaskContainsExtension")); } // If this fires, we added a new BrowsingDataHelper::OriginTypeMask without // updating the user metrics above. static_assert( BrowsingDataHelper::ALL == (BrowsingDataHelper::UNPROTECTED_WEB | BrowsingDataHelper::PROTECTED_WEB | BrowsingDataHelper::EXTENSION), "OriginTypeMask has been updated without updating user metrics"); if ((remove_mask & REMOVE_HISTORY) && may_delete_history) { history::HistoryService* history_service = HistoryServiceFactory::GetForProfile( profile_, ServiceAccessType::EXPLICIT_ACCESS); if (history_service) { // Selective history deletion is currently done through HistoryUI -> // HistoryBackend -> HistoryService, and that is for individual URLs, // not origins. The code below is currently unused, as the only callsite // supplying |remove_url| is the unittest. // TODO(msramek): Make it possible to delete history per origin, not just // per URL, and use that functionality here. std::set restrict_urls; if (!remove_url.is_empty()) restrict_urls.insert(remove_url); content::RecordAction(UserMetricsAction("ClearBrowsingData_History")); waiting_for_clear_history_ = true; history_service->ExpireLocalAndRemoteHistoryBetween( WebHistoryServiceFactory::GetForProfile(profile_), restrict_urls, delete_begin_, delete_end_, base::Bind(&BrowsingDataRemover::OnHistoryDeletionDone, weak_ptr_factory_.GetWeakPtr()), &history_task_tracker_); #if defined(ENABLE_EXTENSIONS) // The extension activity contains details of which websites extensions // were active on. It therefore indirectly stores details of websites a // user has visited so best clean from here as well. extensions::ActivityLog::GetInstance(profile_)->RemoveURLs(restrict_urls); #endif } #if defined(ENABLE_EXTENSIONS) // Clear launch times as they are a form of history. extensions::ExtensionPrefs* extension_prefs = extensions::ExtensionPrefs::Get(profile_); extension_prefs->ClearLastLaunchTimes(); #endif // The power consumption history by origin contains details of websites // that were visited. power::OriginPowerMap* origin_power_map = power::OriginPowerMapFactory::GetForBrowserContext(profile_); if (origin_power_map) origin_power_map->ClearOriginMap(); // Need to clear the host cache and accumulated speculative data, as it also // reveals some history: we have no mechanism to track when these items were // created, so we'll clear them all. Better safe than sorry. if (g_browser_process->io_thread()) { waiting_for_clear_hostname_resolution_cache_ = true; BrowserThread::PostTaskAndReply( BrowserThread::IO, FROM_HERE, base::Bind(&ClearHostnameResolutionCacheOnIOThread, g_browser_process->io_thread()), base::Bind(&BrowsingDataRemover::OnClearedHostnameResolutionCache, weak_ptr_factory_.GetWeakPtr())); } if (profile_->GetNetworkPredictor()) { waiting_for_clear_network_predictor_ = true; BrowserThread::PostTaskAndReply( BrowserThread::IO, FROM_HERE, base::Bind(&ClearNetworkPredictorOnIOThread, profile_->GetNetworkPredictor()), base::Bind(&BrowsingDataRemover::OnClearedNetworkPredictor, weak_ptr_factory_.GetWeakPtr())); } // As part of history deletion we also delete the auto-generated keywords. TemplateURLService* keywords_model = TemplateURLServiceFactory::GetForProfile(profile_); if (keywords_model && !keywords_model->loaded()) { template_url_sub_ = keywords_model->RegisterOnLoadedCallback( base::Bind(&BrowsingDataRemover::OnKeywordsLoaded, weak_ptr_factory_.GetWeakPtr())); keywords_model->Load(); waiting_for_clear_keyword_data_ = true; } else if (keywords_model) { keywords_model->RemoveAutoGeneratedForOriginBetween( remove_url, delete_begin_, delete_end_); } // The PrerenderManager keeps history of prerendered pages, so clear that. // It also may have a prerendered page. If so, the page could be // considered to have a small amount of historical information, so delete // it, too. prerender::PrerenderManager* prerender_manager = prerender::PrerenderManagerFactory::GetForProfile(profile_); if (prerender_manager) { prerender_manager->ClearData( prerender::PrerenderManager::CLEAR_PRERENDER_CONTENTS | prerender::PrerenderManager::CLEAR_PRERENDER_HISTORY); } // If the caller is removing history for all hosts, then clear ancillary // historical information. if (remove_url.is_empty()) { // We also delete the list of recently closed tabs. Since these expire, // they can't be more than a day old, so we can simply clear them all. sessions::TabRestoreService* tab_service = TabRestoreServiceFactory::GetForProfile(profile_); if (tab_service) { tab_service->ClearEntries(); tab_service->DeleteLastSession(); } #if defined(ENABLE_SESSION_SERVICE) // We also delete the last session when we delete the history. SessionService* session_service = SessionServiceFactory::GetForProfile(profile_); if (session_service) session_service->DeleteLastSession(); #endif } // The saved Autofill profiles and credit cards can include the origin from // which these profiles and credit cards were learned. These are a form of // history, so clear them as well. scoped_refptr web_data_service = WebDataServiceFactory::GetAutofillWebDataForProfile( profile_, ServiceAccessType::EXPLICIT_ACCESS); if (web_data_service.get()) { waiting_for_clear_autofill_origin_urls_ = true; web_data_service->RemoveOriginURLsModifiedBetween( delete_begin_, delete_end_); // The above calls are done on the UI thread but do their work on the DB // thread. So wait for it. BrowserThread::PostTaskAndReply( BrowserThread::DB, FROM_HERE, base::Bind(&base::DoNothing), base::Bind(&BrowsingDataRemover::OnClearedAutofillOriginURLs, weak_ptr_factory_.GetWeakPtr())); autofill::PersonalDataManager* data_manager = autofill::PersonalDataManagerFactory::GetForProfile(profile_); if (data_manager) data_manager->Refresh(); } #if defined(ENABLE_WEBRTC) waiting_for_clear_webrtc_logs_ = true; BrowserThread::PostTaskAndReply( BrowserThread::FILE, FROM_HERE, base::Bind( &WebRtcLogUtil::DeleteOldAndRecentWebRtcLogFiles, WebRtcLogList::GetWebRtcLogDirectoryForProfile(profile_->GetPath()), delete_begin_), base::Bind(&BrowsingDataRemover::OnClearedWebRtcLogs, weak_ptr_factory_.GetWeakPtr())); #endif // The SSL Host State that tracks SSL interstitial "proceed" decisions may // include origins that the user has visited, so it must be cleared. if (profile_->GetSSLHostStateDelegate()) profile_->GetSSLHostStateDelegate()->Clear(); #if BUILDFLAG(ANDROID_JAVA_UI) precache::PrecacheManager* precache_manager = precache::PrecacheManagerFactory::GetForBrowserContext(profile_); // |precache_manager| could be nullptr if the profile is off the record. if (!precache_manager) { waiting_for_clear_precache_history_ = true; precache_manager->ClearHistory(); // The above calls are done on the UI thread but do their work on the DB // thread. So wait for it. BrowserThread::PostTaskAndReply( BrowserThread::DB, FROM_HERE, base::Bind(&base::DoNothing), base::Bind(&BrowsingDataRemover::OnClearedPrecacheHistory, weak_ptr_factory_.GetWeakPtr())); } #endif data_reduction_proxy::DataReductionProxySettings* data_reduction_proxy_settings = DataReductionProxyChromeSettingsFactory::GetForBrowserContext( profile_); // |data_reduction_proxy_settings| is null if |profile_| is off the record. if (data_reduction_proxy_settings) { data_reduction_proxy::DataReductionProxyService* data_reduction_proxy_service = data_reduction_proxy_settings->data_reduction_proxy_service(); if (data_reduction_proxy_service) { data_reduction_proxy_service->compression_stats() ->DeleteBrowsingHistory(delete_begin_, delete_end_); } } } if ((remove_mask & REMOVE_DOWNLOADS) && may_delete_history) { content::RecordAction(UserMetricsAction("ClearBrowsingData_Downloads")); content::DownloadManager* download_manager = BrowserContext::GetDownloadManager(profile_); download_manager->RemoveDownloadsByURLAndTime( same_origin_filter, delete_begin_, delete_end_); DownloadPrefs* download_prefs = DownloadPrefs::FromDownloadManager( download_manager); download_prefs->SetSaveFilePath(download_prefs->DownloadPath()); } uint32_t storage_partition_remove_mask = 0; // We ignore the REMOVE_COOKIES request if UNPROTECTED_WEB is not set, // so that callers who request REMOVE_SITE_DATA with PROTECTED_WEB // don't accidentally remove the cookies that are associated with the // UNPROTECTED_WEB origin. This is necessary because cookies are not separated // between UNPROTECTED_WEB and PROTECTED_WEB. if (remove_mask & REMOVE_COOKIES && origin_type_mask_ & BrowsingDataHelper::UNPROTECTED_WEB) { content::RecordAction(UserMetricsAction("ClearBrowsingData_Cookies")); storage_partition_remove_mask |= content::StoragePartition::REMOVE_DATA_MASK_COOKIES; // Clear the safebrowsing cookies only if time period is for "all time". It // doesn't make sense to apply the time period of deleting in the last X // hours/days to the safebrowsing cookies since they aren't the result of // any user action. if (delete_begin_ == base::Time()) { safe_browsing::SafeBrowsingService* sb_service = g_browser_process->safe_browsing_service(); if (sb_service) { scoped_refptr sb_context = sb_service->url_request_context(); ++waiting_for_clear_cookies_count_; BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, base::Bind(&ClearCookiesOnIOThread, delete_begin_, delete_end_, base::RetainedRef(std::move(sb_context)), UIThreadTrampoline( base::Bind(&BrowsingDataRemover::OnClearedCookies, weak_ptr_factory_.GetWeakPtr())))); } } MediaDeviceIDSalt::Reset(profile_->GetPrefs()); } // Channel IDs are not separated for protected and unprotected web // origins. We check the origin_type_mask_ to prevent unintended deletion. if (remove_mask & REMOVE_CHANNEL_IDS && origin_type_mask_ & BrowsingDataHelper::UNPROTECTED_WEB) { content::RecordAction( UserMetricsAction("ClearBrowsingData_ChannelIDs")); // Since we are running on the UI thread don't call GetURLRequestContext(). scoped_refptr rq_context = profile_->GetRequestContext(); if (rq_context) { waiting_for_clear_channel_ids_ = true; BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, base::Bind(&ClearChannelIDsOnIOThread, delete_begin_, delete_end_, std::move(rq_context), base::Bind(&BrowsingDataRemover::OnClearedChannelIDs, weak_ptr_factory_.GetWeakPtr()))); } } if (remove_mask & REMOVE_LOCAL_STORAGE) { storage_partition_remove_mask |= content::StoragePartition::REMOVE_DATA_MASK_LOCAL_STORAGE; } if (remove_mask & REMOVE_INDEXEDDB) { storage_partition_remove_mask |= content::StoragePartition::REMOVE_DATA_MASK_INDEXEDDB; } if (remove_mask & REMOVE_WEBSQL) { storage_partition_remove_mask |= content::StoragePartition::REMOVE_DATA_MASK_WEBSQL; } if (remove_mask & REMOVE_APPCACHE) { storage_partition_remove_mask |= content::StoragePartition::REMOVE_DATA_MASK_APPCACHE; } if (remove_mask & REMOVE_SERVICE_WORKERS) { storage_partition_remove_mask |= content::StoragePartition::REMOVE_DATA_MASK_SERVICE_WORKERS; } if (remove_mask & REMOVE_CACHE_STORAGE) { storage_partition_remove_mask |= content::StoragePartition::REMOVE_DATA_MASK_CACHE_STORAGE; } if (remove_mask & REMOVE_FILE_SYSTEMS) { storage_partition_remove_mask |= content::StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS; } #if defined(ENABLE_PLUGINS) // Plugin is data not separated for protected and unprotected web origins. We // check the origin_type_mask_ to prevent unintended deletion. if (remove_mask & REMOVE_PLUGIN_DATA && origin_type_mask_ & BrowsingDataHelper::UNPROTECTED_WEB) { content::RecordAction(UserMetricsAction("ClearBrowsingData_LSOData")); waiting_for_clear_plugin_data_ = true; DCHECK(!plugin_data_remover_); plugin_data_remover_.reset(content::PluginDataRemover::Create(profile_)); base::WaitableEvent* event = plugin_data_remover_->StartRemoving(delete_begin_); base::WaitableEventWatcher::EventCallback watcher_callback = base::Bind(&BrowsingDataRemover::OnWaitableEventSignaled, weak_ptr_factory_.GetWeakPtr()); watcher_.StartWatching(event, watcher_callback); } #endif if (remove_mask & REMOVE_SITE_USAGE_DATA) { HostContentSettingsMapFactory::GetForProfile(profile_) ->ClearSettingsForOneType(CONTENT_SETTINGS_TYPE_SITE_ENGAGEMENT); } if (remove_mask & REMOVE_SITE_USAGE_DATA || remove_mask & REMOVE_HISTORY) { HostContentSettingsMapFactory::GetForProfile(profile_) ->ClearSettingsForOneType(CONTENT_SETTINGS_TYPE_APP_BANNER); } if (remove_mask & REMOVE_PASSWORDS) { content::RecordAction(UserMetricsAction("ClearBrowsingData_Passwords")); password_manager::PasswordStore* password_store = PasswordStoreFactory::GetForProfile( profile_, ServiceAccessType::EXPLICIT_ACCESS).get(); if (password_store) { waiting_for_clear_passwords_ = true; auto on_cleared_passwords = base::Bind(&BrowsingDataRemover::OnClearedPasswords, weak_ptr_factory_.GetWeakPtr()); password_store->RemoveLoginsByURLAndTime( same_origin_filter, delete_begin_, delete_end_, on_cleared_passwords); } } if (remove_mask & REMOVE_COOKIES) { password_manager::PasswordStore* password_store = PasswordStoreFactory::GetForProfile(profile_, ServiceAccessType::EXPLICIT_ACCESS) .get(); if (password_store) { waiting_for_clear_auto_sign_in_ = true; base::Closure on_cleared_auto_sign_in = base::Bind(&BrowsingDataRemover::OnClearedAutoSignIn, weak_ptr_factory_.GetWeakPtr()); password_store->DisableAutoSignInForAllLogins(on_cleared_auto_sign_in); } } if (remove_mask & REMOVE_HISTORY) { password_manager::PasswordStore* password_store = PasswordStoreFactory::GetForProfile( profile_, ServiceAccessType::EXPLICIT_ACCESS).get(); if (password_store) { waiting_for_clear_passwords_stats_ = true; password_store->RemoveStatisticsCreatedBetween( delete_begin_, delete_end_, base::Bind(&BrowsingDataRemover::OnClearedPasswordsStats, weak_ptr_factory_.GetWeakPtr())); } } if (remove_mask & REMOVE_FORM_DATA) { content::RecordAction(UserMetricsAction("ClearBrowsingData_Autofill")); scoped_refptr web_data_service = WebDataServiceFactory::GetAutofillWebDataForProfile( profile_, ServiceAccessType::EXPLICIT_ACCESS); if (web_data_service.get()) { waiting_for_clear_form_ = true; web_data_service->RemoveFormElementsAddedBetween(delete_begin_, delete_end_); web_data_service->RemoveAutofillDataModifiedBetween( delete_begin_, delete_end_); // The above calls are done on the UI thread but do their work on the DB // thread. So wait for it. BrowserThread::PostTaskAndReply( BrowserThread::DB, FROM_HERE, base::Bind(&base::DoNothing), base::Bind(&BrowsingDataRemover::OnClearedFormData, weak_ptr_factory_.GetWeakPtr())); autofill::PersonalDataManager* data_manager = autofill::PersonalDataManagerFactory::GetForProfile(profile_); if (data_manager) data_manager->Refresh(); } } if (remove_mask & REMOVE_CACHE) { // Tell the renderers to clear their cache. web_cache::WebCacheManager::GetInstance()->ClearCache(); content::RecordAction(UserMetricsAction("ClearBrowsingData_Cache")); waiting_for_clear_cache_ = true; // StoragePartitionHttpCacheDataRemover deletes itself when it is done. browsing_data::StoragePartitionHttpCacheDataRemover::CreateForRange( BrowserContext::GetDefaultStoragePartition(profile_), delete_begin_, delete_end_) ->Remove(base::Bind(&BrowsingDataRemover::ClearedCache, weak_ptr_factory_.GetWeakPtr())); #if !defined(DISABLE_NACL) waiting_for_clear_nacl_cache_ = true; BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, base::Bind(&ClearNaClCacheOnIOThread, UIThreadTrampoline( base::Bind(&BrowsingDataRemover::ClearedNaClCache, weak_ptr_factory_.GetWeakPtr())))); waiting_for_clear_pnacl_cache_ = true; BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, base::Bind(&ClearPnaclCacheOnIOThread, delete_begin_, delete_end_, UIThreadTrampoline( base::Bind(&BrowsingDataRemover::ClearedPnaclCache, weak_ptr_factory_.GetWeakPtr())))); #endif // The PrerenderManager may have a page actively being prerendered, which // is essentially a preemptively cached page. prerender::PrerenderManager* prerender_manager = prerender::PrerenderManagerFactory::GetForProfile(profile_); if (prerender_manager) { prerender_manager->ClearData( prerender::PrerenderManager::CLEAR_PRERENDER_CONTENTS); } // Tell the shader disk cache to clear. content::RecordAction(UserMetricsAction("ClearBrowsingData_ShaderCache")); storage_partition_remove_mask |= content::StoragePartition::REMOVE_DATA_MASK_SHADER_CACHE; storage_partition_remove_mask |= content::StoragePartition::REMOVE_DATA_MASK_WEBRTC_IDENTITY; } if (remove_mask & REMOVE_WEBRTC_IDENTITY) { storage_partition_remove_mask |= content::StoragePartition::REMOVE_DATA_MASK_WEBRTC_IDENTITY; } if (storage_partition_remove_mask) { waiting_for_clear_storage_partition_data_ = true; content::StoragePartition* storage_partition; if (storage_partition_for_testing_) storage_partition = storage_partition_for_testing_; else storage_partition = BrowserContext::GetDefaultStoragePartition(profile_); uint32_t quota_storage_remove_mask = ~content::StoragePartition::QUOTA_MANAGED_STORAGE_MASK_PERSISTENT; if (delete_begin_ == base::Time() || origin_type_mask_ & (BrowsingDataHelper::PROTECTED_WEB | BrowsingDataHelper::EXTENSION)) { // If we're deleting since the beginning of time, or we're removing // protected origins, then remove persistent quota data. quota_storage_remove_mask |= content::StoragePartition::QUOTA_MANAGED_STORAGE_MASK_PERSISTENT; } storage_partition->ClearData( storage_partition_remove_mask, quota_storage_remove_mask, remove_url, base::Bind(&DoesOriginMatchMask, origin_type_mask_), delete_begin_, delete_end_, base::Bind(&BrowsingDataRemover::OnClearedStoragePartitionData, weak_ptr_factory_.GetWeakPtr())); } #if defined(ENABLE_PLUGINS) if (remove_mask & REMOVE_CONTENT_LICENSES) { content::RecordAction( UserMetricsAction("ClearBrowsingData_ContentLicenses")); waiting_for_clear_content_licenses_ = true; if (!pepper_flash_settings_manager_.get()) { pepper_flash_settings_manager_.reset( new PepperFlashSettingsManager(this, profile_)); } deauthorize_content_licenses_request_id_ = pepper_flash_settings_manager_->DeauthorizeContentLicenses(prefs); #if defined(OS_CHROMEOS) // On Chrome OS, also delete any content protection platform keys. const user_manager::User* user = chromeos::ProfileHelper::Get()->GetUserByProfile(profile_); if (!user) { LOG(WARNING) << "Failed to find user for current profile."; } else { chromeos::DBusThreadManager::Get() ->GetCryptohomeClient() ->TpmAttestationDeleteKeys( chromeos::attestation::KEY_USER, cryptohome::Identification(user->GetAccountId()), chromeos::attestation::kContentProtectionKeyPrefix, base::Bind(&BrowsingDataRemover::OnClearPlatformKeys, weak_ptr_factory_.GetWeakPtr())); waiting_for_clear_platform_keys_ = true; } #endif } #endif // Remove omnibox zero-suggest cache results. if ((remove_mask & (REMOVE_CACHE | REMOVE_COOKIES))) prefs->SetString(omnibox::kZeroSuggestCachedResults, std::string()); // Always wipe accumulated network related data (TransportSecurityState and // HttpServerPropertiesManager data). waiting_for_clear_networking_history_ = true; profile_->ClearNetworkingHistorySince( delete_begin_, base::Bind(&BrowsingDataRemover::OnClearedNetworkingHistory, weak_ptr_factory_.GetWeakPtr())); if (remove_mask & (REMOVE_COOKIES | REMOVE_HISTORY)) { domain_reliability::DomainReliabilityService* service = domain_reliability::DomainReliabilityServiceFactory:: GetForBrowserContext(profile_); if (service) { domain_reliability::DomainReliabilityClearMode mode; if (remove_mask & REMOVE_COOKIES) mode = domain_reliability::CLEAR_CONTEXTS; else mode = domain_reliability::CLEAR_BEACONS; waiting_for_clear_domain_reliability_monitor_ = true; service->ClearBrowsingData( mode, base::Bind(&BrowsingDataRemover::OnClearedDomainReliabilityMonitor, weak_ptr_factory_.GetWeakPtr())); } } #if BUILDFLAG(ANDROID_JAVA_UI) if (remove_mask & REMOVE_WEBAPP_DATA) { waiting_for_clear_webapp_data_ = true; webapp_registry_->UnregisterWebapps( base::Bind(&BrowsingDataRemover::OnClearedWebappData, weak_ptr_factory_.GetWeakPtr())); } if ((remove_mask & REMOVE_OFFLINE_PAGE_DATA) && offline_pages::IsOfflinePagesEnabled()) { waiting_for_clear_offline_page_data_ = true; offline_pages::OfflinePageModelFactory::GetForBrowserContext(profile_) ->ClearAll(base::Bind(&BrowsingDataRemover::OnClearedOfflinePageData, weak_ptr_factory_.GetWeakPtr())); } #endif // Record the combined deletion of cookies and cache. CookieOrCacheDeletionChoice choice = NEITHER_COOKIES_NOR_CACHE; if (remove_mask & REMOVE_COOKIES && origin_type_mask_ & BrowsingDataHelper::UNPROTECTED_WEB) { choice = remove_mask & REMOVE_CACHE ? BOTH_COOKIES_AND_CACHE : ONLY_COOKIES; } else if (remove_mask & REMOVE_CACHE) { choice = ONLY_CACHE; } UMA_HISTOGRAM_ENUMERATION( "History.ClearBrowsingData.UserDeletedCookieOrCache", choice, MAX_CHOICE_VALUE); } void BrowsingDataRemover::AddObserver(Observer* observer) { observer_list_.AddObserver(observer); } void BrowsingDataRemover::RemoveObserver(Observer* observer) { observer_list_.RemoveObserver(observer); } void BrowsingDataRemover::OverrideStoragePartitionForTesting( content::StoragePartition* storage_partition) { storage_partition_for_testing_ = storage_partition; } #if BUILDFLAG(ANDROID_JAVA_UI) void BrowsingDataRemover::OverrideWebappRegistryForTesting( scoped_ptr webapp_registry) { webapp_registry_.reset(webapp_registry.release()); } #endif base::Time BrowsingDataRemover::CalculateBeginDeleteTime( TimePeriod time_period) { base::TimeDelta diff; base::Time delete_begin_time = base::Time::Now(); switch (time_period) { case LAST_HOUR: diff = base::TimeDelta::FromHours(1); break; case LAST_DAY: diff = base::TimeDelta::FromHours(24); break; case LAST_WEEK: diff = base::TimeDelta::FromHours(7*24); break; case FOUR_WEEKS: diff = base::TimeDelta::FromHours(4*7*24); break; case EVERYTHING: delete_begin_time = base::Time(); break; } return delete_begin_time - diff; } bool BrowsingDataRemover::AllDone() { return !waiting_for_clear_autofill_origin_urls_ && !waiting_for_clear_cache_ && !waiting_for_clear_content_licenses_ && !waiting_for_clear_channel_ids_ && !waiting_for_clear_cookies_count_ && !waiting_for_clear_domain_reliability_monitor_ && !waiting_for_clear_form_ && !waiting_for_clear_history_ && !waiting_for_clear_hostname_resolution_cache_ && !waiting_for_clear_keyword_data_ && !waiting_for_clear_nacl_cache_ && !waiting_for_clear_network_predictor_ && !waiting_for_clear_networking_history_ && !waiting_for_clear_passwords_ && !waiting_for_clear_passwords_stats_ && !waiting_for_clear_platform_keys_ && !waiting_for_clear_plugin_data_ && !waiting_for_clear_pnacl_cache_ && #if BUILDFLAG(ANDROID_JAVA_UI) !waiting_for_clear_precache_history_ && !waiting_for_clear_webapp_data_ && !waiting_for_clear_offline_page_data_ && #endif #if defined(ENABLE_WEBRTC) !waiting_for_clear_webrtc_logs_ && #endif !waiting_for_clear_storage_partition_data_ && !waiting_for_clear_auto_sign_in_; } void BrowsingDataRemover::OnKeywordsLoaded() { // Deletes the entries from the model, and if we're not waiting on anything // else notifies observers and deletes this BrowsingDataRemover. TemplateURLService* model = TemplateURLServiceFactory::GetForProfile(profile_); model->RemoveAutoGeneratedBetween(delete_begin_, delete_end_); waiting_for_clear_keyword_data_ = false; template_url_sub_.reset(); NotifyIfDone(); } void BrowsingDataRemover::Notify() { SetRemoving(false); // Notify observers. BrowsingDataRemover::NotificationDetails details(delete_begin_, remove_mask_, origin_type_mask_); GetOnBrowsingDataRemovedCallbacks()->Notify(details); FOR_EACH_OBSERVER(Observer, observer_list_, OnBrowsingDataRemoverDone()); } void BrowsingDataRemover::NotifyIfDone() { // TODO(brettw) http://crbug.com/305259: This should also observe session // clearing (what about other things such as passwords, etc.?) and wait for // them to complete before continuing. if (!AllDone()) return; if (completion_inhibitor_) { completion_inhibitor_->OnBrowsingDataRemoverWouldComplete( this, base::Bind(&BrowsingDataRemover::Notify, weak_ptr_factory_.GetWeakPtr())); return; } Notify(); } void BrowsingDataRemover::OnHistoryDeletionDone() { DCHECK_CURRENTLY_ON(BrowserThread::UI); waiting_for_clear_history_ = false; NotifyIfDone(); } void BrowsingDataRemover::OnClearedHostnameResolutionCache() { DCHECK_CURRENTLY_ON(BrowserThread::UI); waiting_for_clear_hostname_resolution_cache_ = false; NotifyIfDone(); } void BrowsingDataRemover::OnClearedNetworkPredictor() { DCHECK_CURRENTLY_ON(BrowserThread::UI); waiting_for_clear_network_predictor_ = false; NotifyIfDone(); } void BrowsingDataRemover::OnClearedNetworkingHistory() { DCHECK_CURRENTLY_ON(BrowserThread::UI); waiting_for_clear_networking_history_ = false; NotifyIfDone(); } void BrowsingDataRemover::ClearedCache() { DCHECK_CURRENTLY_ON(BrowserThread::UI); waiting_for_clear_cache_ = false; NotifyIfDone(); } #if !defined(DISABLE_NACL) void BrowsingDataRemover::ClearedNaClCache() { DCHECK_CURRENTLY_ON(BrowserThread::UI); waiting_for_clear_nacl_cache_ = false; NotifyIfDone(); } void BrowsingDataRemover::ClearedPnaclCache() { DCHECK_CURRENTLY_ON(BrowserThread::UI); waiting_for_clear_pnacl_cache_ = false; NotifyIfDone(); } #endif #if defined(ENABLE_PLUGINS) void BrowsingDataRemover::OnWaitableEventSignaled( base::WaitableEvent* waitable_event) { DCHECK_CURRENTLY_ON(BrowserThread::UI); waiting_for_clear_plugin_data_ = false; plugin_data_remover_.reset(); watcher_.StopWatching(); NotifyIfDone(); } void BrowsingDataRemover::OnDeauthorizeContentLicensesCompleted( uint32_t request_id, bool /* success */) { DCHECK(waiting_for_clear_content_licenses_); DCHECK_EQ(request_id, deauthorize_content_licenses_request_id_); waiting_for_clear_content_licenses_ = false; NotifyIfDone(); } #endif #if defined(OS_CHROMEOS) void BrowsingDataRemover::OnClearPlatformKeys( chromeos::DBusMethodCallStatus call_status, bool result) { DCHECK(waiting_for_clear_platform_keys_); LOG_IF(ERROR, call_status != chromeos::DBUS_METHOD_CALL_SUCCESS || !result) << "Failed to clear platform keys."; waiting_for_clear_platform_keys_ = false; NotifyIfDone(); } #endif void BrowsingDataRemover::OnClearedPasswords() { DCHECK_CURRENTLY_ON(BrowserThread::UI); waiting_for_clear_passwords_ = false; NotifyIfDone(); } void BrowsingDataRemover::OnClearedPasswordsStats() { DCHECK_CURRENTLY_ON(BrowserThread::UI); waiting_for_clear_passwords_stats_ = false; NotifyIfDone(); } void BrowsingDataRemover::OnClearedAutoSignIn() { DCHECK_CURRENTLY_ON(BrowserThread::UI); waiting_for_clear_auto_sign_in_ = false; NotifyIfDone(); } void BrowsingDataRemover::OnClearedCookies() { DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_GT(waiting_for_clear_cookies_count_, 0); --waiting_for_clear_cookies_count_; NotifyIfDone(); } void BrowsingDataRemover::OnClearedChannelIDs() { DCHECK_CURRENTLY_ON(BrowserThread::UI); waiting_for_clear_channel_ids_ = false; NotifyIfDone(); } void BrowsingDataRemover::OnClearedFormData() { DCHECK_CURRENTLY_ON(BrowserThread::UI); waiting_for_clear_form_ = false; NotifyIfDone(); } void BrowsingDataRemover::OnClearedAutofillOriginURLs() { DCHECK_CURRENTLY_ON(BrowserThread::UI); waiting_for_clear_autofill_origin_urls_ = false; NotifyIfDone(); } void BrowsingDataRemover::OnClearedStoragePartitionData() { DCHECK_CURRENTLY_ON(BrowserThread::UI); waiting_for_clear_storage_partition_data_ = false; NotifyIfDone(); } #if defined(ENABLE_WEBRTC) void BrowsingDataRemover::OnClearedWebRtcLogs() { DCHECK_CURRENTLY_ON(BrowserThread::UI); waiting_for_clear_webrtc_logs_ = false; NotifyIfDone(); } #endif #if BUILDFLAG(ANDROID_JAVA_UI) void BrowsingDataRemover::OnClearedPrecacheHistory() { DCHECK_CURRENTLY_ON(BrowserThread::UI); waiting_for_clear_precache_history_ = false; NotifyIfDone(); } void BrowsingDataRemover::OnClearedWebappData() { DCHECK_CURRENTLY_ON(BrowserThread::UI); waiting_for_clear_webapp_data_ = false; NotifyIfDone(); } void BrowsingDataRemover::OnClearedOfflinePageData() { DCHECK_CURRENTLY_ON(BrowserThread::UI); waiting_for_clear_offline_page_data_ = false; NotifyIfDone(); } #endif void BrowsingDataRemover::OnClearedDomainReliabilityMonitor() { DCHECK_CURRENTLY_ON(BrowserThread::UI); waiting_for_clear_domain_reliability_monitor_ = false; NotifyIfDone(); } // static BrowsingDataRemover::CallbackSubscription BrowsingDataRemover::RegisterOnBrowsingDataRemovedCallback( const BrowsingDataRemover::Callback& callback) { return GetOnBrowsingDataRemovedCallbacks()->Add(callback); }