Title: [231622] trunk
Revision
231622
Author
[email protected]
Date
2018-05-09 17:33:37 -0700 (Wed, 09 May 2018)

Log Message

Add initial support for 'Cross-Origin-Options' HTTP response header
https://bugs.webkit.org/show_bug.cgi?id=184996
<rdar://problem/39664620>

Reviewed by Geoff Garen.

Source/WebCore:

Add initial support for 'Cross-Origin-Options' HTTP response header behind an experimental
feature flag, on by default. When the HTTP server services this HTTP response header for a
main resource, we'll set these options on the corresponding Document. This will impact the
behavior of the Document's associated Window API when cross-origin.

The HTTP header has 3 possible values:
- allow: This is the default. Regular cross-origin Window API is available.
- allow-postmessage: Only postMessage() is available on a cross-origin window, trying to
  access anything else will throw a SecurityError.
- deny: Trying to do anything with a cross-origin window will throw a SecurityError.

The header has no effect when accessing same origin windows.

Note that on cross-origin access from Window A to Window B, we check the cross-origin
options for both Window A and Window B and use the lowest common denominator as effective
cross-origin options for the access. So if Window A has 'Cross-Origin-Options: deny' and
tries to call postMessage() on Window B which has 'Cross-Origin-Options: allow-postmessage',
we will throw a SecurityError. This is because Window A's more restrictive options (deny)
apply.

Tests: http/wpt/cross-origin-options/allow-postmessage-from-deny.html
       http/wpt/cross-origin-options/allow-postmessage.html
       http/wpt/cross-origin-options/cross-origin-options-header.html

* bindings/js/JSDOMBindingSecurity.cpp:
(WebCore::BindingSecurity::shouldAllowAccessToDOMWindowGivenMinimumCrossOriginOptions):
* bindings/js/JSDOMBindingSecurity.h:
* bindings/js/JSDOMWindowCustom.cpp:
(WebCore::effectiveCrossOriginOptionsForAccess):
(WebCore::jsDOMWindowGetOwnPropertySlotRestrictedAccess):
(WebCore::JSDOMWindow::getOwnPropertySlot):
(WebCore::JSDOMWindow::getOwnPropertySlotByIndex):
(WebCore::addCrossOriginWindowPropertyNames):
(WebCore::addScopedChildrenIndexes):
(WebCore::addCrossOriginWindowOwnPropertyNames):
(WebCore::JSDOMWindow::getOwnPropertyNames):
* bindings/js/JSDOMWindowCustom.h:
* bindings/js/JSRemoteDOMWindowCustom.cpp:
(WebCore::JSRemoteDOMWindow::getOwnPropertySlot):
(WebCore::JSRemoteDOMWindow::getOwnPropertySlotByIndex):
(WebCore::JSRemoteDOMWindow::getOwnPropertyNames):
* bindings/scripts/CodeGeneratorJS.pm:
(GenerateAttributeGetterBodyDefinition):
(GetCrossOriginsOptionsFromExtendedAttributeValue):
(GenerateAttributeSetterBodyDefinition):
(GenerateOperationBodyDefinition):
* bindings/scripts/IDLAttributes.json:
* dom/Document.cpp:
(WebCore::Document::setCrossOriginOptions):
* dom/Document.h:
(WebCore::Document::crossOriginOptions const):
* loader/FrameLoader.cpp:
(WebCore::FrameLoader::didBeginDocument):
* page/AbstractDOMWindow.cpp:
(WebCore::AbstractDOMWindow::AbstractDOMWindow):
* page/AbstractDOMWindow.h:
(WebCore::AbstractDOMWindow::crossOriginOptions):
(WebCore::AbstractDOMWindow::setCrossOriginOptions):
* page/DOMWindow.cpp:
(WebCore::DOMWindow::DOMWindow):
(WebCore::DOMWindow::didSecureTransitionTo):
* page/DOMWindow.idl:
* page/Frame.h:
* page/RemoteDOMWindow.cpp:
(WebCore::RemoteDOMWindow::RemoteDOMWindow):
* page/RemoteDOMWindow.h:
* page/Settings.yaml:
* platform/network/HTTPHeaderNames.in:
* platform/network/HTTPParsers.cpp:
(WebCore::parseCrossOriginOptionsHeader):
* platform/network/HTTPParsers.h:

Source/WebKit:

* Shared/WebPreferences.yaml:
Add this as an experimental feature, on by default.

* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::frameBecameRemote):
Make sure we pass the cross-origin options from the local Window
to the remote one when transitioning.

LayoutTests:

Add layout test coverage.

* http/wpt/cross-origin-options/allow-postmessage-expected.txt: Added.
* http/wpt/cross-origin-options/allow-postmessage-from-deny-expected.txt: Added.
* http/wpt/cross-origin-options/allow-postmessage-from-deny.html: Added.
* http/wpt/cross-origin-options/allow-postmessage-from-deny.html.headers: Added.
* http/wpt/cross-origin-options/allow-postmessage.html: Added.
* http/wpt/cross-origin-options/cross-origin-options-header-expected.txt: Added.
* http/wpt/cross-origin-options/cross-origin-options-header.html: Added.
* http/wpt/cross-origin-options/resources/cross-origin-options-allow-postmessage-pong.html: Added.
* http/wpt/cross-origin-options/resources/cross-origin-options-allow-postmessage-pong.html.headers: Added.
* http/wpt/cross-origin-options/resources/serve-cross-origin-options-header.py: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (231621 => 231622)


--- trunk/LayoutTests/ChangeLog	2018-05-10 00:08:40 UTC (rev 231621)
+++ trunk/LayoutTests/ChangeLog	2018-05-10 00:33:37 UTC (rev 231622)
@@ -1,3 +1,24 @@
+2018-05-09  Chris Dumez  <[email protected]>
+
+        Add initial support for 'Cross-Origin-Options' HTTP response header
+        https://bugs.webkit.org/show_bug.cgi?id=184996
+        <rdar://problem/39664620>
+
+        Reviewed by Geoff Garen.
+
+        Add layout test coverage.
+
+        * http/wpt/cross-origin-options/allow-postmessage-expected.txt: Added.
+        * http/wpt/cross-origin-options/allow-postmessage-from-deny-expected.txt: Added.
+        * http/wpt/cross-origin-options/allow-postmessage-from-deny.html: Added.
+        * http/wpt/cross-origin-options/allow-postmessage-from-deny.html.headers: Added.
+        * http/wpt/cross-origin-options/allow-postmessage.html: Added.
+        * http/wpt/cross-origin-options/cross-origin-options-header-expected.txt: Added.
+        * http/wpt/cross-origin-options/cross-origin-options-header.html: Added.
+        * http/wpt/cross-origin-options/resources/cross-origin-options-allow-postmessage-pong.html: Added.
+        * http/wpt/cross-origin-options/resources/cross-origin-options-allow-postmessage-pong.html.headers: Added.
+        * http/wpt/cross-origin-options/resources/serve-cross-origin-options-header.py: Added.
+
 2018-05-09  Ryosuke Niwa  <[email protected]>
 
         Release assert in TreeScopeOrderedMap::remove via HTMLImageElement::removedFromAncestor

Added: trunk/LayoutTests/http/wpt/cross-origin-options/allow-postmessage-expected.txt (0 => 231622)


--- trunk/LayoutTests/http/wpt/cross-origin-options/allow-postmessage-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/cross-origin-options/allow-postmessage-expected.txt	2018-05-10 00:33:37 UTC (rev 231622)
@@ -0,0 +1,5 @@
+
+
+PASS postMessage() on Cross-origin iframe with 'Cross-Origin-Options: allow-postmessage' HTTP header 
+PASS postMessage() on Cross-origin popup with 'Cross-Origin-Options: allow-postmessage' HTTP header 
+

Added: trunk/LayoutTests/http/wpt/cross-origin-options/allow-postmessage-from-deny-expected.txt (0 => 231622)


--- trunk/LayoutTests/http/wpt/cross-origin-options/allow-postmessage-from-deny-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/cross-origin-options/allow-postmessage-from-deny-expected.txt	2018-05-10 00:33:37 UTC (rev 231622)
@@ -0,0 +1,5 @@
+
+
+PASS postMessage() on Cross-origin iframe with 'Cross-Origin-Options: allow-postmessage' but current window has 'deny' option 
+PASS postMessage() on Cross-origin popup with 'Cross-Origin-Options: allow-postmessage' but current window has 'deny' option 
+

Added: trunk/LayoutTests/http/wpt/cross-origin-options/allow-postmessage-from-deny.html (0 => 231622)


--- trunk/LayoutTests/http/wpt/cross-origin-options/allow-postmessage-from-deny.html	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/cross-origin-options/allow-postmessage-from-deny.html	2018-05-10 00:33:37 UTC (rev 231622)
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Tests calling postMessage() on a window with 'Cross-Origin-Options: allow-postmessage' from a window with 'Cross-Origin-Options: deny'</title>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+</head>
+<body>
+<script>
+
+promise_test(function(test) {
+    return withIframe("cross-origin-options-allow-postmessage-pong.html", true /* isCrossOrigin */).then((f) => {
+        assert_throws("SecurityError", function() { f.contentWindow.length }, "length property access");
+        assert_throws("SecurityError", function() { f.contentWindow.postMessage("PING", "*"); }, "Calling postMessage() should throw");
+    });
+}, "postMessage() on Cross-origin iframe with 'Cross-Origin-Options: allow-postmessage' but current window has 'deny' option");
+
+promise_test(function(test) {
+    return withPopup("cross-origin-options-allow-postmessage-pong.html", true /* isCrossOrigin */).then((result) => {
+        assert_throws("SecurityError", function() { result.window.length }, "length property access");
+        assert_throws("SecurityError", function() { result.window.postMessage("PING", "*"); }, "Calling postMessage() should throw");
+    });
+}, "postMessage() on Cross-origin popup with 'Cross-Origin-Options: allow-postmessage' but current window has 'deny' option");
+
+</script>
+</body>
+</html>

Added: trunk/LayoutTests/http/wpt/cross-origin-options/allow-postmessage-from-deny.html.headers (0 => 231622)


--- trunk/LayoutTests/http/wpt/cross-origin-options/allow-postmessage-from-deny.html.headers	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/cross-origin-options/allow-postmessage-from-deny.html.headers	2018-05-10 00:33:37 UTC (rev 231622)
@@ -0,0 +1 @@
+Cross-Origin-Options: deny

Added: trunk/LayoutTests/http/wpt/cross-origin-options/allow-postmessage.html (0 => 231622)


--- trunk/LayoutTests/http/wpt/cross-origin-options/allow-postmessage.html	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/cross-origin-options/allow-postmessage.html	2018-05-10 00:33:37 UTC (rev 231622)
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Tests that postMessage() works when 'Cross-Origin-Options: allow-postmessage' HTTP header is served</title>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+</head>
+<body>
+<script>
+
+promise_test(function(test) {
+    return withIframe("cross-origin-options-allow-postmessage-pong.html", true /* isCrossOrigin */).then((f) => {
+        return new Promise((resolve) => {
+            window._onmessage_ = (msg) => {
+                window._onmessage_ = null;
+                assert_equals(msg.data, "PONG");
+                assert_equals(msg.source, f.contentWindow);
+                resolve();
+            };
+            assert_throws("SecurityError", function() { f.contentWindow.length }, "length property access");
+            f.contentWindow.postMessage("PING", "*");
+        });
+    });
+}, "postMessage() on Cross-origin iframe with 'Cross-Origin-Options: allow-postmessage' HTTP header");
+
+promise_test(function(test) {
+    return withPopup("cross-origin-options-allow-postmessage-pong.html", true /* isCrossOrigin */).then((result) => {
+        return new Promise((resolve) => {
+            window._onmessage_ = (msg) => {
+                window._onmessage_ = null;
+                assert_equals(msg.data, "PONG");
+                assert_equals(msg.source, result.window);
+                resolve();
+            };
+            assert_throws("SecurityError", function() { result.window.length }, "length property access");
+            result.window.postMessage("PING", "*");
+        });
+    });
+}, "postMessage() on Cross-origin popup with 'Cross-Origin-Options: allow-postmessage' HTTP header");
+
+</script>
+</body>
+</html>

Added: trunk/LayoutTests/http/wpt/cross-origin-options/cross-origin-options-header-expected.txt (0 => 231622)


--- trunk/LayoutTests/http/wpt/cross-origin-options/cross-origin-options-header-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/cross-origin-options/cross-origin-options-header-expected.txt	2018-05-10 00:33:37 UTC (rev 231622)
@@ -0,0 +1,19 @@
+  
+
+PASS Cross-origin iframe with 'Cross-Origin-Options: deny' HTTP header 
+PASS Cross-origin iframe with 'Cross-Origin-Options: allow-postmessage' HTTP header 
+PASS Cross-origin iframe with 'Cross-Origin-Options: allow' HTTP header 
+PASS Cross-origin iframe with 'Cross-Origin-Options: invalid' HTTP header 
+PASS Same-origin iframe with 'Cross-Origin-Options: deny' HTTP header 
+PASS Same-origin iframe with 'Cross-Origin-Options: allow-postmessage' HTTP header 
+PASS Same-origin iframe with 'Cross-Origin-Options: allow' HTTP header 
+PASS Same-origin iframe with 'Cross-Origin-Options: invalid' HTTP header 
+PASS Cross-origin popup with 'Cross-Origin-Options: deny' HTTP header 
+PASS Cross-origin popup with 'Cross-Origin-Options: allow-postmessage' HTTP header 
+PASS Cross-origin popup with 'Cross-Origin-Options: allow' HTTP header 
+PASS Cross-origin popup with 'Cross-Origin-Options: invalid' HTTP header 
+PASS Same-origin popup with 'Cross-Origin-Options: deny' HTTP header 
+PASS Same-origin popup with 'Cross-Origin-Options: allow-postmessage' HTTP header 
+PASS Same-origin popup with 'Cross-Origin-Options: allow' HTTP header 
+PASS Same-origin popup with 'Cross-Origin-Options: invalid' HTTP header 
+

Added: trunk/LayoutTests/http/wpt/cross-origin-options/cross-origin-options-header.html (0 => 231622)


--- trunk/LayoutTests/http/wpt/cross-origin-options/cross-origin-options-header.html	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/cross-origin-options/cross-origin-options-header.html	2018-05-10 00:33:37 UTC (rev 231622)
@@ -0,0 +1,172 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Basic testing for Cross-Origin-Options HTTP header</title>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+</head>
+<body>
+<script>
+
+// Test frame has a subframe so we expect an indexed property with index 0.
+crossOriginPropertyNames.push('0');
+
+function checkIframePropertyValues(w)
+{
+    assert_equals(w.parent, window, "'parent' property value");
+    assert_equals(w.top, window, "'top' property value");
+    assert_equals(w.opener, null, "'opener' property value");
+    assert_equals(w.length, 1, "'length' property value");
+    assert_not_throwing(function() { w[0]; }, "Subframe access via index");
+    assert_equals(w['subframe'], w[0], "Subframe access by name");
+}
+
+function checkPopupPropertyValues(w)
+{
+    assert_equals(w.parent, w, "'parent' property value");
+    assert_equals(w.top, w, "'top' property value");
+    assert_equals(w.opener, window, "'opener' property value");
+    assert_equals(w.length, 1, "'length' property value");
+    assert_not_throwing(function() { w[0]; }, "Subframe access via index");
+    assert_equals(w['subframe'], w[0], "Subframe access by name");
+}
+
+promise_test(function(test) {
+    return withIframe("serve-cross-origin-options-header.py?value=deny", true /* isCrossOrigin */).then((f) => {
+        testCrossOriginOption(f.contentWindow, "deny", true /* isCrossOrigin */);
+    });
+}, "Cross-origin iframe with 'Cross-Origin-Options: deny' HTTP header");
+
+promise_test(function(test) {
+    return withIframe("serve-cross-origin-options-header.py?value=allow-postmessage", true /* isCrossOrigin */).then((f) => {
+        testCrossOriginOption(f.contentWindow, "allow-postmessage", true /* isCrossOrigin */);
+    });
+}, "Cross-origin iframe with 'Cross-Origin-Options: allow-postmessage' HTTP header");
+
+promise_test(function(test) {
+    return withIframe("serve-cross-origin-options-header.py?value=allow", true /* isCrossOrigin */).then((f) => {
+        const w = f.contentWindow;
+        testCrossOriginOption(w, "allow", true /* isCrossOrigin */);
+
+        checkIframePropertyValues(w);
+    });
+}, "Cross-origin iframe with 'Cross-Origin-Options: allow' HTTP header");
+
+promise_test(function(test) {
+    return withIframe("serve-cross-origin-options-header.py?value=invalid", true /* isCrossOrigin */).then((f) => {
+        const w = f.contentWindow;
+        testCrossOriginOption(w, "allow", true /* isCrossOrigin */);
+        
+        checkIframePropertyValues(w);
+    });
+}, "Cross-origin iframe with 'Cross-Origin-Options: invalid' HTTP header");
+
+promise_test(function(test) {
+    return withIframe("serve-cross-origin-options-header.py?value=deny", false /* isCrossOrigin */).then((f) => {
+         const w = f.contentWindow;
+        testCrossOriginOption(w, "deny", false /* isCrossOrigin */);
+
+        checkIframePropertyValues(w);
+    });
+}, "Same-origin iframe with 'Cross-Origin-Options: deny' HTTP header");
+
+promise_test(function(test) {
+    return withIframe("serve-cross-origin-options-header.py?value=allow-postmessage", false /* isCrossOrigin */).then((f) => {
+         const w = f.contentWindow;
+        testCrossOriginOption(w, "allow-postmessage", false /* isCrossOrigin */);
+
+        checkIframePropertyValues(w);
+    });
+}, "Same-origin iframe with 'Cross-Origin-Options: allow-postmessage' HTTP header");
+
+promise_test(function(test) {
+    return withIframe("serve-cross-origin-options-header.py?value=allow", false /* isCrossOrigin */).then((f) => {
+         const w = f.contentWindow;
+        testCrossOriginOption(w, "allow", false /* isCrossOrigin */);
+
+        checkIframePropertyValues(w);
+    });
+}, "Same-origin iframe with 'Cross-Origin-Options: allow' HTTP header");
+
+promise_test(function(test) {
+    return withIframe("serve-cross-origin-options-header.py?value=invalid", false /* isCrossOrigin */).then((f) => {
+         const w = f.contentWindow;
+        testCrossOriginOption(w, "allow", false /* isCrossOrigin */);
+
+        checkIframePropertyValues(w);
+    });
+}, "Same-origin iframe with 'Cross-Origin-Options: invalid' HTTP header");
+
+promise_test(function(test) {
+    return withPopup("serve-cross-origin-options-header.py?value=deny", true /* isCrossOrigin */).then((result) => {
+        testCrossOriginOption(result.window, "deny", true /* isCrossOrigin */);
+    });
+}, "Cross-origin popup with 'Cross-Origin-Options: deny' HTTP header");
+
+promise_test(function(test) {
+    return withPopup("serve-cross-origin-options-header.py?value=allow-postmessage", true /* isCrossOrigin */).then((result) => {
+        testCrossOriginOption(result.window, "allow-postmessage", true /* isCrossOrigin */);
+    });
+}, "Cross-origin popup with 'Cross-Origin-Options: allow-postmessage' HTTP header");
+
+promise_test(function(test) {
+    return withPopup("serve-cross-origin-options-header.py?value=allow", true /* isCrossOrigin */).then((result) => {
+        const w = result.window;
+        testCrossOriginOption(w, "allow", true /* isCrossOrigin */);
+
+        checkPopupPropertyValues(w);
+    });
+}, "Cross-origin popup with 'Cross-Origin-Options: allow' HTTP header");
+
+promise_test(function(test) {
+    return withPopup("serve-cross-origin-options-header.py?value=invalid", true /* isCrossOrigin */).then((result) => {
+        const w = result.window;
+        testCrossOriginOption(w, "allow", true /* isCrossOrigin */);
+
+        checkPopupPropertyValues(w);
+    });
+}, "Cross-origin popup with 'Cross-Origin-Options: invalid' HTTP header");
+
+promise_test(function(test) {
+    return withPopup("serve-cross-origin-options-header.py?value=deny", false /* isCrossOrigin */).then((result) => {
+         const w = result.window;
+        testCrossOriginOption(w, "deny", false /* isCrossOrigin */);
+
+        checkPopupPropertyValues(w);
+    });
+}, "Same-origin popup with 'Cross-Origin-Options: deny' HTTP header");
+
+promise_test(function(test) {
+    return withPopup("serve-cross-origin-options-header.py?value=allow-postmessage", false /* isCrossOrigin */).then((result) => {
+         const w = result.window;
+        testCrossOriginOption(w, "allow-postmessage", false /* isCrossOrigin */);
+
+        checkPopupPropertyValues(w);
+    });
+}, "Same-origin popup with 'Cross-Origin-Options: allow-postmessage' HTTP header");
+
+promise_test(function(test) {
+    return withPopup("serve-cross-origin-options-header.py?value=allow", false /* isCrossOrigin */).then((result) => {
+         const w = result.window;
+        testCrossOriginOption(w, "allow", false /* isCrossOrigin */);
+
+        checkPopupPropertyValues(w);
+    });
+}, "Same-origin popup with 'Cross-Origin-Options: allow' HTTP header");
+
+promise_test(function(test) {
+    return withPopup("serve-cross-origin-options-header.py?value=invalid", false /* isCrossOrigin */).then((result) => {
+         const w = result.window;
+        testCrossOriginOption(w, "allow", false /* isCrossOrigin */);
+
+        checkPopupPropertyValues(w);
+    });
+}, "Same-origin popup with 'Cross-Origin-Options: invalid' HTTP header");
+
+</script>
+</body>
+</html>

Added: trunk/LayoutTests/http/wpt/cross-origin-options/resources/cross-origin-options-allow-postmessage-pong.html (0 => 231622)


--- trunk/LayoutTests/http/wpt/cross-origin-options/resources/cross-origin-options-allow-postmessage-pong.html	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/cross-origin-options/resources/cross-origin-options-allow-postmessage-pong.html	2018-05-10 00:33:37 UTC (rev 231622)
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script>
+addEventListener('message', (msg) => {
+    if (event.data ="" "PING")
+        event.source.postMessage("PONG", "*");
+    });
+    window.addEventListener('load', () => {
+        const ownerWindow = window.opener ? window.opener : window.top;
+        try {
+            ownerWindow.postMessage("READY", "*");
+        } catch (e) { }
+    });
+</script>
+</body>
+</html>

Added: trunk/LayoutTests/http/wpt/cross-origin-options/resources/cross-origin-options-allow-postmessage-pong.html.headers (0 => 231622)


--- trunk/LayoutTests/http/wpt/cross-origin-options/resources/cross-origin-options-allow-postmessage-pong.html.headers	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/cross-origin-options/resources/cross-origin-options-allow-postmessage-pong.html.headers	2018-05-10 00:33:37 UTC (rev 231622)
@@ -0,0 +1 @@
+Cross-Origin-Options: allow-postmessage

Added: trunk/LayoutTests/http/wpt/cross-origin-options/resources/serve-cross-origin-options-header.py (0 => 231622)


--- trunk/LayoutTests/http/wpt/cross-origin-options/resources/serve-cross-origin-options-header.py	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/cross-origin-options/resources/serve-cross-origin-options-header.py	2018-05-10 00:33:37 UTC (rev 231622)
@@ -0,0 +1,14 @@
+def main(request, response):
+    headers = [("Content-Type", "text/html"),
+               ("Cross-Origin-Options", request.GET['value']),]
+    return 200, headers, """TEST
+        <iframe name="subframe"></iframe>
+        <script>
+            window.addEventListener('load', () => {
+                const ownerWindow = window.opener ? window.opener : window.top;
+                try {
+                    ownerWindow.postMessage("READY", "*");
+                } catch (e) { }
+            });
+        </script>
+    """

Added: trunk/LayoutTests/http/wpt/cross-origin-options/resources/utils.js (0 => 231622)


--- trunk/LayoutTests/http/wpt/cross-origin-options/resources/utils.js	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/cross-origin-options/resources/utils.js	2018-05-10 00:33:37 UTC (rev 231622)
@@ -0,0 +1,150 @@
+const RESOURCES_DIR = "/WebKit/cross-origin-options/resources/";
+
+function isCrossOriginWindow(w)
+{
+    try {
+        w.name;
+    } catch (e) {
+        return true;
+    }
+    return false;
+}
+
+async function waitForCrossOriginLoad(w)
+{
+    return new Promise((resolve) => {
+        window.addEventListener('message', (msg) => {
+            if (msg.source != w || msg.data != "READY")
+                return;
+            resolve();
+        });
+
+        let handle = setInterval(() => {
+            if (isCrossOriginWindow(w)) {
+                clearInterval(handle);
+                try {
+                    w.postMessage;
+                } catch (e) {
+                    // No point in waiting for "READY" message from window since postMessage is
+                    // not available.
+                    resolve();
+                }
+            }
+        }, 5);
+    });
+}
+
+async function withIframe(resourceFile, crossOrigin)
+{
+    return new Promise((resolve) => {
+        let resourceURL = crossOrigin ? get_host_info().HTTP_REMOTE_ORIGIN : get_host_info().HTTP_ORIGIN;
+        resourceURL += RESOURCES_DIR;
+        resourceURL += resourceFile;
+        let frame = document.createElement("iframe");
+        frame.src = ""
+        if (crossOrigin) {
+            document.body.appendChild(frame);
+            waitForCrossOriginLoad(frame.contentWindow).then(() => {
+                resolve(frame);
+            });
+        } else {
+            frame._onload_ = function() { resolve(frame); };
+            document.body.appendChild(frame);
+        }
+    });
+}
+
+async function withPopup(resourceFile, crossOrigin)
+{
+    return new Promise((resolve) => { 
+        let resourceURL = crossOrigin ? get_host_info().HTTP_REMOTE_ORIGIN : get_host_info().HTTP_ORIGIN;
+        resourceURL += RESOURCES_DIR;
+        resourceURL += resourceFile;
+
+        let w = open(resourceURL);
+        if (crossOrigin) {
+            waitForCrossOriginLoad(w).then(() => {
+                resolve({ 'window': w });
+            });
+        } else {
+            w._onload_ = function() { resolve({ 'window': w }); };
+        }
+   });
+}
+
+const crossOriginPropertyNames = [ 'blur', 'close', 'closed', 'focus', 'frames', 'length', 'location', 'opener', 'parent', 'postMessage', 'self', 'top', 'window' ];
+const forbiddenPropertiesCrossOrigin = ["name", "document", "history", "locationbar", "status", "frameElement", "navigator", "alert", "localStorage", "sessionStorage", "event", "foo", "bar"];
+
+function assert_not_throwing(f, message)
+{
+    try {
+        f();
+    } catch (e) {
+        assert_unreached(message);
+    }
+}
+
+function checkCrossOriginPropertiesAccess(w)
+{
+    for (let crossOriginPropertyName of crossOriginPropertyNames)
+       assert_not_throwing(function() { w[crossOriginPropertyName]; }, "Accessing property '" + crossOriginPropertyName +"' on Window should not throw");
+   
+    assert_false(w.closed, "'closed' property value"); 
+    assert_equals(w.frames, w, "'frames' property value");
+    assert_equals(w.self, w, "'self' property value");
+    assert_equals(w.window, w, "'window' property value");
+
+    assert_not_throwing(function() { w.blur(); }, "Calling blur() on Window should should throw");
+    assert_not_throwing(function() { w.focus(); }, "Calling focus() on Window should should throw");
+    assert_not_throwing(function() { w.postMessage('test', '*'); }, "Calling postMessage() on Window should should throw");
+}
+
+function testCrossOriginOption(w, headerValue, isCrossOrigin)
+{
+    if (!isCrossOrigin) {
+        checkCrossOriginPropertiesAccess(w);
+        for (let forbiddenPropertyCrossOrigin of forbiddenPropertiesCrossOrigin)
+            assert_not_throwing(function() { eval("w." + forbiddenPropertyCrossOrigin); }, "Accessing property '" + forbiddenPropertyCrossOrigin + "' on Window should not throw");
+        assert_not_throwing(function() { w.foo = 1; }, "Setting expando property should not throw");
+        assert_equals(w.foo, 1, "expando property value");
+        return;
+    }
+
+    // Cross-origin case.
+    for (let forbiddenPropertyCrossOrigin of forbiddenPropertiesCrossOrigin) {
+        assert_throws("SecurityError", function() { eval("w." + forbiddenPropertyCrossOrigin); }, "Accessing property '" + forbiddenPropertyCrossOrigin + "' on Window should throw");
+        let desc = Object.getOwnPropertyDescriptor(window, forbiddenPropertyCrossOrigin);
+        if (desc && desc.value)
+            assert_throws("SecurityError", function() { desc.value.call(w); }, "Calling function '" + forbiddenPropertyCrossOrigin + "' on Window should throw (using getter from other window)");
+        else if (desc && desc.get)
+            assert_throws("SecurityError", function() { desc.get.call(w); }, "Accessing property '" + forbiddenPropertyCrossOrigin + "' on Window should throw (using getter from other window)");
+    }
+    assert_throws("SecurityError", function() { w.foo = 1; }, "Setting an expando property should throw");
+
+    if (headerValue == "deny" || headerValue == "allow-postmessage") {
+        for (let crossOriginPropertyName of crossOriginPropertyNames) {
+            if (headerValue == "allow-postmessage" && crossOriginPropertyName == "postMessage") {
+                assert_not_throwing(function() { w[crossOriginPropertyName]; }, "Accessing property '" + crossOriginPropertyName +"' on Window should not throw");
+            } else {
+                assert_throws("SecurityError", function() { w[crossOriginPropertyName]; }, "Accessing '" + crossOriginPropertyName + "' property");
+
+                let desc = Object.getOwnPropertyDescriptor(window, crossOriginPropertyName);
+                if (desc && desc.value)
+                    assert_throws("SecurityError", function() { desc.value.call(w); }, "Calling function '" + crossOriginPropertyName + "' on Window should throw (using getter from other window)");
+                else if (desc && desc.get)
+                    assert_throws("SecurityError", function() { desc.get.call(w); }, "Accessing property '" + crossOriginPropertyName + "' on Window should throw (using getter from other window)");
+            }
+        }
+        if (headerValue == "allow-postmessage") {
+            assert_not_throwing(function() { w.postMessage('test', '*'); }, "Calling postMessage() on Window should not throw");
+            assert_not_throwing(function() { Object.getOwnPropertyDescriptor(window, 'postMessage').value.call(w, 'test', '*'); }, "Calling postMessage() on Window should not throw (using getter from other window)");
+        }
+
+        assert_array_equals(Object.getOwnPropertyNames(w).sort(), headerValue == "allow-postmessage" ? ['postMessage'] : [], "Object.getOwnPropertyNames()");
+
+        return;
+    }
+
+    assert_array_equals(Object.getOwnPropertyNames(w).sort(), crossOriginPropertyNames.sort(), "Object.getOwnPropertyNames()");
+    checkCrossOriginPropertiesAccess(w);
+}

Modified: trunk/Source/WebCore/ChangeLog (231621 => 231622)


--- trunk/Source/WebCore/ChangeLog	2018-05-10 00:08:40 UTC (rev 231621)
+++ trunk/Source/WebCore/ChangeLog	2018-05-10 00:33:37 UTC (rev 231622)
@@ -1,3 +1,83 @@
+2018-05-09  Chris Dumez  <[email protected]>
+
+        Add initial support for 'Cross-Origin-Options' HTTP response header
+        https://bugs.webkit.org/show_bug.cgi?id=184996
+        <rdar://problem/39664620>
+
+        Reviewed by Geoff Garen.
+
+        Add initial support for 'Cross-Origin-Options' HTTP response header behind an experimental
+        feature flag, on by default. When the HTTP server services this HTTP response header for a
+        main resource, we'll set these options on the corresponding Document. This will impact the
+        behavior of the Document's associated Window API when cross-origin.
+
+        The HTTP header has 3 possible values:
+        - allow: This is the default. Regular cross-origin Window API is available.
+        - allow-postmessage: Only postMessage() is available on a cross-origin window, trying to
+          access anything else will throw a SecurityError.
+        - deny: Trying to do anything with a cross-origin window will throw a SecurityError.
+
+        The header has no effect when accessing same origin windows.
+
+        Note that on cross-origin access from Window A to Window B, we check the cross-origin
+        options for both Window A and Window B and use the lowest common denominator as effective
+        cross-origin options for the access. So if Window A has 'Cross-Origin-Options: deny' and
+        tries to call postMessage() on Window B which has 'Cross-Origin-Options: allow-postmessage',
+        we will throw a SecurityError. This is because Window A's more restrictive options (deny)
+        apply.
+
+        Tests: http/wpt/cross-origin-options/allow-postmessage-from-deny.html
+               http/wpt/cross-origin-options/allow-postmessage.html
+               http/wpt/cross-origin-options/cross-origin-options-header.html
+
+        * bindings/js/JSDOMBindingSecurity.cpp:
+        (WebCore::BindingSecurity::shouldAllowAccessToDOMWindowGivenMinimumCrossOriginOptions):
+        * bindings/js/JSDOMBindingSecurity.h:
+        * bindings/js/JSDOMWindowCustom.cpp:
+        (WebCore::effectiveCrossOriginOptionsForAccess):
+        (WebCore::jsDOMWindowGetOwnPropertySlotRestrictedAccess):
+        (WebCore::JSDOMWindow::getOwnPropertySlot):
+        (WebCore::JSDOMWindow::getOwnPropertySlotByIndex):
+        (WebCore::addCrossOriginWindowPropertyNames):
+        (WebCore::addScopedChildrenIndexes):
+        (WebCore::addCrossOriginWindowOwnPropertyNames):
+        (WebCore::JSDOMWindow::getOwnPropertyNames):
+        * bindings/js/JSDOMWindowCustom.h:
+        * bindings/js/JSRemoteDOMWindowCustom.cpp:
+        (WebCore::JSRemoteDOMWindow::getOwnPropertySlot):
+        (WebCore::JSRemoteDOMWindow::getOwnPropertySlotByIndex):
+        (WebCore::JSRemoteDOMWindow::getOwnPropertyNames):
+        * bindings/scripts/CodeGeneratorJS.pm:
+        (GenerateAttributeGetterBodyDefinition):
+        (GetCrossOriginsOptionsFromExtendedAttributeValue):
+        (GenerateAttributeSetterBodyDefinition):
+        (GenerateOperationBodyDefinition):
+        * bindings/scripts/IDLAttributes.json:
+        * dom/Document.cpp:
+        (WebCore::Document::setCrossOriginOptions):
+        * dom/Document.h:
+        (WebCore::Document::crossOriginOptions const):
+        * loader/FrameLoader.cpp:
+        (WebCore::FrameLoader::didBeginDocument):
+        * page/AbstractDOMWindow.cpp:
+        (WebCore::AbstractDOMWindow::AbstractDOMWindow):
+        * page/AbstractDOMWindow.h:
+        (WebCore::AbstractDOMWindow::crossOriginOptions):
+        (WebCore::AbstractDOMWindow::setCrossOriginOptions):
+        * page/DOMWindow.cpp:
+        (WebCore::DOMWindow::DOMWindow):
+        (WebCore::DOMWindow::didSecureTransitionTo):
+        * page/DOMWindow.idl:
+        * page/Frame.h:
+        * page/RemoteDOMWindow.cpp:
+        (WebCore::RemoteDOMWindow::RemoteDOMWindow):
+        * page/RemoteDOMWindow.h:
+        * page/Settings.yaml:
+        * platform/network/HTTPHeaderNames.in:
+        * platform/network/HTTPParsers.cpp:
+        (WebCore::parseCrossOriginOptionsHeader):
+        * platform/network/HTTPParsers.h:
+
 2018-05-09  Ryosuke Niwa  <[email protected]>
 
         Release assert in TreeScopeOrderedMap::remove via HTMLImageElement::removedFromAncestor

