Restrict browsing context lookup by name to frames that are related to one another
authorcdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 15 Oct 2018 15:34:39 +0000 (15:34 +0000)
committercdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 15 Oct 2018 15:34:39 +0000 (15:34 +0000)
https://bugs.webkit.org/show_bug.cgi?id=190475

Reviewed by Alex Christensen.

Source/WebCore:

Update our frame lookup by name logic to take in the active / requesting frame and
only a return a frame that is related to it. By related to it, I mean:
- Ancestor <-> Descendant relationship
- Opener <-> Openee relationship

Being able to look up unrelated frames makes process swapping difficult so we need
to be stricter.

This change is being discussed at:
- https://github.com/whatwg/html/issues/313

Tests: http/tests/dom/new-window-can-target-opener.html
       http/tests/dom/noopener-window-cannot-target-opener.html
       http/tests/dom/noopener-window-not-targetable.html
       http/tests/dom/noopener-window-not-targetable2.html
       http/tests/dom/noreferrer-window-not-targetable.html
       http/tests/dom/opened-window-not-targetable-after-disowning-opener.html

* loader/FrameLoader.cpp:
(WebCore::FrameLoader::findFrameForNavigation):
* page/FrameTree.cpp:
(WebCore::isFrameFamiliarWith):
(WebCore::FrameTree::find const):
* page/FrameTree.h:
* rendering/HitTestResult.cpp:
(WebCore::HitTestResult::targetFrame const):

Source/WebKit:

* WebProcess/Plugins/PluginView.cpp:
(WebKit::PluginView::performJavaScriptURLRequest):

Source/WebKitLegacy/mac:

* WebView/WebFrame.mm:
(-[WebFrame findFrameNamed:]):

LayoutTests:

* http/tests/dom/new-window-can-target-opener-expected.txt: Added.
* http/tests/dom/new-window-can-target-opener.html: Added.
* http/tests/dom/noopener-window-cannot-target-opener-expected.txt: Added.
* http/tests/dom/noopener-window-cannot-target-opener.html: Added.
* http/tests/dom/noopener-window-not-targetable-expected.txt: Added.
* http/tests/dom/noopener-window-not-targetable.html: Added.
* http/tests/dom/noopener-window-not-targetable2-expected.txt: Added.
* http/tests/dom/noopener-window-not-targetable2.html: Added.
* http/tests/dom/noreferrer-window-not-targetable-expected.txt: Added.
* http/tests/dom/noreferrer-window-not-targetable.html: Added.
* http/tests/dom/opened-window-not-targetable-after-disowning-opener-expected.txt: Added.
* http/tests/dom/opened-window-not-targetable-after-disowning-opener.html: Added.
* http/tests/dom/resources/new-window-can-target-opener-win.html: Added.
* http/tests/dom/resources/noopener-window-cannot-target-opener-win.html: Added.
Add layout test coverage.

* fast/dom/Window/a-rel-noopener-expected.txt:
* fast/dom/Window/area-rel-noopener-expected.txt:
* fast/dom/Window/resources/rel-noopener.js:
* http/tests/navigation/no-referrer-target-blank-expected.txt:
* http/tests/navigation/resources/no-referrer-helper.php:
* platform/mac-wk1/imported/w3c/web-platform-tests/html/browsers/windows/noreferrer-window-name-expected.txt:
* platform/wk2/imported/w3c/web-platform-tests/html/browsers/windows/noreferrer-window-name-expected.txt:
Update / rebaseline existing tests to reflect behavior change.

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

