WebKit Bugzilla
Attachment 339215 Details for
Bug 184996
: Add initial support for 'Cross-Origin-Options' HTTP response header
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
WIP patch
184996_XFrameIsolate_support_wip.patch (text/plain), 57.83 KB, created by
Chris Dumez
on 2018-05-01 12:49:28 PDT
(
hide
)
Description:
WIP patch
Filename:
MIME Type:
Creator:
Chris Dumez
Created:
2018-05-01 12:49:28 PDT
Size:
57.83 KB
patch
obsolete
>diff --git a/LayoutTests/http/tests/navigation/process-swap-window-open.html b/LayoutTests/http/tests/navigation/process-swap-window-open.html >index cff0f0a79f7..1c1e06207fe 100644 >--- a/LayoutTests/http/tests/navigation/process-swap-window-open.html >+++ b/LayoutTests/http/tests/navigation/process-swap-window-open.html >@@ -1,4 +1,4 @@ >-<!DOCTYPE html><!-- webkit-test-runner [ enableProcessSwapOnNavigation=true ] --> >+<!DOCTYPE html><!-- webkit-test-runner [ enableProcessSwapOnWindowOpenWithOpener=true ] --> > <html> > <body> > <script src="/js-test-resources/js-test.js"></script> >diff --git a/LayoutTests/http/tests/navigation/resources/no-x-frame-isolate.html b/LayoutTests/http/tests/navigation/resources/no-x-frame-isolate.html >new file mode 100644 >index 00000000000..bdd6817af22 >--- /dev/null >+++ b/LayoutTests/http/tests/navigation/resources/no-x-frame-isolate.html >@@ -0,0 +1,6 @@ >+<?php >+header("HTTP/1.1 200"); >+header("X-Frame-Isolate: 1"); >+?> >+TEST >+<iframe name="subframe"></iframe> >diff --git a/LayoutTests/http/tests/navigation/resources/x-frame-isolate-test-frame.php b/LayoutTests/http/tests/navigation/resources/x-frame-isolate-test-frame.php >new file mode 100644 >index 00000000000..a0d73a81ce5 >--- /dev/null >+++ b/LayoutTests/http/tests/navigation/resources/x-frame-isolate-test-frame.php >@@ -0,0 +1,23 @@ >+<?php >+header("HTTP/1.1 200"); >+header("X-Frame-Isolate: 1"); >+?> >+<!DOCTYPE html> >+<html> >+<head> >+<script src="/js-test-resources/js-test.js"></script> >+<script src="x-frame-isolate-testing.js"></script> >+</head> >+<body> >+<script> >+description("Basic testing for X-Frame-Isolate header in subframe with cross-origin parent."); >+ >+debug("* Testing window.parent"); >+verifyWindowLooksFrameless(window.parent); >+ >+debug(""); >+debug("* Testing window.top"); >+verifyWindowLooksFrameless(window.top); >+</script> >+</body> >+</html> >diff --git a/LayoutTests/http/tests/navigation/resources/x-frame-isolate-test-popup.php b/LayoutTests/http/tests/navigation/resources/x-frame-isolate-test-popup.php >new file mode 100644 >index 00000000000..e11511165a5 >--- /dev/null >+++ b/LayoutTests/http/tests/navigation/resources/x-frame-isolate-test-popup.php >@@ -0,0 +1,37 @@ >+<?php >+header("HTTP/1.1 200"); >+header("X-Frame-Isolate: 1"); >+?> >+<!DOCTYPE html> >+<html> >+<head> >+<script src="/js-test-resources/js-test.js"></script> >+<script src="x-frame-isolate-testing.js"></script> >+</head> >+<body> >+<script> >+if (window.testRunner) { >+ testRunner.dumpAsText(); >+ testRunner.waitUntilDone(); >+} >+ >+function logAsAlert(msg) { >+ let parser = new DOMParser(); >+ let htmlDoc = parser.parseFromString(msg, "text/html"); >+ alert(htmlDoc.body.innerText); >+} >+ >+description = logAsAlert; >+debug = logAsAlert; >+ >+description("Basic testing for X-Frame-Isolate header in popup with cross-origin opener."); >+ >+debug(""); >+debug("* Testing window.opener"); >+verifyWindowLooksFrameless(window.opener); >+ >+if (window.testRunner) >+ testRunner.notifyDone(); >+</script> >+</body> >+</html> >diff --git a/LayoutTests/http/tests/navigation/resources/x-frame-isolate-testing.js b/LayoutTests/http/tests/navigation/resources/x-frame-isolate-testing.js >new file mode 100644 >index 00000000000..46188916c91 >--- /dev/null >+++ b/LayoutTests/http/tests/navigation/resources/x-frame-isolate-testing.js >@@ -0,0 +1,47 @@ >+const expectedPropertyNames = [ 'blur', 'close', 'closed', 'focus', 'frames', 'length', 'location', 'opener', 'parent', 'postMessage', 'self', 'top', 'window' ]; >+function verifyWindowLooksFrameless(testWindow) { >+ w = testWindow; >+ >+ shouldNotThrow("w.foo = 1"); >+ >+ forbiddenProperties = ["name", "document", "history", "locationbar", "status", "frameElement", "navigator", "alert", "localStorage", "sessionStorage", "event", "foo", "bar"]; >+ for (forbiddenProperty of forbiddenProperties) >+ shouldThrowErrorName("w." + forbiddenProperty, "SecurityError"); >+ shouldThrowErrorName("w[0]", "SecurityError"); >+ shouldNotThrow("w[0] = 1"); >+ shouldThrowErrorName("w[0]", "SecurityError"); >+ >+ // The window should look as if it is frameless. >+ shouldBeTrue("w.closed"); >+ shouldBe("w.length", "0"); >+ shouldBeNull("w.frames"); >+ shouldBeNull("w.location"); >+ shouldBeNull("w.opener"); >+ shouldBeNull("w.parent"); >+ shouldBeNull("w.self"); >+ shouldBeNull("w.top"); >+ shouldBeNull("w.window"); >+ shouldNotThrow("w.focus()"); >+ shouldNotThrow("w.blur()"); >+ shouldNotThrow("w.close()"); >+ shouldNotThrow("w.postMessage('', '*')"); >+ >+ shouldBeTrue("areArraysEqual(Object.getOwnPropertyNames(w).sort(), expectedPropertyNames.sort())"); >+} >+ >+function verifyWindowIsSameOrigin(testWindow) { >+ w = testWindow; >+ >+ shouldBeEqualToString("w.location.href", "http://127.0.0.1:8000/navigation/resources/x-frame-isolate.php"); >+ shouldNotThrow("w.foo = 1"); >+ shouldBe("w.foo", "1"); >+ >+ shouldBeFalse("w.closed"); >+ shouldBe("w.length", "1"); >+ shouldBe("w.frames", "w"); >+ shouldBeNull("w.opener"); >+ shouldBe("w.parent", "window"); >+ shouldBe("w.self", "w"); >+ shouldBe("w.top", "window"); >+ shouldBe("w.window", "w"); >+} >diff --git a/LayoutTests/http/tests/navigation/resources/x-frame-isolate.php b/LayoutTests/http/tests/navigation/resources/x-frame-isolate.php >new file mode 100644 >index 00000000000..bdd6817af22 >--- /dev/null >+++ b/LayoutTests/http/tests/navigation/resources/x-frame-isolate.php >@@ -0,0 +1,6 @@ >+<?php >+header("HTTP/1.1 200"); >+header("X-Frame-Isolate: 1"); >+?> >+TEST >+<iframe name="subframe"></iframe> >diff --git a/LayoutTests/http/tests/navigation/x-frame-isolate-basic-expected.txt b/LayoutTests/http/tests/navigation/x-frame-isolate-basic-expected.txt >new file mode 100644 >index 00000000000..7802173fe08 >--- /dev/null >+++ b/LayoutTests/http/tests/navigation/x-frame-isolate-basic-expected.txt >@@ -0,0 +1,120 @@ >+Basic testing for X-Frame-Isolate header in subframes. >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+* Test with a regular cross-origin frameless window >+PASS w.foo = 1 did not throw exception. >+PASS w.name threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.document threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.history threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.locationbar threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.status threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.frameElement threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.navigator threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.alert threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.localStorage threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.sessionStorage threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.event threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.foo threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.bar threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w[0] threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w[0] = 1 did not throw exception. >+PASS w[0] threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.closed is true >+PASS w.length is 0 >+PASS w.frames is null >+PASS w.location is null >+PASS w.opener is null >+PASS w.parent is null >+PASS w.self is null >+PASS w.top is null >+PASS w.window is null >+PASS w.focus() did not throw exception. >+PASS w.blur() did not throw exception. >+PASS w.close() did not throw exception. >+PASS w.postMessage('', '*') did not throw exception. >+PASS areArraysEqual(Object.getOwnPropertyNames(w).sort(), expectedPropertyNames.sort()) is true >+ >+* Test with a X-Frame-Isolate cross-origin window which should look frameless even though it isn't (iframe) >+PASS w.foo = 1 did not throw exception. >+PASS w.name threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.document threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.history threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.locationbar threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.status threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.frameElement threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.navigator threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.alert threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.localStorage threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.sessionStorage threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.event threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.foo threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.bar threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w[0] threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w[0] = 1 did not throw exception. >+PASS w[0] threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.closed is true >+PASS w.length is 0 >+PASS w.frames is null >+PASS w.location is null >+PASS w.opener is null >+PASS w.parent is null >+PASS w.self is null >+PASS w.top is null >+PASS w.window is null >+PASS w.focus() did not throw exception. >+PASS w.blur() did not throw exception. >+PASS w.close() did not throw exception. >+PASS w.postMessage('', '*') did not throw exception. >+PASS areArraysEqual(Object.getOwnPropertyNames(w).sort(), expectedPropertyNames.sort()) is true >+ >+* Test with a X-Frame-Isolate same-origin window >+PASS w.location.href is "http://127.0.0.1:8000/navigation/resources/x-frame-isolate.php" >+PASS w.foo = 1 did not throw exception. >+PASS w.foo is 1 >+PASS w.closed is false >+PASS w.length is 1 >+PASS w.frames is w >+PASS w.opener is null >+PASS w.parent is window >+PASS w.self is w >+PASS w.top is window >+PASS w.window is w >+ >+* Test with a X-Frame-Isolate cross-origin window which should look frameless even though it isn't (popup) >+PASS w.foo = 1 did not throw exception. >+PASS w.name threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.document threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.history threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.locationbar threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.status threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.frameElement threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.navigator threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.alert threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.localStorage threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.sessionStorage threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.event threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.foo threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.bar threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w[0] threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w[0] = 1 did not throw exception. >+PASS w[0] threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.closed is true >+PASS w.length is 0 >+PASS w.frames is null >+PASS w.location is null >+PASS w.opener is null >+PASS w.parent is null >+PASS w.self is null >+PASS w.top is null >+PASS w.window is null >+PASS w.focus() did not throw exception. >+PASS w.blur() did not throw exception. >+PASS w.close() did not throw exception. >+PASS w.postMessage('', '*') did not throw exception. >+PASS areArraysEqual(Object.getOwnPropertyNames(w).sort(), expectedPropertyNames.sort()) is true >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/http/tests/navigation/x-frame-isolate-basic.html b/LayoutTests/http/tests/navigation/x-frame-isolate-basic.html >new file mode 100644 >index 00000000000..413120b62e7 >--- /dev/null >+++ b/LayoutTests/http/tests/navigation/x-frame-isolate-basic.html >@@ -0,0 +1,62 @@ >+<!DOCTYPE html> >+<html> >+<head> >+<script src="/js-test-resources/js-test.js"></script> >+<script src="resources/x-frame-isolate-testing.js"></script> >+</head> >+<body> >+<iframe src="http://localhost:8000/navigation/resources/x-frame-isolate.php" id="XFrameIsolateCrossOriginFrame"></iframe> >+<iframe src="http://localhost:8000/navigation/resources/no-x-frame-isolate.html" id="NoXFrameIsolateCrossOriginFrame"></iframe> >+<iframe src="resources/x-frame-isolate.php" id="XFrameIsolateSameOriginFrame"></iframe> >+<script> >+description("Basic testing for X-Frame-Isolate header in subframes."); >+jsTestIsAsync = true; >+ >+if (window.testRunner) >+ testRunner.setCanOpenWindows(true); >+ >+function isCrossOrigin(w) >+{ >+ try { >+ w.name; >+ } catch(e) { >+ return true; >+ } >+ return false; >+} >+ >+onload = function() { >+ let f = document.getElementById("NoXFrameIsolateCrossOriginFrame"); >+ let framelessWindow = f.contentWindow; >+ f.remove(); // Detach the window. >+ f = null; >+ gc(); >+ setTimeout(function() { >+ gc(); >+ >+ debug("* Test with a regular cross-origin frameless window"); >+ verifyWindowLooksFrameless(framelessWindow); >+ >+ debug(""); >+ debug("* Test with a X-Frame-Isolate cross-origin window which should look frameless even though it isn't (iframe)"); >+ verifyWindowLooksFrameless(document.getElementById("XFrameIsolateCrossOriginFrame").contentWindow); >+ >+ debug(""); >+ debug("* Test with a X-Frame-Isolate same-origin window"); >+ verifyWindowIsSameOrigin(document.getElementById("XFrameIsolateSameOriginFrame").contentWindow); >+ >+ debug(""); >+ debug("* Test with a X-Frame-Isolate cross-origin window which should look frameless even though it isn't (popup)"); >+ popupWindow = open("http://localhost:8000/navigation/resources/x-frame-isolate.php"); >+ handle = setInterval(function() { >+ if (!isCrossOrigin(popupWindow)) >+ return; >+ >+ verifyWindowLooksFrameless(popupWindow); >+ finishJSTest(); >+ }, 5); >+ }, 0); >+} >+</script> >+</body> >+</html> >diff --git a/LayoutTests/http/tests/navigation/x-frame-isolate-popup-expected.txt b/LayoutTests/http/tests/navigation/x-frame-isolate-popup-expected.txt >new file mode 100644 >index 00000000000..07781cd82d3 >--- /dev/null >+++ b/LayoutTests/http/tests/navigation/x-frame-isolate-popup-expected.txt >@@ -0,0 +1,38 @@ >+ALERT: Basic testing for X-Frame-Isolate header in popup with cross-origin opener. >+ALERT: >+ALERT: * Testing window.opener >+ALERT: PASS w.foo = 1 did not throw exception. >+ALERT: PASS w.name threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+ALERT: PASS w.document threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+ALERT: PASS w.history threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+ALERT: PASS w.locationbar threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+ALERT: PASS w.status threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+ALERT: PASS w.frameElement threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+ALERT: PASS w.navigator threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+ALERT: PASS w.alert threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+ALERT: PASS w.localStorage threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+ALERT: PASS w.sessionStorage threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+ALERT: PASS w.event threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+ALERT: PASS w.foo threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+ALERT: PASS w.bar threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+ALERT: PASS w[0] threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+ALERT: PASS w[0] = 1 did not throw exception. >+ALERT: PASS w[0] threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+ALERT: PASS w.closed is true >+ALERT: PASS w.length is 0 >+ALERT: PASS w.frames is null >+ALERT: PASS w.location is null >+ALERT: PASS w.opener is null >+ALERT: PASS w.parent is null >+ALERT: PASS w.self is null >+ALERT: PASS w.top is null >+ALERT: PASS w.window is null >+ALERT: PASS w.focus() did not throw exception. >+ALERT: PASS w.blur() did not throw exception. >+ALERT: PASS w.close() did not throw exception. >+ALERT: PASS w.postMessage('', '*') did not throw exception. >+ALERT: PASS areArraysEqual(Object.getOwnPropertyNames(w).sort(), expectedPropertyNames.sort()) is true >+ALERT: PASS successfullyParsed is true >+ALERT: >+TEST COMPLETE >+ >diff --git a/LayoutTests/http/tests/navigation/x-frame-isolate-popup.html b/LayoutTests/http/tests/navigation/x-frame-isolate-popup.html >new file mode 100644 >index 00000000000..b1a0779f600 >--- /dev/null >+++ b/LayoutTests/http/tests/navigation/x-frame-isolate-popup.html >@@ -0,0 +1,16 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<script> >+ if (window.testRunner) { >+ testRunner.waitUntilDone(); >+ testRunner.dumpChildFramesAsText(); >+ testRunner.setCanOpenWindows(true); >+ } >+ >+ w = open("http://localhost:8000/navigation/resources/x-frame-isolate-test-popup.php"); >+</script> >+</body> >+</html> >diff --git a/LayoutTests/http/tests/navigation/x-frame-isolate-subframe-expected.txt b/LayoutTests/http/tests/navigation/x-frame-isolate-subframe-expected.txt >new file mode 100644 >index 00000000000..4e765439d96 >--- /dev/null >+++ b/LayoutTests/http/tests/navigation/x-frame-isolate-subframe-expected.txt >@@ -0,0 +1,79 @@ >+ >+ >+-------- >+Frame: '<!--framePath //<!--frame0-->-->' >+-------- >+Basic testing for X-Frame-Isolate header in subframe with cross-origin parent. >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+* Testing window.parent >+PASS w.foo = 1 did not throw exception. >+PASS w.name threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.document threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.history threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.locationbar threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.status threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.frameElement threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.navigator threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.alert threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.localStorage threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.sessionStorage threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.event threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.foo threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.bar threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w[0] threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w[0] = 1 did not throw exception. >+PASS w[0] threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.closed is true >+PASS w.length is 0 >+PASS w.frames is null >+PASS w.location is null >+PASS w.opener is null >+PASS w.parent is null >+PASS w.self is null >+PASS w.top is null >+PASS w.window is null >+PASS w.focus() did not throw exception. >+PASS w.blur() did not throw exception. >+PASS w.close() did not throw exception. >+PASS w.postMessage('', '*') did not throw exception. >+PASS areArraysEqual(Object.getOwnPropertyNames(w).sort(), expectedPropertyNames.sort()) is true >+ >+* Testing window.top >+PASS w.foo = 1 did not throw exception. >+PASS w.name threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.document threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.history threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.locationbar threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.status threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.frameElement threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.navigator threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.alert threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.localStorage threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.sessionStorage threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.event threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.foo threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.bar threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w[0] threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w[0] = 1 did not throw exception. >+PASS w[0] threw exception SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a cross-origin frame. Protocols, domains, and ports must match.. >+PASS w.closed is true >+PASS w.length is 0 >+PASS w.frames is null >+PASS w.location is null >+PASS w.opener is null >+PASS w.parent is null >+PASS w.self is null >+PASS w.top is null >+PASS w.window is null >+PASS w.focus() did not throw exception. >+PASS w.blur() did not throw exception. >+PASS w.close() did not throw exception. >+PASS w.postMessage('', '*') did not throw exception. >+PASS areArraysEqual(Object.getOwnPropertyNames(w).sort(), expectedPropertyNames.sort()) is true >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/http/tests/navigation/x-frame-isolate-subframe.html b/LayoutTests/http/tests/navigation/x-frame-isolate-subframe.html >new file mode 100644 >index 00000000000..c79649f5cda >--- /dev/null >+++ b/LayoutTests/http/tests/navigation/x-frame-isolate-subframe.html >@@ -0,0 +1,11 @@ >+<!DOCTYPE html> >+<html> >+<body> >+<script> >+if (window.testRunner) >+ testRunner.dumpChildFramesAsText(); >+</script> >+<iframe src="http://localhost:8000/navigation/resources/x-frame-isolate-test-frame.php"></iframe> >+</script> >+</body> >+</html> >diff --git a/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp b/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp >index 281ea4e7004..f50cb0fc7a2 100644 >--- a/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp >+++ b/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp >@@ -57,6 +57,14 @@ using namespace JSC; > > EncodedJSValue JSC_HOST_CALL jsDOMWindowInstanceFunctionShowModalDialog(ExecState*); > >+static inline Frame* frameForScript(ExecState& state, JSDOMWindow* jsWindow) >+{ >+ ASSERT(jsWindow); >+ auto& window = jsWindow->wrapped(); >+ auto* frame = window.frame(); >+ return frame && !window.shouldLookFrameless(activeDOMWindow(state)) ? frame : nullptr; >+} >+ > void JSDOMWindow::visitAdditionalChildren(SlotVisitor& visitor) > { > if (Frame* frame = wrapped().frame()) >@@ -146,7 +154,8 @@ bool jsDOMWindowGetOwnPropertySlotRestrictedAccess(JSDOMGlobalObject* thisObject > // properties that are in Moz but not IE. Since we have some of these, we have to do it > // the Moz way. > // FIXME: Add support to named attributes on RemoteFrames. >- if (frame && is<Frame>(*frame)) { >+ if (windowType == DOMWindowType::Local && frame) { >+ ASSERT(frameForScript(*exec, jsCast<JSDOMWindow*>(thisObject)) == frame); > if (auto* scopedChild = downcast<Frame>(*frame).tree().scopedChild(propertyNameToAtomicString(propertyName))) { > slot.setValue(thisObject, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::DontEnum, toJS(exec, scopedChild->document()->domWindow())); > return true; >@@ -172,7 +181,7 @@ bool JSDOMWindow::getOwnPropertySlot(JSObject* object, ExecState* state, Propert > return getOwnPropertySlotByIndex(object, state, index.value(), slot); > > auto* thisObject = jsCast<JSDOMWindow*>(object); >- auto* frame = thisObject->wrapped().frame(); >+ auto* frame = frameForScript(*state, thisObject); > > // Hand off all cross-domain access to jsDOMWindowGetOwnPropertySlotRestrictedAccess. > String errorMessage; >@@ -213,7 +222,7 @@ bool JSDOMWindow::getOwnPropertySlot(JSObject* object, ExecState* state, Propert > bool JSDOMWindow::getOwnPropertySlotByIndex(JSObject* object, ExecState* state, unsigned index, PropertySlot& slot) > { > auto* thisObject = jsCast<JSDOMWindow*>(object); >- auto* frame = thisObject->wrapped().frame(); >+ auto* frame = frameForScript(*state, thisObject); > > // Indexed getters take precendence over regular properties, so caching would be invalid. > slot.disableCaching(); >@@ -240,7 +249,7 @@ bool JSDOMWindow::put(JSCell* cell, ExecState* state, PropertyName propertyName, > auto scope = DECLARE_THROW_SCOPE(vm); > > auto* thisObject = jsCast<JSDOMWindow*>(cell); >- if (!thisObject->wrapped().frame()) >+ if (!frameForScript(*state, thisObject)) > return false; > > String errorMessage; >@@ -262,7 +271,7 @@ bool JSDOMWindow::put(JSCell* cell, ExecState* state, PropertyName propertyName, > bool JSDOMWindow::putByIndex(JSCell* cell, ExecState* exec, unsigned index, JSValue value, bool shouldThrow) > { > auto* thisObject = jsCast<JSDOMWindow*>(cell); >- if (!thisObject->wrapped().frame() || !BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->wrapped())) >+ if (!frameForScript(*exec, thisObject) || !BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->wrapped())) > return false; > > return Base::putByIndex(thisObject, exec, index, value, shouldThrow); >@@ -308,13 +317,9 @@ static void addCrossOriginWindowPropertyNames(VM& vm, PropertyNameArray& propert > propertyNames.add(*property); > } > >-static void addScopedChildrenIndexes(ExecState& state, DOMWindow& window, PropertyNameArray& propertyNames) >+static void addScopedChildrenIndexes(ExecState& state, JSDOMWindow* jsWindow, PropertyNameArray& propertyNames) > { >- auto* document = window.document(); >- if (!document) >- return; >- >- auto* frame = document->frame(); >+ auto* frame = frameForScript(state, jsWindow); > if (!frame) > return; > >@@ -339,7 +344,7 @@ void JSDOMWindow::getOwnPropertyNames(JSObject* object, ExecState* exec, Propert > { > JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object); > >- addScopedChildrenIndexes(*exec, thisObject->wrapped(), propertyNames); >+ addScopedChildrenIndexes(*exec, thisObject, propertyNames); > > if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->wrapped(), DoNotReportSecurityError)) { > if (mode.includeDontEnumProperties()) >diff --git a/Source/WebCore/dom/Document.h b/Source/WebCore/dom/Document.h >index 4381d9ba504..4c245bdca9c 100644 >--- a/Source/WebCore/dom/Document.h >+++ b/Source/WebCore/dom/Document.h >@@ -1431,6 +1431,9 @@ public: > > String signedPublicKeyAndChallengeString(unsigned keySizeIndex, const String& challengeString, const URL&); > >+ void setIsXFrameIsolated(bool value) { m_isXFrameIsolated = value; } >+ bool isXFrameIsolated() const { return m_isXFrameIsolated; } >+ > protected: > enum ConstructionFlags { Synthesized = 1, NonRenderedPlaceholder = 1 << 1 }; > Document(Frame*, const URL&, unsigned = DefaultDocumentClass, unsigned constructionFlags = 0); >@@ -1909,6 +1912,7 @@ private: > > bool m_hasFrameSpecificStorageAccess { false }; > bool m_grantStorageAccessOverride { false }; >+ bool m_isXFrameIsolated { false }; > > RefPtr<DocumentTimeline> m_timeline; > DocumentIdentifier m_identifier; >diff --git a/Source/WebCore/loader/FrameLoader.cpp b/Source/WebCore/loader/FrameLoader.cpp >index 97cf0b68e11..7826fe27658 100644 >--- a/Source/WebCore/loader/FrameLoader.cpp >+++ b/Source/WebCore/loader/FrameLoader.cpp >@@ -739,6 +739,9 @@ void FrameLoader::didBeginDocument(bool dispatch) > if (!headerContentLanguage.isEmpty()) > m_frame.document()->setContentLanguage(headerContentLanguage); > } >+ >+ if (!m_documentLoader->response().httpHeaderField(HTTPHeaderName::XFrameIsolate).isNull()) >+ m_frame.document()->setIsXFrameIsolated(true); > } > > history().restoreDocumentState(); >@@ -1309,12 +1312,6 @@ void FrameLoader::loadURL(FrameLoadRequest&& frameLoadRequest, const String& ref > > NavigationAction action { frameLoadRequest.requester(), request, frameLoadRequest.initiatedByMainFrame(), newLoadType, isFormSubmission, event, frameLoadRequest.shouldOpenExternalURLsPolicy(), frameLoadRequest.downloadAttribute() }; > action.setIsCrossOriginWindowOpenNavigation(frameLoadRequest.isCrossOriginWindowOpenNavigation()); >- if (auto* opener = this->opener()) { >- auto pageID = opener->loader().client().pageID(); >- auto frameID = opener->loader().client().frameID(); >- if (pageID && frameID) >- action.setOpener(std::make_pair(*pageID, *frameID)); >- } > > if (!targetFrame && !frameName.isEmpty()) { > action = action.copyWithShouldOpenExternalURLsPolicy(shouldOpenExternalURLsPolicyToApply(m_frame, frameLoadRequest)); >diff --git a/Source/WebCore/loader/PolicyChecker.cpp b/Source/WebCore/loader/PolicyChecker.cpp >index fc241949838..33c4973f8bd 100644 >--- a/Source/WebCore/loader/PolicyChecker.cpp >+++ b/Source/WebCore/loader/PolicyChecker.cpp >@@ -88,6 +88,13 @@ void PolicyChecker::checkNavigationPolicy(ResourceRequest&& request, bool didRec > action = NavigationAction { *m_frame.document(), request, InitiatedByMainFrame::Unknown, NavigationType::Other, loader->shouldOpenExternalURLsPolicyToPropagate() }; > loader->setTriggeringAction(action); > } >+ action.setOpener(std::nullopt); >+ if (auto* opener = m_frame.loader().opener()) { >+ auto pageID = opener->loader().client().pageID(); >+ auto frameID = opener->loader().client().frameID(); >+ if (pageID && frameID) >+ action.setOpener(std::make_pair(*pageID, *frameID)); >+ } > > // Don't ask more than once for the same request or if we are loading an empty URL. > // This avoids confusion on the part of the client. >diff --git a/Source/WebCore/page/DOMWindow.cpp b/Source/WebCore/page/DOMWindow.cpp >index c709a2d86dc..4307a468844 100644 >--- a/Source/WebCore/page/DOMWindow.cpp >+++ b/Source/WebCore/page/DOMWindow.cpp >@@ -812,6 +812,13 @@ Location* DOMWindow::location() const > return m_location.get(); > } > >+Location* DOMWindow::locationForBindings(DOMWindow& activeDOMWindow) const >+{ >+ if (shouldLookFrameless(activeDOMWindow)) >+ return nullptr; >+ return location(); >+} >+ > VisualViewport* DOMWindow::visualViewport() const > { > if (!isCurrentlyDisplayedInFrame()) >@@ -917,7 +924,7 @@ ExceptionOr<Storage*> DOMWindow::localStorage() const > > ExceptionOr<void> DOMWindow::postMessage(JSC::ExecState& state, DOMWindow& incumbentWindow, JSC::JSValue messageValue, const String& targetOrigin, Vector<JSC::Strong<JSC::JSObject>>&& transfer) > { >- if (!isCurrentlyDisplayedInFrame()) >+ if (!isCurrentlyDisplayedInFrame() || shouldLookFrameless(activeDOMWindow(state))) > return { }; > > Document* sourceDocument = incumbentWindow.document(); >@@ -1013,9 +1020,9 @@ Element* DOMWindow::frameElement() const > return m_frame->ownerElement(); > } > >-void DOMWindow::focus(DOMWindow& incumbentWindow) >+void DOMWindow::focus(DOMWindow& incumbentWindow, DOMWindow& activeWindow) > { >- auto* opener = this->opener(); >+ auto* opener = this->opener(activeWindow); > focus(opener && opener != self() && incumbentWindow.self() == opener); > } > >@@ -1047,9 +1054,9 @@ void DOMWindow::focus(bool allowFocus) > m_frame->eventHandler().focusDocumentView(); > } > >-void DOMWindow::blur() >+void DOMWindow::blur(DOMWindow& activeWindow) > { >- if (!m_frame) >+ if (!m_frame || shouldLookFrameless(activeWindow)) > return; > > Page* page = m_frame->page(); >@@ -1065,9 +1072,9 @@ void DOMWindow::blur() > page->chrome().unfocus(); > } > >-void DOMWindow::close(Document& document) >+void DOMWindow::close(Document& incumbentDocument, DOMWindow& activeWindow) > { >- if (!document.canNavigate(m_frame)) >+ if (!incumbentDocument.canNavigate(m_frame) || shouldLookFrameless(activeWindow)) > return; > close(); > } >@@ -1360,14 +1367,32 @@ int DOMWindow::scrollY() const > return view->mapFromLayoutToCSSUnits(view->contentsScrollPosition().y()); > } > >-bool DOMWindow::closed() const >+bool DOMWindow::shouldLookFrameless(DOMWindow& activeWindow) const > { >- return !m_frame; >+ auto* targetDocument = document(); >+ if (!targetDocument) >+ return true; >+ >+ auto* sourceDocument = activeWindow.document(); >+ ASSERT(sourceDocument); >+ >+ if (!targetDocument->isXFrameIsolated() && !sourceDocument->isXFrameIsolated()) >+ return false; >+ >+ return !sourceDocument->securityOrigin().canAccess(targetDocument->securityOrigin()); > } > >-unsigned DOMWindow::length() const >+bool DOMWindow::closed(DOMWindow& activeWindow) const > { >- if (!isCurrentlyDisplayedInFrame()) >+ if (!m_frame || shouldLookFrameless(activeWindow)) >+ return true; >+ >+ return false; >+} >+ >+unsigned DOMWindow::length(DOMWindow& activeWindow) const >+{ >+ if (!isCurrentlyDisplayedInFrame() || shouldLookFrameless(activeWindow)) > return 0; > > return m_frame->tree().scopedChildCount(); >@@ -1427,9 +1452,17 @@ WindowProxy* DOMWindow::self() const > return &m_frame->windowProxy(); > } > >-WindowProxy* DOMWindow::opener() const >+WindowProxy* DOMWindow::selfForBindings(DOMWindow& activeWindow) const > { >- if (!m_frame) >+ if (shouldLookFrameless(activeWindow)) >+ return nullptr; >+ >+ return self(); >+} >+ >+WindowProxy* DOMWindow::opener(DOMWindow& activeWindow) const >+{ >+ if (!m_frame || shouldLookFrameless(activeWindow)) > return nullptr; > > auto* openerFrame = m_frame->loader().opener(); >@@ -1445,9 +1478,9 @@ void DOMWindow::disownOpener() > m_frame->loader().setOpener(nullptr); > } > >-WindowProxy* DOMWindow::parent() const >+WindowProxy* DOMWindow::parent(DOMWindow& activeWindow) const > { >- if (!m_frame) >+ if (!m_frame || shouldLookFrameless(activeWindow)) > return nullptr; > > auto* parentFrame = m_frame->tree().parent(); >@@ -1457,9 +1490,9 @@ WindowProxy* DOMWindow::parent() const > return &m_frame->windowProxy(); > } > >-WindowProxy* DOMWindow::top() const >+WindowProxy* DOMWindow::top(DOMWindow& activeWindow) const > { >- if (!m_frame) >+ if (!m_frame || shouldLookFrameless(activeWindow)) > return nullptr; > > if (!m_frame->page()) >diff --git a/Source/WebCore/page/DOMWindow.h b/Source/WebCore/page/DOMWindow.h >index c7ba7477902..bf405633c1a 100644 >--- a/Source/WebCore/page/DOMWindow.h >+++ b/Source/WebCore/page/DOMWindow.h >@@ -144,6 +144,7 @@ public: > Navigator* clientInformation() const { return navigator(); } > > Location* location() const; >+ Location* locationForBindings(DOMWindow& activeDOMWindow) const; > void setLocation(DOMWindow& activeWindow, DOMWindow& firstWindow, const String& location, SetLocationLocking = LockHistoryBasedOnGestureState); > > DOMSelection* getSelection(); >@@ -151,10 +152,10 @@ public: > Element* frameElement() const; > > WEBCORE_EXPORT void focus(bool allowFocus = false); >- void focus(DOMWindow& incumbentWindow); >- void blur(); >+ void focus(DOMWindow& incumbentWindow, DOMWindow& activeWindow); >+ void blur(DOMWindow& activeWindow); > WEBCORE_EXPORT void close(); >- void close(Document&); >+ void close(Document& incumbentDocument, DOMWindow& activeWindow); > void print(); > void stop(); > >@@ -181,9 +182,9 @@ public: > int scrollX() const; > int scrollY() const; > >- bool closed() const; >+ bool closed(DOMWindow& activeWindow) const; > >- unsigned length() const; >+ unsigned length(DOMWindow& activeWindow) const; > > String name() const; > void setName(const String&); >@@ -194,11 +195,12 @@ public: > void setDefaultStatus(const String&); > > WindowProxy* self() const; >+ WindowProxy* selfForBindings(DOMWindow& activeWindow) const; > >- WindowProxy* opener() const; >+ WindowProxy* opener(DOMWindow& activeWindow) const; > void disownOpener(); >- WindowProxy* parent() const; >- WindowProxy* top() const; >+ WindowProxy* parent(DOMWindow& activeWindow) const; >+ WindowProxy* top(DOMWindow& activeWindow) const; > > Frame* frame() const final { return FrameDestructionObserver::frame(); } > >@@ -337,6 +339,8 @@ public: > > WeakPtr<DOMWindow> createWeakPtr() { return m_weakPtrFactory.createWeakPtr(*this); } > >+ bool shouldLookFrameless(DOMWindow& activeWindow) const; >+ > private: > explicit DOMWindow(Document&); > >diff --git a/Source/WebCore/page/DOMWindow.idl b/Source/WebCore/page/DOMWindow.idl >index e696178eac6..89973bf8464 100644 >--- a/Source/WebCore/page/DOMWindow.idl >+++ b/Source/WebCore/page/DOMWindow.idl >@@ -49,11 +49,11 @@ typedef USVString CSSOMString; > PrimaryGlobal, > ] interface DOMWindow : EventTarget { > // The current browsing context. >- [DoNotCheckSecurity, Unforgeable, ImplementedAs=self] readonly attribute WindowProxy window; >- [Replaceable, DoNotCheckSecurityOnGetter] readonly attribute WindowProxy self; >+ [DoNotCheckSecurity, Unforgeable, ImplementedAs=selfForBindings, CallWith=ActiveWindow] readonly attribute WindowProxy window; >+ [Replaceable, DoNotCheckSecurityOnGetter, ImplementedAs=selfForBindings, CallWith=ActiveWindow] readonly attribute WindowProxy self; > [Unforgeable] readonly attribute Document document; > attribute DOMString name; >- [DoNotCheckSecurity, PutForwards=href, Unforgeable] readonly attribute Location? location; // FIXME: Should not be nullable. >+ [DoNotCheckSecurity, PutForwards=href, Unforgeable, ImplementedAs=locationForBindings, CallWith=ActiveWindow] readonly attribute Location? location; // FIXME: Should not be nullable. > readonly attribute History history; > [EnabledAtRuntime=CustomElements, ImplementedAs=ensureCustomElementRegistry] readonly attribute CustomElementRegistry customElements; > [Replaceable] readonly attribute BarProp locationbar; >@@ -63,18 +63,18 @@ typedef USVString CSSOMString; > [Replaceable] readonly attribute BarProp statusbar; > [Replaceable] readonly attribute BarProp toolbar; > attribute DOMString status; >- [DoNotCheckSecurity, CallWith=IncumbentDocument, ForwardDeclareInHeader] void close(); >- [DoNotCheckSecurity, ForwardDeclareInHeader] readonly attribute boolean closed; >+ [DoNotCheckSecurity, CallWith=IncumbentDocument&ActiveWindow, ForwardDeclareInHeader] void close(); >+ [DoNotCheckSecurity, ForwardDeclareInHeader, CallWith=ActiveWindow] readonly attribute boolean closed; > void stop(); >- [DoNotCheckSecurity, CallWith=IncumbentWindow, ForwardDeclareInHeader] void focus(); >- [DoNotCheckSecurity, ForwardDeclareInHeader] void blur(); >+ [DoNotCheckSecurity, CallWith=IncumbentWindow&ActiveWindow, ForwardDeclareInHeader] void focus(); >+ [DoNotCheckSecurity, ForwardDeclareInHeader, CallWith=ActiveWindow] void blur(); > > // Other browsing contexts. >- [Replaceable, DoNotCheckSecurityOnGetter, ImplementedAs=self] readonly attribute WindowProxy frames; >- [Replaceable, DoNotCheckSecurityOnGetter] readonly attribute unsigned long length; >- [DoNotCheckSecurityOnGetter, Unforgeable] readonly attribute WindowProxy? top; >- [DoNotCheckSecurityOnGetter, CustomSetter] attribute WindowProxy? opener; >- [Replaceable, DoNotCheckSecurityOnGetter] readonly attribute WindowProxy? parent; >+ [Replaceable, DoNotCheckSecurityOnGetter, ImplementedAs=selfForBindings, CallWith=ActiveWindow] readonly attribute WindowProxy frames; >+ [Replaceable, DoNotCheckSecurityOnGetter, CallWith=ActiveWindow] readonly attribute unsigned long length; >+ [DoNotCheckSecurityOnGetter, Unforgeable, CallWith=ActiveWindow] readonly attribute WindowProxy? top; >+ [DoNotCheckSecurityOnGetter, CustomSetter, CallWith=ActiveWindow] attribute WindowProxy? opener; >+ [Replaceable, DoNotCheckSecurityOnGetter, CallWith=ActiveWindow] readonly attribute WindowProxy? parent; > [CheckSecurityForNode] readonly attribute Element? frameElement; > [CallWith=ActiveWindow&FirstWindow] WindowProxy? open(optional USVString url = "about:blank", optional DOMString target = "_blank", optional [TreatNullAs=EmptyString] DOMString features = ""); > >diff --git a/Source/WebCore/platform/network/HTTPHeaderNames.in b/Source/WebCore/platform/network/HTTPHeaderNames.in >index 3e192856e9e..88bcf4dffac 100644 >--- a/Source/WebCore/platform/network/HTTPHeaderNames.in >+++ b/Source/WebCore/platform/network/HTTPHeaderNames.in >@@ -98,6 +98,7 @@ Vary > Via > X-Content-Type-Options > X-DNS-Prefetch-Control >+X-Frame-Isolate > X-Frame-Options > X-SourceMap > X-WebKit-CSP >diff --git a/Source/WebCore/workers/service/ServiceWorkerClientData.cpp b/Source/WebCore/workers/service/ServiceWorkerClientData.cpp >index 5c4402b720c..7f54eeafdce 100644 >--- a/Source/WebCore/workers/service/ServiceWorkerClientData.cpp >+++ b/Source/WebCore/workers/service/ServiceWorkerClientData.cpp >@@ -31,6 +31,7 @@ > #include "DOMWindow.h" > #include "Document.h" > #include "Frame.h" >+#include "FrameLoader.h" > > namespace WebCore { > >@@ -45,10 +46,9 @@ static ServiceWorkerClientFrameType toServiceWorkerClientFrameType(ScriptExecuti > return ServiceWorkerClientFrameType::None; > > if (frame->isMainFrame()) { >- if (auto* window = document.domWindow()) { >- if (window->opener()) >- return ServiceWorkerClientFrameType::Auxiliary; >- } >+ // FIXME: We should probably rely on Page::openedByDOM() instead since the opener can be disowned. >+ if (frame->loader().opener()) >+ return ServiceWorkerClientFrameType::Auxiliary; > return ServiceWorkerClientFrameType::TopLevel; > } > return ServiceWorkerClientFrameType::Nested; >diff --git a/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp b/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp >index a0ed08e4e67..8c710441389 100644 >--- a/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp >+++ b/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp >@@ -397,6 +397,17 @@ static ResourceError fromOriginResourceError(const URL& url) > return { errorDomainWebKitInternal, 0, url, ASCIILiteral { "Cancelled load because it violates the resource's From-Origin response header." }, ResourceError::Type::AccessControl }; > } > >+static ResourceResponse synthesizeXFrameIsolateRedirect(const URL& url) >+{ >+ ResourceResponse synthesizedRedirect; >+ synthesizedRedirect.setURL(url); >+ synthesizedRedirect.setHTTPHeaderField(HTTPHeaderName::Location, url); >+ synthesizedRedirect.setHTTPStatusCode(302); >+ synthesizedRedirect.setHTTPHeaderField(HTTPHeaderName::CacheControl, ASCIILiteral("no-store")); >+ synthesizedRedirect.setHTTPHeaderField(HTTPHeaderName::XFrameIsolate, emptyString()); >+ return synthesizedRedirect; >+} >+ > auto NetworkResourceLoader::didReceiveResponse(ResourceResponse&& receivedResponse) -> ShouldContinueDidReceiveResponse > { > RELEASE_LOG_IF_ALLOWED("didReceiveResponse: (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ", httpStatusCode = %d, length = %" PRId64 ")", m_parameters.webPageID, m_parameters.webFrameID, m_parameters.identifier, receivedResponse.httpStatusCode(), receivedResponse.expectedContentLength()); >@@ -423,6 +434,16 @@ auto NetworkResourceLoader::didReceiveResponse(ResourceResponse&& receivedRespon > } else > m_cacheEntryForValidation = nullptr; > } >+ >+ if (isMainResource() && !m_response.httpHeaderField(HTTPHeaderName::XFrameIsolate).isNull()) { >+ ASSERT(!isSynchronous()); >+ >+ // Synthesize a redirect to cause another decidePolicyForNavigationAction and a potential process swap. >+ m_shouldSendResponseOnContinueWillSendRequest = true; >+ send(Messages::WebResourceLoader::WillSendRequest(originalRequest(), synthesizeXFrameIsolateRedirect(m_response.url()))); >+ return ShouldContinueDidReceiveResponse::No; >+ } >+ > bool shouldSendDidReceiveResponse = !m_cacheEntryForValidation; > > bool shouldWaitContinueDidReceiveResponse = isMainResource(); >@@ -631,6 +652,12 @@ void NetworkResourceLoader::continueWillSendRequest(ResourceRequest&& newRequest > > RELEASE_LOG_IF_ALLOWED("continueWillSendRequest: (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ")", m_parameters.webPageID, m_parameters.webFrameID, m_parameters.identifier); > >+ if (m_shouldSendResponseOnContinueWillSendRequest) { >+ m_shouldSendResponseOnContinueWillSendRequest = false; >+ send(Messages::WebResourceLoader::DidReceiveResponse { m_response, true }); >+ return; >+ } >+ > if (m_networkLoadChecker) > m_networkLoadChecker->prepareRedirectedRequest(newRequest); > >@@ -751,6 +778,16 @@ void NetworkResourceLoader::didRetrieveCacheEntry(std::unique_ptr<NetworkCache:: > return; > } > >+ if (isMainResource() && !response.httpHeaderField(HTTPHeaderName::XFrameIsolate).isNull()) { >+ ASSERT(!isSynchronous()); >+ >+ // Synthesize a redirect to cause another decidePolicyForNavigationAction and a potential process swap. >+ m_shouldSendResponseOnContinueWillSendRequest = true; >+ send(Messages::WebResourceLoader::WillSendRequest(originalRequest(), synthesizeXFrameIsolateRedirect(response.url()))); >+ m_cacheEntryWaitingForContinueDidReceiveResponse = WTFMove(entry); >+ return; >+ } >+ > bool needsContinueDidReceiveResponseMessage = isMainResource(); > send(Messages::WebResourceLoader::DidReceiveResponse { response, needsContinueDidReceiveResponseMessage }); > >diff --git a/Source/WebKit/NetworkProcess/NetworkResourceLoader.h b/Source/WebKit/NetworkProcess/NetworkResourceLoader.h >index 8769708c0a2..0d2b024cbea 100644 >--- a/Source/WebKit/NetworkProcess/NetworkResourceLoader.h >+++ b/Source/WebKit/NetworkProcess/NetworkResourceLoader.h >@@ -184,6 +184,7 @@ private: > bool m_isWaitingContinueWillSendRequestForCachedRedirect { false }; > std::unique_ptr<NetworkCache::Entry> m_cacheEntryWaitingForContinueDidReceiveResponse; > RefPtr<NetworkLoadChecker> m_networkLoadChecker; >+ bool m_shouldSendResponseOnContinueWillSendRequest { false }; > }; > > } // namespace WebKit >diff --git a/Source/WebKit/UIProcess/WebPageProxy.cpp b/Source/WebKit/UIProcess/WebPageProxy.cpp >index c9b48cb8fa9..c8224b9b898 100644 >--- a/Source/WebKit/UIProcess/WebPageProxy.cpp >+++ b/Source/WebKit/UIProcess/WebPageProxy.cpp >@@ -2481,6 +2481,9 @@ void WebPageProxy::continueNavigationInNewProcess(API::Navigation& navigation, R > if (!navigation.isCrossOriginWindowOpenNavigation() || !navigatedFrameIdentifierInPreviousProcess) > return; > >+ if (!this->process().processPool().configuration().processSwapsOnWindowOpenWithOpener()) >+ return; >+ > m_mainFrameWindowCreationHandler = [this, previousProcess = WTFMove(previousProcess), navigatedFrameIdentifierInPreviousProcess = *navigatedFrameIdentifierInPreviousProcess](const GlobalWindowIdentifier& windowIdentifier) { > ASSERT(m_mainFrame); > GlobalFrameIdentifier navigatedFrameIdentifierInNewProcess { pageID(), m_mainFrame->frameID() }; >diff --git a/Tools/WebKitTestRunner/TestController.cpp b/Tools/WebKitTestRunner/TestController.cpp >index 68c49c84130..25c118517ff 100644 >--- a/Tools/WebKitTestRunner/TestController.cpp >+++ b/Tools/WebKitTestRunner/TestController.cpp >@@ -506,7 +506,10 @@ void TestController::createWebViewWithOptions(const TestOptions& options) > WKArrayAppendItem(overrideLanguages.get(), adoptWK(WKStringCreateWithUTF8CString(language.utf8().data())).get()); > WKContextConfigurationSetOverrideLanguages(contextConfiguration.get(), overrideLanguages.get()); > >- if (options.enableProcessSwapOnNavigation) { >+ if (options.enableProcessSwapOnNavigation) >+ WKContextConfigurationSetProcessSwapsOnNavigation(contextConfiguration.get(), true); >+ >+ if (options.enableProcessSwapOnWindowOpenWithOpener) { > WKContextConfigurationSetProcessSwapsOnNavigation(contextConfiguration.get(), true); > WKContextConfigurationSetProcessSwapsOnWindowOpenWithOpener(contextConfiguration.get(), true); > } >@@ -1115,6 +1118,8 @@ static void updateTestOptionsFromTestHeader(TestOptions& testOptions, const std: > testOptions.enableCSSAnimationsAndCSSTransitionsBackedByWebAnimations = parseBooleanTestHeaderValue(value); > if (key == "enableProcessSwapOnNavigation") > testOptions.enableProcessSwapOnNavigation = parseBooleanTestHeaderValue(value); >+ if (key == "enableProcessSwapOnWindowOpenWithOpener") >+ testOptions.enableProcessSwapOnWindowOpenWithOpener = parseBooleanTestHeaderValue(value); > pairStart = pairEnd + 1; > } > } >diff --git a/Tools/WebKitTestRunner/TestOptions.h b/Tools/WebKitTestRunner/TestOptions.h >index bf89a071a2f..abab4722bf1 100644 >--- a/Tools/WebKitTestRunner/TestOptions.h >+++ b/Tools/WebKitTestRunner/TestOptions.h >@@ -57,6 +57,7 @@ struct TestOptions { > bool allowCrossOriginSubresourcesToAskForCredentials { false }; > bool enableCSSAnimationsAndCSSTransitionsBackedByWebAnimations { false }; > bool enableProcessSwapOnNavigation { false }; >+ bool enableProcessSwapOnWindowOpenWithOpener { false }; > > float deviceScaleFactor { 1 }; > Vector<String> overrideLanguages; >@@ -88,7 +89,8 @@ struct TestOptions { > || applicationManifest != options.applicationManifest > || allowCrossOriginSubresourcesToAskForCredentials != options.allowCrossOriginSubresourcesToAskForCredentials > || enableCSSAnimationsAndCSSTransitionsBackedByWebAnimations != options.enableCSSAnimationsAndCSSTransitionsBackedByWebAnimations >- || enableProcessSwapOnNavigation != options.enableProcessSwapOnNavigation) >+ || enableProcessSwapOnNavigation != options.enableProcessSwapOnNavigation >+ || enableProcessSwapOnWindowOpenWithOpener != options.enableProcessSwapOnWindowOpenWithOpener) > return false; > > return true;
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Flags:
ews-watchlist
:
commit-queue-
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 184996
:
338788
|
338803
|
338811
|
338812
|
338820
|
338825
|
338840
|
339215
|
339223
|
339225
|
339226
|
339242
|
339897
|
339922
|
339923
|
339973
|
339978
|
339980
|
339995
|
339998
|
340000
|
340007
|
340010
|
340022
|
340031
|
340035
|
340039
|
340041
|
340042
|
340046
|
340047
|
340049