Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / net / http / http_cache_transaction.cc
index 286a526..b06e8f3 100644 (file)
@@ -238,6 +238,13 @@ void RecordNoStoreHeaderHistogram(int load_flags,
   }
 }
 
+enum ExternallyConditionalizedType {
+  EXTERNALLY_CONDITIONALIZED_CACHE_REQUIRES_VALIDATION,
+  EXTERNALLY_CONDITIONALIZED_CACHE_USABLE,
+  EXTERNALLY_CONDITIONALIZED_MISMATCHED_VALIDATORS,
+  EXTERNALLY_CONDITIONALIZED_MAX
+};
+
 }  // namespace
 
 namespace net {
@@ -329,15 +336,16 @@ HttpCache::Transaction::Transaction(
       read_offset_(0),
       effective_load_flags_(0),
       write_len_(0),
-      weak_factory_(this),
-      io_callback_(base::Bind(&Transaction::OnIOComplete,
-                              weak_factory_.GetWeakPtr())),
       transaction_pattern_(PATTERN_UNDEFINED),
       total_received_bytes_(0),
-      websocket_handshake_stream_base_create_helper_(NULL) {
+      websocket_handshake_stream_base_create_helper_(NULL),
+      weak_factory_(this) {
   COMPILE_ASSERT(HttpCache::Transaction::kNumValidationHeaders ==
                  arraysize(kValidationHeaders),
                  Invalid_number_of_validation_headers);
+
+  io_callback_ = base::Bind(&Transaction::OnIOComplete,
+                              weak_factory_.GetWeakPtr());
 }
 
 HttpCache::Transaction::~Transaction() {
@@ -347,7 +355,7 @@ HttpCache::Transaction::~Transaction() {
 
   if (cache_) {
     if (entry_) {
-      bool cancel_request = reading_ && response_.headers;
+      bool cancel_request = reading_ && response_.headers.get();
       if (cancel_request) {
         if (partial_) {
           entry_->disk_entry->CancelSparseIO();
@@ -1382,12 +1390,30 @@ int HttpCache::Transaction::DoAddToEntry() {
     if (bypass_lock_for_test_) {
       OnAddToEntryTimeout(entry_lock_waiting_since_);
     } else {
-      const int kTimeoutSeconds = 20;
+      int timeout_milliseconds = 20 * 1000;
+      if (partial_ && new_entry_->writer &&
+          new_entry_->writer->range_requested_) {
+        // Quickly timeout and bypass the cache if we're a range request and
+        // we're blocked by the reader/writer lock. Doing so eliminates a long
+        // running issue, http://crbug.com/31014, where two of the same media
+        // resources could not be played back simultaneously due to one locking
+        // the cache entry until the entire video was downloaded.
+        //
+        // Bypassing the cache is not ideal, as we are now ignoring the cache
+        // entirely for all range requests to a resource beyond the first. This
+        // is however a much more succinct solution than the alternatives, which
+        // would require somewhat significant changes to the http caching logic.
+        //
+        // Allow some timeout slack for the entry addition to complete in case
+        // the writer lock is imminently released; we want to avoid skipping
+        // the cache if at all possible. See http://crbug.com/408765
+        timeout_milliseconds = 25;
+      }
       base::MessageLoop::current()->PostDelayedTask(
           FROM_HERE,
           base::Bind(&HttpCache::Transaction::OnAddToEntryTimeout,
                      weak_factory_.GetWeakPtr(), entry_lock_waiting_since_),
-          TimeDelta::FromSeconds(kTimeoutSeconds));
+          TimeDelta::FromMilliseconds(timeout_milliseconds));
     }
   }
   return rv;
@@ -1559,15 +1585,6 @@ int HttpCache::Transaction::DoOverwriteCachedResponse() {
     return OK;
   }
 
-  if (handling_206_ && !CanResume(false)) {
-    // There is no point in storing this resource because it will never be used.
-    DoneWritingToEntry(false);
-    if (partial_.get())
-      partial_->FixResponseHeaders(response_.headers.get(), true);
-    next_state_ = STATE_PARTIAL_HEADERS_RECEIVED;
-    return OK;
-  }
-
   target_state_ = STATE_TRUNCATE_CACHED_DATA;
   next_state_ = truncated_ ? STATE_CACHE_WRITE_TRUNCATED_RESPONSE :
                              STATE_CACHE_WRITE_RESPONSE;
@@ -2220,6 +2237,22 @@ int HttpCache::Transaction::BeginExternallyConditionalizedRequest() {
     }
   }
 
+  // TODO(ricea): This calculation is expensive to perform just to collect
+  // statistics. Either remove it or use the result, depending on the result of
+  // the experiment.
+  ExternallyConditionalizedType type =
+      EXTERNALLY_CONDITIONALIZED_CACHE_USABLE;
+  if (mode_ == NONE)
+    type = EXTERNALLY_CONDITIONALIZED_MISMATCHED_VALIDATORS;
+  else if (RequiresValidation())
+    type = EXTERNALLY_CONDITIONALIZED_CACHE_REQUIRES_VALIDATION;
+
+  // TODO(ricea): Add CACHE_USABLE_STALE once stale-while-revalidate CL landed.
+  // TODO(ricea): Either remove this histogram or make it permanent by M40.
+  UMA_HISTOGRAM_ENUMERATION("HttpCache.ExternallyConditionalized",
+                            type,
+                            EXTERNALLY_CONDITIONALIZED_MAX);
+
   next_state_ = STATE_SEND_REQUEST;
   return OK;
 }
@@ -2307,9 +2340,10 @@ bool HttpCache::Transaction::ConditionalizeRequest() {
     return false;
   }
 
-  // We should have handled this case before.
-  DCHECK(response_.headers->response_code() != 206 ||
-         response_.headers->HasStrongValidators());
+  if (response_.headers->response_code() == 206 &&
+      !response_.headers->HasStrongValidators()) {
+    return false;
+  }
 
   // Just use the first available ETag and/or Last-Modified header value.
   // TODO(darin): Or should we use the last?