34 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/dom/Window/a-rel-noopener-expected.txt
LayoutTests/fast/dom/Window/area-rel-noopener-expected.txt
LayoutTests/fast/dom/Window/resources/rel-noopener.js
LayoutTests/http/tests/dom/new-window-can-target-opener-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/dom/new-window-can-target-opener.html [new file with mode: 0644]
LayoutTests/http/tests/dom/noopener-window-cannot-target-opener-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/dom/noopener-window-cannot-target-opener.html [new file with mode: 0644]
LayoutTests/http/tests/dom/noopener-window-not-targetable-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/dom/noopener-window-not-targetable.html [new file with mode: 0644]
LayoutTests/http/tests/dom/noopener-window-not-targetable2-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/dom/noopener-window-not-targetable2.html [new file with mode: 0644]
LayoutTests/http/tests/dom/noreferrer-window-not-targetable-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/dom/noreferrer-window-not-targetable.html [new file with mode: 0644]
LayoutTests/http/tests/dom/opened-window-not-targetable-after-disowning-opener-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/dom/opened-window-not-targetable-after-disowning-opener.html [new file with mode: 0644]
LayoutTests/http/tests/dom/resources/new-window-can-target-opener-win.html [new file with mode: 0644]
LayoutTests/http/tests/dom/resources/noopener-window-cannot-target-opener-win.html [new file with mode: 0644]
LayoutTests/http/tests/navigation/no-referrer-reset-expected.txt
LayoutTests/http/tests/navigation/no-referrer-subframe-expected.txt
LayoutTests/http/tests/navigation/no-referrer-target-blank-expected.txt
LayoutTests/http/tests/navigation/resources/no-referrer-helper.php
LayoutTests/platform/mac-wk1/imported/w3c/web-platform-tests/html/browsers/windows/noreferrer-window-name-expected.txt
LayoutTests/platform/wk2/imported/w3c/web-platform-tests/html/browsers/windows/noreferrer-window-name-expected.txt
Source/WebCore/ChangeLog
Source/WebCore/loader/FrameLoader.cpp
Source/WebCore/page/FrameTree.cpp
Source/WebCore/page/FrameTree.h
Source/WebCore/rendering/HitTestResult.cpp
Source/WebKit/ChangeLog
Source/WebKit/WebProcess/Plugins/PluginView.cpp
Source/WebKitLegacy/mac/ChangeLog
Source/WebKitLegacy/mac/WebView/WebFrame.mm
Source/WebKitLegacy/win/WebFrame.cpp

index ed9c55d..573bf15 100644 (file)
@@ -1,3 +1,35 @@
+2018-10-15  Chris Dumez  <cdumez@apple.com>
+
+        Restrict browsing context lookup by name to frames that are related to one another
+        https://bugs.webkit.org/show_bug.cgi?id=190475
+
+        Reviewed by Alex Christensen.
+
+        * http/tests/dom/new-window-can-target-opener-expected.txt: Added.
+        * http/tests/dom/new-window-can-target-opener.html: Added.
+        * http/tests/dom/noopener-window-cannot-target-opener-expected.txt: Added.
+        * http/tests/dom/noopener-window-cannot-target-opener.html: Added.
+        * http/tests/dom/noopener-window-not-targetable-expected.txt: Added.
+        * http/tests/dom/noopener-window-not-targetable.html: Added.
+        * http/tests/dom/noopener-window-not-targetable2-expected.txt: Added.
+        * http/tests/dom/noopener-window-not-targetable2.html: Added.
+        * http/tests/dom/noreferrer-window-not-targetable-expected.txt: Added.
+        * http/tests/dom/noreferrer-window-not-targetable.html: Added.
+        * http/tests/dom/opened-window-not-targetable-after-disowning-opener-expected.txt: Added.
+        * http/tests/dom/opened-window-not-targetable-after-disowning-opener.html: Added.
+        * http/tests/dom/resources/new-window-can-target-opener-win.html: Added.
+        * http/tests/dom/resources/noopener-window-cannot-target-opener-win.html: Added.
+        Add layout test coverage.
+
+        * fast/dom/Window/a-rel-noopener-expected.txt:
+        * fast/dom/Window/area-rel-noopener-expected.txt:
+        * fast/dom/Window/resources/rel-noopener.js:
+        * http/tests/navigation/no-referrer-target-blank-expected.txt:
+        * http/tests/navigation/resources/no-referrer-helper.php:
+        * platform/mac-wk1/imported/w3c/web-platform-tests/html/browsers/windows/noreferrer-window-name-expected.txt:
+        * platform/wk2/imported/w3c/web-platform-tests/html/browsers/windows/noreferrer-window-name-expected.txt:
+        Update / rebaseline existing tests to reflect behavior change.
+
 2018-10-15  YUHAN WU  <yuhan_wu@apple.com>
 
         Implement error handler of MediaRecorder
