Commit 78612bf0 authored by Jay Civelli's avatar Jay Civelli Committed by Commit Bot

Add HTTP cache clearing to the network service

Adding a method to the NetworkContext to clear the HTTP cache. The
implementation in the network service duplicates some of the code from
content::StoragePartitionHttpCacheDataRemover.

Changed the BrowsingDataRemoverBrowserTest.Cache test to work with the
network service. Since we do not want to expose more cache states
(such as cache size) for tests, we rely on reloading pages after
stopping the embedded server to test the page is available in the
cache.

Cq-Include-Trybots: master.tryserver.chromium.linux:linux_mojo
Change-Id: I5c7687f931d57cf09119e6e26ae5d1d61eb247f3
Reviewed-on: https://chromium-review.googlesource.com/909949Reviewed-by: default avatarTom Sepez <tsepez@chromium.org>
Reviewed-by: default avatarMartin Šrámek <msramek@chromium.org>
Reviewed-by: default avatarJohn Abd-El-Malek <jam@chromium.org>
Reviewed-by: default avatarMatt Menke <mmenke@chromium.org>
Commit-Queue: Jay Civelli <jcivelli@chromium.org>
Cr-Commit-Position: refs/heads/master@{#540279}
parent 942dc32d
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/test/scoped_feature_list.h" #include "base/test/scoped_feature_list.h"
#include "base/threading/thread_restrictions.h" #include "base/threading/thread_restrictions.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browsing_data/browsing_data_helper.h" #include "chrome/browser/browsing_data/browsing_data_helper.h"
#include "chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.h" #include "chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.h"
#include "chrome/browser/browsing_data/counters/cache_counter.h" #include "chrome/browser/browsing_data/counters/cache_counter.h"
...@@ -19,6 +20,7 @@ ...@@ -19,6 +20,7 @@
#include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/external_protocol/external_protocol_handler.h" #include "chrome/browser/external_protocol/external_protocol_handler.h"
#include "chrome/browser/net/system_network_context_manager.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/tabs/tab_strip_model.h"
...@@ -34,14 +36,20 @@ ...@@ -34,14 +36,20 @@
#include "content/public/browser/browsing_data_filter_builder.h" #include "content/public/browser/browsing_data_filter_builder.h"
#include "content/public/browser/browsing_data_remover.h" #include "content/public/browser/browsing_data_remover.h"
#include "content/public/browser/download_manager.h" #include "content/public/browser/download_manager.h"
#include "content/public/browser/network_service_instance.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "content/public/common/content_paths.h" #include "content/public/common/content_paths.h"
#include "content/public/test/browser_test_utils.h" #include "content/public/test/browser_test_utils.h"
#include "content/public/test/browsing_data_remover_test_util.h" #include "content/public/test/browsing_data_remover_test_util.h"
#include "content/public/test/download_test_observer.h" #include "content/public/test/download_test_observer.h"
#include "content/public/test/simple_url_loader_test_helper.h"
#include "media/mojo/services/video_decode_perf_history.h" #include "media/mojo/services/video_decode_perf_history.h"
#include "net/dns/mock_host_resolver.h" #include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h" #include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
using content::BrowserThread; using content::BrowserThread;
...@@ -112,22 +120,6 @@ class BrowsingDataRemoverBrowserTest : public InProcessBrowserTest { ...@@ -112,22 +120,6 @@ class BrowsingDataRemoverBrowserTest : public InProcessBrowserTest {
VerifyDownloadCount(1u); VerifyDownloadCount(1u);
} }
browsing_data::BrowsingDataCounter::ResultInt GetCacheSize() {
base::RunLoop run_loop;
browsing_data::BrowsingDataCounter::ResultInt size;
Profile* profile = browser()->profile();
CacheCounter counter(profile);
counter.Init(profile->GetPrefs(),
browsing_data::ClearBrowsingDataTab::ADVANCED,
base::Bind(&BrowsingDataRemoverBrowserTest::OnCacheSizeResult,
base::Unretained(this), base::Unretained(&run_loop),
base::Unretained(&size)));
counter.Restart();
run_loop.Run();
return size;
}
void RemoveAndWait(int remove_mask) { void RemoveAndWait(int remove_mask) {
content::BrowsingDataRemover* remover = content::BrowsingDataRemover* remover =
content::BrowserContext::GetBrowsingDataRemover(browser()->profile()); content::BrowserContext::GetBrowsingDataRemover(browser()->profile());
...@@ -218,6 +210,12 @@ class BrowsingDataRemoverBrowserTest : public InProcessBrowserTest { ...@@ -218,6 +210,12 @@ class BrowsingDataRemoverBrowserTest : public InProcessBrowserTest {
run_loop->QuitWhenIdle(); run_loop->QuitWhenIdle();
} }
network::mojom::NetworkContext* network_context() const {
return content::BrowserContext::GetDefaultStoragePartition(
browser()->profile())
->GetNetworkContext();
}
private: private:
void OnCacheSizeResult( void OnCacheSizeResult(
base::RunLoop* run_loop, base::RunLoop* run_loop,
...@@ -352,23 +350,28 @@ IN_PROC_BROWSER_TEST_F(BrowsingDataRemoverBrowserTest, Database) { ...@@ -352,23 +350,28 @@ IN_PROC_BROWSER_TEST_F(BrowsingDataRemoverBrowserTest, Database) {
RunScriptAndCheckResult("getRecords()", "text2"); RunScriptAndCheckResult("getRecords()", "text2");
} }
// Verify that cache deleting cache finishes successfully. Complete deletion // Verifies that cache deletion finishes successfully. Completes deletion of
// of cache should leave it empty, and partial deletion should leave nonzero // cache should leave it empty, and partial deletion should leave nonzero
// amount of data. Note that this tests the integration of BrowsingDataRemover // amount of data. Note that this tests the integration of BrowsingDataRemover
// with ConditionalCacheDeletionHelper. Whether ConditionalCacheDeletionHelper // with ConditionalCacheDeletionHelper. Whether ConditionalCacheDeletionHelper
// actually deletes the correct entries is tested // actually deletes the correct entries is tested
// in ConditionalCacheDeletionHelperBrowsertest. // in ConditionalCacheDeletionHelperBrowsertest.
// TODO(crbug.com/817417): check the cache size instead of stopping the server
// and loading the request again.
IN_PROC_BROWSER_TEST_F(BrowsingDataRemoverBrowserTest, Cache) { IN_PROC_BROWSER_TEST_F(BrowsingDataRemoverBrowserTest, Cache) {
// Load several resources. // Load several resources.
GURL url1 = embedded_test_server()->GetURL("/simple.html"); GURL url1 = embedded_test_server()->GetURL("/cachetime");
GURL url2 = embedded_test_server()->GetURL(kExampleHost, "/simple.html"); GURL url2 = embedded_test_server()->GetURL(kExampleHost, "/cachetime");
ASSERT_FALSE(url::IsSameOriginWith(url1, url2)); ASSERT_FALSE(url::IsSameOriginWith(url1, url2));
ui_test_utils::NavigateToURL(browser(), url1);
ui_test_utils::NavigateToURL(browser(), url2);
// The cache is nonempty, because we created entries by visiting websites. EXPECT_EQ(net::OK, content::LoadBasicRequest(network_context(), url1));
browsing_data::BrowsingDataCounter::ResultInt original_size = GetCacheSize(); EXPECT_EQ(net::OK, content::LoadBasicRequest(network_context(), url2));
EXPECT_GT(original_size, 0);
// Check that the cache has been populated by revisiting these pages with the
// server stopped.
ASSERT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete());
EXPECT_EQ(net::OK, content::LoadBasicRequest(network_context(), url1));
EXPECT_EQ(net::OK, content::LoadBasicRequest(network_context(), url2));
// Partially delete cache data. Delete data for localhost, which is the origin // Partially delete cache data. Delete data for localhost, which is the origin
// of |url1|, but not for |kExampleHost|, which is the origin of |url2|. // of |url1|, but not for |kExampleHost|, which is the origin of |url2|.
...@@ -379,8 +382,8 @@ IN_PROC_BROWSER_TEST_F(BrowsingDataRemoverBrowserTest, Cache) { ...@@ -379,8 +382,8 @@ IN_PROC_BROWSER_TEST_F(BrowsingDataRemoverBrowserTest, Cache) {
std::move(filter_builder)); std::move(filter_builder));
// After the partial deletion, the cache should be smaller but still nonempty. // After the partial deletion, the cache should be smaller but still nonempty.
browsing_data::BrowsingDataCounter::ResultInt new_size = GetCacheSize(); EXPECT_NE(net::OK, content::LoadBasicRequest(network_context(), url1));
EXPECT_LT(new_size, original_size); EXPECT_EQ(net::OK, content::LoadBasicRequest(network_context(), url2));
// Another partial deletion with the same filter should have no effect. // Another partial deletion with the same filter should have no effect.
filter_builder = filter_builder =
...@@ -388,13 +391,37 @@ IN_PROC_BROWSER_TEST_F(BrowsingDataRemoverBrowserTest, Cache) { ...@@ -388,13 +391,37 @@ IN_PROC_BROWSER_TEST_F(BrowsingDataRemoverBrowserTest, Cache) {
filter_builder->AddOrigin(url::Origin::Create(url1)); filter_builder->AddOrigin(url::Origin::Create(url1));
RemoveWithFilterAndWait(content::BrowsingDataRemover::DATA_TYPE_CACHE, RemoveWithFilterAndWait(content::BrowsingDataRemover::DATA_TYPE_CACHE,
std::move(filter_builder)); std::move(filter_builder));
EXPECT_EQ(new_size, GetCacheSize()); EXPECT_NE(net::OK, content::LoadBasicRequest(network_context(), url1));
EXPECT_EQ(net::OK, content::LoadBasicRequest(network_context(), url2));
// Delete the remaining data. // Delete the remaining data.
RemoveAndWait(content::BrowsingDataRemover::DATA_TYPE_CACHE); RemoveAndWait(content::BrowsingDataRemover::DATA_TYPE_CACHE);
// The cache is empty. // The cache should be empty.
EXPECT_EQ(0, GetCacheSize()); EXPECT_NE(net::OK, content::LoadBasicRequest(network_context(), url1));
EXPECT_NE(net::OK, content::LoadBasicRequest(network_context(), url2));
}
// Crashes the network service while clearing the HTTP cache to make sure the
// clear operation does complete.
// Note that there is a race between crashing the network service and clearing
// the cache, so the test might flakily fail if the tested behavior does not
// work.
// TODO(crbug.com/813882): test retry behavior by validating the cache is empty
// after the crash.
IN_PROC_BROWSER_TEST_F(BrowsingDataRemoverBrowserTest,
ClearCacheAndNetworkServiceCrashes) {
if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
return;
// Clear the cached data with a task posted to crash the network service.
// The task should be run while waiting for the cache clearing operation to
// complete, hopefully it happens before the cache has been cleared.
base::SequencedTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce([]() { content::SimulateNetworkServiceCrash(); }));
RemoveAndWait(content::BrowsingDataRemover::DATA_TYPE_CACHE);
} }
IN_PROC_BROWSER_TEST_F(BrowsingDataRemoverBrowserTest, IN_PROC_BROWSER_TEST_F(BrowsingDataRemoverBrowserTest,
......
...@@ -160,6 +160,20 @@ BrowsingDataFilterBuilderImpl::BuildGeneralFilter() const { ...@@ -160,6 +160,20 @@ BrowsingDataFilterBuilderImpl::BuildGeneralFilter() const {
return base::BindRepeating(&MatchesURL, origins_, domains_, mode_); return base::BindRepeating(&MatchesURL, origins_, domains_, mode_);
} }
network::mojom::ClearCacheUrlFilterPtr
BrowsingDataFilterBuilderImpl::BuildClearCacheUrlFilter() const {
network::mojom::ClearCacheUrlFilterPtr filter =
network::mojom::ClearCacheUrlFilter::New();
filter->type = (mode_ == Mode::WHITELIST)
? network::mojom::ClearCacheUrlFilter::Type::DELETE_MATCHES
: network::mojom::ClearCacheUrlFilter::Type::KEEP_MATCHES;
filter->origins.insert(filter->origins.begin(), origins_.begin(),
origins_.end());
filter->domains.insert(filter->domains.begin(), domains_.begin(),
domains_.end());
return filter;
}
base::RepeatingCallback<bool(const net::CanonicalCookie& cookie)> base::RepeatingCallback<bool(const net::CanonicalCookie& cookie)>
BrowsingDataFilterBuilderImpl::BuildCookieFilter() const { BrowsingDataFilterBuilderImpl::BuildCookieFilter() const {
DCHECK(origins_.empty()) << DCHECK(origins_.empty()) <<
......
...@@ -24,6 +24,8 @@ class CONTENT_EXPORT BrowsingDataFilterBuilderImpl ...@@ -24,6 +24,8 @@ class CONTENT_EXPORT BrowsingDataFilterBuilderImpl
bool IsEmptyBlacklist() const override; bool IsEmptyBlacklist() const override;
base::RepeatingCallback<bool(const GURL&)> base::RepeatingCallback<bool(const GURL&)>
BuildGeneralFilter() const override; BuildGeneralFilter() const override;
network::mojom::ClearCacheUrlFilterPtr BuildClearCacheUrlFilter()
const override;
base::RepeatingCallback<bool(const net::CanonicalCookie& pattern)> base::RepeatingCallback<bool(const net::CanonicalCookie& pattern)>
BuildCookieFilter() const override; BuildCookieFilter() const override;
base::RepeatingCallback<bool(const std::string& server_id)> base::RepeatingCallback<bool(const std::string& server_id)>
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "content/public/browser/download_manager.h" #include "content/public/browser/download_manager.h"
#include "content/public/browser/notification_service.h" #include "content/public/browser/notification_service.h"
#include "content/public/browser/storage_partition.h" #include "content/public/browser/storage_partition.h"
#include "mojo/public/cpp/bindings/callback_helpers.h"
#include "net/base/net_errors.h" #include "net/base/net_errors.h"
#include "net/cookies/cookie_store.h" #include "net/cookies/cookie_store.h"
#include "net/http/http_network_session.h" #include "net/http/http_network_session.h"
...@@ -36,6 +37,7 @@ ...@@ -36,6 +37,7 @@
#include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h" #include "net/url_request/url_request_context_getter.h"
#include "ppapi/features/features.h" #include "ppapi/features/features.h"
#include "services/network/public/cpp/features.h"
#include "storage/browser/quota/special_storage_policy.h" #include "storage/browser/quota/special_storage_policy.h"
#include "url/origin.h" #include "url/origin.h"
...@@ -45,6 +47,19 @@ namespace content { ...@@ -45,6 +47,19 @@ namespace content {
namespace { namespace {
base::OnceClosure RunsOrPostOnCurrentTaskRunner(base::OnceClosure closure) {
return base::BindOnce(
[](base::OnceClosure closure,
scoped_refptr<base::TaskRunner> task_runner) {
if (base::ThreadTaskRunnerHandle::Get() == task_runner) {
std::move(closure).Run();
return;
}
task_runner->PostTask(FROM_HERE, std::move(closure));
},
std::move(closure), base::ThreadTaskRunnerHandle::Get());
}
// Returns whether |origin| matches |origin_type_mask| given the special // Returns whether |origin| matches |origin_type_mask| given the special
// storage |policy|; and if |predicate| is not null, then also whether // storage |policy|; and if |predicate| is not null, then also whether
// it matches |predicate|. If |origin_type_mask| contains embedder-specific // it matches |predicate|. If |origin_type_mask| contains embedder-specific
...@@ -446,18 +461,32 @@ void BrowsingDataRemoverImpl::RemoveImpl( ...@@ -446,18 +461,32 @@ void BrowsingDataRemoverImpl::RemoveImpl(
if (remove_mask & DATA_TYPE_CACHE) { if (remove_mask & DATA_TYPE_CACHE) {
base::RecordAction(UserMetricsAction("ClearBrowsingData_Cache")); base::RecordAction(UserMetricsAction("ClearBrowsingData_Cache"));
network::mojom::NetworkContext* network_context =
storage_partition->GetNetworkContext();
// TODO(msramek): Clear the cache of all renderers. // TODO(msramek): Clear the cache of all renderers.
if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
// The clearing of the HTTP cache happens in the network service process
// when enabled.
network_context->ClearHttpCache(
delete_begin, delete_end, filter_builder.BuildClearCacheUrlFilter(),
CreatePendingTaskCompletionClosureForMojo());
}
// In the network service case, the call below will only clear the media
// cache.
// TODO(crbug.com/813882): implement retry on network service.
storage_partition->ClearHttpAndMediaCaches( storage_partition->ClearHttpAndMediaCaches(
delete_begin, delete_end, delete_begin, delete_end,
filter_builder.IsEmptyBlacklist() ? base::Callback<bool(const GURL&)>() filter_builder.IsEmptyBlacklist() ? base::Callback<bool(const GURL&)>()
: filter, : filter,
CreatePendingTaskCompletionClosure()); CreatePendingTaskCompletionClosureForMojo());
// When clearing cache, wipe accumulated network related data // When clearing cache, wipe accumulated network related data
// (TransportSecurityState and HttpServerPropertiesManager data). // (TransportSecurityState and HttpServerPropertiesManager data).
storage_partition->GetNetworkContext()->ClearNetworkingHistorySince( network_context->ClearNetworkingHistorySince(
delete_begin, CreatePendingTaskCompletionClosure()); delete_begin, CreatePendingTaskCompletionClosureForMojo());
// Tell the shader disk cache to clear. // Tell the shader disk cache to clear.
base::RecordAction(UserMetricsAction("ClearBrowsingData_ShaderCache")); base::RecordAction(UserMetricsAction("ClearBrowsingData_ShaderCache"));
...@@ -605,6 +634,14 @@ BrowsingDataRemoverImpl::CreatePendingTaskCompletionClosure() { ...@@ -605,6 +634,14 @@ BrowsingDataRemoverImpl::CreatePendingTaskCompletionClosure() {
return base::BindOnce(&BrowsingDataRemoverImpl::OnTaskComplete, GetWeakPtr()); return base::BindOnce(&BrowsingDataRemoverImpl::OnTaskComplete, GetWeakPtr());
} }
base::OnceClosure
BrowsingDataRemoverImpl::CreatePendingTaskCompletionClosureForMojo() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
return RunsOrPostOnCurrentTaskRunner(mojo::WrapCallbackWithDropHandler(
CreatePendingTaskCompletionClosure(),
base::BindOnce(&BrowsingDataRemoverImpl::OnTaskComplete, GetWeakPtr())));
}
base::WeakPtr<BrowsingDataRemoverImpl> BrowsingDataRemoverImpl::GetWeakPtr() { base::WeakPtr<BrowsingDataRemoverImpl> BrowsingDataRemoverImpl::GetWeakPtr() {
DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_CURRENTLY_ON(BrowserThread::UI);
base::WeakPtr<BrowsingDataRemoverImpl> weak_ptr = base::WeakPtr<BrowsingDataRemoverImpl> weak_ptr =
......
...@@ -152,6 +152,11 @@ class CONTENT_EXPORT BrowsingDataRemoverImpl ...@@ -152,6 +152,11 @@ class CONTENT_EXPORT BrowsingDataRemoverImpl
// created by this method have been invoked. // created by this method have been invoked.
base::OnceClosure CreatePendingTaskCompletionClosure(); base::OnceClosure CreatePendingTaskCompletionClosure();
// Same as CreatePendingTaskCompletionClosure() but guarantees that
// OnTaskComplete() is called if the task is dropped. That can typically
// happen when the connection is closed while an interface call is made.
base::OnceClosure CreatePendingTaskCompletionClosureForMojo();
// Like GetWeakPtr(), but returns a weak pointer to BrowsingDataRemoverImpl // Like GetWeakPtr(), but returns a weak pointer to BrowsingDataRemoverImpl
// for internal purposes. // for internal purposes.
base::WeakPtr<BrowsingDataRemoverImpl> GetWeakPtr(); base::WeakPtr<BrowsingDataRemoverImpl> GetWeakPtr();
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "base/callback_forward.h" #include "base/callback_forward.h"
#include "content/common/content_export.h" #include "content/common/content_export.h"
#include "services/network/public/mojom/network_service.mojom.h"
class GURL; class GURL;
...@@ -69,6 +70,11 @@ class CONTENT_EXPORT BrowsingDataFilterBuilder { ...@@ -69,6 +70,11 @@ class CONTENT_EXPORT BrowsingDataFilterBuilder {
virtual base::RepeatingCallback<bool(const GURL&)> virtual base::RepeatingCallback<bool(const GURL&)>
BuildGeneralFilter() const = 0; BuildGeneralFilter() const = 0;
// Builds a filter that can be used with the network service, more precisely
// with NetworkContext.ClearHttpCache().
virtual network::mojom::ClearCacheUrlFilterPtr BuildClearCacheUrlFilter()
const = 0;
// Builds a filter that matches cookies whose sources are in the whitelist, // Builds a filter that matches cookies whose sources are in the whitelist,
// or aren't in the blacklist. // or aren't in the blacklist.
virtual base::RepeatingCallback<bool(const net::CanonicalCookie& pattern)> virtual base::RepeatingCallback<bool(const net::CanonicalCookie& pattern)>
......
...@@ -2445,7 +2445,7 @@ void SimulateNetworkServiceCrash() { ...@@ -2445,7 +2445,7 @@ void SimulateNetworkServiceCrash() {
ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface( ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface(
mojom::kNetworkServiceName, &network_service_test); mojom::kNetworkServiceName, &network_service_test);
base::RunLoop run_loop; base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
network_service_test.set_connection_error_handler(run_loop.QuitClosure()); network_service_test.set_connection_error_handler(run_loop.QuitClosure());
network_service_test->SimulateCrash(); network_service_test->SimulateCrash();
......
...@@ -119,6 +119,10 @@ class MockNetworkContext final : public network::mojom::NetworkContext { ...@@ -119,6 +119,10 @@ class MockNetworkContext final : public network::mojom::NetworkContext {
void ClearNetworkingHistorySince( void ClearNetworkingHistorySince(
base::Time time, base::Time time,
base::OnceClosure completion_callback) override {} base::OnceClosure completion_callback) override {}
void ClearHttpCache(base::Time start_time,
base::Time end_time,
network::mojom::ClearCacheUrlFilterPtr filter,
ClearHttpCacheCallback callback) override {}
void SetNetworkConditions( void SetNetworkConditions(
const std::string& profile_id, const std::string& profile_id,
network::mojom::NetworkConditionsPtr conditions) override {} network::mojom::NetworkConditionsPtr conditions) override {}
......
...@@ -150,7 +150,7 @@ void ControlMessageProxy::FlushForTesting() { ...@@ -150,7 +150,7 @@ void ControlMessageProxy::FlushForTesting() {
auto input_ptr = interface_control::RunInput::New(); auto input_ptr = interface_control::RunInput::New();
input_ptr->set_flush_for_testing(interface_control::FlushForTesting::New()); input_ptr->set_flush_for_testing(interface_control::FlushForTesting::New());
base::RunLoop run_loop; base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
run_loop_quit_closure_ = run_loop.QuitClosure(); run_loop_quit_closure_ = run_loop.QuitClosure();
SendRunMessage( SendRunMessage(
receiver_, std::move(input_ptr), receiver_, std::move(input_ptr),
......
...@@ -925,6 +925,10 @@ int EntryImpl::ReadyForSparseIO(const CompletionCallback& callback) { ...@@ -925,6 +925,10 @@ int EntryImpl::ReadyForSparseIO(const CompletionCallback& callback) {
return net::ERR_IO_PENDING; return net::ERR_IO_PENDING;
} }
void EntryImpl::SetLastUsedTimeForTest(base::Time time) {
SetTimes(time, time);
}
// When an entry is deleted from the cache, we clean up all the data associated // When an entry is deleted from the cache, we clean up all the data associated
// with it for two reasons: to simplify the reuse of the block (we know that any // with it for two reasons: to simplify the reuse of the block (we know that any
// unused block is filled with zeros), and to simplify the handling of write / // unused block is filled with zeros), and to simplify the handling of write /
......
...@@ -193,6 +193,7 @@ class NET_EXPORT_PRIVATE EntryImpl ...@@ -193,6 +193,7 @@ class NET_EXPORT_PRIVATE EntryImpl
bool CouldBeSparse() const override; bool CouldBeSparse() const override;
void CancelSparseIO() override; void CancelSparseIO() override;
int ReadyForSparseIO(const CompletionCallback& callback) override; int ReadyForSparseIO(const CompletionCallback& callback) override;
void SetLastUsedTimeForTest(base::Time time) override;
private: private:
enum { enum {
......
...@@ -382,6 +382,11 @@ class NET_EXPORT Entry { ...@@ -382,6 +382,11 @@ class NET_EXPORT Entry {
// Note: This method is deprecated. // Note: This method is deprecated.
virtual int ReadyForSparseIO(const CompletionCallback& callback) = 0; virtual int ReadyForSparseIO(const CompletionCallback& callback) = 0;
// Used in tests to set the last used time. Note that backend might have
// limited precision. Also note that this call may modify the last modified
// time.
virtual void SetLastUsedTimeForTest(base::Time time) = 0;
protected: protected:
virtual ~Entry() {} virtual ~Entry() {}
}; };
......
...@@ -272,6 +272,10 @@ int MemEntryImpl::ReadyForSparseIO(const CompletionCallback& callback) { ...@@ -272,6 +272,10 @@ int MemEntryImpl::ReadyForSparseIO(const CompletionCallback& callback) {
return net::OK; return net::OK;
} }
void MemEntryImpl::SetLastUsedTimeForTest(base::Time time) {
last_used_ = time;
}
size_t MemEntryImpl::EstimateMemoryUsage() const { size_t MemEntryImpl::EstimateMemoryUsage() const {
// Subtlety: the entries in children_ are not double counted, as the entry // Subtlety: the entries in children_ are not double counted, as the entry
// pointers won't be followed by EstimateMemoryUsage. // pointers won't be followed by EstimateMemoryUsage.
......
...@@ -133,6 +133,7 @@ class NET_EXPORT_PRIVATE MemEntryImpl final ...@@ -133,6 +133,7 @@ class NET_EXPORT_PRIVATE MemEntryImpl final
bool CouldBeSparse() const override; bool CouldBeSparse() const override;
void CancelSparseIO() override {} void CancelSparseIO() override {}
int ReadyForSparseIO(const CompletionCallback& callback) override; int ReadyForSparseIO(const CompletionCallback& callback) override;
void SetLastUsedTimeForTest(base::Time time) override;
size_t EstimateMemoryUsage() const; size_t EstimateMemoryUsage() const;
private: private:
......
...@@ -599,6 +599,13 @@ int SimpleEntryImpl::ReadyForSparseIO(const CompletionCallback& callback) { ...@@ -599,6 +599,13 @@ int SimpleEntryImpl::ReadyForSparseIO(const CompletionCallback& callback) {
return net::OK; return net::OK;
} }
void SimpleEntryImpl::SetLastUsedTimeForTest(base::Time time) {
// Note that we do not update |last_used_| here as it gets overwritten
// by UpdateDataFromEntryStat with the current time. It would be more involved
// to make that value stick and is not needed by the current tests.
backend_->index()->SetLastUsedTimeForTest(entry_hash_, time);
}
size_t SimpleEntryImpl::EstimateMemoryUsage() const { size_t SimpleEntryImpl::EstimateMemoryUsage() const {
// TODO(xunjieli): crbug.com/669108. It'd be nice to have the rest of |entry| // TODO(xunjieli): crbug.com/669108. It'd be nice to have the rest of |entry|
// measured, but the ownership of SimpleSynchronousEntry isn't straightforward // measured, but the ownership of SimpleSynchronousEntry isn't straightforward
......
...@@ -132,6 +132,7 @@ class NET_EXPORT_PRIVATE SimpleEntryImpl : public Entry, ...@@ -132,6 +132,7 @@ class NET_EXPORT_PRIVATE SimpleEntryImpl : public Entry,
bool CouldBeSparse() const override; bool CouldBeSparse() const override;
void CancelSparseIO() override; void CancelSparseIO() override;
int ReadyForSparseIO(const CompletionCallback& callback) override; int ReadyForSparseIO(const CompletionCallback& callback) override;
void SetLastUsedTimeForTest(base::Time time) override;
// Returns the estimate of dynamically allocated memory in bytes. // Returns the estimate of dynamically allocated memory in bytes.
size_t EstimateMemoryUsage() const; size_t EstimateMemoryUsage() const;
......
...@@ -278,6 +278,13 @@ size_t SimpleIndex::EstimateMemoryUsage() const { ...@@ -278,6 +278,13 @@ size_t SimpleIndex::EstimateMemoryUsage() const {
base::trace_event::EstimateMemoryUsage(removed_entries_); base::trace_event::EstimateMemoryUsage(removed_entries_);
} }
void SimpleIndex::SetLastUsedTimeForTest(uint64_t entry_hash,
const base::Time last_used) {
EntrySet::iterator it = entries_set_.find(entry_hash);
DCHECK(it != entries_set_.end());
it->second.SetLastUsedTime(last_used);
}
void SimpleIndex::Insert(uint64_t entry_hash) { void SimpleIndex::Insert(uint64_t entry_hash) {
DCHECK(io_thread_checker_.CalledOnValidThread()); DCHECK(io_thread_checker_.CalledOnValidThread());
// Upon insert we don't know yet the size of the entry. // Upon insert we don't know yet the size of the entry.
......
...@@ -192,6 +192,8 @@ class NET_EXPORT_PRIVATE SimpleIndex ...@@ -192,6 +192,8 @@ class NET_EXPORT_PRIVATE SimpleIndex
// Returns the estimate of dynamically allocated memory in bytes. // Returns the estimate of dynamically allocated memory in bytes.
size_t EstimateMemoryUsage() const; size_t EstimateMemoryUsage() const;
void SetLastUsedTimeForTest(uint64_t entry_hash, const base::Time last_used);
private: private:
friend class SimpleIndexTest; friend class SimpleIndexTest;
FRIEND_TEST_ALL_PREFIXES(SimpleIndexTest, IndexSizeCorrectOnMerge); FRIEND_TEST_ALL_PREFIXES(SimpleIndexTest, IndexSizeCorrectOnMerge);
......
...@@ -325,6 +325,10 @@ int MockDiskEntry::ReadyForSparseIO(const CompletionCallback& callback) { ...@@ -325,6 +325,10 @@ int MockDiskEntry::ReadyForSparseIO(const CompletionCallback& callback) {
return ERR_IO_PENDING; return ERR_IO_PENDING;
} }
void MockDiskEntry::SetLastUsedTimeForTest(base::Time time) {
NOTREACHED();
}
// If |value| is true, don't deliver any completion callbacks until called // If |value| is true, don't deliver any completion callbacks until called
// again with |value| set to false. Caution: remember to enable callbacks // again with |value| set to false. Caution: remember to enable callbacks
// again or all subsequent tests will fail. // again or all subsequent tests will fail.
......
...@@ -73,6 +73,7 @@ class MockDiskEntry : public disk_cache::Entry, ...@@ -73,6 +73,7 @@ class MockDiskEntry : public disk_cache::Entry,
bool CouldBeSparse() const override; bool CouldBeSparse() const override;
void CancelSparseIO() override; void CancelSparseIO() override;
int ReadyForSparseIO(const CompletionCallback& completion_callback) override; int ReadyForSparseIO(const CompletionCallback& completion_callback) override;
void SetLastUsedTimeForTest(base::Time time) override;
uint8_t in_memory_data() const { return in_memory_data_; } uint8_t in_memory_data() const { return in_memory_data_; }
void set_in_memory_data(uint8_t val) { in_memory_data_ = val; } void set_in_memory_data(uint8_t val) { in_memory_data_ = val; }
......
...@@ -10,12 +10,16 @@ import("//services/service_manager/public/tools/test/service_test.gni") ...@@ -10,12 +10,16 @@ import("//services/service_manager/public/tools/test/service_test.gni")
component("network_service") { component("network_service") {
sources = [ sources = [
"conditional_cache_deletion_helper.cc",
"conditional_cache_deletion_helper.h",
"cookie_manager.cc", "cookie_manager.cc",
"cookie_manager.h", "cookie_manager.h",
"cors/preflight_controller.cc", "cors/preflight_controller.cc",
"cors/preflight_controller.h", "cors/preflight_controller.h",
"data_pipe_element_reader.cc", "data_pipe_element_reader.cc",
"data_pipe_element_reader.h", "data_pipe_element_reader.h",
"http_cache_data_remover.cc",
"http_cache_data_remover.h",
"http_server_properties_pref_delegate.cc", "http_server_properties_pref_delegate.cc",
"http_server_properties_pref_delegate.h", "http_server_properties_pref_delegate.h",
"ignore_errors_cert_verifier.cc", "ignore_errors_cert_verifier.cc",
...@@ -119,6 +123,7 @@ source_set("tests") { ...@@ -119,6 +123,7 @@ source_set("tests") {
"cors/cors_url_loader_unittest.cc", "cors/cors_url_loader_unittest.cc",
"cors/preflight_controller_unittest.cc", "cors/preflight_controller_unittest.cc",
"data_pipe_element_reader_unittest.cc", "data_pipe_element_reader_unittest.cc",
"http_cache_data_remover_unittest.cc",
"ignore_errors_cert_verifier_unittest.cc", "ignore_errors_cert_verifier_unittest.cc",
"keepalive_statistics_recorder_unittest.cc", "keepalive_statistics_recorder_unittest.cc",
"network_change_manager_unittest.cc", "network_change_manager_unittest.cc",
......
// Copyright 2018 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 "services/network/conditional_cache_deletion_helper.h"
#include "base/callback.h"
#include "base/location.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
namespace {
bool EntryPredicateFromURLsAndTime(
const base::RepeatingCallback<bool(const GURL&)>& url_matcher,
const base::Time& begin_time,
const base::Time& end_time,
const disk_cache::Entry* entry) {
return (entry->GetLastUsed() >= begin_time &&
entry->GetLastUsed() < end_time &&
url_matcher.Run(GURL(entry->GetKey())));
}
} // namespace
namespace network {
// static
std::unique_ptr<ConditionalCacheDeletionHelper>
ConditionalCacheDeletionHelper::CreateAndStart(
disk_cache::Backend* cache,
const base::RepeatingCallback<bool(const GURL&)>& url_matcher,
const base::Time& begin_time,
const base::Time& end_time,
base::OnceClosure completion_callback) {
std::unique_ptr<ConditionalCacheDeletionHelper> deletion_helper(
new ConditionalCacheDeletionHelper(
base::BindRepeating(
&EntryPredicateFromURLsAndTime, url_matcher,
begin_time.is_null() ? base::Time() : begin_time,
end_time.is_null() ? base::Time::Max() : end_time),
std::move(completion_callback), cache->CreateIterator()));
deletion_helper->IterateOverEntries(net::OK);
return deletion_helper;
}
ConditionalCacheDeletionHelper::ConditionalCacheDeletionHelper(
const base::RepeatingCallback<bool(const disk_cache::Entry*)>& condition,
base::OnceClosure completion_callback,
std::unique_ptr<disk_cache::Backend::Iterator> iterator)
: condition_(condition),
completion_callback_(std::move(completion_callback)),
iterator_(std::move(iterator)),
weak_factory_(this) {}
ConditionalCacheDeletionHelper::~ConditionalCacheDeletionHelper() = default;
void ConditionalCacheDeletionHelper::IterateOverEntries(int error) {
while (error != net::ERR_IO_PENDING) {
// If the entry obtained in the previous iteration matches the condition,
// mark it for deletion. The iterator is already one step forward, so it
// won't be invalidated. Always close the previous entry so it does not
// leak.
if (previous_entry_) {
if (condition_.Run(previous_entry_)) {
previous_entry_->Doom();
}
previous_entry_->Close();
}
if (error == net::ERR_FAILED) {
// The iteration finished successfully or we can no longer iterate
// (e.g. the cache was destroyed). We cannot distinguish between the two,
// but we know that there is nothing more that we can do.
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(&ConditionalCacheDeletionHelper::NotifyCompletion,
weak_factory_.GetWeakPtr()));
return;
}
previous_entry_ = current_entry_;
error = iterator_->OpenNextEntry(
&current_entry_,
base::BindRepeating(&ConditionalCacheDeletionHelper::IterateOverEntries,
weak_factory_.GetWeakPtr()));
}
}
void ConditionalCacheDeletionHelper::NotifyCompletion() {
std::move(completion_callback_).Run();
}
} // namespace network
// Copyright 2018 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.
#ifndef SERVICES_NETWORK_CONDITIONAL_CACHE_DELETION_HELPER_H_
#define SERVICES_NETWORK_CONDITIONAL_CACHE_DELETION_HELPER_H_
#include <memory>
#include "base/callback_forward.h"
#include "base/memory/weak_ptr.h"
#include "base/sequenced_task_runner_helpers.h"
#include "net/base/net_errors.h"
#include "net/disk_cache/disk_cache.h"
#include "url/gurl.h"
namespace disk_cache {
class Entry;
}
namespace network {
// Helper to remove HTTP cache data.
class ConditionalCacheDeletionHelper {
public:
// Creates a helper to delete |cache| entries whose last modified time is
// between |begin_time| (inclusively), |end_time| (exclusively) and whose URL
// is matched by the |url_matcher|. Note that |begin_time| and |end_time| can
// be null to indicate unbounded time interval in their respective direction.
// Starts the deletion and calls |completion_callback| when done.
static std::unique_ptr<ConditionalCacheDeletionHelper> CreateAndStart(
disk_cache::Backend* cache,
const base::RepeatingCallback<bool(const GURL&)>& url_matcher,
const base::Time& begin_time,
const base::Time& end_time,
base::OnceClosure completion_callback);
~ConditionalCacheDeletionHelper();
private:
ConditionalCacheDeletionHelper(
const base::RepeatingCallback<bool(const disk_cache::Entry*)>& condition,
base::OnceClosure completion_callback,
std::unique_ptr<disk_cache::Backend::Iterator> iterator);
void IterateOverEntries(int error);
void NotifyCompletion();
const base::RepeatingCallback<bool(const disk_cache::Entry*)> condition_;
base::OnceClosure completion_callback_;
std::unique_ptr<disk_cache::Backend::Iterator> iterator_;
disk_cache::Entry* current_entry_ = nullptr;
disk_cache::Entry* previous_entry_ = nullptr;
base::WeakPtrFactory<ConditionalCacheDeletionHelper> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(ConditionalCacheDeletionHelper);
};
} // namespace network
#endif // SERVICES_NETWORK_CONDITIONAL_CACHE_DELETION_HELPER_H_
// Copyright 2018 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 "services/network/http_cache_data_remover.h"
#include <set>
#include <string>
#include "base/location.h"
#include "base/memory/ptr_util.h"
#include "base/threading/sequenced_task_runner_handle.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/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
#include "url/gurl.h"
namespace network {
namespace {
bool DoesUrlMatchFilter(mojom::ClearCacheUrlFilter_Type filter_type,
const std::set<url::Origin>& origins,
const std::set<std::string>& domains,
const GURL& url) {
std::string url_registerable_domain =
net::registry_controlled_domains::GetDomainAndRegistry(
url, net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
bool found_domain = (domains.find(url_registerable_domain != ""
? url_registerable_domain
: url.host()) != domains.end());
bool found_origin = (origins.find(url::Origin::Create(url)) != origins.end());
return ((found_domain || found_origin) ==
(filter_type == mojom::ClearCacheUrlFilter_Type::DELETE_MATCHES));
}
} // namespace
HttpCacheDataRemover::HttpCacheDataRemover(
mojom::ClearCacheUrlFilterPtr 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)),
weak_factory_(this) {
DCHECK(!done_callback_.is_null());
if (!url_filter)
return;
// Use the filter to create the |url_matcher_| callback.
std::set<std::string> domains;
domains.insert(url_filter->domains.begin(), url_filter->domains.end());
std::set<url::Origin> origins;
origins.insert(url_filter->origins.begin(), url_filter->origins.end());
url_matcher_ = base::BindRepeating(&DoesUrlMatchFilter, url_filter->type,
origins, domains);
}
HttpCacheDataRemover::~HttpCacheDataRemover() = default;
// static.
std::unique_ptr<HttpCacheDataRemover> HttpCacheDataRemover::CreateAndStart(
net::URLRequestContext* url_request_context,
mojom::ClearCacheUrlFilterPtr url_filter,
base::Time delete_begin,
base::Time delete_end,
HttpCacheDataRemoverCallback done_callback) {
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::SequencedTaskRunnerHandle::Get()->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/817849): add a browser test to validate the QUIC information
// is cleared.
http_cache->GetSession()
->quic_stream_factory()
->ClearCachedStatesInCryptoConfig(remover->url_matcher_);
auto backend = std::make_unique<disk_cache::Backend*>();
disk_cache::Backend** backend_ptr = backend.get();
// IMPORTANT: we have to keep the callback on the stack so that |backend| is
// not deleted before this method returns, as its deletion would make
// |backend_ptr| invalid and it's needed for the CacheRetrieved() call below.
net::CompletionCallback callback =
base::Bind(&HttpCacheDataRemover::CacheRetrieved,
remover->weak_factory_.GetWeakPtr(), base::Passed(&backend));
int rv = http_cache->GetBackend(backend_ptr, callback);
if (rv != net::ERR_IO_PENDING) {
remover->CacheRetrieved(
std::make_unique<disk_cache::Backend*>(*backend_ptr), rv);
}
return remover;
}
void HttpCacheDataRemover::CacheRetrieved(
std::unique_ptr<disk_cache::Backend*> backend,
int rv) {
DCHECK(done_callback_);
disk_cache::Backend* cache = *backend;
// |cache| can be null if it cannot be initialized.
if (!cache || rv != net::OK) {
base::SequencedTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&HttpCacheDataRemover::ClearHttpCacheDone,
weak_factory_.GetWeakPtr(), rv));
return;
}
if (!url_matcher_.is_null()) {
deletion_helper_ = ConditionalCacheDeletionHelper::CreateAndStart(
cache, 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 = cache->DoomAllEntries(base::Bind(
&HttpCacheDataRemover::ClearHttpCacheDone, weak_factory_.GetWeakPtr()));
} else {
rv = cache->DoomEntriesBetween(
delete_begin_, delete_end_,
base::Bind(&HttpCacheDataRemover::ClearHttpCacheDone,
weak_factory_.GetWeakPtr()));
}
if (rv != net::ERR_IO_PENDING) {
// Notify by posting a task to avoid reentrency.
base::SequencedTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&HttpCacheDataRemover::ClearHttpCacheDone,
weak_factory_.GetWeakPtr(), rv));
}
}
void HttpCacheDataRemover::ClearHttpCacheDone(int rv) {
std::move(done_callback_).Run(this);
}
} // namespace network
// Copyright 2018 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.
#ifndef SERVICES_NETWORK_HTTP_CACHE_DATA_REMOVER_H_
#define SERVICES_NETWORK_HTTP_CACHE_DATA_REMOVER_H_
#include <memory>
#include "base/callback_forward.h"
#include "base/component_export.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "net/base/completion_callback.h"
#include "services/network/conditional_cache_deletion_helper.h"
#include "services/network/public/mojom/network_service.mojom.h"
#include "url/gurl.h"
namespace disk_cache {
class Backend;
}
namespace net {
class URLRequestContext;
}
namespace network {
// Helper to remove data from the HTTP cache.
class COMPONENT_EXPORT(NETWORK_SERVICE) HttpCacheDataRemover {
public:
using HttpCacheDataRemoverCallback =
base::OnceCallback<void(HttpCacheDataRemover*)>;
// Creates an HttpCacheDataRemover that starts deleting cache entries in the
// time range between |delete_begin| (inclusively) and |delete_end|
// (exclusively) and that are matched by |url_filter|. Invokes |done_callback|
// when finished.
// Note that deletion with URL filtering is not built in to the cache
// interface and might be slow.
static std::unique_ptr<HttpCacheDataRemover> CreateAndStart(
net::URLRequestContext* url_request_context,
mojom::ClearCacheUrlFilterPtr url_filter,
base::Time delete_begin,
base::Time delete_end,
HttpCacheDataRemoverCallback done_callback);
~HttpCacheDataRemover();
private:
HttpCacheDataRemover(mojom::ClearCacheUrlFilterPtr url_filter,
base::Time delete_begin,
base::Time delete_end,
HttpCacheDataRemoverCallback done_callback);
void CacheRetrieved(std::unique_ptr<disk_cache::Backend*> backend, int rv);
void ClearHttpCacheDone(int rv);
base::RepeatingCallback<bool(const GURL&)> url_matcher_;
const base::Time delete_begin_;
const base::Time delete_end_;
HttpCacheDataRemoverCallback done_callback_;
std::unique_ptr<ConditionalCacheDeletionHelper> deletion_helper_;
base::WeakPtrFactory<HttpCacheDataRemover> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(HttpCacheDataRemover);
};
} // namespace network
#endif // SERVICES_NETWORK_HTTP_CACHE_DATA_REMOVER_H_
This diff is collapsed.
...@@ -443,6 +443,34 @@ void NetworkContext::ClearNetworkingHistorySince( ...@@ -443,6 +443,34 @@ void NetworkContext::ClearNetworkingHistorySince(
std::move(completion_callback)); std::move(completion_callback));
} }
void NetworkContext::ClearHttpCache(base::Time start_time,
base::Time end_time,
mojom::ClearCacheUrlFilterPtr filter,
ClearHttpCacheCallback callback) {
// It's safe to use Unretained below as the HttpCacheDataRemover is owner by
// |this| and guarantees it won't call its callback if deleted.
http_cache_data_removers_.push_back(HttpCacheDataRemover::CreateAndStart(
url_request_context_getter_->GetURLRequestContext(), std::move(filter),
start_time, end_time,
base::BindOnce(&NetworkContext::OnHttpCacheCleared,
base::Unretained(this), std::move(callback))));
}
void NetworkContext::OnHttpCacheCleared(ClearHttpCacheCallback callback,
HttpCacheDataRemover* remover) {
bool removed = false;
for (auto iter = http_cache_data_removers_.begin();
iter != http_cache_data_removers_.end(); ++iter) {
if (iter->get() == remover) {
removed = true;
http_cache_data_removers_.erase(iter);
break;
}
}
DCHECK(removed);
std::move(callback).Run();
}
void NetworkContext::SetNetworkConditions( void NetworkContext::SetNetworkConditions(
const std::string& profile_id, const std::string& profile_id,
mojom::NetworkConditionsPtr conditions) { mojom::NetworkConditionsPtr conditions) {
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector>
#include "base/callback.h" #include "base/callback.h"
#include "base/component_export.h" #include "base/component_export.h"
...@@ -17,6 +18,7 @@ ...@@ -17,6 +18,7 @@
#include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/bindings/strong_binding_set.h" #include "mojo/public/cpp/bindings/strong_binding_set.h"
#include "services/network/cookie_manager.h" #include "services/network/cookie_manager.h"
#include "services/network/http_cache_data_remover.h"
#include "services/network/public/mojom/network_service.mojom.h" #include "services/network/public/mojom/network_service.mojom.h"
#include "services/network/public/mojom/udp_socket.mojom.h" #include "services/network/public/mojom/udp_socket.mojom.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h" #include "services/network/public/mojom/url_loader_factory.mojom.h"
...@@ -102,6 +104,10 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext ...@@ -102,6 +104,10 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
void ClearNetworkingHistorySince( void ClearNetworkingHistorySince(
base::Time time, base::Time time,
base::OnceClosure completion_callback) override; base::OnceClosure completion_callback) override;
void ClearHttpCache(base::Time start_time,
base::Time end_time,
mojom::ClearCacheUrlFilterPtr filter,
ClearHttpCacheCallback callback) override;
void SetNetworkConditions(const std::string& profile_id, void SetNetworkConditions(const std::string& profile_id,
mojom::NetworkConditionsPtr conditions) override; mojom::NetworkConditionsPtr conditions) override;
void CreateUDPSocket(mojom::UDPSocketRequest request, void CreateUDPSocket(mojom::UDPSocketRequest request,
...@@ -132,6 +138,10 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext ...@@ -132,6 +138,10 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
// Constructor only used in tests. // Constructor only used in tests.
explicit NetworkContext(mojom::NetworkContextParamsPtr params); explicit NetworkContext(mojom::NetworkContextParamsPtr params);
// Invoked when the HTTP cache was cleared. Invokes |callback|.
void OnHttpCacheCleared(ClearHttpCacheCallback callback,
HttpCacheDataRemover* remover);
// On connection errors the NetworkContext destroys itself. // On connection errors the NetworkContext destroys itself.
void OnConnectionError(); void OnConnectionError();
...@@ -161,6 +171,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext ...@@ -161,6 +171,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
std::unique_ptr<UDPSocketFactory> udp_socket_factory_; std::unique_ptr<UDPSocketFactory> udp_socket_factory_;
std::vector<std::unique_ptr<HttpCacheDataRemover>> http_cache_data_removers_;
int current_resource_scheduler_client_id_ = 0; int current_resource_scheduler_client_id_ = 0;
// TODO(yhirano): Consult with switches::kDisableResourceScheduler. // TODO(yhirano): Consult with switches::kDisableResourceScheduler.
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "base/barrier_closure.h"
#include "base/bind.h" #include "base/bind.h"
#include "base/command_line.h" #include "base/command_line.h"
#include "base/files/file_path.h" #include "base/files/file_path.h"
...@@ -536,6 +537,97 @@ TEST_F(NetworkContextTest, ClearHttpServerPropertiesInMemory) { ...@@ -536,6 +537,97 @@ TEST_F(NetworkContextTest, ClearHttpServerPropertiesInMemory) {
->GetSupportsSpdy(kSchemeHostPort)); ->GetSupportsSpdy(kSchemeHostPort));
} }
// Validates that clearing the HTTP cache when no cache exists does complete.
TEST_F(NetworkContextTest, ClearHttpCacheWithNoCache) {
mojom::NetworkContextParamsPtr context_params = CreateContextParams();
context_params->http_cache_enabled = false;
std::unique_ptr<NetworkContext> network_context =
CreateContextWithParams(std::move(context_params));
net::HttpCache* cache = network_context->GetURLRequestContext()
->http_transaction_factory()
->GetCache();
ASSERT_EQ(nullptr, cache);
base::RunLoop run_loop;
network_context->ClearHttpCache(base::Time(), base::Time(),
/*filter=*/nullptr,
base::BindOnce(run_loop.QuitClosure()));
run_loop.Run();
}
TEST_F(NetworkContextTest, ClearHttpCache) {
mojom::NetworkContextParamsPtr context_params = CreateContextParams();
context_params->http_cache_enabled = true;
base::ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
context_params->http_cache_path = temp_dir.GetPath();
std::unique_ptr<NetworkContext> network_context =
CreateContextWithParams(std::move(context_params));
net::HttpCache* cache = network_context->GetURLRequestContext()
->http_transaction_factory()
->GetCache();
std::vector<std::string> entry_urls = {
"http://www.google.com", "https://www.google.com",
"http://www.wikipedia.com", "https://www.wikipedia.com",
"http://localhost:1234", "https://localhost:1234",
};
ASSERT_TRUE(cache);
disk_cache::Backend* backend = nullptr;
net::TestCompletionCallback callback;
int rv = cache->GetBackend(&backend, callback.callback());
EXPECT_EQ(net::OK, callback.GetResult(rv));
ASSERT_TRUE(backend);
for (const auto& url : entry_urls) {
disk_cache::Entry* entry = nullptr;
base::RunLoop run_loop;
if (backend->CreateEntry(
url, &entry,
base::Bind([](base::OnceClosure quit_loop,
int rv) { std::move(quit_loop).Run(); },
run_loop.QuitClosure())) == net::ERR_IO_PENDING) {
run_loop.Run();
}
entry->Close();
}
EXPECT_EQ(entry_urls.size(), static_cast<size_t>(backend->GetEntryCount()));
base::RunLoop run_loop;
network_context->ClearHttpCache(base::Time(), base::Time(),
/*filter=*/nullptr,
base::BindOnce(run_loop.QuitClosure()));
run_loop.Run();
EXPECT_EQ(0U, static_cast<size_t>(backend->GetEntryCount()));
}
// Checks that when multiple calls are made to clear the HTTP cache, all
// callbacks are invoked.
TEST_F(NetworkContextTest, MultipleClearHttpCacheCalls) {
constexpr int kNumberOfClearCalls = 10;
mojom::NetworkContextParamsPtr context_params = CreateContextParams();
context_params->http_cache_enabled = true;
base::ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
context_params->http_cache_path = temp_dir.GetPath();
std::unique_ptr<NetworkContext> network_context =
CreateContextWithParams(std::move(context_params));
base::RunLoop run_loop;
base::RepeatingClosure barrier_closure = base::BarrierClosure(
/*num_closures=*/kNumberOfClearCalls, run_loop.QuitClosure());
for (int i = 0; i < kNumberOfClearCalls; i++) {
network_context->ClearHttpCache(base::Time(), base::Time(),
/*filter=*/nullptr,
base::BindOnce(barrier_closure));
}
run_loop.Run();
// If all the callbacks were invoked, we should terminate.
}
void SetCookieCallback(base::RunLoop* run_loop, bool* result_out, bool result) { void SetCookieCallback(base::RunLoop* run_loop, bool* result_out, bool result) {
*result_out = result; *result_out = result;
run_loop->Quit(); run_loop->Quit();
......
...@@ -79,6 +79,7 @@ mojom("mojom") { ...@@ -79,6 +79,7 @@ mojom("mojom") {
"//mojo/common:common_custom_types", "//mojo/common:common_custom_types",
"//services/proxy_resolver/public/mojom", "//services/proxy_resolver/public/mojom",
"//url/mojom:url_mojom_gurl", "//url/mojom:url_mojom_gurl",
"//url/mojom:url_mojom_origin",
] ]
# TODO(crbug/598073): When moving the service implementation to # TODO(crbug/598073): When moving the service implementation to
......
...@@ -13,6 +13,7 @@ import "url_loader_factory.mojom"; ...@@ -13,6 +13,7 @@ import "url_loader_factory.mojom";
import "restricted_cookie_manager.mojom"; import "restricted_cookie_manager.mojom";
import "mojo/common/file_path.mojom"; import "mojo/common/file_path.mojom";
import "mojo/common/time.mojom"; import "mojo/common/time.mojom";
import "url/mojom/origin.mojom";
import "url/mojom/url.mojom"; import "url/mojom/url.mojom";
import "services/network/public/mojom/udp_socket.mojom"; import "services/network/public/mojom/udp_socket.mojom";
import "services/proxy_resolver/public/mojom/proxy_resolver.mojom"; import "services/proxy_resolver/public/mojom/proxy_resolver.mojom";
...@@ -121,6 +122,24 @@ struct NetworkConditions { ...@@ -121,6 +122,24 @@ struct NetworkConditions {
double upload_throughput; double upload_throughput;
}; };
// Used in NetworkContext.ClearHttpCache() to specify the resources to
// keep/delete based on their URLs.
struct ClearCacheUrlFilter {
enum Type {DELETE_MATCHES, KEEP_MATCHES};
Type type;
// A list of registrable domains (e.g. google.com), internal hostnames
// (e.g. localhost), or IP addresses (e.g. 127.0.0.1). Other domains, such as
// third and lower level domains (e.g. www.google.com) are not accepted.
// Formally, it must hold that GetDomainAndRegistry(|domain|, _) is |domain|
// itself or an empty string.
array<string> domains;
// List of URL origins.
array<url.mojom.Origin> origins;
};
// Represents a distinct context for making network requests, with its own // Represents a distinct context for making network requests, with its own
// storage (e.g. cookies and cache). // storage (e.g. cookies and cache).
interface NetworkContext { interface NetworkContext {
...@@ -147,6 +166,13 @@ interface NetworkContext { ...@@ -147,6 +166,13 @@ interface NetworkContext {
// The callback will be invoked once the data has been deleted. // The callback will be invoked once the data has been deleted.
ClearNetworkingHistorySince(mojo.common.mojom.Time start_time) => (); ClearNetworkingHistorySince(mojo.common.mojom.Time start_time) => ();
// Clears content from the HTTP cache. A specific range of time can be
// specified with |start_time| and |end_time|. This supports unbounded deletes
// in either direction by using null Time values for either argument.
ClearHttpCache(mojo.common.mojom.Time start_time,
mojo.common.mojom.Time end_time,
ClearCacheUrlFilter? filter) => ();
// Configures network conditions for the specified throttling profile. // Configures network conditions for the specified throttling profile.
// The throttling will be applied only to requests that have // The throttling will be applied only to requests that have
// X-DevTools-Emulate-Network-Conditions-Client-Id: <profile_id> // X-DevTools-Emulate-Network-Conditions-Client-Id: <profile_id>
......
...@@ -154,6 +154,7 @@ class DelayedReadEntry : public disk_cache::Entry { ...@@ -154,6 +154,7 @@ class DelayedReadEntry : public disk_cache::Entry {
int ReadyForSparseIO(const CompletionCallback& callback) override { int ReadyForSparseIO(const CompletionCallback& callback) override {
return entry_->ReadyForSparseIO(callback); return entry_->ReadyForSparseIO(callback);
} }
void SetLastUsedTimeForTest(base::Time time) override { NOTREACHED(); }
private: private:
disk_cache::ScopedEntryPtr entry_; disk_cache::ScopedEntryPtr entry_;
......
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
-BackgroundXhrTest.HttpAuth -BackgroundXhrTest.HttpAuth
-BackgroundXhrTest.TlsClientAuth -BackgroundXhrTest.TlsClientAuth
-BrowserTest.InterstitialCancelsGuestViewDialogs -BrowserTest.InterstitialCancelsGuestViewDialogs
-BrowsingDataRemoverBrowserTest.Cache
-BrowsingDataRemoverBrowserTest.CookieDeletion -BrowsingDataRemoverBrowserTest.CookieDeletion
-ChromeSecurityExploitBrowserTest.CreateFilesystemURLInExtensionOrigin -ChromeSecurityExploitBrowserTest.CreateFilesystemURLInExtensionOrigin
-ChromeSitePerProcessTest.LaunchExternalProtocolFromSubframe -ChromeSitePerProcessTest.LaunchExternalProtocolFromSubframe
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment