Bug 1143894 - Part 2: Support Vary headers including multiple header names in DOM Cache; r=bkelly
authorEhsan Akhgari <ehsan@mozilla.com>
Tue, 17 Mar 2015 10:30:30 -0400
changeset 265256 3ea234420460f0e87a05df0bf4ff2e36b5b03442
parent 265255 958151e0cfd26a957c61b120cbae9ab1513ece7c
child 265257 edf516516fb35eb9811e7655251eeb90d244cfb1
push id830
push userraliiev@mozilla.com
push dateFri, 19 Jun 2015 19:24:37 +0000
treeherdermozilla-release@932614382a68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbkelly
bugs1143894
milestone39.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1143894 - Part 2: Support Vary headers including multiple header names in DOM Cache; r=bkelly The Vary header may include one or more HTTP header field names, so we need to extract those names here, similar to the way that the nsHttpChannel::ResponseWouldVary() function consumes the Vary header.
dom/cache/DBSchema.cpp
dom/cache/FetchPut.cpp
--- a/dom/cache/DBSchema.cpp
+++ b/dom/cache/DBSchema.cpp
@@ -9,16 +9,18 @@
 #include "ipc/IPCMessageUtils.h"
 #include "mozilla/dom/InternalHeaders.h"
 #include "mozilla/dom/cache/PCacheTypes.h"
 #include "mozilla/dom/cache/SavedTypes.h"
 #include "mozIStorageConnection.h"
 #include "mozIStorageStatement.h"
 #include "nsCOMPtr.h"
 #include "nsTArray.h"