index 8e8704a..e135f52 100644 (file)
@@ -1,3 +1,4 @@
+CONSOLE MESSAGE: line 11: PASS: window.opener is null
 Test that window.opener is null when a new window is opened from an anchor element with rel='noopener'.
 
-PASS: window.opener is null
+
index b6ece8b..e6202cd 100644 (file)
@@ -1,4 +1,5 @@
+CONSOLE MESSAGE: line 11: PASS: window.opener is null
 Test that window.opener is null when a new window is opened from an area element with rel='noopener'.
 
 
-PASS: window.opener is null
+
index bb5d46e..b3b59ba 100644 (file)
@@ -5,11 +5,10 @@ if (window.testRunner) {
 }
 
 if (document.location.hash === "#new-window") {
-    var console = window.open("", "originalWindow").document.getElementById("console");
     if (window.opener)
-        console.innerText = "FAIL: window.opener is non-null";
+        console.log("FAIL: window.opener is non-null");
     else
-        console.innerText = "PASS: window.opener is null";
+        console.log("PASS: window.opener is null");
     testRunner.notifyDone();
 } else {
     window.name = "originalWindow";
diff --git a/LayoutTests/http/tests/dom/new-window-can-target-opener-expected.txt b/LayoutTests/http/tests/dom/new-window-can-target-opener-expected.txt
new file mode 100644 (file)
index 0000000..72a8dce
--- /dev/null
@@ -0,0 +1,9 @@
+CONSOLE MESSAGE: line 15: PASS: New window should have an opener
+CONSOLE MESSAGE: line 21: PASS: New window should be able to look up opener by name
+CONSOLE MESSAGE: line 27: PASS: New window should have URL 'http://127.0.0.1:8000/dom/new-window-can-target-opener.html'
+Make sure that windows opened via window.open can target their opener
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+
diff --git a/LayoutTests/http/tests/dom/new-window-can-target-opener.html b/LayoutTests/http/tests/dom/new-window-can-target-opener.html
new file mode 100644 (file)
index 0000000..39f1398
--- /dev/null
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="/js-test-resources/js-test.js"></script>
+</head>
+<body>
+<script>
+description("Make sure that windows opened via window.open can target their opener");
+jsTestIsAsync = true;
+
+if (window.testRunner)
+    testRunner.setCanOpenWindows();    
+onload = function() {
+    window.name = "opener";
+    w = open("resources/new-window-can-target-opener-win.html", "");
+}    
+</script>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/dom/noopener-window-cannot-target-opener-expected.txt b/LayoutTests/http/tests/dom/noopener-window-cannot-target-opener-expected.txt
new file mode 100644 (file)
index 0000000..a23c400
--- /dev/null
@@ -0,0 +1,9 @@
+CONSOLE MESSAGE: line 17: PASS: New window should not have an opener
+CONSOLE MESSAGE: line 21: PASS: New window should have URL 'about:blank'
+Make sure that windows opened with 'noopener' via window.open cannot target their opener.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS w is null
+
diff --git a/LayoutTests/http/tests/dom/noopener-window-cannot-target-opener.html b/LayoutTests/http/tests/dom/noopener-window-cannot-target-opener.html
new file mode 100644 (file)
index 0000000..7d0de75
--- /dev/null
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="/js-test-resources/js-test.js"></script>
+</head>
+<body>
+<script>
+description("Make sure that windows opened with 'noopener' via window.open cannot target their opener.");
+jsTestIsAsync = true;
+
+if (window.testRunner)
+    testRunner.setCanOpenWindows();    
+onload = function() {
+    window.name = "opener";
+    w = open("resources/noopener-window-cannot-target-opener-win.html", "", "noopener");
+    shouldBeNull("w");
+}    
+</script>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/dom/noopener-window-not-targetable-expected.txt b/LayoutTests/http/tests/dom/noopener-window-not-targetable-expected.txt
new file mode 100644 (file)
index 0000000..63d7b07
--- /dev/null
@@ -0,0 +1,11 @@
+Make sure that windows opened with 'noopener' via an anchor are not targetable. If testing manually, you should see 2 tabs open.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS w.location.href is "about:blank"
+PASS testRunner.windowCount() is 3
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/dom/noopener-window-not-targetable.html b/LayoutTests/http/tests/dom/noopener-window-not-targetable.html
new file mode 100644 (file)
index 0000000..34f9c53
--- /dev/null
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="/js-test-resources/js-test.js"></script>
+</head>
+<body>
+<a id="testLink" target="foo" rel="noopener" href="/navigation/resources/otherpage.html"></a>
+<script>
+description("Make sure that windows opened with 'noopener' via an anchor are not targetable. If testing manually, you should see 2 tabs open.");
+jsTestIsAsync = true;
+
+if (window.testRunner)
+    testRunner.setCanOpenWindows();    
+onload = function() {
+    testLink.click();
+
+    setTimeout(function() {
+        w = open("/navigation/resources/otherpage.html", "foo"); // Should create a new window.
+        shouldBeEqualToString("w.location.href", "about:blank");
+        w.onload = function() {
+            if (window.testRunner)
+                shouldBe("testRunner.windowCount()", "3");
+            finishJSTest();
+        }
+    }, 100);
+}    
+</script>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/dom/noopener-window-not-targetable2-expected.txt b/LayoutTests/http/tests/dom/noopener-window-not-targetable2-expected.txt
new file mode 100644 (file)
index 0000000..9cd9761
--- /dev/null
@@ -0,0 +1,12 @@
+Make sure that windows opened with 'noopener' via window.open are not targetable. If testing manually, you should see 2 tabs open.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS w is null
+PASS w.location.href is "about:blank"
+PASS testRunner.windowCount() is 3
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/dom/noopener-window-not-targetable2.html b/LayoutTests/http/tests/dom/noopener-window-not-targetable2.html
new file mode 100644 (file)
index 0000000..d9c019b
--- /dev/null
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="/js-test-resources/js-test.js"></script>
+</head>
+<body>
+<script>
+description("Make sure that windows opened with 'noopener' via window.open are not targetable. If testing manually, you should see 2 tabs open.");
+jsTestIsAsync = true;
+
+if (window.testRunner)
+    testRunner.setCanOpenWindows();    
+
+onload = function() {
+    w = window.open("/navigation/resources/otherpage.html", "foo", "noopener");
+    shouldBeNull("w");
+
+    setTimeout(function() {
+        w = open("/navigation/resources/otherpage.html", "foo"); // Should create a new window.
+        shouldBeEqualToString("w.location.href", "about:blank");
+        w.onload = function() {
+            if (window.testRunner)
+                shouldBe("testRunner.windowCount()", "3");
+            finishJSTest();
+        }
+    }, 100);
+}    
+</script>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/dom/noreferrer-window-not-targetable-expected.txt b/LayoutTests/http/tests/dom/noreferrer-window-not-targetable-expected.txt
new file mode 100644 (file)
index 0000000..9ebeb73
--- /dev/null
@@ -0,0 +1,11 @@
+Make sure that windows opened with 'noreferrer' are not targetable. If testing manually, you should see 2 tabs open.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS w.location.href is "about:blank"
+PASS testRunner.windowCount() is 3
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/dom/noreferrer-window-not-targetable.html b/LayoutTests/http/tests/dom/noreferrer-window-not-targetable.html
new file mode 100644 (file)
index 0000000..842921c
--- /dev/null
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="/js-test-resources/js-test.js"></script>
+</head>
+<body>
+<a id="testLink" target="foo" rel="noreferrer" href="/navigation/resources/otherpage.html"></a>
+<script>
+description("Make sure that windows opened with 'noreferrer' are not targetable. If testing manually, you should see 2 tabs open.");
+jsTestIsAsync = true;
+
+if (window.testRunner)
+    testRunner.setCanOpenWindows();    
+
+onload = function() {
+    testLink.click();
+    setTimeout(function() {
+        w = open("/navigation/resources/otherpage.html", "foo"); // Should create a new window.
+        shouldBeEqualToString("w.location.href", "about:blank");
+        w.onload = function() {
+            if (window.testRunner)
+                shouldBe("testRunner.windowCount()", "3");
+            finishJSTest();
+        }
+    }, 100);
+}    
+</script>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/dom/opened-window-not-targetable-after-disowning-opener-expected.txt b/LayoutTests/http/tests/dom/opened-window-not-targetable-after-disowning-opener-expected.txt
new file mode 100644 (file)
index 0000000..46f5dc4
--- /dev/null
@@ -0,0 +1,11 @@
+Make sure that windows opened via window.open are not targetable by their opener after it is disowned. If testing manually, you should see 2 tabs open.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS w.location.href is "about:blank"
+PASS testRunner.windowCount() is 3
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/dom/opened-window-not-targetable-after-disowning-opener.html b/LayoutTests/http/tests/dom/opened-window-not-targetable-after-disowning-opener.html
new file mode 100644 (file)
index 0000000..84ff71b
--- /dev/null
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="/js-test-resources/js-test.js"></script>
+</head>
+<body>
+<script>
+description("Make sure that windows opened via window.open are not targetable by their opener after it is disowned. If testing manually, you should see 2 tabs open.");
+jsTestIsAsync = true;
+
+if (window.testRunner)
+    testRunner.setCanOpenWindows();    
+
+onload = function() {
+    w = window.open("/navigation/resources/otherpage.html", "foo");
+    w.opener = null;
+
+    setTimeout(function() {
+        w = open("/navigation/resources/otherpage.html", "foo"); // Should create a new window.
+        shouldBeEqualToString("w.location.href", "about:blank");
+        w.onload = function() {
+            if (window.testRunner)
+                shouldBe("testRunner.windowCount()", "3");
+            finishJSTest();
+        }
+    }, 100);
+}    
+</script>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/dom/resources/new-window-can-target-opener-win.html b/LayoutTests/http/tests/dom/resources/new-window-can-target-opener-win.html
new file mode 100644 (file)
index 0000000..8613a48
--- /dev/null
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="/js-test-resources/js-test.js"></script>
+</head>
+<body>
+<script>
+jsTestIsAsync = true;
+
+if (window.testRunner)
+    testRunner.setCanOpenWindows();
+
+onload = function() {
+    if (window.opener)
+        console.log("PASS: New window should have an opener");
+    else
+        console.log("FAIL: New window should have an opener");
+
+    openerByName = open("", "opener"); // Should return the opener.
+    if (openerByName === opener)
+        console.log("PASS: New window should be able to look up opener by name");
+    else
+        console.log("FAIL: New window should be able to look up opener by name");
+
+    const expectedOpenerURL = "http://127.0.0.1:8000/dom/new-window-can-target-opener.html";
+    if (openerByName.location.href == expectedOpenerURL)
+        console.log("PASS: New window should have URL '" + expectedOpenerURL + "'");
+    else
+        console.log("FAIL: New window should have URL '" + expectedOpenerURL + "' but got '" + openerByName.location.href + "'");
+
+    finishJSTest();
+};
+</script>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/dom/resources/noopener-window-cannot-target-opener-win.html b/LayoutTests/http/tests/dom/resources/noopener-window-cannot-target-opener-win.html
new file mode 100644 (file)
index 0000000..cb880ee
--- /dev/null
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="/js-test-resources/js-test.js"></script>
+</head>
+<body>
+<script>
+jsTestIsAsync = true;
+
+if (window.testRunner)
+    testRunner.setCanOpenWindows();
+
+onload = function() {
+    if (window.opener)
+        console.log("FAIL: New window should not have an opener");
+    else
+        console.log("PASS: New window should not have an opener");
+
+    opener = open("", "opener"); // Should open a new window.
+    if (opener.location.href == "about:blank")
+        console.log("PASS: New window should have URL 'about:blank'");
+    else
+        console.log("FAIL: New window should have URL 'about:blank' but got '" + opener.location.href + "'");
+
+    finishJSTest();
+};
+</script>
+</body>
+</html>
index ada1d16..0eb21f7 100644 (file)
@@ -1,3 +1,5 @@
+CONSOLE MESSAGE: line 15: Referrer: http://127.0.0.1:8000/navigation/resources/no-referrer-reset-helper.php
+CONSOLE MESSAGE: line 16: window.opener: http://127.0.0.1:8000/navigation/no-referrer-reset.html
 This tests whether referrer information gets properly set and reset when "noreferrer" links are present. We do the following:
 1. Open a link in a new window: referrer is sent and window.opener is sent.
 2. Click a rel="noreferrer" link: referrer is null, but window.opener remains set since the link was not opened with target="_blank".
@@ -7,5 +9,3 @@ Referrer: http://127.0.0.1:8000/navigation/no-referrer-reset.html
 window.opener: http://127.0.0.1:8000/navigation/no-referrer-reset.html
 Referrer:
 window.opener: http://127.0.0.1:8000/navigation/no-referrer-reset.html
-Referrer: http://127.0.0.1:8000/navigation/resources/no-referrer-reset-helper.php
-window.opener: http://127.0.0.1:8000/navigation/no-referrer-reset.html
index 8f6b790..6b109eb 100644 (file)
@@ -1,4 +1,5 @@
+CONSOLE MESSAGE: line 15: Referrer:
+CONSOLE MESSAGE: line 16: window.opener: 
 This tests behavior of "noreferrer" links in subframes. A referrer should not be sent and window.opener should remain null.
 Load subframe 
-Referrer:
-window.opener:
+
index 5c32e5e..caadabe 100644 (file)
@@ -1,4 +1,5 @@
+CONSOLE MESSAGE: line 15: Referrer:
+CONSOLE MESSAGE: line 16: window.opener: 
 This tests the functionality of the "noreferrer" link relation on anchor tags. The link below should not send an http referrer, and the resulting window should have its opener attribute set to null. The values of the referrer and window.opener should be empty below.
 Start no referrer test
-Referrer:
-window.opener:
+
index fea93dc..5c2abf3 100644 (file)
@@ -18,11 +18,8 @@ function log(msg)
     document.getElementById('console').appendChild(line);
 }
 
