blob: ca1a7e8755f96ea90c79c4b433050141cdc95c35 [file] [log] [blame]
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "services/network/http_cache_data_remover.h"
#include <set>
#include <string>
#include "base/containers/flat_set.h"
#include "base/functional/bind.h"
#include "base/location.h"
#include "base/task/sequenced_task_runner.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/disk_cache/disk_cache.h"
#include "net/http/http_cache.h"
#include "net/http/http_network_session.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
#include "services/network/data_remover_util.h"
#include "services/network/public/mojom/clear_data_filter.mojom.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "url/gurl.h"
#include "url/origin.h"
namespace network {
HttpCacheDataRemover::HttpCacheDataRemover(
mojom::ClearDataFilterPtr url_filter,
base::Time delete_begin,
base::Time delete_end,
HttpCacheDataRemoverCallback done_callback)
: delete_begin_(delete_begin),
delete_end_(delete_end),
done_callback_(std::move(done_callback)),
backend_(nullptr) {
DCHECK(!done_callback_.is_null());
if (!url_filter) {
return;
}
url_matcher_ = BindDoesUrlMatchFilter(url_filter->type, url_filter->origins,
url_filter->domains);
}
HttpCacheDataRemover::~HttpCacheDataRemover() = default;
// static.
std::unique_ptr<HttpCacheDataRemover> HttpCacheDataRemover::CreateAndStart(
net::URLRequestContext* url_request_context,
mojom::ClearDataFilterPtr url_filter,
base::Time delete_begin,
base::Time delete_end,
HttpCacheDataRemoverCallback done_callback) {
// Store data from `url_filter` needed by ClearNoVarySearchCache() before we
// move `url_filter` into HttpCacheDataRemover.
base::flat_set<url::Origin> origins;
base::flat_set<std::string> domains;
// Default to deleting everything in the specified time range if `url_filter`
// was not supplied.
net::UrlFilterType url_filter_type = net::UrlFilterType::kFalseIfMatches;
if (url_filter) {
const mojom::ClearDataFilter& filter = *url_filter;
url_filter_type = ConvertClearDataFilterType(filter.type);
origins = base::flat_set<url::Origin>(filter.origins.begin(),
filter.origins.end());
domains = base::flat_set<std::string>(filter.domains.begin(),
filter.domains.end());
}
DCHECK(done_callback);
std::unique_ptr<HttpCacheDataRemover> remover(
new HttpCacheDataRemover(std::move(url_filter), delete_begin, delete_end,
std::move(done_callback)));
net::HttpCache* http_cache =
url_request_context->http_transaction_factory()->GetCache();
if (!http_cache) {
// Some contexts might not have a cache, in which case we are done.
// Notify by posting a task to avoid reentrency.
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(&HttpCacheDataRemover::ClearHttpCacheDone,
remover->weak_factory_.GetWeakPtr(), net::OK));
return remover;
}
// Clear QUIC server information from memory and the disk cache.
// TODO(crbug.com/41374118): add a browser test to validate the QUIC
// information is cleared.
http_cache->GetSession()
->quic_session_pool()
->ClearCachedStatesInCryptoConfig(remover->url_matcher_);
// Clear the in-memory mapping of URLs using the No-Vary-Search response
// header, and its persisted version on disk.
http_cache->ClearNoVarySearchCache(url_filter_type, origins, domains,
delete_begin, delete_end);
auto callback = base::BindOnce(&HttpCacheDataRemover::CacheRetrieved,
remover->weak_factory_.GetWeakPtr());
net::HttpCache::GetBackendResult result =
http_cache->GetBackend(std::move(callback));
if (result.first != net::ERR_IO_PENDING) {
remover->CacheRetrieved(result);
}
return remover;
}
void HttpCacheDataRemover::CacheRetrieved(
std::pair<int, raw_ptr<disk_cache::Backend>> result) {
DCHECK(done_callback_);
int rv = result.first;
backend_ = result.second;
// |backend_| can be null if it cannot be initialized.
if (rv != net::OK || !backend_) {
backend_ = nullptr;
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, base::BindOnce(&HttpCacheDataRemover::ClearHttpCacheDone,
weak_factory_.GetWeakPtr(), rv));
return;
}
if (!url_matcher_.is_null()) {
deletion_helper_ = ConditionalCacheDeletionHelper::CreateAndStart(
backend_, url_matcher_, delete_begin_, delete_end_,
base::BindOnce(&HttpCacheDataRemover::ClearHttpCacheDone,
weak_factory_.GetWeakPtr(), net::OK));
return;
}
if (delete_begin_.is_null() && delete_end_.is_max()) {
rv = backend_->DoomAllEntries(base::BindOnce(
&HttpCacheDataRemover::ClearHttpCacheDone, weak_factory_.GetWeakPtr()));
} else {
rv = backend_->DoomEntriesBetween(
delete_begin_, delete_end_,
base::BindOnce(&HttpCacheDataRemover::ClearHttpCacheDone,
weak_factory_.GetWeakPtr()));
}
if (rv != net::ERR_IO_PENDING) {
// Notify by posting a task to avoid reentrency.
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, base::BindOnce(&HttpCacheDataRemover::ClearHttpCacheDone,
weak_factory_.GetWeakPtr(), rv));
}
}
void HttpCacheDataRemover::ClearHttpCacheDone(int rv) {
std::move(done_callback_).Run(this);
}
} // namespace network