Index: net/http/http_cache_transaction.cc |
diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc |
index 518944650747e6a3dc7f39c58b4b4d7cb1610758..1a0fd493a98bb22c61a9974b8e3d04331851d8c2 100644 |
--- a/net/http/http_cache_transaction.cc |
+++ b/net/http/http_cache_transaction.cc |
@@ -69,6 +69,22 @@ void RecordNoStoreHeaderHistogram(int load_flags, |
} |
} |
+disk_cache::Backend::OracleJudgement CheckIfUnusable(uint8_t flags) { |
+ // If the entry is marked as an unused prefetch, we have to open it up |
+ // to check. |
+ if (flags & HttpCache::OBH_UNUSED_SINCE_PREFETCH) |
+ return disk_cache::Backend::OracleJudgement::HIT; |
+ if ((flags & HttpCache::OBH_ZERO_LIFETIME) && |
+ (flags & HttpCache::OBH_RESPONSE_CANT_CONDITIONALIZE)) { |
+ // TODO(morlovich): Just zero-lifetime is sufficient for e.g. |
+ // PUT/DELETE, also could potentially encode vary-mismatch case. |
+ return disk_cache::Backend::OracleJudgement::MISS_AND_DOOM; |
+ } |
+ |
+ // Default |
+ return disk_cache::Backend::OracleJudgement::HIT; |
+} |
+ |
} // namespace |
#define CACHE_STATUS_HISTOGRAMS(type) \ |
@@ -991,7 +1007,12 @@ int HttpCache::Transaction::DoOpenEntry() { |
cache_pending_ = true; |
net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_OPEN_ENTRY); |
first_cache_access_since_ = TimeTicks::Now(); |
- return cache_->OpenEntry(cache_key_, &new_entry_, this); |
+ // See if we could potentially quick reject the entry. |
+ if (!(effective_load_flags_ & LOAD_SKIP_CACHE_VALIDATION)) |
+ return cache_->OpenEntry(cache_key_, &new_entry_, |
+ base::Bind(&CheckIfUnusable), this); |
+ return cache_->OpenEntry(cache_key_, &new_entry_, |
+ disk_cache::Backend::OracleCallback(), this); |
} |
int HttpCache::Transaction::DoOpenEntryComplete(int result) { |
@@ -2337,40 +2358,57 @@ bool HttpCache::Transaction::RequiresValidation() { |
return validation_required_by_headers; |
} |
-bool HttpCache::Transaction::ConditionalizeRequest() { |
+bool HttpCache::Transaction::ResponseConditionalizable( |
+ std::string* etag_value, |
+ std::string* last_modified_value) { |
DCHECK(response_.headers.get()); |
- if (request_->method == "PUT" || request_->method == "DELETE") |
- return false; |
- |
// This only makes sense for cached 200 or 206 responses. |
if (response_.headers->response_code() != 200 && |
response_.headers->response_code() != 206) { |
return false; |
} |
- if (fail_conditionalization_for_test_) |
- return false; |
- |
+ // ### this looks scary. |
DCHECK(response_.headers->response_code() != 206 || |
response_.headers->HasStrongValidators()); |
// Just use the first available ETag and/or Last-Modified header value. |
// TODO(darin): Or should we use the last? |
- std::string etag_value; |
if (response_.headers->GetHttpVersion() >= HttpVersion(1, 1)) |
- response_.headers->EnumerateHeader(NULL, "etag", &etag_value); |
+ response_.headers->EnumerateHeader(NULL, "etag", etag_value); |
- std::string last_modified_value; |
- if (!vary_mismatch_) { |
- response_.headers->EnumerateHeader(NULL, "last-modified", |
- &last_modified_value); |
- } |
+ response_.headers->EnumerateHeader(NULL, "last-modified", |
+ last_modified_value); |
+ |
+ if (etag_value->empty() && last_modified_value->empty()) |
+ return false; |
+ |
+ return true; |
+} |
+ |
+bool HttpCache::Transaction::ConditionalizeRequest() { |
+ DCHECK(response_.headers.get()); |
- if (etag_value.empty() && last_modified_value.empty()) |
+ if (request_->method == "PUT" || request_->method == "DELETE") |
+ return false; |
+ |
+ if (fail_conditionalization_for_test_) |
return false; |
+ std::string etag_value; |
+ std::string last_modified_value; |
+ if (!ResponseConditionalizable(&etag_value, &last_modified_value)) |
+ return false; |
+ |
+ if (vary_mismatch_) { |
+ // Can't rely on last-modified if vary is different. |
+ last_modified_value.clear(); |
+ if (etag_value.empty()) |
+ return false; |
+ } |
+ |
if (!partial_) { |
// Need to customize the request, so this forces us to allocate :( |
custom_request_.reset(new HttpRequestInfo(*request_)); |
@@ -2631,6 +2669,19 @@ int HttpCache::Transaction::WriteResponseInfoToEntry(bool truncated) { |
data->Done(); |
io_buf_len_ = data->pickle()->size(); |
+ |
+ uint8_t hints = 0; |
+ // ### recomputing this too much? |
+ if (response_.headers->GetFreshnessLifetimes(response_.response_time) |
+ .freshness.is_zero()) |
+ hints |= HttpCache::OBH_ZERO_LIFETIME; |
+ std::string etag_ignored, last_modified_ignored; |
+ if (!ResponseConditionalizable(&etag_ignored, &last_modified_ignored)) |
+ hints |= HttpCache::OBH_RESPONSE_CANT_CONDITIONALIZE; |
+ if (response_.unused_since_prefetch) |
+ hints |= HttpCache::OBH_UNUSED_SINCE_PREFETCH; |
+ entry_->disk_entry->SetOracleByte(hints); |
+ |
return entry_->disk_entry->WriteData(kResponseInfoIndex, 0, data.get(), |
io_buf_len_, io_callback_, true); |
} |