-    var consoleWindow = window.open("", "consoleWindow");
-    if (consoleWindow) {
-        consoleWindow.log(document.getElementById("referrer").innerText);
-        consoleWindow.log("window.opener: " + (window.opener ? window.opener.location : ""));
-    }
+    console.log(document.getElementById("referrer").innerText);
+    console.log("window.opener: " + (window.opener ? window.opener.location : ""));
     
     if (window.testRunner)
         testRunner.notifyDone();
index 0b77561..11ede65 100644 (file)
@@ -1,9 +1,3 @@
-CONSOLE MESSAGE: line 37: Unsafe JavaScript attempt to initiate navigation for frame with URL '' from frame with URL 'http://localhost:8800/html/browsers/windows/noreferrer-window-name.html'. The frame attempting navigation is neither same-origin with the target, nor is it the target's parent or opener.
-
-CONSOLE MESSAGE: line 38: Unsafe JavaScript attempt to initiate navigation for frame with URL '' from frame with URL 'http://localhost:8800/html/browsers/windows/noreferrer-window-name.html'. The frame attempting navigation is neither same-origin with the target, nor is it the target's parent or opener.
-
-CONSOLE MESSAGE: line 38: Unsafe JavaScript attempt to initiate navigation for frame with URL '' from frame with URL 'http://localhost:8800/html/browsers/windows/noreferrer-window-name.html'. The frame attempting navigation is neither same-origin with the target, nor is it the target's parent or opener.
-
 
 Harness Error (TIMEOUT), message = null
 
