Use document referrer policy when preloading

Previously, preload requests used the referrer policy from meta tags
encountered during scanning, but not from headers delivered with the
page. This CL uses the document's current referrer policy when the
preload scan starts.

BUG=605451

Review-Url: https://codereview.chromium.org/1913983002
Cr-Commit-Position: refs/heads/master@{#390264}
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/referrer-from-document-on-preload-expected.html b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/referrer-from-document-on-preload-expected.html
new file mode 100644
index 0000000..d2fd832
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/referrer-from-document-on-preload-expected.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<html>
+<head>
+</head>
+<body>
+    <img src="/security/resources/green250x50.png" />
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/referrer-from-document-on-preload.php b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/referrer-from-document-on-preload.php
new file mode 100644
index 0000000..a8a89cc
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/referrer-from-document-on-preload.php
@@ -0,0 +1,8 @@
+<?php
+header("Content-Security-Policy: referrer origin-when-cross-origin");
+?>
+<html>
+<head>
+</head>
+<img src="http://localhost:8000/security/resources/green-if-referrer-is-origin.php" />
+</html>
\ No newline at end of file
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.cpp b/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.cpp
index d4734de6..01b52462 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.cpp
+++ b/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.cpp
@@ -484,6 +484,7 @@
 {
     ASSERT(m_documentParameters.get());
     ASSERT(m_mediaValues.get());
+    m_cssScanner.setReferrerPolicy(m_documentParameters->referrerPolicy);
 }
 
 TokenPreloadScanner::~TokenPreloadScanner()
@@ -541,8 +542,9 @@
 
 static void handleMetaReferrer(const String& attributeValue, CachedDocumentParameters* documentParameters, CSSPreloadScanner* cssScanner)
 {
-    if (attributeValue.isEmpty() || attributeValue.isNull() || !SecurityPolicy::referrerPolicyFromString(attributeValue, &documentParameters->referrerPolicy)) {
-        documentParameters->referrerPolicy = ReferrerPolicyDefault;
+    ReferrerPolicy metaReferrerPolicy = ReferrerPolicyDefault;
+    if (!attributeValue.isEmpty() && !attributeValue.isNull() && SecurityPolicy::referrerPolicyFromString(attributeValue, &metaReferrerPolicy)) {
+        documentParameters->referrerPolicy = metaReferrerPolicy;
     }
     cssScanner->setReferrerPolicy(documentParameters->referrerPolicy);
 }
@@ -799,7 +801,7 @@
     defaultViewportMinWidth = document->viewportDefaultMinWidth();
     viewportMetaZeroValuesQuirk = document->settings() && document->settings()->viewportMetaZeroValuesQuirk();
     viewportMetaEnabled = document->settings() && document->settings()->viewportMetaEnabled();
-    referrerPolicy = ReferrerPolicyDefault;
+    referrerPolicy = document->getReferrerPolicy();
 }
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLPreloadScannerTest.cpp b/third_party/WebKit/Source/core/html/parser/HTMLPreloadScannerTest.cpp
index dda2b79a..a026cf2 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLPreloadScannerTest.cpp
+++ b/third_party/WebKit/Source/core/html/parser/HTMLPreloadScannerTest.cpp
@@ -123,13 +123,14 @@
         return data;
     }
 
-    void runSetUp(ViewportState viewportState, PreloadState preloadState = PreloadEnabled)
+    void runSetUp(ViewportState viewportState, PreloadState preloadState = PreloadEnabled, ReferrerPolicy documentReferrerPolicy = ReferrerPolicyDefault)
     {
         HTMLParserOptions options(&m_dummyPageHolder->document());
         KURL documentURL(ParsedURLString, "http://whatever.test/");
         m_dummyPageHolder->document().settings()->setViewportEnabled(viewportState == ViewportEnabled);
         m_dummyPageHolder->document().settings()->setViewportMetaEnabled(viewportState == ViewportEnabled);
         m_dummyPageHolder->document().settings()->setDoHtmlPreloadScanning(preloadState == PreloadEnabled);
+        m_dummyPageHolder->document().setReferrerPolicy(documentReferrerPolicy);
         m_scanner = HTMLPreloadScanner::create(options, documentURL, CachedDocumentParameters::create(&m_dummyPageHolder->document()), createMediaValuesData());
     }
 
@@ -362,6 +363,28 @@
         test(testCase);
 }
 
+// Tests that a document-level referrer policy (e.g. one set by HTTP
+// header) is applied for preload requests.
+TEST_F(HTMLPreloadScannerTest, testReferrerPolicyOnDocument)
+{
+    runSetUp(ViewportEnabled, PreloadEnabled, ReferrerPolicyOrigin);
+    ReferrerPolicyTestCase testCases[] = {
+        { "http://example.test", "<img src='blah.gif'/>", "blah.gif", "http://example.test/", Resource::Image, 0, ReferrerPolicyOrigin },
+        { "http://example.test", "<style>@import url('blah.css');</style>", "blah.css", "http://example.test/", Resource::CSSStyleSheet, 0, ReferrerPolicyOrigin },
+        // Tests that a meta-delivered referrer policy with an
+        // unrecognized policy value does not override the document's
+        // referrer policy.
+        { "http://example.test", "<meta name='referrer' content='not-a-valid-policy'><img src='bla.gif'/>", "bla.gif", "http://example.test/", Resource::Image, 0, ReferrerPolicyOrigin },
+        // Tests that a meta-delivered referrer policy with a
+        // valid policy value does override the document's
+        // referrer policy.
+        { "http://example.test", "<meta name='referrer' content='unsafe-url'><img src='bla.gif'/>", "bla.gif", "http://example.test/", Resource::Image, 0, ReferrerPolicyAlways },
+    };
+
+    for (const auto& testCase : testCases)
+        test(testCase);
+}
+
 TEST_F(HTMLPreloadScannerTest, testLinkRelPreload)
 {
     TestCase testCases[] = {