Modified: trunk/Source/WebCore/bindings/js/JSDOMBindingSecurity.cpp (231621 => 231622)


--- trunk/Source/WebCore/bindings/js/JSDOMBindingSecurity.cpp	2018-05-10 00:08:40 UTC (rev 231621)
+++ trunk/Source/WebCore/bindings/js/JSDOMBindingSecurity.cpp	2018-05-10 00:33:37 UTC (rev 231622)
@@ -25,6 +25,7 @@
 #include "DOMWindow.h"
 #include "Document.h"
 #include "Frame.h"
+#include "HTTPParsers.h"
 #include "JSDOMExceptionHandling.h"
 #include "JSDOMWindowBase.h"
 #include "SecurityOrigin.h"
@@ -99,4 +100,19 @@
     return !target || canAccessDocument(&state, &target->document(), LogSecurityError);
 }
 
+bool BindingSecurity::shouldAllowAccessToDOMWindowGivenMinimumCrossOriginOptions(JSC::ExecState* state, DOMWindow& target, CrossOriginOptions minimumCrossOriginOptions, SecurityReportingOption reportingOption)
+{
+    DOMWindow& source = activeDOMWindow(*state);
+    ASSERT(minimumCrossOriginOptions > CrossOriginOptions::Deny);
+
+    static_assert(CrossOriginOptions::Deny < CrossOriginOptions::AllowPostMessage && CrossOriginOptions::AllowPostMessage < CrossOriginOptions::Allow, "More restrictive cross-origin options should have lower values");
+
+    // Fast path.
+    auto effectiveCrossOriginOptions = std::min(source.crossOriginOptions(), target.crossOriginOptions());
+    if (effectiveCrossOriginOptions >= minimumCrossOriginOptions)
+        return true;
+
+    return shouldAllowAccessToDOMWindow(state, target, reportingOption);
+}
+
 } // namespace WebCore

Modified: trunk/Source/WebCore/bindings/js/JSDOMBindingSecurity.h (231621 => 231622)


--- trunk/Source/WebCore/bindings/js/JSDOMBindingSecurity.h	2018-05-10 00:08:40 UTC (rev 231621)
+++ trunk/Source/WebCore/bindings/js/JSDOMBindingSecurity.h	2018-05-10 00:33:37 UTC (rev 231622)
@@ -36,6 +36,8 @@
 class Frame;
 class Node;
 
+enum class CrossOriginOptions;
+
 void printErrorMessageForFrame(Frame*, const String& message);
 
 enum SecurityReportingOption { DoNotReportSecurityError, LogSecurityError, ThrowSecurityError };
@@ -53,6 +55,8 @@
 bool shouldAllowAccessToFrame(JSC::ExecState&, Frame&, String& message);
 bool shouldAllowAccessToNode(JSC::ExecState&, Node*);
 
+bool shouldAllowAccessToDOMWindowGivenMinimumCrossOriginOptions(JSC::ExecState*, DOMWindow&, CrossOriginOptions, SecurityReportingOption = LogSecurityError);
+
 };
 
 template<typename T> inline T* BindingSecurity::checkSecurityForNode(JSC::ExecState& state, T& node)

Modified: trunk/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp (231621 => 231622)


--- trunk/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp	2018-05-10 00:08:40 UTC (rev 231621)
+++ trunk/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp	2018-05-10 00:33:37 UTC (rev 231622)
@@ -26,6 +26,7 @@
 #include "HTMLCollection.h"
 #include "HTMLDocument.h"
 #include "HTMLFrameOwnerElement.h"
+#include "HTTPParsers.h"
 #include "JSDOMBindingSecurity.h"
 #include "JSDOMConvertNullable.h"
 #include "JSDOMConvertNumbers.h"
@@ -55,6 +56,12 @@
 namespace WebCore {
 using namespace JSC;
 
+static CrossOriginOptions effectiveCrossOriginOptionsForAccess(ExecState& state, AbstractDOMWindow& target)
+{
+    static_assert(CrossOriginOptions::Deny < CrossOriginOptions::AllowPostMessage && CrossOriginOptions::AllowPostMessage < CrossOriginOptions::Allow, "More restrictive cross-origin options should have lower values");
+    return std::min(activeDOMWindow(state).crossOriginOptions(), target.crossOriginOptions());
+}
+
 EncodedJSValue JSC_HOST_CALL jsDOMWindowInstanceFunctionShowModalDialog(ExecState*);
 
 void JSDOMWindow::visitAdditionalChildren(SlotVisitor& visitor)
@@ -80,9 +87,9 @@
 #endif
 
 template <DOMWindowType windowType>
-bool jsDOMWindowGetOwnPropertySlotRestrictedAccess(JSDOMGlobalObject* thisObject, AbstractFrame* frame, ExecState* exec, PropertyName propertyName, PropertySlot& slot, const String& errorMessage)
+bool jsDOMWindowGetOwnPropertySlotRestrictedAccess(JSDOMGlobalObject* thisObject, AbstractDOMWindow& window, ExecState& state, PropertyName propertyName, PropertySlot& slot, const String& errorMessage)
 {
-    VM& vm = exec->vm();
+    VM& vm = state.vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     auto& builtinNames = static_cast<JSVMClientData*>(vm.clientData)->builtinNames();
@@ -93,6 +100,21 @@
         return true;
     }
 
+    switch (effectiveCrossOriginOptionsForAccess(state, window)) {
+    case CrossOriginOptions::AllowPostMessage:
+        if (propertyName == builtinNames.postMessagePublicName()) {
+            slot.setCustom(thisObject, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum), windowType == DOMWindowType::Remote ? nonCachingStaticFunctionGetter<jsRemoteDOMWindowInstanceFunctionPostMessage, 0> : nonCachingStaticFunctionGetter<jsDOMWindowInstanceFunctionPostMessage, 2>);
+            return true;
+        }
+        FALLTHROUGH;
+    case CrossOriginOptions::Deny:
+        throwSecurityError(state, scope, errorMessage);
+        slot.setUndefined();
+        return false;
+    case CrossOriginOptions::Allow:
+        break;
+    }
+
     // These are the functions we allow access to cross-origin (DoNotCheckSecurity in IDL).
     // Always provide the original function, on a fresh uncached function object.
     if (propertyName == builtinNames.blurPublicName()) {
@@ -136,7 +158,7 @@
         // For any other entries in the static property table, deny access. (Early return also prevents
         // named getter from returning frames with matching names - this seems a little questionable, see
         // FIXME comment on prototype search below.)
-        throwSecurityError(*exec, scope, errorMessage);
+        throwSecurityError(state, scope, errorMessage);
         slot.setUndefined();
         return false;
     }
@@ -146,19 +168,20 @@
     // 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.
+    auto* frame = window.frame();
     if (frame && is<Frame>(*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()));
+            slot.setValue(thisObject, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::DontEnum, toJS(&state, scopedChild->document()->domWindow()));
             return true;
         }
     }
 
-    throwSecurityError(*exec, scope, errorMessage);
+    throwSecurityError(state, scope, errorMessage);
     slot.setUndefined();
     return false;
 }
-template bool jsDOMWindowGetOwnPropertySlotRestrictedAccess<DOMWindowType::Local>(JSDOMGlobalObject*, AbstractFrame*, ExecState*, PropertyName, PropertySlot&, const String&);
-template bool jsDOMWindowGetOwnPropertySlotRestrictedAccess<DOMWindowType::Remote>(JSDOMGlobalObject*, AbstractFrame*, ExecState*, PropertyName, PropertySlot&, const String&);
+template bool jsDOMWindowGetOwnPropertySlotRestrictedAccess<DOMWindowType::Local>(JSDOMGlobalObject*, AbstractDOMWindow&, ExecState&, PropertyName, PropertySlot&, const String&);
+template bool jsDOMWindowGetOwnPropertySlotRestrictedAccess<DOMWindowType::Remote>(JSDOMGlobalObject*, AbstractDOMWindow&, ExecState&, PropertyName, PropertySlot&, const String&);
 
 // Property access sequence is:
 // (1) indexed properties,
@@ -172,13 +195,12 @@
         return getOwnPropertySlotByIndex(object, state, index.value(), slot);
 
     auto* thisObject = jsCast<JSDOMWindow*>(object);
-    auto* frame = thisObject->wrapped().frame();
 
     // Hand off all cross-domain access to jsDOMWindowGetOwnPropertySlotRestrictedAccess.
     String errorMessage;
     if (!BindingSecurity::shouldAllowAccessToDOMWindow(*state, thisObject->wrapped(), errorMessage))
-        return jsDOMWindowGetOwnPropertySlotRestrictedAccess<DOMWindowType::Local>(thisObject, frame, state, propertyName, slot, errorMessage);
-    
+        return jsDOMWindowGetOwnPropertySlotRestrictedAccess<DOMWindowType::Local>(thisObject, thisObject->wrapped(), *state, propertyName, slot, errorMessage);
+
     // FIXME: this need more explanation.
     // (Particularly, is it correct that this exists here but not in getOwnPropertySlotByIndex?)
     slot.setWatchpointSet(thisObject->m_windowCloseWatchpoints);
@@ -186,6 +208,8 @@
     // (2) Regular own properties.
     PropertySlot slotCopy = slot;
     if (Base::getOwnPropertySlot(thisObject, state, propertyName, slot)) {
+        auto* frame = thisObject->wrapped().frame();
+
         // Detect when we're getting the property 'showModalDialog', this is disabled, and has its original value.
         bool isShowModalDialogAndShouldHide = propertyName == static_cast<JSVMClientData*>(state->vm().clientData)->builtinNames().showModalDialogPublicName()
             && (!frame || !DOMWindow::canShowModalDialog(*frame))
@@ -213,22 +237,39 @@
 bool JSDOMWindow::getOwnPropertySlotByIndex(JSObject* object, ExecState* state, unsigned index, PropertySlot& slot)
 {
     auto* thisObject = jsCast<JSDOMWindow*>(object);
-    auto* frame = thisObject->wrapped().frame();
+    auto& window = thisObject->wrapped();
+    auto* frame = window.frame();
 
     // Indexed getters take precendence over regular properties, so caching would be invalid.
     slot.disableCaching();
 
+    String errorMessage;
+    std::optional<bool> cachedIsCrossOriginAccess;
+    auto isCrossOriginAccess = [&] {
+        if (!cachedIsCrossOriginAccess)
+            cachedIsCrossOriginAccess = !BindingSecurity::shouldAllowAccessToDOMWindow(*state, window, errorMessage);
+        return *cachedIsCrossOriginAccess;
+    };
+
     // (1) First, indexed properties.
-    // These are also allowed cross-orgin, so come before the access check.
-    if (frame && index < frame->tree().scopedChildCount()) {
-        slot.setValue(thisObject, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly), toJS(state, frame->tree().scopedChild(index)->document()->domWindow()));
-        return true;
+    // These are also allowed cross-origin, so come before the access check.
+    switch (effectiveCrossOriginOptionsForAccess(*state, window)) {
+    case CrossOriginOptions::Deny:
+    case CrossOriginOptions::AllowPostMessage:
+        if (isCrossOriginAccess())
+            break;
+        FALLTHROUGH;
+    case CrossOriginOptions::Allow:
+        if (frame && index < frame->tree().scopedChildCount()) {
+            slot.setValue(thisObject, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly), toJS(state, frame->tree().scopedChild(index)->document()->domWindow()));
+            return true;
+        }
+        break;
     }
 
     // Hand off all cross-domain/frameless access to jsDOMWindowGetOwnPropertySlotRestrictedAccess.
-    String errorMessage;
-    if (!BindingSecurity::shouldAllowAccessToDOMWindow(*state, thisObject->wrapped(), errorMessage))
-        return jsDOMWindowGetOwnPropertySlotRestrictedAccess<DOMWindowType::Local>(thisObject, frame, state, Identifier::from(state, index), slot, errorMessage);
+    if (isCrossOriginAccess())
+        return jsDOMWindowGetOwnPropertySlotRestrictedAccess<DOMWindowType::Local>(thisObject, window, *state, Identifier::from(state, index), slot, errorMessage);
 
     // (2) Regular own properties.
     return Base::getOwnPropertySlotByIndex(thisObject, state, index, slot);
@@ -287,8 +328,10 @@
 }
 
 // https://html.spec.whatwg.org/#crossoriginproperties-(-o-)