index 067ed0a..cba574f 100644 (file)
@@ -1,5 +1,3 @@
-CONSOLE MESSAGE: Unsafe JavaScript attempt to initiate navigation for frame with URL '' from frame with URL 'http://localhost:8800/html/browsers/windows/noreferrer-window-name.html'. The frame attempting navigation is neither same-origin with the target, nor is it the target's parent or opener.
-
 
 Harness Error (TIMEOUT), message = null
 
index 2945605..10d047a 100644 (file)
@@ -1,3 +1,37 @@
+2018-10-15  Chris Dumez  <cdumez@apple.com>
+
+        Restrict browsing context lookup by name to frames that are related to one another
+        https://bugs.webkit.org/show_bug.cgi?id=190475
+
+        Reviewed by Alex Christensen.
+
+        Update our frame lookup by name logic to take in the active / requesting frame and
+        only a return a frame that is related to it. By related to it, I mean:
+        - Ancestor <-> Descendant relationship
+        - Opener <-> Openee relationship
+
+        Being able to look up unrelated frames makes process swapping difficult so we need
+        to be stricter.
+
+        This change is being discussed at:
+        - https://github.com/whatwg/html/issues/313
+
+        Tests: http/tests/dom/new-window-can-target-opener.html
+               http/tests/dom/noopener-window-cannot-target-opener.html
+               http/tests/dom/noopener-window-not-targetable.html
+               http/tests/dom/noopener-window-not-targetable2.html
+               http/tests/dom/noreferrer-window-not-targetable.html
+               http/tests/dom/opened-window-not-targetable-after-disowning-opener.html
+
+        * loader/FrameLoader.cpp:
+        (WebCore::FrameLoader::findFrameForNavigation):
+        * page/FrameTree.cpp:
+        (WebCore::isFrameFamiliarWith):
+        (WebCore::FrameTree::find const):
+        * page/FrameTree.h:
+        * rendering/HitTestResult.cpp:
+        (WebCore::HitTestResult::targetFrame const):
+
 2018-10-15  Alex Christensen  <achristensen@webkit.org>
 
         Shrink more enum classes
