Referrer policy should be inherited from creator
authordbates@webkit.org <dbates@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 19 Oct 2017 18:46:22 +0000 (18:46 +0000)
committerdbates@webkit.org <dbates@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 19 Oct 2017 18:46:22 +0000 (18:46 +0000)
https://bugs.webkit.org/show_bug.cgi?id=178403
<rdar://problem/31546136>

Reviewed by Andy Estes.

Source/WebCore:

As per section Browsing contexts of the the HTML standard, <https://html.spec.whatwg.org/multipage/browsers.html>
(17 October 2017), the referrer policy of a document should initially be inherited from its
creator.

Tests: http/tests/security/referrer-policy-nested-subframe.html
       http/tests/security/referrer-policy-nested-window-open.html
       http/tests/security/referrer-policy-subframe-window-open.html
       http/tests/security/referrer-policy-window-open-subframe.html

* dom/Document.cpp:
(WebCore::Document::initSecurityContext): Ask the loader for the effective referrer policy.
* loader/FrameLoader.cpp:
(WebCore::FrameLoader::effectiveReferrerPolicy const): Added. Returns the referrer policy
of the creator document. The creator document is document of the parent frame or the document
of the opener for a subframe or child window, respectively. If we do not have a creator frame
then we return the default referrer policy, non-referrer-when-downgrade, by <https://www.w3.org/TR/2017/CR-referrer-policy-20170126/#referrer-policy-empty-string>.
* loader/FrameLoader.h:

LayoutTests:

Add tests to ensure that the referrer policy of a document is initially inherited from its creator.

* http/tests/security/referrer-policy-nested-subframe-expected.txt: Added.
* http/tests/security/referrer-policy-nested-subframe.html: Added.
* http/tests/security/referrer-policy-nested-window-open-expected.txt: Added.
* http/tests/security/referrer-policy-nested-window-open.html: Added.
* http/tests/security/referrer-policy-subframe-window-open-expected.txt: Added.
* http/tests/security/referrer-policy-subframe-window-open.html: Added.
* http/tests/security/referrer-policy-window-open-subframe-expected.txt: Added.
* http/tests/security/referrer-policy-window-open-subframe.html: Added.
* http/tests/security/resources/referrer-policy-postmessage.php:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@223697 268f45cc-cd09-0410-ab3c-d52691b4dbfc

14 files changed:
LayoutTests/ChangeLog
LayoutTests/http/tests/security/referrer-policy-nested-subframe-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/security/referrer-policy-nested-subframe.html [new file with mode: 0644]
LayoutTests/http/tests/security/referrer-policy-nested-window-open-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/security/referrer-policy-nested-window-open.html [new file with mode: 0644]
LayoutTests/http/tests/security/referrer-policy-subframe-window-open-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/security/referrer-policy-subframe-window-open.html [new file with mode: 0644]
LayoutTests/http/tests/security/referrer-policy-window-open-subframe-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/security/referrer-policy-window-open-subframe.html [new file with mode: 0644]
LayoutTests/http/tests/security/resources/referrer-policy-postmessage.php
Source/WebCore/ChangeLog
Source/WebCore/dom/Document.cpp
Source/WebCore/loader/FrameLoader.cpp
Source/WebCore/loader/FrameLoader.h

index 040da04..568495c 100644 (file)
@@ -1,3 +1,23 @@
+2017-10-19  Daniel Bates  <dabates@apple.com>
+
+        Referrer policy should be inherited from creator
+        https://bugs.webkit.org/show_bug.cgi?id=178403
+        <rdar://problem/31546136>
+
+        Reviewed by Andy Estes.
+
+        Add tests to ensure that the referrer policy of a document is initially inherited from its creator.
+
+        * http/tests/security/referrer-policy-nested-subframe-expected.txt: Added.
+        * http/tests/security/referrer-policy-nested-subframe.html: Added.
+        * http/tests/security/referrer-policy-nested-window-open-expected.txt: Added.
+        * http/tests/security/referrer-policy-nested-window-open.html: Added.
+        * http/tests/security/referrer-policy-subframe-window-open-expected.txt: Added.
+        * http/tests/security/referrer-policy-subframe-window-open.html: Added.
+        * http/tests/security/referrer-policy-window-open-subframe-expected.txt: Added.
+        * http/tests/security/referrer-policy-window-open-subframe.html: Added.
+        * http/tests/security/resources/referrer-policy-postmessage.php:
+
 2017-10-19  Chris Dumez  <cdumez@apple.com>
 
         Unreviewed, revert r223650 as it caused crashes on the bots.
