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(
const std::string& referrer,
const base::Callback<void(const Fetcher&)>& callback,
bool is_resource_request,
size_t max_bytes)
size_t max_bytes,
bool revalidation_only)
: request_context_(request_context),
url_(url),
referrer_(referrer),
callback_(callback),
is_resource_request_(is_resource_request),
max_bytes_(max_bytes),
revalidation_only_(revalidation_only),
response_bytes_(0),
network_response_bytes_(0),
was_cached_(false) {
......@@ -330,7 +332,8 @@ void PrecacheFetcher::Fetcher::OnURLFetchComplete(
const net::URLFetcher* source) {
CHECK(source);
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()->HasValidators()))) {
// If the resource was not found in the cache, request it from the
......@@ -488,7 +491,8 @@ void PrecacheFetcher::Start() {
pool_.Add(base::MakeUnique<Fetcher>(
request_context_.get(), config_url, std::string(),
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() {
......@@ -503,7 +507,8 @@ void PrecacheFetcher::StartNextResourceFetch() {
pool_.Add(base::MakeUnique<Fetcher>(
request_context_.get(), resource.url, resource.referrer,
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_to_fetch_.pop_front();
......@@ -519,7 +524,8 @@ void PrecacheFetcher::StartNextManifestFetches() {
request_context_.get(), top_host.manifest_url, top_host.hostname,
base::Bind(&PrecacheFetcher::OnManifestFetchComplete, AsWeakPtr(),
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_to_fetch_.pop_front();
}
......
......@@ -292,14 +292,25 @@ class PrecacheFetcher : public base::SupportsWeakPtr<PrecacheFetcher> {
// network_url_fetcher() will return nullptr.
class PrecacheFetcher::Fetcher : public net::URLFetcherDelegate {
public:
// Construct a new Fetcher. This will create and start a new URLFetcher for
// the specified URL using the specified request context.
// Construct a new Fetcher. This will create and start a new URLFetcher
// 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,
const GURL& url,
const std::string& referrer,
const base::Callback<void(const Fetcher&)>& callback,
bool is_resource_request,
size_t max_bytes);
size_t max_bytes,
bool revalidation_only);
~Fetcher() override;
void OnURLFetchDownloadProgress(const net::URLFetcher* source,
int64_t current,
......@@ -322,12 +333,14 @@ class PrecacheFetcher::Fetcher : public net::URLFetcherDelegate {
void LoadFromCache();
void LoadFromNetwork();
// The arguments to this Fetcher's constructor.
net::URLRequestContextGetter* const request_context_;
const GURL url_;
const std::string referrer_;
const base::Callback<void(const Fetcher&)> callback_;
const bool is_resource_request_;
const size_t max_bytes_;
const bool revalidation_only_;
FetchStage fetch_stage_;
// The cache_url_fetcher_ is kept alive until Fetcher destruction for testing.
......
......@@ -239,7 +239,7 @@ TEST_F(PrecacheFetcherFetcherTest, Config) {
PrecacheFetcher::Fetcher precache_fetcher(
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();
......@@ -256,12 +256,11 @@ TEST_F(PrecacheFetcherFetcherTest, ResourceNotInCache) {
.WillOnce(factory_.RespondWith("", &fetcher2));
EXPECT_CALL(*this,
Callback(Property(&PrecacheFetcher::Fetcher::network_url_fetcher,
NotNull())))
.Times(1);
NotNull())));
PrecacheFetcher::Fetcher precache_fetcher(
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();
......@@ -286,7 +285,7 @@ TEST_F(PrecacheFetcherFetcherTest, ResourceHasValidators) {
PrecacheFetcher::Fetcher precache_fetcher(
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();
......@@ -301,7 +300,75 @@ TEST_F(PrecacheFetcherFetcherTest, ResourceHasValidators) {
TEST_F(PrecacheFetcherFetcherTest, ResourceHasNoValidators) {
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, _))
.WillOnce(factory_.RespondWith("", &fetcher));
EXPECT_CALL(*this,
......@@ -310,7 +377,7 @@ TEST_F(PrecacheFetcherFetcherTest, ResourceHasNoValidators) {
PrecacheFetcher::Fetcher precache_fetcher(
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();
......@@ -339,7 +406,8 @@ TEST_F(PrecacheFetcherFetcherTest, ResourceTooBig) {
PrecacheFetcher::Fetcher precache_fetcher(
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();
}
......
......@@ -105,4 +105,8 @@ message PrecacheConfigurationSettings {
// affects the fetcher's behavior with respect to max_bytes_total and
// total_resources_count.
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