Skip to content
Permalink
Browse files
switch web share's permission policy back to 'self'
https://bugs.webkit.org/show_bug.cgi?id=247407
rdar://101893272

After agreement with other engines, everyone is hoping to switch to 'self' hopefully around the same time.
Chrome is aiming to have this in stable early next year. Firefox is already shipping.

Reviewed by Tim Horton.

* LayoutTests/http/tests/webshare/webshare-allow-attribute-canShare.https-expected.txt:
* LayoutTests/http/tests/webshare/webshare-allow-attribute-canShare.https.html:
* LayoutTests/http/tests/webshare/webshare-allow-attribute-share.https-expected.txt:
* LayoutTests/http/tests/webshare/webshare-allow-attribute-share.https.html:
* LayoutTests/imported/w3c/web-platform-tests/web-share/canShare.https.html:
* LayoutTests/imported/w3c/web-platform-tests/web-share/disabled-by-permissions-policy-cross-origin.https.sub-expected.txt: Added.
* LayoutTests/imported/w3c/web-platform-tests/web-share/disabled-by-permissions-policy-cross-origin.https.sub.html: Added.
* LayoutTests/imported/w3c/web-platform-tests/web-share/disabled-by-permissions-policy.https.sub-expected.txt: Added.
* LayoutTests/imported/w3c/web-platform-tests/web-share/disabled-by-permissions-policy.https.sub.html: Added.
* LayoutTests/imported/w3c/web-platform-tests/web-share/disabled-by-permissions-policy.https.sub.html.headers: Added.
* LayoutTests/imported/w3c/web-platform-tests/web-share/feature-policy-listed-expected.txt: Added.
* LayoutTests/imported/w3c/web-platform-tests/web-share/feature-policy-listed.html: Added.
* LayoutTests/imported/w3c/web-platform-tests/web-share/resources/post-message.html: Added.
* Source/WebCore/html/FeaturePolicy.cpp:
(WebCore::FeaturePolicy::parse):

Canonical link: https://commits.webkit.org/256556@main
  • Loading branch information
marcoscaceres authored and whsieh committed Nov 11, 2022
1 parent 08e4dc1 commit ded7a6094a6ca38833e63a7915b7b6a2832f5734
Show file tree
Hide file tree
Showing 14 changed files with 243 additions and 7 deletions.
@@ -1,8 +1,9 @@
CONSOLE MESSAGE: Feature policy 'WebShare' check failed for iframe with origin 'https://localhost:8443' and allow attribute ''.
CONSOLE MESSAGE: Feature policy 'WebShare' check failed for iframe with origin 'https://localhost:8443' and allow attribute 'web-share 'none''.
CONSOLE MESSAGE: Feature policy 'WebShare' check failed for iframe with origin 'https://127.0.0.1:8443' and allow attribute 'web-share 'none''.
CONSOLE MESSAGE: Feature policy 'WebShare' check failed for iframe with origin 'https://localhost:8443' and allow attribute 'web-share 'self''.
CONSOLE MESSAGE: Feature policy 'WebShare' check failed for iframe with origin 'https://127.0.0.1:8443' and allow attribute 'web-share https://localhost:8443'.
PASS iframe src: "https://localhost:8443/webshare/resources/webshare-postmessage.html" with allow="" is allowed to call canShare().
PASS iframe src: "https://localhost:8443/webshare/resources/webshare-postmessage.html" with allow="" MUST NOT be allowed to call canShare().
PASS iframe src: "https://127.0.0.1:8443/webshare/resources/webshare-postmessage.html" with allow="" is allowed to call canShare().
PASS iframe src: "https://localhost:8443/webshare/resources/webshare-postmessage.html" with allow="web-share" is allowed to call canShare().
PASS iframe src: "https://127.0.0.1:8443/webshare/resources/webshare-postmessage.html" with allow="web-share" is allowed to call canShare().
@@ -48,7 +48,7 @@
</head>
<body>
<iframe
data-enabled="true"
data-enabled="false"
src="https://localhost:8443/webshare/resources/webshare-postmessage.html"
></iframe>
<iframe
@@ -1,8 +1,9 @@
CONSOLE MESSAGE: Feature policy 'WebShare' check failed for iframe with origin 'https://localhost:8443' and allow attribute ''.
CONSOLE MESSAGE: Feature policy 'WebShare' check failed for iframe with origin 'https://localhost:8443' and allow attribute 'web-share 'none''.
CONSOLE MESSAGE: Feature policy 'WebShare' check failed for iframe with origin 'https://127.0.0.1:8443' and allow attribute 'web-share 'none''.
CONSOLE MESSAGE: Feature policy 'WebShare' check failed for iframe with origin 'https://localhost:8443' and allow attribute 'web-share 'self''.
CONSOLE MESSAGE: Feature policy 'WebShare' check failed for iframe with origin 'https://127.0.0.1:8443' and allow attribute 'web-share https://localhost:8443'.
PASS iframe src: "https://localhost:8443/webshare/resources/webshare-postmessage.html" with allow="" is allowed to call share().
PASS iframe src: "https://localhost:8443/webshare/resources/webshare-postmessage.html" with allow="" MUST NOT be allowed to call share(). NotAllowedError Third-party iframes are not allowed to call share() unless explicitly allowed via Feature-Policy (web-share)
PASS iframe src: "https://127.0.0.1:8443/webshare/resources/webshare-postmessage.html" with allow="" is allowed to call share().
PASS iframe src: "https://localhost:8443/webshare/resources/webshare-postmessage.html" with allow="web-share" is allowed to call share().
PASS iframe src: "https://127.0.0.1:8443/webshare/resources/webshare-postmessage.html" with allow="web-share" is allowed to call share().
@@ -26,7 +26,7 @@