-static void addCrossOriginWindowPropertyNames(VM& vm, PropertyNameArray& propertyNames)
+static void addCrossOriginWindowPropertyNames(ExecState& state, AbstractDOMWindow& window, PropertyNameArray& propertyNames)
 {
+    auto& vm = state.vm();
+
     static const Identifier* const properties[] = {
         &static_cast<JSVMClientData*>(vm.clientData)->builtinNames().blurPublicName(),
         &static_cast<JSVMClientData*>(vm.clientData)->builtinNames().closePublicName(),
@@ -304,8 +347,18 @@
         &static_cast<JSVMClientData*>(vm.clientData)->builtinNames().topPublicName(),
         &static_cast<JSVMClientData*>(vm.clientData)->builtinNames().windowPublicName()
     };
-    for (auto* property : properties)
-        propertyNames.add(*property);
+
+    switch (effectiveCrossOriginOptionsForAccess(state, window)) {
+    case CrossOriginOptions::Allow:
+        for (auto* property : properties)
+            propertyNames.add(*property);
+        break;
+    case CrossOriginOptions::AllowPostMessage:
+        propertyNames.add(static_cast<JSVMClientData*>(vm.clientData)->builtinNames().postMessagePublicName());
+        break;
+    case CrossOriginOptions::Deny:
+        break;
+    }
 }
 
 static void addScopedChildrenIndexes(ExecState& state, DOMWindow& window, PropertyNameArray& propertyNames)
@@ -318,6 +371,14 @@
     if (!frame)
         return;
 
+    switch (effectiveCrossOriginOptionsForAccess(state, window)) {
+    case CrossOriginOptions::Allow:
+        break;
+    case CrossOriginOptions::Deny:
+    case CrossOriginOptions::AllowPostMessage:
+        return;
+    }
+
     unsigned scopedChildCount = frame->tree().scopedChildCount();
     for (unsigned i = 0; i < scopedChildCount; ++i)
         propertyNames.add(Identifier::from(&state, i));
@@ -324,11 +385,11 @@
 }
 
 // https://html.spec.whatwg.org/#crossoriginownpropertykeys-(-o-)
-void addCrossOriginWindowOwnPropertyNames(ExecState& state, PropertyNameArray& propertyNames)
+void addCrossOriginWindowOwnPropertyNames(ExecState& state, AbstractDOMWindow& window, PropertyNameArray& propertyNames)
 {
-    VM& vm = state.vm();
-    addCrossOriginWindowPropertyNames(vm, propertyNames);
+    addCrossOriginWindowPropertyNames(state, window, propertyNames);
 
+    auto& vm = state.vm();
     propertyNames.add(vm.propertyNames->toStringTagSymbol);
     propertyNames.add(vm.propertyNames->hasInstanceSymbol);
     propertyNames.add(vm.propertyNames->isConcatSpreadableSymbol);
@@ -343,7 +404,7 @@
 
     if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->wrapped(), DoNotReportSecurityError)) {
         if (mode.includeDontEnumProperties())
-            addCrossOriginWindowOwnPropertyNames(*exec, propertyNames);
+            addCrossOriginWindowOwnPropertyNames(*exec, thisObject->wrapped(), propertyNames);
         return;
     }
     Base::getOwnPropertyNames(thisObject, exec, propertyNames, mode);

Modified: trunk/Source/WebCore/bindings/js/JSDOMWindowCustom.h (231621 => 231622)


--- trunk/Source/WebCore/bindings/js/JSDOMWindowCustom.h	2018-05-10 00:08:40 UTC (rev 231621)
+++ trunk/Source/WebCore/bindings/js/JSDOMWindowCustom.h	2018-05-10 00:33:37 UTC (rev 231622)
@@ -22,6 +22,7 @@
 
 namespace WebCore {
 
+class AbstractDOMWindow;
 class AbstractFrame;
 
 inline JSDOMWindow* asJSDOMWindow(JSC::JSGlobalObject* globalObject)
@@ -37,8 +38,8 @@
 enum class DOMWindowType { Local, Remote };
 
 template <DOMWindowType windowType>
-bool jsDOMWindowGetOwnPropertySlotRestrictedAccess(JSDOMGlobalObject*, AbstractFrame*, JSC::ExecState*, JSC::PropertyName, JSC::PropertySlot&, const String&);
+bool jsDOMWindowGetOwnPropertySlotRestrictedAccess(JSDOMGlobalObject*, AbstractDOMWindow&, JSC::ExecState&, JSC::PropertyName, JSC::PropertySlot&, const String&);
 
-void addCrossOriginWindowOwnPropertyNames(JSC::ExecState&, JSC::PropertyNameArray&);
+void addCrossOriginWindowOwnPropertyNames(JSC::ExecState&, AbstractDOMWindow&, JSC::PropertyNameArray&);
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/bindings/js/JSRemoteDOMWindowCustom.cpp (231621 => 231622)


--- trunk/Source/WebCore/bindings/js/JSRemoteDOMWindowCustom.cpp	2018-05-10 00:08:40 UTC (rev 231621)
+++ trunk/Source/WebCore/bindings/js/JSRemoteDOMWindowCustom.cpp	2018-05-10 00:33:37 UTC (rev 231622)
@@ -37,15 +37,12 @@
         return getOwnPropertySlotByIndex(object, state, index.value(), slot);
 
     auto* thisObject = jsCast<JSRemoteDOMWindow*>(object);
-    auto* frame = thisObject->wrapped().frame();
-
-    return jsDOMWindowGetOwnPropertySlotRestrictedAccess<DOMWindowType::Remote>(thisObject, frame, state, propertyName, slot, String());
+    return jsDOMWindowGetOwnPropertySlotRestrictedAccess<DOMWindowType::Remote>(thisObject, thisObject->wrapped(), *state, propertyName, slot, String());
 }
 
 bool JSRemoteDOMWindow::getOwnPropertySlotByIndex(JSObject* object, ExecState* state, unsigned index, PropertySlot& slot)
 {
     auto* thisObject = jsCast<JSRemoteDOMWindow*>(object);
-    auto* frame = thisObject->wrapped().frame();
 
     // Indexed getters take precendence over regular properties, so caching would be invalid.
     slot.disableCaching();
@@ -52,7 +49,7 @@
 
     // FIXME: Add support for indexed properties.
 
-    return jsDOMWindowGetOwnPropertySlotRestrictedAccess<DOMWindowType::Remote>(thisObject, frame, state, Identifier::from(state, index), slot, String());
+    return jsDOMWindowGetOwnPropertySlotRestrictedAccess<DOMWindowType::Remote>(thisObject, thisObject->wrapped(), *state, Identifier::from(state, index), slot, String());
 }
 
 bool JSRemoteDOMWindow::put(JSCell* cell, ExecState* state, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
@@ -100,12 +97,14 @@
     return false;
 }
 
-void JSRemoteDOMWindow::getOwnPropertyNames(JSObject*, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+void JSRemoteDOMWindow::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
 {
+    auto* thisObject = jsCast<JSRemoteDOMWindow*>(object);
+
     // FIXME: Add scoped children indexes.
 
     if (mode.includeDontEnumProperties())
-        addCrossOriginWindowOwnPropertyNames(*exec, propertyNames);
+        addCrossOriginWindowOwnPropertyNames(*exec, thisObject->wrapped(), propertyNames);
 }
 
 bool JSRemoteDOMWindow::defineOwnProperty(JSC::JSObject*, JSC::ExecState* state, JSC::PropertyName, const JSC::PropertyDescriptor&, bool)

Modified: trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm (231621 => 231622)


--- trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm	2018-05-10 00:08:40 UTC (rev 231621)
+++ trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm	2018-05-10 00:33:37 UTC (rev 231622)
@@ -4706,7 +4706,13 @@
         !$attribute->extendedAttributes->{DoNotCheckSecurityOnGetter}) {
         AddToImplIncludes("JSDOMBindingSecurity.h", $conditional);
         if ($interface->type->name eq "DOMWindow") {
-            push(@$outputArray, "    if (!BindingSecurity::shouldAllowAccessToDOMWindow(&state, thisObject.wrapped(), ThrowSecurityError))\n");
+            if ($attribute->extendedAttributes->{DoNotCheckSecurityIf}) {
+                my $crossOriginOptions = GetCrossOriginsOptionsFromExtendedAttributeValue($attribute->extendedAttributes->{DoNotCheckSecurityIf});
+                AddToImplIncludes("HTTPParsers.h", $conditional);
+                push(@$outputArray, "    if (!BindingSecurity::shouldAllowAccessToDOMWindowGivenMinimumCrossOriginOptions(&state, thisObject.wrapped(), $crossOriginOptions, ThrowSecurityError))\n");
+            } else {
+                push(@$outputArray, "    if (!BindingSecurity::shouldAllowAccessToDOMWindow(&state, thisObject.wrapped(), ThrowSecurityError))\n");
+            }
         } else {
             push(@$outputArray, "    if (!BindingSecurity::shouldAllowAccessToFrame(&state, thisObject.wrapped().frame(), ThrowSecurityError))\n");
         }
@@ -4814,6 +4820,15 @@
     push(@$outputArray, "#endif\n\n") if $conditional;
 }
 