+#include "nsCRT.h"
+#include "nsHttp.h"
 
 namespace mozilla {
 namespace dom {
 namespace cache {
 
 
 const int32_t DBSchema::kMaxWipeSchemaVersion = 3;
 const int32_t DBSchema::kLatestSchemaVersion = 3;
@@ -810,36 +812,50 @@ DBSchema::MatchByVaryHeader(mozIStorageC
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
   nsRefPtr<InternalHeaders> queryHeaders = new InternalHeaders(aRequest.headers());
 
   // Assume the vary headers match until we find a conflict
   bool varyHeadersMatch = true;
 
   for (uint32_t i = 0; i < varyValues.Length(); ++i) {
-    if (varyValues[i].EqualsLiteral("*")) {
-      continue;
+    // Extract the header names inside the Vary header value.
+    nsAutoCString varyValue(varyValues[i]);
+    char* rawBuffer = varyValue.BeginWriting();
+    char* token = nsCRT::strtok(rawBuffer, NS_HTTP_HEADER_SEPS, &rawBuffer);
+    bool bailOut = false;
+    for (; token;
+         token = nsCRT::strtok(rawBuffer, NS_HTTP_HEADER_SEPS, &rawBuffer)) {
+      nsDependentCString header(token);
+      if (header.EqualsLiteral("*")) {
+        continue;
+      }
+
+      nsAutoCString queryValue;
+      queryHeaders->Get(header, queryValue, errorResult);
+      if (errorResult.Failed()) {
+        errorResult.ClearMessage();
+        return errorResult.ErrorCode();
+      }
+
+      nsAutoCString cachedValue;
+      cachedHeaders->Get(header, cachedValue, errorResult);
+      if (errorResult.Failed()) {
+        errorResult.ClearMessage();
+        return errorResult.ErrorCode();
+      }
+
+      if (queryValue != cachedValue) {
+        varyHeadersMatch = false;
+        bailOut = true;
+        break;
+      }
     }
 
-    nsAutoCString queryValue;
-    queryHeaders->Get(varyValues[i], queryValue, errorResult);
-    if (errorResult.Failed()) {
-      errorResult.ClearMessage();
-      return errorResult.ErrorCode();
-    }
-
-    nsAutoCString cachedValue;
-    cachedHeaders->Get(varyValues[i], cachedValue, errorResult);
-    if (errorResult.Failed()) {
-      errorResult.ClearMessage();
-      return errorResult.ErrorCode();
-    }
-
-    if (queryValue != cachedValue) {
-      varyHeadersMatch = false;
+    if (bailOut) {
       break;
     }
   }
 
   *aSuccessOut = varyHeadersMatch;
   return rv;
 }
 
--- a/dom/cache/FetchPut.cpp
+++ b/dom/cache/FetchPut.cpp
@@ -15,16 +15,18 @@
 #include "mozilla/dom/Response.h"
 #include "mozilla/dom/ResponseBinding.h"
 #include "mozilla/dom/UnionTypes.h"
 #include "mozilla/dom/cache/ManagerId.h"
 #include "mozilla/dom/cache/PCacheTypes.h"
 #include "nsContentUtils.h"
 #include "nsNetUtil.h"
 #include "nsThreadUtils.h"
+#include "nsCRT.h"
+#include "nsHttp.h"
 
 namespace mozilla {
 namespace dom {
 namespace cache {
 
 class FetchPut::Runnable final : public nsRunnable
 {
 public:
@@ -362,41 +364,57 @@ FetchPut::MatchInPutList(const PCacheReq
     ErrorResult rv;
     cachedResponseHeaders->GetAll(NS_LITERAL_CSTRING("vary"), varyHeaders, rv);
     MOZ_ALWAYS_TRUE(!rv.Failed());
 
     // Assume the vary headers match until we find a conflict
     bool varyHeadersMatch = true;
 
     for (uint32_t j = 0; j < varyHeaders.Length(); ++j) {
-      if (varyHeaders[i].EqualsLiteral("*")) {
-        continue;
+      // Extract the header names inside the Vary header value.
+      nsAutoCString varyValue(varyHeaders[j]);
+      char* rawBuffer = varyValue.BeginWriting();
+      char* token = nsCRT::strtok(rawBuffer, NS_HTTP_HEADER_SEPS, &rawBuffer);
+      bool bailOut = false;
+      for (; token;
+           token = nsCRT::strtok(rawBuffer, NS_HTTP_HEADER_SEPS, &rawBuffer)) {
+        nsDependentCString header(token);
+        if (header.EqualsLiteral("*")) {
+          continue;
+        }
+
+        // The VARY header could in theory contain an illegal header name.  So
+        // we need to detect the error in the Get() calls below.  Treat these
+        // as not matching.
+        ErrorResult headerRv;
+
+        nsAutoCString value;
+        requestHeaders->Get(header, value, rv);
+        if (NS_WARN_IF(rv.Failed())) {
+          varyHeadersMatch = false;
+          bailOut = true;
+          break;
+        }
+
+        nsAutoCString cachedValue;
+        cachedRequestHeaders->Get(header, value, rv);
+        if (NS_WARN_IF(rv.Failed())) {
+          varyHeadersMatch = false;
+          bailOut = true;
+          break;
+        }
+
+        if (value != cachedValue) {
+          varyHeadersMatch = false;
+          bailOut = true;
+          break;
+        }
       }
 
-      // The VARY header could in theory contain an illegal header name.  So
-      // we need to detect the error in the Get() calls below.  Treat these
-      // as not matching.
-      ErrorResult headerRv;
-
-      nsAutoCString value;
-      requestHeaders->Get(varyHeaders[j], value, rv);
-      if (NS_WARN_IF(rv.Failed())) {
-        varyHeadersMatch = false;
-        break;
-      }
-
-      nsAutoCString cachedValue;
-      cachedRequestHeaders->Get(varyHeaders[j], value, rv);
-      if (NS_WARN_IF(rv.Failed())) {
-        varyHeadersMatch = false;
-        break;
-      }
-
-      if (value != cachedValue) {
-        varyHeadersMatch = false;
+      if (bailOut) {
         break;
       }
     }
 
     // URL was equal and all vary headers match!
     if (varyHeadersMatch) {
       return true;
     }