index 8403876..0beb28f 100644 (file)
@@ -3540,12 +3540,12 @@ bool FrameLoader::shouldTreatURLAsSrcdocDocument(const URL& url) const
 
 Frame* FrameLoader::findFrameForNavigation(const AtomicString& name, Document* activeDocument)
 {
-    Frame* frame = m_frame.tree().find(name);
-
     // FIXME: Eventually all callers should supply the actual activeDocument so we can call canNavigate with the right document.
     if (!activeDocument)
         activeDocument = m_frame.document();
 
+    auto* frame = m_frame.tree().find(name, activeDocument->frame() ? *activeDocument->frame() : m_frame);
+
     if (!activeDocument->canNavigate(frame))
         return nullptr;
 
index 42cb333..a9fec15 100644 (file)
@@ -208,7 +208,23 @@ Frame* FrameTree::child(const AtomicString& name) const
     return nullptr;
 }
 
-Frame* FrameTree::find(const AtomicString& name) const
+// FrameTree::find() only returns frames in pages that are related to the active
+// page by an opener <-> openee relationship.
+static bool isFrameFamiliarWith(Frame& frameA, Frame& frameB)
+{
+    if (frameA.page() == frameB.page())
+        return true;
+
+    if (auto* frameAOpener = frameA.mainFrame().loader().opener())
+        return isFrameFamiliarWith(*frameAOpener, frameB);
+
+    if (auto* frameBOpener = frameB.mainFrame().loader().opener())
+        return isFrameFamiliarWith(frameA, *frameBOpener);
+
+    return false;
+}
+
+Frame* FrameTree::find(const AtomicString& name, Frame& activeFrame) const
 {
     // FIXME: _current is not part of the HTML specification.
     if (equalIgnoringASCIICase(name, "_self") || name == "_current" || name.isEmpty())
@@ -245,8 +261,8 @@ Frame* FrameTree::find(const AtomicString& name) const
     for (auto* otherPage : page->group().pages()) {
         if (otherPage == page)
             continue;
-        for (Frame* frame = &otherPage->mainFrame(); frame; frame = frame->tree().traverseNext()) {
-            if (frame->tree().uniqueName() == name)
+        for (auto* frame = &otherPage->mainFrame(); frame; frame = frame->tree().traverseNext()) {
+            if (frame->tree().uniqueName() == name && isFrameFamiliarWith(activeFrame, *frame))
                 return frame;
         }
     }
index 0b6a763..97c8f2b 100644 (file)
@@ -75,7 +75,7 @@ public:
 
     Frame* child(unsigned index) const;
     Frame* child(const AtomicString& name) const;
-    WEBCORE_EXPORT Frame* find(const AtomicString& name) const;
+    WEBCORE_EXPORT Frame* find(const AtomicString& name, Frame& activeFrame) const;
     WEBCORE_EXPORT unsigned childCount() const;
     WEBCORE_EXPORT Frame& top() const;
 
index 748eae3..85eb798 100644 (file)
@@ -177,13 +177,13 @@ Frame* HitTestResult::innerNodeFrame() const
 Frame* HitTestResult::targetFrame() const
 {
     if (!m_innerURLElement)
-        return 0;
+        return nullptr;
 
     Frame* frame = m_innerURLElement->document().frame();
     if (!frame)
-        return 0;
+        return nullptr;
 
-    return frame->tree().find(m_innerURLElement->target());
+    return frame->tree().find(m_innerURLElement->target(), *frame);
 }
 
 bool HitTestResult::isSelected() const
index 2b4f04d..40db008 100644 (file)
@@ -1,3 +1,13 @@
+2018-10-15  Chris Dumez  <cdumez@apple.com>
+
+        Restrict browsing context lookup by name to frames that are related to one another
+        https://bugs.webkit.org/show_bug.cgi?id=190475
+
+        Reviewed by Alex Christensen.
+
+        * WebProcess/Plugins/PluginView.cpp:
+        (WebKit::PluginView::performJavaScriptURLRequest):
+
 2018-10-15  Alex Christensen  <achristensen@webkit.org>
 
         Fix assertion after r237102
index f0752bd..75808b1 100644 (file)
@@ -1238,7 +1238,7 @@ void PluginView::performJavaScriptURLRequest(URLRequest* request)
 
     if (!request->target().isNull()) {
         // For security reasons, only allow JS requests to be made on the frame that contains the plug-in.
-        if (frame->tree().find(request->target()) != frame) {
+        if (frame->tree().find(request->target(), *frame) != frame) {
             // Let the plug-in know that its frame load failed.
             m_plugin->frameDidFail(request->requestID(), false);
             return;
index fdf0fb3..083c770 100644 (file)
@@ -1,3 +1,13 @@
+2018-10-15  Chris Dumez  <cdumez@apple.com>
+
+        Restrict browsing context lookup by name to frames that are related to one another
+        https://bugs.webkit.org/show_bug.cgi?id=190475
+
+        Reviewed by Alex Christensen.
+
+        * WebView/WebFrame.mm:
+        (-[WebFrame findFrameNamed:]):
+
 2018-10-15  Alex Christensen  <achristensen@webkit.org>
 
         Remove InjectedBundle processing of back/forward lists
index 37b33c8..7262ce2 100644 (file)
@@ -2587,7 +2587,7 @@ static NSURL *createUniqueWebDataURL()
     Frame* coreFrame = _private->coreFrame;
     if (!coreFrame)
         return nil;
-    return kit(coreFrame->tree().find(name));
+    return kit(coreFrame->tree().find(name, *coreFrame));
 }
 
 - (WebFrame *)parentFrame
index ab2f69e..ea3103f 100644 (file)
@@ -732,7 +732,7 @@ HRESULT WebFrame::findFrameNamed(_In_ BSTR name, _COM_Outptr_opt_ IWebFrame** fr
     if (!coreFrame)
         return E_UNEXPECTED;
 
-    Frame* foundFrame = coreFrame->tree().find(AtomicString(name, SysStringLen(name)));
+    Frame* foundFrame = coreFrame->tree().find(AtomicString(name, SysStringLen(name)), *coreFrame);
     if (!foundFrame)
         return S_OK;