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)