diff --git a/LayoutTests/http/tests/security/referrer-policy-nested-subframe-expected.txt b/LayoutTests/http/tests/security/referrer-policy-nested-subframe-expected.txt
new file mode 100644 (file)
index 0000000..6579b30
--- /dev/null
@@ -0,0 +1,5 @@
+This test embeds a subframe that embeds a subframe. It passes, if the referrer is the origin only.
+
+HTTP Referer header is http://127.0.0.1:8000/
+Referrer is http://127.0.0.1:8000/
+
diff --git a/LayoutTests/http/tests/security/referrer-policy-nested-subframe.html b/LayoutTests/http/tests/security/referrer-policy-nested-subframe.html
new file mode 100644 (file)
index 0000000..082ba2c
--- /dev/null
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta name="referrer" content="origin">
+<script>
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.waitUntilDone();
+}
+
+function receiveMessage(messageEvent) {
+    if (messageEvent.data === "done") {
+        if (window.testRunner)
+            testRunner.notifyDone();
+    } else if (messageEvent.data === "ready")
+        document.getElementById("target").contentWindow.postMessage("new-subframe", "*");
+    else
+        document.getElementById("log").innerHTML += messageEvent.data + "<br>";
+}
+
+window.addEventListener("message", receiveMessage, false);
+</script>
+</head>
+<body>
+<p>This test embeds a subframe that embeds a subframe. It passes, if the referrer is the origin only.</p>
+<div id="log"></div>
+<iframe id="target" src="resources/nested-referrer-policy-postmessage.html"></iframe>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/security/referrer-policy-nested-window-open-expected.txt b/LayoutTests/http/tests/security/referrer-policy-nested-window-open-expected.txt
new file mode 100644 (file)
index 0000000..562a353
--- /dev/null
@@ -0,0 +1,5 @@
+This test opens a new window that opens a new window. It passes, if the referrer is the origin only.
+
+HTTP Referer header is http://127.0.0.1:8000/
+Referrer is http://127.0.0.1:8000/
+
diff --git a/LayoutTests/http/tests/security/referrer-policy-nested-window-open.html b/LayoutTests/http/tests/security/referrer-policy-nested-window-open.html
new file mode 100644 (file)
index 0000000..e7feaa6
--- /dev/null
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta name="referrer" content="origin">
+<script>
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.waitUntilDone();
+    testRunner.setCanOpenWindows();
+}
+
+function receiveMessage(messageEvent) {
+    if (messageEvent.data === "done") {
+        if (window.testRunner)
+            testRunner.notifyDone();
+    } else if (messageEvent.data === "ready")
+        target.postMessage("new-window", "*");
+    else
+        document.getElementById("log").innerHTML += messageEvent.data + "<br>";
+}
+
+window.addEventListener("message", receiveMessage, false);
+</script>
+</head>
+<body>
+<p>This test opens a new window that opens a new window. It passes, if the referrer is the origin only.</p>
+<div id="log"></div>
+<script>
+var target = window.open("resources/nested-referrer-policy-postmessage.html");
+</script>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/security/referrer-policy-subframe-window-open-expected.txt b/LayoutTests/http/tests/security/referrer-policy-subframe-window-open-expected.txt
new file mode 100644 (file)
index 0000000..80123a6
--- /dev/null
@@ -0,0 +1,5 @@
+This test embeds a subframe that opens a new window. It passes, if the referrer is the origin only.
+
+HTTP Referer header is http://127.0.0.1:8000/
+Referrer is http://127.0.0.1:8000/
+
diff --git a/LayoutTests/http/tests/security/referrer-policy-subframe-window-open.html b/LayoutTests/http/tests/security/referrer-policy-subframe-window-open.html
new file mode 100644 (file)
index 0000000..a6f3a86
--- /dev/null
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta name="referrer" content="origin">
+<script>
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.waitUntilDone();
+}
+
+function receiveMessage(messageEvent) {
+    if (messageEvent.data === "done") {
+        if (window.testRunner)
+            testRunner.notifyDone();
+    } else if (messageEvent.data === "ready")
+        document.getElementById("target").contentWindow.postMessage("new-window", "*");
+    else
+        document.getElementById("log").innerHTML += messageEvent.data + "<br>";
+}
+
+window.addEventListener("message", receiveMessage, false);
+</script>
+</head>
+<body>
+<p>This test embeds a subframe that opens a new window. It passes, if the referrer is the origin only.</p>
+<div id="log"></div>
+<iframe id="target" src="resources/nested-referrer-policy-postmessage.html"></iframe>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/security/referrer-policy-window-open-subframe-expected.txt b/LayoutTests/http/tests/security/referrer-policy-window-open-subframe-expected.txt
new file mode 100644 (file)
index 0000000..0be7f3c
--- /dev/null
@@ -0,0 +1,5 @@
+This test opens a new window that embeds a subframe. It passes, if the referrer is the origin only.
+
+HTTP Referer header is http://127.0.0.1:8000/
+Referrer is http://127.0.0.1:8000/
+
diff --git a/LayoutTests/http/tests/security/referrer-policy-window-open-subframe.html b/LayoutTests/http/tests/security/referrer-policy-window-open-subframe.html
new file mode 100644 (file)
index 0000000..9d5c721
--- /dev/null
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta name="referrer" content="origin">
+<script>
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.waitUntilDone();
+    testRunner.setCanOpenWindows();
+}
+
+function receiveMessage(messageEvent) {
+    if (messageEvent.data === "done") {
+        if (window.testRunner)
+            testRunner.notifyDone();
+    } else if (messageEvent.data === "ready")
+        target.postMessage("new-subframe", "*");
+    else
+        document.getElementById("log").innerHTML += messageEvent.data + "<br>";
+}
+
+window.addEventListener("message", receiveMessage, false);
+</script>
+</head>
+<body>
+<p>This test opens a new window that embeds a subframe. It passes, if the referrer is the origin only.</p>
+<div id="log"></div>
+<script>
+var target = window.open("resources/nested-referrer-policy-postmessage.html");
+</script>
+</body>
+</html>
index f697a5d..3413851 100644 (file)
@@ -1,11 +1,21 @@
 <html>
 <head>
 <script>
