Resource Timing: Use original Timing-Allow-Origin for cache validating

For 304 responses, we need to check the Timing-Allow-Origin header of the
original response. Even though we keep the original response during
revalidation, it isn't available at the time passesTimingAllowCheck() evaluates
the final response. This CL makes ResourceTimingInfo keep the original value
of the Timing-Allow-Origin header so that passesTimingAllowCheck() can
refer the original value.

BUG=368966

Review URL: https://codereview.chromium.org/271083002

git-svn-id: svn://svn.chromium.org/blink/trunk@173813 bbb929c8-8fbe-4397-9dbb-9b2b20218538
diff --git a/LayoutTests/http/tests/css/resource-timing-details-for-revalidation-expected.txt b/LayoutTests/http/tests/css/resource-timing-details-for-revalidation-expected.txt
new file mode 100644
index 0000000..ef43990
--- /dev/null
+++ b/LayoutTests/http/tests/css/resource-timing-details-for-revalidation-expected.txt
@@ -0,0 +1,6 @@
+PASS successfullyParsed is true
+
+TEST COMPLETE
+PASS entry.domainLookupStart > 0 is true
+This fetches ahem font.
+
diff --git a/LayoutTests/http/tests/css/resource-timing-details-for-revalidation.html b/LayoutTests/http/tests/css/resource-timing-details-for-revalidation.html
new file mode 100644
index 0000000..7951903
--- /dev/null
+++ b/LayoutTests/http/tests/css/resource-timing-details-for-revalidation.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<script src="/js-test-resources/js-test.js"></script>
+<style>
+@font-face {
+    font-family: ahem;
+    src: url(http://localhost:8080/css/resources/cors-ahem.php);
+}
+</style>
+
+<div style="font-family: ahem;">This fetches ahem font.<div>
+
+<script>
+if (window.testRunner)
+    testRunner.waitUntilDone();
+
+var entry;
+if (location.hash == '#check') {
+    document.fonts.ready().then(function() {
+        entry = performance.getEntriesByName('http://localhost:8080/css/resources/cors-ahem.php')[0];
+        shouldBeTrue('entry.domainLookupStart > 0');
+        if (window.testRunner)
+            testRunner.notifyDone();
+    });
+} else {
+    document.fonts.ready().then(function() {
+        location.hash = 'check';
+        location.reload();
+    });
+}
+</script>
diff --git a/LayoutTests/http/tests/css/resources/cors-ahem.php b/LayoutTests/http/tests/css/resources/cors-ahem.php
new file mode 100644
index 0000000..a18850e
--- /dev/null
+++ b/LayoutTests/http/tests/css/resources/cors-ahem.php
@@ -0,0 +1,19 @@
+<?php
+
+if (isset($_SERVER["HTTP_IF_MODIFIED_SINCE"])) {
+    header("HTTP/1.1 304 Not Modified");
+} else {
+    $font = "../../../../resources/Ahem.ttf";
+
+    header("Cache-Control: public, max-age=86400");
+    header('Last-Modified: ' . gmdate("D, d M Y H:i:s", filemtime($font)) . " GMT");
+    header("Content-Type: font/truetype");
+    header("Content-Length: " . filesize($font));
+    header("Access-Control-Allow-Origin: *");
+    header("Timing-Allow-Origin: *");
+    ob_clean();
+    flush();
+    readfile($font);
+}
+
+?>
diff --git a/Source/core/fetch/ResourceFetcher.cpp b/Source/core/fetch/ResourceFetcher.cpp
index 9848632..f2a2eb2 100644
--- a/Source/core/fetch/ResourceFetcher.cpp
+++ b/Source/core/fetch/ResourceFetcher.cpp
@@ -872,6 +872,12 @@
 
     RefPtr<ResourceTimingInfo> info = ResourceTimingInfo::create(resource->options().initiatorInfo.name, monotonicallyIncreasingTime());
 
+    if (resource->isCacheValidator()) {
+        const AtomicString& timingAllowOrigin = resource->resourceToRevalidate()->response().httpHeaderField("Timing-Allow-Origin");
+        if (!timingAllowOrigin.isEmpty())
+            info->setOriginalTimingAllowOrigin(timingAllowOrigin);
+    }
+
     if (resource->type() == Resource::MainResource) {
         // <iframe>s should report the initial navigation requested by the parent document, but not subsequent navigations.
         if (frame()->ownerElement() && !frame()->ownerElement()->loadedNonEmptyDocument()) {
diff --git a/Source/core/timing/Performance.cpp b/Source/core/timing/Performance.cpp
index e2e0928..66601ed 100644
--- a/Source/core/timing/Performance.cpp
+++ b/Source/core/timing/Performance.cpp
@@ -157,7 +157,7 @@
         dispatchEvent(Event::create(EventTypeNames::webkitresourcetimingbufferfull));
 }
 
-static bool passesTimingAllowCheck(const ResourceResponse& response, Document* requestingDocument)
+static bool passesTimingAllowCheck(const ResourceResponse& response, Document* requestingDocument, const AtomicString& originalTimingAllowOrigin)
 {
     AtomicallyInitializedStatic(AtomicString&, timingAllowOrigin = *new AtomicString("timing-allow-origin"));
 
@@ -165,7 +165,7 @@
     if (resourceOrigin->isSameSchemeHostPort(requestingDocument->securityOrigin()))
         return true;
 
-    const AtomicString& timingAllowOriginString = response.httpHeaderField(timingAllowOrigin);
+    const AtomicString& timingAllowOriginString = originalTimingAllowOrigin.isEmpty() ? response.httpHeaderField(timingAllowOrigin) : originalTimingAllowOrigin;
     if (timingAllowOriginString.isEmpty() || equalIgnoringCase(timingAllowOriginString, "null"))
         return false;
 
@@ -185,11 +185,11 @@
 
 static bool allowsTimingRedirect(const Vector<ResourceResponse>& redirectChain, const ResourceResponse& finalResponse, Document* initiatorDocument)
 {
-    if (!passesTimingAllowCheck(finalResponse, initiatorDocument))
+    if (!passesTimingAllowCheck(finalResponse, initiatorDocument, emptyAtom))
         return false;
 
     for (size_t i = 0; i < redirectChain.size(); i++) {
-        if (!passesTimingAllowCheck(redirectChain[i], initiatorDocument))
+        if (!passesTimingAllowCheck(redirectChain[i], initiatorDocument, emptyAtom))
             return false;
     }
 
@@ -202,7 +202,7 @@
         return;
 
     const ResourceResponse& finalResponse = info.finalResponse();
-    bool allowTimingDetails = passesTimingAllowCheck(finalResponse, initiatorDocument);
+    bool allowTimingDetails = passesTimingAllowCheck(finalResponse, initiatorDocument, info.originalTimingAllowOrigin());
     double startTime = info.initialTime();
 
     if (info.redirectChain().isEmpty()) {
diff --git a/Source/core/timing/ResourceTimingInfo.h b/Source/core/timing/ResourceTimingInfo.h
index ef3f42d..ff8094e 100644
--- a/Source/core/timing/ResourceTimingInfo.h
+++ b/Source/core/timing/ResourceTimingInfo.h
@@ -49,6 +49,9 @@
     void setInitiatorType(const AtomicString& type) { m_type = type; }
     const AtomicString& initiatorType() const { return m_type; }
 
+    void setOriginalTimingAllowOrigin(const AtomicString& originalTimingAllowOrigin) { m_originalTimingAllowOrigin = originalTimingAllowOrigin; }
+    const AtomicString& originalTimingAllowOrigin() const { return m_originalTimingAllowOrigin; }
+
     void setLoadFinishTime(double time) { m_loadFinishTime = time; }
     double loadFinishTime() const { return m_loadFinishTime; }
 
@@ -76,6 +79,7 @@
     }
 
     AtomicString m_type;
+    AtomicString m_originalTimingAllowOrigin;
     double m_initialTime;
     double m_loadFinishTime;
     ResourceRequest m_initialRequest;