| Index: net/http/http_cache_transaction.cc
|
| diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc
|
| index 9bc83264feab97d61d1c8acdcd567b2442cc5ea9..caf2155cea305a2304885b8115278f863424340d 100644
|
| --- a/net/http/http_cache_transaction.cc
|
| +++ b/net/http/http_cache_transaction.cc
|
| @@ -1036,6 +1036,15 @@ int HttpCache::Transaction::DoOpenEntryComplete(int result) {
|
| return OK;
|
| }
|
|
|
| + if (result == ERR_CACHE_ENTRY_NOT_SUITABLE) {
|
| + DCHECK_EQ(mode_, READ_WRITE);
|
| + // Record this as CantConditionalize, but otherwise proceed as we would
|
| + // below --- as OpenEntry has already dropped the old entry for us.
|
| + couldnt_conditionalize_request_ = true;
|
| + response_.was_cached = true;
|
| + UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE);
|
| + }
|
| +
|
| if (method_ == "PUT" || method_ == "DELETE" ||
|
| (method_ == "HEAD" && mode_ == READ_WRITE)) {
|
| DCHECK(mode_ == READ_WRITE || mode_ == WRITE || method_ == "HEAD");
|
| @@ -2436,40 +2445,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 (method_ == "PUT" || 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())
|
| + if (etag_value->empty() && last_modified_value->empty())
|
| + return false;
|
| +
|
| + return true;
|
| +}
|
| +
|
| +bool HttpCache::Transaction::ConditionalizeRequest() {
|
| + DCHECK(response_.headers.get());
|
| +
|
| + if (method_ == "PUT" || 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_));
|
| @@ -2509,6 +2535,39 @@ bool HttpCache::Transaction::ConditionalizeRequest() {
|
| return true;
|
| }
|
|
|
| +bool HttpCache::Transaction::MaybeRejectBasedOnMemoryEntryData(
|
| + uint8_t in_memory_info) {
|
| + // Not going to be clever with those... though is it even set here?
|
| + if (partial_)
|
| + return false;
|
| +
|
| + // Unclear how to reconcile trying to avoid opening the entry with UPDATE's
|
| + // semantics.
|
| + if (mode_ == UPDATE)
|
| + return false;
|
| +
|
| + // We can tell that some entries in cache may be unusable under present
|
| + // circumstances if:
|
| + // 1) We aren't using everything because of LOAD_SKIP_CACHE_VALIDATION.
|
| + // 2) We aren't holding on to results of an unused prefetch.
|
| + // 3) The entry has zero freshness (so it's known to be expired!)
|
| + // 4) We know the entry can't be revalidated
|
| + // (we may be able to match more things here).
|
| + if (effective_load_flags_ & LOAD_SKIP_CACHE_VALIDATION)
|
| + return false;
|
| +
|
| + if (in_memory_info & HttpCache::OBH_UNUSED_SINCE_PREFETCH)
|
| + return false;
|
| +
|
| + if (!(in_memory_info & HttpCache::OBH_ZERO_LIFETIME))
|
| + return false;
|
| +
|
| + if (!(in_memory_info & OBH_RESPONSE_CANT_CONDITIONALIZE))
|
| + return false;
|
| +
|
| + return true;
|
| +}
|
| +
|
| // We just received some headers from the server. We may have asked for a range,
|
| // in which case partial_ has an object. This could be the first network request
|
| // we make to fulfill the original request, or we may be already reading (from
|
| @@ -2731,6 +2790,18 @@ 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;
|
| + cache_->GetCurrentBackend()->SetMemoryEntryData(cache_key_, hints);
|
| return entry_->disk_entry->WriteData(kResponseInfoIndex, 0, data.get(),
|
| io_buf_len_, io_callback_, true);
|
| }
|
|
|