const iframeDetails = [
{
enabled: "true",
enabled: "false",
src: "https://localhost:8443/webshare/resources/webshare-postmessage.html",
},
{
@@ -101,7 +101,7 @@
assert_true(navigator.canShare({ text: "" }), "ok to share empty text");

assert_true(
navigator.canShare({ text: "some text 🤔" }),
navigator.canShare({ text: "some text 🤔" }),
"ok to share unicode"
);

@@ -0,0 +1,14 @@
CONSOLE MESSAGE: Feature policy 'WebShare' check failed for iframe with origin 'https://127.0.0.1:9443' and allow attribute 'undefined'.
CONSOLE MESSAGE: Feature policy 'WebShare' check failed for iframe with origin 'https://127.0.0.1:9443' and allow attribute 'web-share=()'.
CONSOLE MESSAGE: Feature policy 'WebShare' check failed for iframe with origin 'https://127.0.0.1:9443' and allow attribute 'web-share=(self)'.
CONSOLE MESSAGE: Feature policy 'WebShare' check failed for iframe with origin 'https://127.0.0.1:9443' and allow attribute 'undefined'.
CONSOLE MESSAGE: Feature policy 'WebShare' check failed for iframe with origin 'https://127.0.0.1:9443' and allow attribute 'web-share=("https://127.0.0.1:9443")'.
CONSOLE MESSAGE: Feature policy 'WebShare' check failed for iframe with origin 'https://localhost:9443' and allow attribute 'web-share=(self)'.

PASS share() is disabled by default 'self' by permissions policy for cross-origin iframes
PASS share() is disabled explicitly by permissions policy for cross-origin iframe
PASS share() not allowed, as only allowed to share with self
PASS canShare() not allowed to share by default permissions policy cross-origin
FAIL canShare() is allowed by permissions policy to share cross-origin on a particular origin assert_equals: Expected true, is it can now share on https://localhost:9443. expected true but got false
FAIL canShare() with self assert_equals: Expected true, at it can share with self. expected true but got false

@@ -0,0 +1,116 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>WebShare Test: is disabled by permissions policy cross-origin</title>
<link
rel="help"
href="https://w3c.github.io/web-share/#permissions-policy"
/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body></body>
<script>
const crossOrigin = "https://{{hosts[alt][]}}:{{ports[https][0]}}";
const sameOriginPath = "/web-share/resources/post-message.html";
const crossOriginSrc = `${crossOrigin}${sameOriginPath}`;
const shareData = {
title: "WebShare Test",
text: "This is a test of the Web Share API",
url: "https://example.com/",
};

function waitForMessage(message) {
return new Promise((resolve) => {
window.addEventListener("message", function listener(event) {
if (event.data.action !== message) return;
window.removeEventListener("message", listener);
resolve(event.data);
});
});
}

async function loadIframe(t, src, allowList) {
const iframe = document.createElement("iframe");
if (allowList !== null) iframe.allow = allowList;
t.add_cleanup(() => {
iframe.remove();
});
await new Promise((resolve) => {
iframe.src = src;
document.body.appendChild(iframe);
iframe.onload = resolve;
});
await waitForMessage("loaded");
return iframe;
}

promise_test(async (t) => {
const iframe = await loadIframe(t, crossOriginSrc);
const iframeWindow = iframe.contentWindow;
iframeWindow.postMessage({ action: "share", data: shareData }, "*");
const data = await waitForMessage("share");
assert_equals(data.result, "error");
assert_equals(data.error, "NotAllowedError");
}, "share() is disabled by default 'self' by permissions policy for cross-origin iframes");

promise_test(async (t) => {
const iframe = await loadIframe(t, crossOriginSrc, "web-share=()");
const iframeWindow = iframe.contentWindow;
iframeWindow.postMessage({ action: "share", data: shareData }, "*");
const data = await waitForMessage("share");
assert_equals(data.result, "error");
assert_equals(data.error, "NotAllowedError");
}, "share() is disabled explicitly by permissions policy for cross-origin iframe");

promise_test(async (t) => {
const iframe = await loadIframe(t, crossOriginSrc, "web-share=(self)");
const iframeWindow = iframe.contentWindow;
iframeWindow.postMessage({ action: "share", data: shareData }, "*");
const data = await waitForMessage("share");
assert_equals(data.result, "error");
assert_equals(data.error, "NotAllowedError");
}, "share() not allowed, as only allowed to share with self");

promise_test(async (t) => {
const iframe = await loadIframe(t, crossOriginSrc);
const iframeWindow = iframe.contentWindow;
iframeWindow.postMessage({ action: "canShare", data: shareData }, "*");
const data = await waitForMessage("canShare");
assert_equals(data.result, false, "Expected false, as it can't share.");
}, "canShare() not allowed to share by default permissions policy cross-origin");

promise_test(async (t) => {
const iframe = await loadIframe(
t,
crossOriginSrc,
`web-share=("${crossOrigin}")`
);
iframe.contentWindow.postMessage(
{ action: "canShare", data: shareData },
"*"
);
const data = await waitForMessage("canShare");
assert_equals(
data.result,
true,
`Expected true, is it can now share on ${origin}.`
);
}, "canShare() is allowed by permissions policy to share cross-origin on a particular origin");

promise_test(async (t) => {
const iframe = await loadIframe(t, sameOriginPath, "web-share=(self)");
iframe.contentWindow.postMessage(
{ action: "canShare", data: shareData },
"*"
);
const data = await waitForMessage("canShare");
assert_equals(
data.result,
true,
"Expected true, at it can share with self."
);
}, "canShare() with self");
</script>
</html>
@@ -0,0 +1,4 @@

FAIL share() can be disabled by permissions policy promise_rejects_dom: function "function () { throw e }" threw object "TypeError: Type error" that is not a DOMException NotAllowedError: property "code" is equal to undefined, expected 0
FAIL canShare() can be disabled by permissions policy assert_false: not allowed to share expected false got true

@@ -0,0 +1,27 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>WebShare Test: Can be disabled by permissions policy</title>
<link rel="help" href="https://w3c.github.io/web-share/#permissions-policy">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
</head>
<body>
<script>
promise_test(async (t) => {
await test_driver.bless("web share");
await promise_rejects_dom(t, "NotAllowedError", navigator.share({}));
}, "share() can be disabled by permissions policy");

test((t) => {
assert_false(
navigator.canShare({ text: "foo" }),
"not allowed to share"
);
}, "canShare() can be disabled by permissions policy");
</script>
</body>
</html>
@@ -0,0 +1 @@
Permissions-Policy: web-share=()
@@ -0,0 +1,6 @@

FAIL allowsFeature() returns true for web-share undefined is not an object (evaluating 'document.featurePolicy.allowsFeature')
FAIL features() includes web-share undefined is not an object (evaluating 'document.featurePolicy.features')
FAIL allowedFeatures() includes web-share undefined is not an object (evaluating 'document.featurePolicy.allowedFeatures')
FAIL allowsFeature() returns a single entry for web-share undefined is not an object (evaluating 'document.featurePolicy.getAllowlistForFeature')

@@ -0,0 +1,31 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>WebShare Test: policy is listed</title>
<link rel="help" href="https://w3c.github.io/web-share/#permissions-policy">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<script>
'use strict';

test(() => {
assert_true(document.featurePolicy.allowsFeature('web-share'));
}, 'allowsFeature() returns true for web-share');

test(() => {
assert_true(document.featurePolicy.features().includes('web-share'));
}, 'features() includes web-share');

test(() => {
assert_true(document.featurePolicy.allowedFeatures().includes('web-share'));
}, 'allowedFeatures() includes web-share');

test(() => {
assert_equals(Array.from(document.featurePolicy.getAllowlistForFeature('web-share')).length, 1);
}, 'allowsFeature() returns a single entry for web-share');
</script>
</body>
</html>
@@ -0,0 +1,35 @@
<!DOCTYPE html>
<meta charset="utf-8" />
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<script>
window.addEventListener("message", async (event) => {
const {
data: { action, data },
} = event;
const response = {};
try {
switch (action) {
case "share":
await test_driver.bless("share");
await navigator.share(data);
response.result = "unreached";
break;
case "canShare":
response.result = navigator.canShare(data);
break;
}
} catch (error) {
response.result = "error";
response.error = error.name;
} finally {
event.source.postMessage({ ...response, action }, "*");
}
});

// send message to parent that we loaded
function sendLoadMessage() {
window.parent.postMessage({ action: "loaded" }, "*");
}
</script>
<body onload="sendLoadMessage()"></body>
@@ -282,7 +282,7 @@ FeaturePolicy FeaturePolicy::parse(Document& document, const HTMLIFrameElement&
#endif
}

// By default, camera, microphone, speaker-selection, display-capture, fullscreen and xr-spatial-tracking, screen-wake-lock policy is 'self'.
// By default, camera, microphone, speaker-selection, display-capture, fullscreen, xr-spatial-tracking, screen-wake-lock, and web-share policy is 'self'.
if (!isCameraInitialized)
policy.m_cameraRule.allowedList.add(document.securityOrigin().data());
if (!isMicrophoneInitialized)
@@ -298,7 +298,7 @@ FeaturePolicy FeaturePolicy::parse(Document& document, const HTMLIFrameElement&
if (!isPaymentInitialized)
policy.m_paymentRule.allowedList.add(document.securityOrigin().data());
if (!isWebShareInitialized)
policy.m_webShareRule.type = FeaturePolicy::AllowRule::Type::All;
policy.m_webShareRule.allowedList.add(document.securityOrigin().data());
#if ENABLE(DEVICE_ORIENTATION)
if (!isGyroscopeInitialized)
policy.m_gyroscopeRule.allowedList.add(document.securityOrigin().data());

0 comments on commit ded7a60

Please sign in to comment.