-function log(msg) {
-    window.opener.postMessage(msg, "*");
+function ownerWindow()
+{
+    var owner = window.parent;
+    if (owner === this)
+        owner = window.opener;
+    return owner;
 }
 
-function runTest() {
+function log(message)
+{
+    ownerWindow().postMessage(message, "*");
+}
+
+function runTest()
+{
     var referrerHeader = "<?php echo $_SERVER['HTTP_REFERER'] ?>";
     if (referrerHeader == "")
         log("HTTP Referer header is empty");
index 1eab6bf..b32e641 100644 (file)
@@ -1,3 +1,29 @@
+2017-10-19  Daniel Bates  <dabates@apple.com>
+
+        Referrer policy should be inherited from creator
+        https://bugs.webkit.org/show_bug.cgi?id=178403
+        <rdar://problem/31546136>
+
+        Reviewed by Andy Estes.
+
+        As per section Browsing contexts of the the HTML standard, <https://html.spec.whatwg.org/multipage/browsers.html>
+        (17 October 2017), the referrer policy of a document should initially be inherited from its
+        creator.
+
+        Tests: http/tests/security/referrer-policy-nested-subframe.html
+               http/tests/security/referrer-policy-nested-window-open.html
+               http/tests/security/referrer-policy-subframe-window-open.html
+               http/tests/security/referrer-policy-window-open-subframe.html
+
+        * dom/Document.cpp:
+        (WebCore::Document::initSecurityContext): Ask the loader for the effective referrer policy.
+        * loader/FrameLoader.cpp:
+        (WebCore::FrameLoader::effectiveReferrerPolicy const): Added. Returns the referrer policy
+        of the creator document. The creator document is document of the parent frame or the document
+        of the opener for a subframe or child window, respectively. If we do not have a creator frame
+        then we return the default referrer policy, non-referrer-when-downgrade, by <https://www.w3.org/TR/2017/CR-referrer-policy-20170126/#referrer-policy-empty-string>.
+        * loader/FrameLoader.h:
+
 2017-10-19  Zalan Bujtas  <zalan@apple.com>
 
         [FrameView::layout cleanup] Do not reenter FrameView::performPostLayoutTasks
index 1cd443c..d52d591 100644 (file)
@@ -5365,6 +5365,7 @@ void Document::initSecurityContext()
     // loading URL with a fresh content security policy.
     setCookieURL(m_url);
     enforceSandboxFlags(m_frame->loader().effectiveSandboxFlags());
+    setReferrerPolicy(m_frame->loader().effectiveReferrerPolicy());
 
     if (shouldEnforceContentDispositionAttachmentSandbox())
         applyContentDispositionAttachmentSandbox();
index 8392f96..3236243 100644 (file)
@@ -3553,6 +3553,15 @@ RetainPtr<CFDictionaryRef> FrameLoader::connectionProperties(ResourceLoader* loa
 }
 #endif
 
+ReferrerPolicy FrameLoader::effectiveReferrerPolicy() const
+{
+    if (auto* parentFrame = m_frame.tree().parent())
+        return parentFrame->document()->referrerPolicy();
+    if (m_opener)
+        return m_opener->document()->referrerPolicy();
+    return ReferrerPolicy::NoReferrerWhenDowngrade;
+}
+
 String FrameLoader::referrer() const
 {
     return m_documentLoader ? m_documentLoader->request().httpReferrer() : emptyString();
index 64ece0d..c5f69e3 100644 (file)
@@ -36,6 +36,7 @@
 #include "FrameLoaderTypes.h"
 #include "LayoutMilestones.h"
 #include "MixedContentChecker.h"
+#include "ReferrerPolicy.h"
 #include "ResourceLoadNotifier.h"
 #include "ResourceLoaderOptions.h"
 #include "ResourceRequestBase.h"
@@ -147,6 +148,8 @@ public:
     WEBCORE_EXPORT bool frameHasLoaded() const;
 
     WEBCORE_EXPORT int numPendingOrLoadingRequests(bool recurse) const;
+
+    ReferrerPolicy effectiveReferrerPolicy() const;
     String referrer() const;
     WEBCORE_EXPORT String outgoingReferrer() const;
     String outgoingOrigin() const;