Commit 8586921e authored by twifkak's avatar twifkak Committed by Commit bot

Add revalidation_only option to precache config.

When specified, resources are only fetched over the network if they have
an existing cache entry with revalidation headers. This serves as a
lower-bound approximation of the efficacy of a client-only wifi precache
mechanism, as it is limited to URLs that are only on the client AND in
the manifests.

BUG=679533

Review-Url: https://codereview.chromium.org/2614403003
Cr-Commit-Position: refs/heads/master@{#442999}
parent 29140a41
...@@ -241,13 +241,15 @@ PrecacheFetcher::Fetcher::Fetcher( ...@@ -241,13 +241,15 @@ PrecacheFetcher::Fetcher::Fetcher(
const std::string& referrer, const std::string& referrer,
const base::Callback<void(const Fetcher&)>& callback, const base::Callback<void(const Fetcher&)>& callback,
bool is_resource_request, bool is_resource_request,
size_t max_bytes) size_t max_bytes,
bool revalidation_only)
: request_context_(request_context), : request_context_(request_context),
url_(url), url_(url),
referrer_(referrer), referrer_(referrer),
callback_(callback), callback_(callback),
is_resource_request_(is_resource_request), is_resource_request_(is_resource_request),
max_bytes_(max_bytes), max_bytes_(max_bytes),
revalidation_only_(revalidation_only),
response_bytes_(0), response_bytes_(0),
network_response_bytes_(0), network_response_bytes_(0),
was_cached_(false) { was_cached_(false) {
...@@ -330,7 +332,8 @@ void PrecacheFetcher::Fetcher::OnURLFetchComplete( ...@@ -330,7 +332,8 @@ void PrecacheFetcher::Fetcher::OnURLFetchComplete(
const net::URLFetcher* source) { const net::URLFetcher* source) {
CHECK(source); CHECK(source);
if (fetch_stage_ == FetchStage::CACHE && if (fetch_stage_ == FetchStage::CACHE &&
(source->GetStatus().error() == net::ERR_CACHE_MISS || ((source->GetStatus().error() == net::ERR_CACHE_MISS &&
!revalidation_only_) ||
(source->GetResponseHeaders() && (source->GetResponseHeaders() &&
source->GetResponseHeaders()->HasValidators()))) { source->GetResponseHeaders()->HasValidators()))) {
// If the resource was not found in the cache, request it from the // If the resource was not found in the cache, request it from the
...@@ -488,7 +491,8 @@ void PrecacheFetcher::Start() { ...@@ -488,7 +491,8 @@ void PrecacheFetcher::Start() {
pool_.Add(base::MakeUnique<Fetcher>( pool_.Add(base::MakeUnique<Fetcher>(
request_context_.get(), config_url, std::string(), request_context_.get(), config_url, std::string(),
base::Bind(&PrecacheFetcher::OnConfigFetchComplete, AsWeakPtr()), base::Bind(&PrecacheFetcher::OnConfigFetchComplete, AsWeakPtr()),
false /* is_resource_request */, std::numeric_limits<int32_t>::max())); false /* is_resource_request */, std::numeric_limits<int32_t>::max(),
false /* revalidation_only */));
} }
void PrecacheFetcher::StartNextResourceFetch() { void PrecacheFetcher::StartNextResourceFetch() {
...@@ -503,7 +507,8 @@ void PrecacheFetcher::StartNextResourceFetch() { ...@@ -503,7 +507,8 @@ void PrecacheFetcher::StartNextResourceFetch() {
pool_.Add(base::MakeUnique<Fetcher>( pool_.Add(base::MakeUnique<Fetcher>(
request_context_.get(), resource.url, resource.referrer, request_context_.get(), resource.url, resource.referrer,
base::Bind(&PrecacheFetcher::OnResourceFetchComplete, AsWeakPtr()), base::Bind(&PrecacheFetcher::OnResourceFetchComplete, AsWeakPtr()),
true /* is_resource_request */, max_bytes)); true /* is_resource_request */, max_bytes,
unfinished_work_->config_settings().revalidation_only()));
resources_fetching_.push_back(std::move(resource)); resources_fetching_.push_back(std::move(resource));
resources_to_fetch_.pop_front(); resources_to_fetch_.pop_front();
...@@ -519,7 +524,8 @@ void PrecacheFetcher::StartNextManifestFetches() { ...@@ -519,7 +524,8 @@ void PrecacheFetcher::StartNextManifestFetches() {
request_context_.get(), top_host.manifest_url, top_host.hostname, request_context_.get(), top_host.manifest_url, top_host.hostname,
base::Bind(&PrecacheFetcher::OnManifestFetchComplete, AsWeakPtr(), base::Bind(&PrecacheFetcher::OnManifestFetchComplete, AsWeakPtr(),
top_host.visits), top_host.visits),
false /* is_resource_request */, std::numeric_limits<int32_t>::max())); false /* is_resource_request */, std::numeric_limits<int32_t>::max(),
false /* revalidation_only */));
top_hosts_fetching_.push_back(std::move(top_host)); top_hosts_fetching_.push_back(std::move(top_host));
top_hosts_to_fetch_.pop_front(); top_hosts_to_fetch_.pop_front();
} }
......
...@@ -292,14 +292,25 @@ class PrecacheFetcher : public base::SupportsWeakPtr<PrecacheFetcher> { ...@@ -292,14 +292,25 @@ class PrecacheFetcher : public base::SupportsWeakPtr<PrecacheFetcher> {
// network_url_fetcher() will return nullptr. // network_url_fetcher() will return nullptr.
class PrecacheFetcher::Fetcher : public net::URLFetcherDelegate { class PrecacheFetcher::Fetcher : public net::URLFetcherDelegate {
public: public:
// Construct a new Fetcher. This will create and start a new URLFetcher for // Construct a new Fetcher. This will create and start a new URLFetcher
// the specified URL using the specified request context. // immediately. Parameters:
// request_context: The request context to pass to the URLFetcher.
// url: The URL to fetch.
// referrer: The hostname of the manifest requesting this resource. Empty
// for config fetches.
// callback: Called when the fetch is finished or cancelled.
// is_resource_request: If true, the URL may be refreshed using
// LOAD_VALIDATE_CACHE.
// max_bytes: The number of bytes to download before cancelling.
// revalidation_only: If true, the URL is fetched only if it has an existing
// cache entry with conditional headers.
Fetcher(net::URLRequestContextGetter* request_context, Fetcher(net::URLRequestContextGetter* request_context,
const GURL& url, const GURL& url,
const std::string& referrer, const std::string& referrer,
const base::Callback<void(const Fetcher&)>& callback, const base::Callback<void(const Fetcher&)>& callback,
bool is_resource_request, bool is_resource_request,
size_t max_bytes); size_t max_bytes,
bool revalidation_only);
~Fetcher() override; ~Fetcher() override;
void OnURLFetchDownloadProgress(const net::URLFetcher* source, void OnURLFetchDownloadProgress(const net::URLFetcher* source,
int64_t current, int64_t current,
...@@ -322,12 +333,14 @@ class PrecacheFetcher::Fetcher : public net::URLFetcherDelegate { ...@@ -322,12 +333,14 @@ class PrecacheFetcher::Fetcher : public net::URLFetcherDelegate {
void LoadFromCache(); void LoadFromCache();
void LoadFromNetwork(); void LoadFromNetwork();
// The arguments to this Fetcher's constructor.
net::URLRequestContextGetter* const request_context_; net::URLRequestContextGetter* const request_context_;
const GURL url_; const GURL url_;
const std::string referrer_; const std::string referrer_;
const base::Callback<void(const Fetcher&)> callback_; const base::Callback<void(const Fetcher&)> callback_;
const bool is_resource_request_; const bool is_resource_request_;
const size_t max_bytes_; const size_t max_bytes_;
const bool revalidation_only_;
FetchStage fetch_stage_; FetchStage fetch_stage_;
// The cache_url_fetcher_ is kept alive until Fetcher destruction for testing. // The cache_url_fetcher_ is kept alive until Fetcher destruction for testing.
......
...@@ -239,7 +239,7 @@ TEST_F(PrecacheFetcherFetcherTest, Config) { ...@@ -239,7 +239,7 @@ TEST_F(PrecacheFetcherFetcherTest, Config) {
PrecacheFetcher::Fetcher precache_fetcher( PrecacheFetcher::Fetcher precache_fetcher(
request_context_.get(), url, url.host(), callback_, request_context_.get(), url, url.host(), callback_,
false /* is_resource_request */, SIZE_MAX); false /* is_resource_request */, SIZE_MAX, false /* revalidation_only */);
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
...@@ -256,12 +256,11 @@ TEST_F(PrecacheFetcherFetcherTest, ResourceNotInCache) { ...@@ -256,12 +256,11 @@ TEST_F(PrecacheFetcherFetcherTest, ResourceNotInCache) {
.WillOnce(factory_.RespondWith("", &fetcher2)); .WillOnce(factory_.RespondWith("", &fetcher2));
EXPECT_CALL(*this, EXPECT_CALL(*this,
Callback(Property(&PrecacheFetcher::Fetcher::network_url_fetcher, Callback(Property(&PrecacheFetcher::Fetcher::network_url_fetcher,
NotNull()))) NotNull())));
.Times(1);
PrecacheFetcher::Fetcher precache_fetcher( PrecacheFetcher::Fetcher precache_fetcher(
request_context_.get(), url, url.host(), callback_, request_context_.get(), url, url.host(), callback_,
true /* is_resource_request */, SIZE_MAX); true /* is_resource_request */, SIZE_MAX, false /* revalidation_only */);
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
...@@ -286,7 +285,7 @@ TEST_F(PrecacheFetcherFetcherTest, ResourceHasValidators) { ...@@ -286,7 +285,7 @@ TEST_F(PrecacheFetcherFetcherTest, ResourceHasValidators) {
PrecacheFetcher::Fetcher precache_fetcher( PrecacheFetcher::Fetcher precache_fetcher(
request_context_.get(), url, url.host(), callback_, request_context_.get(), url, url.host(), callback_,
true /* is_resource_request */, SIZE_MAX); true /* is_resource_request */, SIZE_MAX, false /* revalidation_only */);
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
...@@ -301,7 +300,75 @@ TEST_F(PrecacheFetcherFetcherTest, ResourceHasValidators) { ...@@ -301,7 +300,75 @@ TEST_F(PrecacheFetcherFetcherTest, ResourceHasValidators) {
TEST_F(PrecacheFetcherFetcherTest, ResourceHasNoValidators) { TEST_F(PrecacheFetcherFetcherTest, ResourceHasNoValidators) {
GURL url(kGoodResourceURL); GURL url(kGoodResourceURL);
net::FakeURLFetcher* fetcher; net::FakeURLFetcher* fetcher = nullptr;
EXPECT_CALL(factory_, DoCreateURLFetcher(_, url, net::URLFetcher::GET, _))
.WillOnce(factory_.RespondWith("", &fetcher));
EXPECT_CALL(*this,
Callback(Property(&PrecacheFetcher::Fetcher::network_url_fetcher,
nullptr))); // It never reached the network.
PrecacheFetcher::Fetcher precache_fetcher(
request_context_.get(), url, url.host(), callback_,
true /* is_resource_request */, SIZE_MAX, false /* revalidation_only */);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(
net::LOAD_ONLY_FROM_CACHE | net::LOAD_SKIP_CACHE_VALIDATION | kNoTracking,
fetcher->GetLoadFlags());
}
TEST_F(PrecacheFetcherFetcherTest, RevalidationOnlyResourceNotInCache) {
GURL url(kGoodResourceURL);
net::FakeURLFetcher* fetcher = nullptr;
EXPECT_CALL(factory_, DoCreateURLFetcher(_, url, net::URLFetcher::GET, _))
.WillOnce(factory_.RespondWith("", CacheMiss, &fetcher));
EXPECT_CALL(*this,
Callback(Property(&PrecacheFetcher::Fetcher::network_url_fetcher,
nullptr))); // It never reached the network.
PrecacheFetcher::Fetcher precache_fetcher(
request_context_.get(), url, url.host(), callback_,
true /* is_resource_request */, SIZE_MAX, true /* revalidation_only */);
base::RunLoop().RunUntilIdle();
ASSERT_NE(nullptr, fetcher);
EXPECT_EQ(
net::LOAD_ONLY_FROM_CACHE | net::LOAD_SKIP_CACHE_VALIDATION | kNoTracking,
fetcher->GetLoadFlags());
}
TEST_F(PrecacheFetcherFetcherTest, RevalidationOnlyResourceHasValidators) {
GURL url(kGoodResourceURL);
net::FakeURLFetcher *fetcher1 = nullptr, *fetcher2 = nullptr;
EXPECT_CALL(factory_, DoCreateURLFetcher(_, url, net::URLFetcher::GET, _))
.WillOnce(factory_.RespondWith("", HasETag, &fetcher1))
.WillOnce(factory_.RespondWith("", &fetcher2));
EXPECT_CALL(*this,
Callback(Property(&PrecacheFetcher::Fetcher::network_url_fetcher,
NotNull())));
PrecacheFetcher::Fetcher precache_fetcher(
request_context_.get(), url, url.host(), callback_,
true /* is_resource_request */, SIZE_MAX, true /* revalidation_only */);
base::RunLoop().RunUntilIdle();
ASSERT_NE(nullptr, fetcher1);
EXPECT_EQ(
net::LOAD_ONLY_FROM_CACHE | net::LOAD_SKIP_CACHE_VALIDATION | kNoTracking,
fetcher1->GetLoadFlags());
ASSERT_NE(nullptr, fetcher2);
EXPECT_EQ(net::LOAD_VALIDATE_CACHE | kNoTracking, fetcher2->GetLoadFlags());
}
TEST_F(PrecacheFetcherFetcherTest, RevalidationOnlyResourceHasNoValidators) {
GURL url(kGoodResourceURL);
net::FakeURLFetcher* fetcher = nullptr;
EXPECT_CALL(factory_, DoCreateURLFetcher(_, url, net::URLFetcher::GET, _)) EXPECT_CALL(factory_, DoCreateURLFetcher(_, url, net::URLFetcher::GET, _))
.WillOnce(factory_.RespondWith("", &fetcher)); .WillOnce(factory_.RespondWith("", &fetcher));
EXPECT_CALL(*this, EXPECT_CALL(*this,
...@@ -310,7 +377,7 @@ TEST_F(PrecacheFetcherFetcherTest, ResourceHasNoValidators) { ...@@ -310,7 +377,7 @@ TEST_F(PrecacheFetcherFetcherTest, ResourceHasNoValidators) {
PrecacheFetcher::Fetcher precache_fetcher( PrecacheFetcher::Fetcher precache_fetcher(
request_context_.get(), url, url.host(), callback_, request_context_.get(), url, url.host(), callback_,
true /* is_resource_request */, SIZE_MAX); true /* is_resource_request */, SIZE_MAX, true /* revalidation_only */);
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
...@@ -339,7 +406,8 @@ TEST_F(PrecacheFetcherFetcherTest, ResourceTooBig) { ...@@ -339,7 +406,8 @@ TEST_F(PrecacheFetcherFetcherTest, ResourceTooBig) {
PrecacheFetcher::Fetcher precache_fetcher( PrecacheFetcher::Fetcher precache_fetcher(
request_context_.get(), url, url.host(), callback_, request_context_.get(), url, url.host(), callback_,
true /* is_resource_request */, 99 /* max_bytes */); true /* is_resource_request */, 99 /* max_bytes */,
false /* revalidation_only */);
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
} }
......
...@@ -105,4 +105,8 @@ message PrecacheConfigurationSettings { ...@@ -105,4 +105,8 @@ message PrecacheConfigurationSettings {
// affects the fetcher's behavior with respect to max_bytes_total and // affects the fetcher's behavior with respect to max_bytes_total and
// total_resources_count. // total_resources_count.
optional bool global_ranking = 9 [default = false]; optional bool global_ranking = 9 [default = false];
// If true, resource fetches are only made over the network for a given URL if
// an existing cache entry exists and has revalidation headers.
optional bool revalidation_only = 10 [default = false];
}; };
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