+sub GetCrossOriginsOptionsFromExtendedAttributeValue
+{
+    my $extendedAttributeValue = shift;
+
+    return "CrossOriginOptions::Allow" if $extendedAttributeValue eq "CrossOriginOptionsAllow";
+    return "CrossOriginOptions::AllowPostMessage" if $extendedAttributeValue eq "CrossOriginOptionsAllowPostMessage";
+    die "Unsupported CrossOriginOptions: " + $extendedAttributeValue;
+}
+
 sub GenerateAttributeSetterBodyDefinition
 {
     my ($outputArray, $interface, $className, $attribute, $attributeSetterBodyName, $conditional) = @_;
@@ -4836,7 +4851,13 @@
     if ($interface->extendedAttributes->{CheckSecurity} && !$attribute->extendedAttributes->{DoNotCheckSecurity} && !$attribute->extendedAttributes->{DoNotCheckSecurityOnSetter}) {
         AddToImplIncludes("JSDOMBindingSecurity.h", $conditional);
         if ($interface->type->name eq "DOMWindow") {
-            push(@$outputArray, "    if (!BindingSecurity::shouldAllowAccessToDOMWindow(&state, thisObject.wrapped(), ThrowSecurityError))\n");
+            if ($attribute->extendedAttributes->{DoNotCheckSecurityIf}) {
+                my $crossOriginOptions = GetCrossOriginsOptionsFromExtendedAttributeValue($attribute->extendedAttributes->{DoNotCheckSecurityIf});
+                AddToImplIncludes("HTTPParsers.h", $conditional);
+                push(@$outputArray, "    if (!BindingSecurity::shouldAllowAccessToDOMWindowGivenMinimumCrossOriginOptions(&state, thisObject.wrapped(), $crossOriginOptions, ThrowSecurityError))\n");
+            } else {
+                push(@$outputArray, "    if (!BindingSecurity::shouldAllowAccessToDOMWindow(&state, thisObject.wrapped(), ThrowSecurityError))\n");
+            }
         } else {
             push(@$outputArray, "    if (!BindingSecurity::shouldAllowAccessToFrame(&state, thisObject.wrapped().frame(), ThrowSecurityError))\n");
         }
@@ -5057,7 +5078,13 @@
             
             AddToImplIncludes("JSDOMBindingSecurity.h", $conditional);
             if ($interface->type->name eq "DOMWindow") {
-                push(@$outputArray, "    if (!BindingSecurity::shouldAllowAccessToDOMWindow(state, castedThis->wrapped(), ThrowSecurityError))\n");
+                if ($operation->extendedAttributes->{DoNotCheckSecurityIf}) {
+                    my $crossOriginOptions = GetCrossOriginsOptionsFromExtendedAttributeValue($operation->extendedAttributes->{DoNotCheckSecurityIf});
+                    AddToImplIncludes("HTTPParsers.h", $conditional);
+                    push(@$outputArray, "    if (!BindingSecurity::shouldAllowAccessToDOMWindowGivenMinimumCrossOriginOptions(state, castedThis->wrapped(), $crossOriginOptions, ThrowSecurityError))\n");
+                } else {
+                    push(@$outputArray, "    if (!BindingSecurity::shouldAllowAccessToDOMWindow(state, castedThis->wrapped(), ThrowSecurityError))\n");
+                }
                 push(@$outputArray, "        return JSValue::encode(jsUndefined());\n");
             } else {
                 push(@$outputArray, "    if (!BindingSecurity::shouldAllowAccessToFrame(state, castedThis->wrapped().frame(), ThrowSecurityError))\n");

Modified: trunk/Source/WebCore/bindings/scripts/IDLAttributes.json (231621 => 231622)


--- trunk/Source/WebCore/bindings/scripts/IDLAttributes.json	2018-05-10 00:08:40 UTC (rev 231621)
+++ trunk/Source/WebCore/bindings/scripts/IDLAttributes.json	2018-05-10 00:33:37 UTC (rev 231622)
@@ -161,6 +161,10 @@
         "DoNotCheckSecurity": {
             "contextsAllowed": ["attribute", "operation"]
         },
+        "DoNotCheckSecurityIf": {
+            "contextsAllowed": ["attribute", "operation"],
+            "values": ["CrossOriginOptionsAllow", "CrossOriginOptionsAllowPostMessage"]
+        },
         "DoNotCheckSecurityOnGetter": {
             "contextsAllowed": ["attribute"]
         },

Modified: trunk/Source/WebCore/dom/Document.cpp (231621 => 231622)


--- trunk/Source/WebCore/dom/Document.cpp	2018-05-10 00:08:40 UTC (rev 231621)
+++ trunk/Source/WebCore/dom/Document.cpp	2018-05-10 00:33:37 UTC (rev 231622)
@@ -517,6 +517,7 @@
     , m_didAssociateFormControlsTimer(*this, &Document::didAssociateFormControlsTimerFired)
     , m_cookieCacheExpiryTimer(*this, &Document::invalidateDOMCookieCache)
     , m_socketProvider(page() ? &page()->socketProvider() : nullptr)
+    , m_crossOriginOptions { CrossOriginOptions::Allow }
     , m_isSynthesized(constructionFlags & Synthesized)
     , m_isNonRenderedPlaceholder(constructionFlags & NonRenderedPlaceholder)
     , m_orientationNotifier(currentOrientation(frame))
@@ -7806,4 +7807,11 @@
     return page->chrome().client().signedPublicKeyAndChallengeString(keySizeIndex, challengeString, url);
 }
 
+void Document::setCrossOriginOptions(CrossOriginOptions value)
+{
+    m_crossOriginOptions = value;
+    if (auto* window = domWindow())
+        window->setCrossOriginOptions(value);
+}
+
 } // namespace WebCore

Modified: trunk/Source/WebCore/dom/Document.h (231621 => 231622)


--- trunk/Source/WebCore/dom/Document.h	2018-05-10 00:08:40 UTC (rev 231621)
+++ trunk/Source/WebCore/dom/Document.h	2018-05-10 00:33:37 UTC (rev 231622)
@@ -194,6 +194,7 @@
 template<typename> class ExceptionOr;
 
 enum CollectionType;
+enum class CrossOriginOptions;
 enum class ShouldOpenExternalURLsPolicy;
 
 enum class RouteSharingPolicy;
@@ -1430,6 +1431,9 @@
 
     String signedPublicKeyAndChallengeString(unsigned keySizeIndex, const String& challengeString, const URL&);
 
+    CrossOriginOptions crossOriginOptions() const { return m_crossOriginOptions; }
+    void setCrossOriginOptions(CrossOriginOptions value);
+
 protected:
     enum ConstructionFlags { Synthesized = 1, NonRenderedPlaceholder = 1 << 1 };
     Document(Frame*, const URL&, unsigned = DefaultDocumentClass, unsigned constructionFlags = 0);
@@ -1815,6 +1819,8 @@
 
     unsigned m_writeRecursionDepth { 0 };
 
+    CrossOriginOptions m_crossOriginOptions;
+
     InheritedBool m_designMode { inherit };
     MediaProducer::MediaStateFlags m_mediaState { MediaProducer::IsNotPlaying };
     bool m_userHasInteractedWithMediaElement { false };

Modified: trunk/Source/WebCore/loader/FrameLoader.cpp (231621 => 231622)


--- trunk/Source/WebCore/loader/FrameLoader.cpp	2018-05-10 00:08:40 UTC (rev 231621)
+++ trunk/Source/WebCore/loader/FrameLoader.cpp	2018-05-10 00:33:37 UTC (rev 231622)
@@ -742,6 +742,12 @@
             if (!headerContentLanguage.isEmpty())
                 m_frame.document()->setContentLanguage(headerContentLanguage);
         }
+
+        if (m_frame.settings().crossOriginOptionsSupportEnabled()) {
+            String crossOriginOptionsHeader = m_documentLoader->response().httpHeaderField(HTTPHeaderName::CrossOriginOptions);
+            if (!crossOriginOptionsHeader.isEmpty())
+                m_frame.document()->setCrossOriginOptions(parseCrossOriginOptionsHeader(crossOriginOptionsHeader));
+        }
     }
 
     history().restoreDocumentState();

Modified: trunk/Source/WebCore/page/AbstractDOMWindow.cpp (231621 => 231622)


--- trunk/Source/WebCore/page/AbstractDOMWindow.cpp	2018-05-10 00:08:40 UTC (rev 231621)
+++ trunk/Source/WebCore/page/AbstractDOMWindow.cpp	2018-05-10 00:33:37 UTC (rev 231622)
@@ -37,8 +37,9 @@
     return map;
 }
 
-AbstractDOMWindow::AbstractDOMWindow(GlobalWindowIdentifier&& identifier)
+AbstractDOMWindow::AbstractDOMWindow(GlobalWindowIdentifier&& identifier, CrossOriginOptions crossOriginOptions)
     : m_identifier(WTFMove(identifier))
