// 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 <map>
#include <set>
#include <string>

#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<void(const BrowsingDataRemover::NotificationDetails&)>;

// 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 <typename T>
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 <typename T>
base::Callback<void(T)> IgnoreArgument(const base::Closure& callback) {
  return base::Bind(&IgnoreArgumentHelper<T>, 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<int>(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<net::URLRequestContextGetter> 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<bool(const GURL& url)> 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<GURL> 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<autofill::AutofillWebDataService> 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()));
    }

    // Clear the history information (last launch time and origin URL) of any
    // registered webapps. The webapp_registry makes a JNI call into a Java-side
    // AsyncTask, so don't wait for the reply.
    waiting_for_clear_webapp_history_ = true;
    webapp_registry_->ClearWebappHistory(
        base::Bind(&BrowsingDataRemover::OnClearedWebappHistory,
          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<net::URLRequestContextGetter> 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<net::URLRequestContextGetter> 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<autofill::AutofillWebDataService> 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) {
    // Clear all data associated with registered webapps. The webapp_registry
    // makes a JNI call into a Java-side AsyncTask, so don't wait for the reply.
    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<WebappRegistry> 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_webapp_history_ &&
         !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::OnClearedWebappHistory() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  waiting_for_clear_webapp_history_ = 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);
}