+    , m_crossOriginOptions(crossOriginOptions)
 {
     ASSERT(!allWindows().contains(identifier));
     allWindows().add(identifier, this);

Modified: trunk/Source/WebCore/page/AbstractDOMWindow.h (231621 => 231622)


--- trunk/Source/WebCore/page/AbstractDOMWindow.h	2018-05-10 00:08:40 UTC (rev 231621)
+++ trunk/Source/WebCore/page/AbstractDOMWindow.h	2018-05-10 00:33:37 UTC (rev 231622)
@@ -35,6 +35,8 @@
 
 class AbstractFrame;
 
+enum class CrossOriginOptions;
+
 // FIXME: Rename DOMWindow to LocalWindow and AbstractDOMWindow to DOMWindow.
 class AbstractDOMWindow : public RefCounted<AbstractDOMWindow>, public EventTargetWithInlineData {
 public:
@@ -52,8 +54,11 @@
     using RefCounted::ref;
     using RefCounted::deref;
 
+    CrossOriginOptions crossOriginOptions() { return m_crossOriginOptions; }
+    void setCrossOriginOptions(CrossOriginOptions value) { m_crossOriginOptions = value; }
+
 protected:
-    explicit AbstractDOMWindow(GlobalWindowIdentifier&&);
+    AbstractDOMWindow(GlobalWindowIdentifier&&, CrossOriginOptions);
 
     EventTargetInterface eventTargetInterface() const final { return DOMWindowEventTargetInterfaceType; }
     void refEventTarget() final { ref(); }
@@ -61,6 +66,7 @@
 
 private:
     GlobalWindowIdentifier m_identifier;
+    CrossOriginOptions m_crossOriginOptions;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/page/DOMWindow.cpp (231621 => 231622)


--- trunk/Source/WebCore/page/DOMWindow.cpp	2018-05-10 00:08:40 UTC (rev 231621)
+++ trunk/Source/WebCore/page/DOMWindow.cpp	2018-05-10 00:33:37 UTC (rev 231622)
@@ -402,7 +402,7 @@
 }
 
 DOMWindow::DOMWindow(Document& document)
-    : AbstractDOMWindow(GlobalWindowIdentifier { Process::identifier(), generateObjectIdentifier<WindowIdentifierType>() })
+    : AbstractDOMWindow(GlobalWindowIdentifier { Process::identifier(), generateObjectIdentifier<WindowIdentifierType>() }, document.crossOriginOptions())
     , ContextDestructionObserver(&document)
     , FrameDestructionObserver(document.frame())
 {
@@ -413,6 +413,7 @@
 void DOMWindow::didSecureTransitionTo(Document& document)
 {
     observeContext(&document);
+    setCrossOriginOptions(document.crossOriginOptions());
 }
 
 DOMWindow::~DOMWindow()

Modified: trunk/Source/WebCore/page/DOMWindow.idl (231621 => 231622)


--- trunk/Source/WebCore/page/DOMWindow.idl	2018-05-10 00:08:40 UTC (rev 231621)
+++ trunk/Source/WebCore/page/DOMWindow.idl	2018-05-10 00:33:37 UTC (rev 231622)
@@ -49,11 +49,11 @@
     PrimaryGlobal,
 ] interface DOMWindow : EventTarget {
     // The current browsing context.
-    [DoNotCheckSecurity, Unforgeable, ImplementedAs=self] readonly attribute WindowProxy window;
-    [Replaceable, DoNotCheckSecurityOnGetter] readonly attribute WindowProxy self;
+    [DoNotCheckSecurityIf=CrossOriginOptionsAllow, Unforgeable, ImplementedAs=self] readonly attribute WindowProxy window;
+    [Replaceable, DoNotCheckSecurityIf=CrossOriginOptionsAllow] 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.
+    [DoNotCheckSecurityIf=CrossOriginOptionsAllow, PutForwards=href, Unforgeable] 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 @@
     [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;
+    [DoNotCheckSecurityIf=CrossOriginOptionsAllow, CallWith=IncumbentDocument, ForwardDeclareInHeader] void close();
+    [DoNotCheckSecurityIf=CrossOriginOptionsAllow, ForwardDeclareInHeader] readonly attribute boolean closed;
     void stop();
-    [DoNotCheckSecurity, CallWith=IncumbentWindow, ForwardDeclareInHeader] void focus();
-    [DoNotCheckSecurity, ForwardDeclareInHeader] void blur();
+    [DoNotCheckSecurityIf=CrossOriginOptionsAllow, CallWith=IncumbentWindow, ForwardDeclareInHeader] void focus();
+    [DoNotCheckSecurityIf=CrossOriginOptionsAllow, ForwardDeclareInHeader] 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, DoNotCheckSecurityIf=CrossOriginOptionsAllow, ImplementedAs=self] readonly attribute WindowProxy frames;
+    [Replaceable, DoNotCheckSecurityIf=CrossOriginOptionsAllow] readonly attribute unsigned long length;
+    [DoNotCheckSecurityIf=CrossOriginOptionsAllow, Unforgeable] readonly attribute WindowProxy? top;
+    [DoNotCheckSecurityIf=CrossOriginOptionsAllow, CustomSetter] attribute WindowProxy? opener;
+    [Replaceable, DoNotCheckSecurityIf=CrossOriginOptionsAllow] readonly attribute WindowProxy? parent;
     [CheckSecurityForNode] readonly attribute Element? frameElement;
     [CallWith=ActiveWindow&FirstWindow] WindowProxy? open(optional USVString url = "" optional DOMString target = "_blank", optional [TreatNullAs=EmptyString] DOMString features = "");
 
@@ -92,7 +92,7 @@
     long requestAnimationFrame(RequestAnimationFrameCallback callback); // FIXME: Should return an unsigned long.
     void cancelAnimationFrame(long handle); // FIXME: handle should be an unsigned long.
 
-    [CallWith=ScriptState&IncumbentWindow, DoNotCheckSecurity, ForwardDeclareInHeader, MayThrowException] void postMessage(any message, USVString targetOrigin, optional sequence<object> transfer = []);
+    [CallWith=ScriptState&IncumbentWindow, DoNotCheckSecurityIf=CrossOriginOptionsAllowPostMessage, ForwardDeclareInHeader, MayThrowException] void postMessage(any message, USVString targetOrigin, optional sequence<object> transfer = []);
 
     // Obsolete members, still part of the HTML specification (https://html.spec.whatwg.org/#Window-partial).
     void captureEvents(); // Not implemented. Also not in modern standards. Empty function may help compatibility with legacy content.

Modified: trunk/Source/WebCore/page/Frame.h (231621 => 231622)


--- trunk/Source/WebCore/page/Frame.h	2018-05-10 00:08:40 UTC (rev 231621)
+++ trunk/Source/WebCore/page/Frame.h	2018-05-10 00:33:37 UTC (rev 231622)
@@ -136,7 +136,7 @@
 
     WEBCORE_EXPORT ~Frame();
 
-    DOMWindow* window() const;
+    WEBCORE_EXPORT DOMWindow* window() const;
 
     void addDestructionObserver(FrameDestructionObserver*);
     void removeDestructionObserver(FrameDestructionObserver*);

Modified: trunk/Source/WebCore/page/RemoteDOMWindow.cpp (231621 => 231622)


--- trunk/Source/WebCore/page/RemoteDOMWindow.cpp	2018-05-10 00:08:40 UTC (rev 231621)
+++ trunk/Source/WebCore/page/RemoteDOMWindow.cpp	2018-05-10 00:33:37 UTC (rev 231622)
@@ -32,8 +32,8 @@
 
 namespace WebCore {
 
-RemoteDOMWindow::RemoteDOMWindow(Ref<RemoteFrame>&& frame, GlobalWindowIdentifier&& identifier)
-    : AbstractDOMWindow(WTFMove(identifier))
+RemoteDOMWindow::RemoteDOMWindow(Ref<RemoteFrame>&& frame, GlobalWindowIdentifier&& identifier, CrossOriginOptions crossOriginOptions)
+    : AbstractDOMWindow(WTFMove(identifier), crossOriginOptions)
     , m_frame(WTFMove(frame))
 {
     m_frame->setWindow(this);

Modified: trunk/Source/WebCore/page/RemoteDOMWindow.h (231621 => 231622)


--- trunk/Source/WebCore/page/RemoteDOMWindow.h	2018-05-10 00:08:40 UTC (rev 231621)
+++ trunk/Source/WebCore/page/RemoteDOMWindow.h	2018-05-10 00:33:37 UTC (rev 231622)
@@ -44,9 +44,9 @@
 
 class RemoteDOMWindow final : public AbstractDOMWindow {
 public:
-    static Ref<RemoteDOMWindow> create(Ref<RemoteFrame>&& frame, GlobalWindowIdentifier&& identifier)
+    static Ref<RemoteDOMWindow> create(Ref<RemoteFrame>&& frame, GlobalWindowIdentifier&& identifier, CrossOriginOptions crossOriginOptions)
     {
-        return adoptRef(*new RemoteDOMWindow(WTFMove(frame), WTFMove(identifier)));
+        return adoptRef(*new RemoteDOMWindow(WTFMove(frame), WTFMove(identifier), crossOriginOptions));
     }
 
     ~RemoteDOMWindow() final;
@@ -68,7 +68,7 @@
     void postMessage(JSC::ExecState&, DOMWindow& incumbentWindow, JSC::JSValue message, const String& targetOrigin, Vector<JSC::Strong<JSC::JSObject>>&&);
 
 private:
-    WEBCORE_EXPORT RemoteDOMWindow(Ref<RemoteFrame>&&, GlobalWindowIdentifier&&);
+    WEBCORE_EXPORT RemoteDOMWindow(Ref<RemoteFrame>&&, GlobalWindowIdentifier&&, CrossOriginOptions);
 
     bool isRemoteDOMWindow() const final { return true; }
     bool isLocalDOMWindow() const final { return false; }

Modified: trunk/Source/WebCore/page/Settings.yaml (231621 => 231622)


--- trunk/Source/WebCore/page/Settings.yaml	2018-05-10 00:08:40 UTC (rev 231621)
+++ trunk/Source/WebCore/page/Settings.yaml	2018-05-10 00:33:37 UTC (rev 231622)
@@ -742,6 +742,9 @@
   initial: false
   onChange: setNeedsRecalcStyleInAllFrames
 
+crossOriginOptionsSupportEnabled:
+  initial: true
+
 accessibilityEventsEnabled:
   initial: true
   conditional: ACCESSIBILITY_EVENTS

Modified: trunk/Source/WebCore/platform/network/HTTPHeaderNames.in (231621 => 231622)


--- trunk/Source/WebCore/platform/network/HTTPHeaderNames.in	2018-05-10 00:08:40 UTC (rev 231621)
+++ trunk/Source/WebCore/platform/network/HTTPHeaderNames.in	2018-05-10 00:33:37 UTC (rev 231622)
@@ -50,6 +50,7 @@
 Content-Range
 Cookie
 Cookie2
+Cross-Origin-Options
 Date
 DNT
 Default-Style

Modified: trunk/Source/WebCore/platform/network/HTTPParsers.cpp (231621 => 231622)


--- trunk/Source/WebCore/platform/network/HTTPParsers.cpp	2018-05-10 00:08:40 UTC (rev 231621)
+++ trunk/Source/WebCore/platform/network/HTTPParsers.cpp	2018-05-10 00:33:37 UTC (rev 231622)
@@ -913,4 +913,19 @@
     return FromOriginDisposition::Invalid;
 }
 
+CrossOriginOptions parseCrossOriginOptionsHeader(StringView header)
+{
+    auto strippedHeader = stripLeadingAndTrailingHTTPSpaces(header);
+    if (strippedHeader.isEmpty())
+        return CrossOriginOptions::Allow;
+
+    if (equalLettersIgnoringASCIICase(strippedHeader, "deny"))
+        return CrossOriginOptions::Deny;
+
+    if (equalLettersIgnoringASCIICase(strippedHeader, "allow-postmessage"))
+        return CrossOriginOptions::AllowPostMessage;
+
+    return CrossOriginOptions::Allow;
 }
+
+}

Modified: trunk/Source/WebCore/platform/network/HTTPParsers.h (231621 => 231622)


--- trunk/Source/WebCore/platform/network/HTTPParsers.h	2018-05-10 00:08:40 UTC (rev 231621)
+++ trunk/Source/WebCore/platform/network/HTTPParsers.h	2018-05-10 00:33:37 UTC (rev 231622)
@@ -71,6 +71,13 @@
     Invalid
 };
 
+// Should be sorted from most restrictive to most permissive.
+enum class CrossOriginOptions {
+    Deny,
+    AllowPostMessage,
+    Allow,
+};
+
 bool isValidReasonPhrase(const String&);
 bool isValidHTTPHeaderValue(const String&);
 bool isValidAcceptHeaderValue(const String&);
@@ -111,6 +118,7 @@
 String normalizeHTTPMethod(const String&);
 
 WEBCORE_EXPORT FromOriginDisposition parseFromOriginHeader(const String&);
+CrossOriginOptions parseCrossOriginOptionsHeader(StringView);
 
 inline bool isHTTPSpace(UChar character)
 {

Modified: trunk/Source/WebKit/ChangeLog (231621 => 231622)


--- trunk/Source/WebKit/ChangeLog	2018-05-10 00:08:40 UTC (rev 231621)
+++ trunk/Source/WebKit/ChangeLog	2018-05-10 00:33:37 UTC (rev 231622)
@@ -1,3 +1,19 @@
+2018-05-09  Chris Dumez  <[email protected]>
+
+        Add initial support for 'Cross-Origin-Options' HTTP response header
+        https://bugs.webkit.org/show_bug.cgi?id=184996
+        <rdar://problem/39664620>
+
+        Reviewed by Geoff Garen.
+
+        * Shared/WebPreferences.yaml:
+        Add this as an experimental feature, on by default.
+
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::frameBecameRemote):
+        Make sure we pass the cross-origin options from the local Window
+        to the remote one when transitioning.
+
 2018-05-09  Wenson Hsieh  <[email protected]>
 
         [Extra zoom mode] fast/viewport/extrazoom/viewport-change-min-device-width.html sometimes fails

Modified: trunk/Source/WebKit/Shared/WebPreferences.yaml (231621 => 231622)


--- trunk/Source/WebKit/Shared/WebPreferences.yaml	2018-05-10 00:08:40 UTC (rev 231621)
+++ trunk/Source/WebKit/Shared/WebPreferences.yaml	2018-05-10 00:33:37 UTC (rev 231622)
@@ -1097,6 +1097,13 @@
   humanReadableDescription: "Enable CSS constant() values"
   category: experimental
 
+CrossOriginOptionsSupportEnabled:
+  type: bool
+  defaultValue: true
+  humanReadableName: "Cross-Origin-Options HTTP Header"
+  humanReadableDescription: "Enable support for Cross-Origin-Options HTTP Header"
+  category: experimental
+
 SpringTimingFunctionEnabled:
   type: bool
   defaultValue: DEFAULT_EXPERIMENTAL_FEATURES_ENABLED

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp (231621 => 231622)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp	2018-05-10 00:08:40 UTC (rev 231621)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp	2018-05-10 00:33:37 UTC (rev 231622)
@@ -5905,8 +5905,13 @@
     if (frame->page() != this)
         return;
 
+    auto* coreFrame = frame->coreFrame();
+    auto* previousWindow = coreFrame->window();
+    if (!previousWindow)
+        return;
+
     auto remoteFrame = RemoteFrame::create(WTFMove(remoteFrameIdentifier));
-    auto remoteWindow = RemoteDOMWindow::create(remoteFrame.copyRef(), WTFMove(remoteWindowIdentifier));
+    auto remoteWindow = RemoteDOMWindow::create(remoteFrame.copyRef(), WTFMove(remoteWindowIdentifier), previousWindow->crossOriginOptions());
     UNUSED_PARAM(remoteWindow);
 
     remoteFrame->setOpener(frame->coreFrame()->loader().opener());
@@ -5915,7 +5920,6 @@
     remoteFrame->windowProxy().setJSWindowProxies(WTFMove(jsWindowProxies));
     remoteFrame->windowProxy().setDOMWindow(remoteWindow.ptr());
 
-    auto* coreFrame = frame->coreFrame();
     coreFrame->setView(nullptr);
     coreFrame->willDetachPage();
     coreFrame->detachFromPage();

Modified: trunk/Source/WebKitLegacy/mac/WebView/WebPreferenceKeysPrivate.h (231621 => 231622)


--- trunk/Source/WebKitLegacy/mac/WebView/WebPreferenceKeysPrivate.h	2018-05-10 00:08:40 UTC (rev 231621)
+++ trunk/Source/WebKitLegacy/mac/WebView/WebPreferenceKeysPrivate.h	2018-05-10 00:33:37 UTC (rev 231622)
@@ -173,6 +173,7 @@
 #define WebKitDataTransferItemsEnabledPreferenceKey @"WebKitDataTransferItemsEnabled"
 #define WebKitCustomPasteboardDataEnabledPreferenceKey @"WebKitCustomPasteboardDataEnabled"
 #define WebKitCacheAPIEnabledPreferenceKey @"WebKitCacheAPIEnabled"
+#define WebKitCrossOriginOptionsSupportEnabledPreferenceKey @"WebKitCrossOriginOptionsSupportEnabled"
 #define WebKitFetchAPIEnabledPreferenceKey @"WebKitFetchAPIEnabled"
 #define WebKitWritableStreamAPIEnabledPreferenceKey @"WebKitWritableStreamAPIEnabled"
 #define WebKitReadableByteStreamAPIEnabledPreferenceKey @"WebKitReadableByteStreamAPIEnabled"

Modified: trunk/Source/WebKitLegacy/mac/WebView/WebPreferences.mm (231621 => 231622)


--- trunk/Source/WebKitLegacy/mac/WebView/WebPreferences.mm	2018-05-10 00:08:40 UTC (rev 231621)
+++ trunk/Source/WebKitLegacy/mac/WebView/WebPreferences.mm	2018-05-10 00:33:37 UTC (rev 231622)
@@ -634,6 +634,7 @@
         [NSNumber numberWithBool:NO], WebKitWebGPUEnabledPreferenceKey,
 #endif
         [NSNumber numberWithBool:NO], WebKitCacheAPIEnabledPreferenceKey,
+        [NSNumber numberWithBool:NO], WebKitCrossOriginOptionsSupportEnabledPreferenceKey,
         [NSNumber numberWithBool:YES], WebKitFetchAPIEnabledPreferenceKey,
 
 #if ENABLE(STREAMS_API)
@@ -3009,6 +3010,16 @@
     [self _setBoolValue:flag forKey:WebKitCacheAPIEnabledPreferenceKey];
 }
 
+- (BOOL)crossOriginOptionsSupportEnabled
+{
+    return [self _boolValueForKey:WebKitCrossOriginOptionsSupportEnabledPreferenceKey];
+}
+
+- (void)setCrossOriginOptionsSupportEnabled:(BOOL)flag
+{
+    [self _setBoolValue:flag forKey:WebKitCrossOriginOptionsSupportEnabledPreferenceKey];
+}
+
 - (BOOL)fetchAPIEnabled
 {
     return [self _boolValueForKey:WebKitFetchAPIEnabledPreferenceKey];

Modified: trunk/Source/WebKitLegacy/mac/WebView/WebPreferencesPrivate.h (231621 => 231622)


--- trunk/Source/WebKitLegacy/mac/WebView/WebPreferencesPrivate.h	2018-05-10 00:08:40 UTC (rev 231621)
+++ trunk/Source/WebKitLegacy/mac/WebView/WebPreferencesPrivate.h	2018-05-10 00:33:37 UTC (rev 231622)
@@ -543,6 +543,9 @@
 - (BOOL)cacheAPIEnabled;
 - (void)setCacheAPIEnabled:(BOOL)enabled;
 
+- (BOOL)crossOriginOptionsSupportEnabled;
+- (void)setCrossOriginOptionsSupportEnabled:(BOOL)enabled;
+
 - (void)setFetchAPIEnabled:(BOOL)flag;
 - (BOOL)fetchAPIEnabled;
 

Modified: trunk/Source/WebKitLegacy/mac/WebView/WebView.mm (231621 => 231622)


--- trunk/Source/WebKitLegacy/mac/WebView/WebView.mm	2018-05-10 00:08:40 UTC (rev 231621)
+++ trunk/Source/WebKitLegacy/mac/WebView/WebView.mm	2018-05-10 00:33:37 UTC (rev 231622)
@@ -3062,6 +3062,7 @@
     settings.setViewportFitEnabled([preferences viewportFitEnabled]);
     settings.setConstantPropertiesEnabled([preferences constantPropertiesEnabled]);
     settings.setColorFilterEnabled([preferences colorFilterEnabled]);
+    settings.setCrossOriginOptionsSupportEnabled([preferences crossOriginOptionsSupportEnabled]);
 
 #if ENABLE(GAMEPAD)
     RuntimeEnabledFeatures::sharedFeatures().setGamepadsEnabled([preferences gamepadsEnabled]);

Modified: trunk/Source/WebKitLegacy/win/Interfaces/IWebPreferencesPrivate.idl (231621 => 231622)


--- trunk/Source/WebKitLegacy/win/Interfaces/IWebPreferencesPrivate.idl	2018-05-10 00:08:40 UTC (rev 231621)
+++ trunk/Source/WebKitLegacy/win/Interfaces/IWebPreferencesPrivate.idl	2018-05-10 00:33:37 UTC (rev 231622)
@@ -228,3 +228,10 @@
     HRESULT menuItemElementEnabled([out, retval] BOOL* enabled);
     HRESULT setMenuItemElementEnabled([in] BOOL enabled);
 }
+
+[uuid(9A49D1DE-53DD-11E8-95E6-003EE1C28AB6)]
+interface IWebPreferencesPrivate7 : IWebPreferencesPrivate6
+{
+    HRESULT crossOriginOptionsSupportEnabled([out, retval] BOOL* enabled);
+    HRESULT setCrossOriginOptionsSupportEnabled([in] BOOL enabled);
+}

Modified: trunk/Source/WebKitLegacy/win/WebPreferenceKeysPrivate.h (231621 => 231622)


--- trunk/Source/WebKitLegacy/win/WebPreferenceKeysPrivate.h	2018-05-10 00:08:40 UTC (rev 231621)
+++ trunk/Source/WebKitLegacy/win/WebPreferenceKeysPrivate.h	2018-05-10 00:33:37 UTC (rev 231622)
@@ -180,6 +180,8 @@
 
 #define WebKitMenuItemElementEnabledPreferenceKey "WebKitMenuItemElementEnabled"
 
+#define WebKitCrossOriginOptionsSupportEnabledPreferenceKey "WebKitCrossOriginOptionsSupportEnabled"
+
 #define WebKitModernMediaControlsEnabledPreferenceKey "WebKitModernMediaControlsEnabled"
 
 #define WebKitWebAnimationsEnabledPreferenceKey "WebKitWebAnimationsEnabled"

Modified: trunk/Source/WebKitLegacy/win/WebPreferences.cpp (231621 => 231622)


--- trunk/Source/WebKitLegacy/win/WebPreferences.cpp	2018-05-10 00:08:40 UTC (rev 231621)
+++ trunk/Source/WebKitLegacy/win/WebPreferences.cpp	2018-05-10 00:33:37 UTC (rev 231622)
@@ -249,6 +249,7 @@
     CFDictionaryAddValue(defaults, CFSTR(WebKitShouldDisplaySubtitlesPreferenceKey), kCFBooleanFalse);
     CFDictionaryAddValue(defaults, CFSTR(WebKitShouldDisplayCaptionsPreferenceKey), kCFBooleanFalse);
     CFDictionaryAddValue(defaults, CFSTR(WebKitShouldDisplayTextDescriptionsPreferenceKey), kCFBooleanFalse);
+    CFDictionaryAddValue(defaults, CFSTR(WebKitCrossOriginOptionsSupportEnabledPreferenceKey), kCFBooleanFalse);
 
     RetainPtr<CFStringRef> linkBehaviorStringRef = adoptCF(CFStringCreateWithFormat(0, 0, CFSTR("%d"), WebKitEditableLinkDefaultBehavior));
     CFDictionaryAddValue(defaults, CFSTR(WebKitEditableLinkBehaviorPreferenceKey), linkBehaviorStringRef.get());
@@ -2029,6 +2030,20 @@
     return S_OK;
 }
 
+HRESULT WebPreferences::crossOriginOptionsSupportEnabled(_Out_ BOOL* enabled)
+{
+    if (!enabled)
+        return E_POINTER;
+    *enabled = boolValueForKey(WebKitCrossOriginOptionsSupportEnabledPreferenceKey);
+    return S_OK;
+}
+
+HRESULT WebPreferences::setCrossOriginOptionsSupportEnabled(BOOL enabled)
+{
+    setBoolValue(WebKitCrossOriginOptionsSupportEnabledPreferenceKey, enabled);
+    return S_OK;
+}
+
 HRESULT WebPreferences::setModernMediaControlsEnabled(BOOL enabled)
 {
     setBoolValue(WebKitModernMediaControlsEnabledPreferenceKey, enabled);

Modified: trunk/Source/WebKitLegacy/win/WebPreferences.h (231621 => 231622)


--- trunk/Source/WebKitLegacy/win/WebPreferences.h	2018-05-10 00:08:40 UTC (rev 231621)
+++ trunk/Source/WebKitLegacy/win/WebPreferences.h	2018-05-10 00:33:37 UTC (rev 231622)
@@ -276,6 +276,10 @@
     virtual HRESULT STDMETHODCALLTYPE menuItemElementEnabled(_Out_ BOOL*);
     virtual HRESULT STDMETHODCALLTYPE setMenuItemElementEnabled(BOOL);
 
+    // IWebPreferencesPrivate7
+    virtual HRESULT STDMETHODCALLTYPE crossOriginOptionsSupportEnabled(_Out_ BOOL*);
+    virtual HRESULT STDMETHODCALLTYPE setCrossOriginOptionsSupportEnabled(BOOL);
+
     // WebPreferences
 
     // This method accesses a different preference key than developerExtrasEnabled.

Modified: trunk/Source/WebKitLegacy/win/WebView.cpp (231621 => 231622)


--- trunk/Source/WebKitLegacy/win/WebView.cpp	2018-05-10 00:08:40 UTC (rev 231621)
+++ trunk/Source/WebKitLegacy/win/WebView.cpp	2018-05-10 00:33:37 UTC (rev 231622)
@@ -5150,7 +5150,7 @@
     settings.setShouldDisplayTextDescriptions(enabled);
 #endif
 
-    COMPtr<IWebPreferencesPrivate6> prefsPrivate { Query, preferences };
+    COMPtr<IWebPreferencesPrivate7> prefsPrivate { Query, preferences };
     if (prefsPrivate) {
         hr = prefsPrivate->localStorageDatabasePath(&str);
         if (FAILED(hr))
@@ -5279,6 +5279,11 @@
         return hr;
     settings.setVisualViewportAPIEnabled(!!enabled);
 
+    hr = prefsPrivate->crossOriginOptionsSupportEnabled(&enabled);
+    if (FAILED(hr))
+        return hr;
+    settings.setCrossOriginOptionsSupportEnabled(!!enabled);
+
     hr = preferences->privateBrowsingEnabled(&enabled);
     if (FAILED(hr))
         return hr;

Modified: trunk/Tools/DumpRenderTree/mac/DumpRenderTree.mm (231621 => 231622)


--- trunk/Tools/DumpRenderTree/mac/DumpRenderTree.mm	2018-05-10 00:08:40 UTC (rev 231621)
+++ trunk/Tools/DumpRenderTree/mac/DumpRenderTree.mm	2018-05-10 00:33:37 UTC (rev 231622)
@@ -862,6 +862,7 @@
     [preferences setAccessibilityObjectModelEnabled:YES];
     [preferences setVisualViewportAPIEnabled:YES];
     [preferences setColorFilterEnabled:YES];
+    [preferences setCrossOriginOptionsSupportEnabled:YES];
 }
 
 // Called before each test.

Modified: trunk/Tools/DumpRenderTree/win/DumpRenderTree.cpp (231621 => 231622)


--- trunk/Tools/DumpRenderTree/win/DumpRenderTree.cpp	2018-05-10 00:08:40 UTC (rev 231621)
+++ trunk/Tools/DumpRenderTree/win/DumpRenderTree.cpp	2018-05-10 00:33:37 UTC (rev 231622)
@@ -788,6 +788,7 @@
     prefsPrivate->setWebAnimationsEnabled(TRUE);
     // FIXME: WebGL2
     // FIXME: WebRTC
+    prefsPrivate->setCrossOriginOptionsSupportEnabled(TRUE);
 }
 
 static void resetWebPreferencesToConsistentValues(IWebPreferences* preferences)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to