Skip to content

Commit

Permalink
Reland "Reject getDisplayMedia calls without user activation"
Browse files Browse the repository at this point in the history
This reverts commit 085deeae4f99ba12f7982aae69f6576f7f18b9c1.

Reason for revert: Fixing permission policy tests

Original change's description:
> Revert "Reject getDisplayMedia calls without user activation"
>
> This reverts commit 5fbd1e8cdadc327dedfad9ce896e24c562e59fbf.
>
> Reason for revert: Reverted by Sheriff on suspicion of causing a test failure. https://ci.chromium.org/ui/p/chromium/builders/ci/Linux%20Tests%20(dbg)(1)/110084/test-results?sortby=&groupby=&q=ExactID%3Aninja%3A%2F%2F%3Ablink_wpt_tests%2Fexternal%2Fwpt%2Fscreen-capture%2Fpermissions-policy-audio%2Bvideo.https.sub.html+VHash%3A9f5ebdc6f73354e7.
>
> The test failure lists getDisplayMedia failing as the cause, and this CL is in the blame set and looks related.
>
> Original change's description:
> > Reject getDisplayMedia calls without user activation
> >
> > This CL makes sure getDisplayMedia() returned promise reject with
> > InvalidStateError when called without user activation.
> > Note that speculation rules tests are updated as well[1].
> >
> > [1] WICG/nav-speculation#225
> >
> > Intent to remove: https://groups.google.com/a/chromium.org/g/blink-dev/c/YGmuAVOqftI
> >
> > Bug: 1198918
> > Change-Id: I530761d95e6db412582d0f19c0170803516c33f7
> > Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4096797
> > Reviewed-by: Dale Curtis <dalecurtis@chromium.org>
> > Reviewed-by: Hiroki Nakagawa <nhiroki@chromium.org>
> > Reviewed-by: Elad Alon <eladalon@chromium.org>
> > Commit-Queue: Fr <beaufort.francois@gmail.com>
> > Cr-Commit-Position: refs/heads/main@{#1086033}
>
> Bug: 1198918
> Change-Id: I14d0e47ee406aa09b6eec763e94d8e83f282a04d
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4119423
> Auto-Submit: Peter Williamson <petewil@chromium.org>
> Quick-Run: Peter Williamson <petewil@chromium.org>
> Commit-Queue: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
> Owners-Override: Peter Williamson <petewil@chromium.org>
> Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
> Cr-Commit-Position: refs/heads/main@{#1086147}

Bug: 1198918
Change-Id: I456423c03c1430399f4b44e275a77e0411f6bda7
  • Loading branch information
beaufortfrancois authored and chromium-wpt-export-bot committed Dec 27, 2022
1 parent 2a3871b commit 87866ea
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 78 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@
<title>MediaStreamTrack transfer to iframe</title>
<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>
<script>
promise_test(async () => {
const iframe = document.createElement("iframe");
await test_driver.bless('getDisplayMedia');
const stream = await navigator.mediaDevices.getDisplayMedia({audio:true, video: true});
const track = stream.getAudioTracks()[0];
const cloned_track = track.clone();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@
<title>MediaStreamTrack transfer to iframe</title>
<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>
<script>
promise_test(async () => {
const iframe = document.createElement("iframe");
await test_driver.bless('getDisplayMedia');
const stream = await navigator.mediaDevices.getDisplayMedia({video: true});
const track = stream.getVideoTracks()[0];
const cloned_track = track.clone();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@
var feature_name = 'permissions policy "payment"';
var header = 'allow="payment" attribute';

async_test(t => {
test_feature_availability_with_post_message_result(
promise_test(t => {
return test_feature_availability_with_post_message_result(
t, cross_origin_src, "NotSupportedError#The 'payment' feature is not " +
"enabled in this document. Permissions Policy may be used to " +
"delegate Web Payment capabilities to cross-origin child frames.");
}, feature_name + ' is not supported in cross-origin iframe without ' + header);

async_test(t => {
test_feature_availability_with_post_message_result(
promise_test(t => {
return test_feature_availability_with_post_message_result(
t, cross_origin_src, 'OK', 'payment');
}, feature_name + ' can be enabled in cross-origin iframe using ' + header);
</script>
Expand Down
60 changes: 36 additions & 24 deletions permissions-policy/resources/permissions-policy.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,11 @@ function assert_permissions_policy_supported() {
// https://github.com/w3c/webappsec-permissions-policy/blob/main/features.md
// allow_attribute: Optional argument, only used for testing fullscreen or
// payment: either "allowfullscreen" or "allowpaymentrequest" is passed.
// is_promise_test: Optional argument, true if this call should return a
// promise. Used by test_feature_availability_with_post_message_result()
function test_feature_availability(
feature_description, test, src, expect_feature_available, feature_name,
allow_attribute) {
allow_attribute, is_promise_test = false) {
let frame = document.createElement('iframe');
frame.src = src;

Expand All @@ -40,16 +42,26 @@ function test_feature_availability(
frame.setAttribute(allow_attribute, true);
}

window.addEventListener('message', test.step_func(evt => {
function expectFeatureAvailable(evt) {
if (evt.source === frame.contentWindow &&
evt.data.type === 'availability-result') {
expect_feature_available(evt.data, feature_description);
document.body.removeChild(frame);
test.done();
}
}));
}

if (!is_promise_test) {
window.addEventListener('message', test.step_func(expectFeatureAvailable));
document.body.appendChild(frame);
return;
}

const promise = new Promise((resolve) => {
window.addEventListener('message', resolve);
}).then(expectFeatureAvailable);
document.body.appendChild(frame);
return promise;
}

// Default helper functions to test a feature's availability:
Expand All @@ -76,7 +88,8 @@ function test_feature_availability_with_post_message_result(
const test_result = ({ name, message }, feature_description) => {
assert_equals(name, expected_result, message + '.');
};
test_feature_availability(null, test, src, test_result, allow_attribute);
return test_feature_availability(
null, test, src, test_result, allow_attribute, undefined, true);
}

// If this page is intended to test the named feature (according to the URL),
Expand Down Expand Up @@ -163,39 +176,39 @@ function run_all_fp_tests_allow_self(

// 2. Allowed in same-origin iframe.
const same_origin_frame_pathname = same_origin_url(feature_name);
async_test(
promise_test(
t => {
test_feature_availability_with_post_message_result(
return test_feature_availability_with_post_message_result(
t, same_origin_frame_pathname, '#OK');
},
'Default "' + feature_name +
'" permissions policy ["self"] allows same-origin iframes.');

// 3. Blocked in cross-origin iframe.
const cross_origin_frame_url = cross_origin_url(cross_origin, feature_name);
async_test(
promise_test(
t => {
test_feature_availability_with_post_message_result(
return test_feature_availability_with_post_message_result(
t, cross_origin_frame_url, error_name);
},
'Default "' + feature_name +
'" permissions policy ["self"] disallows cross-origin iframes.');

// 4. Allowed in cross-origin iframe with "allow" attribute.
async_test(
promise_test(
t => {
test_feature_availability_with_post_message_result(
return test_feature_availability_with_post_message_result(
t, cross_origin_frame_url, '#OK', feature_name);
},
'permissions policy "' + feature_name +
'" can be enabled in cross-origin iframes using "allow" attribute.');

// 5. Blocked in same-origin iframe with "allow" attribute set to 'none'.
async_test(
promise_test(
t => {
test_feature_availability_with_post_message_result(
return test_feature_availability_with_post_message_result(
t, same_origin_frame_pathname, error_name,
feature_name + " 'none'");
feature_name + ' \'none\'');
},
'permissions policy "' + feature_name +
'" can be disabled in same-origin iframes using "allow" attribute.');
Expand Down Expand Up @@ -246,40 +259,39 @@ function run_all_fp_tests_allow_all(

// 2. Allowed in same-origin iframe.
const same_origin_frame_pathname = same_origin_url(feature_name);
async_test(
promise_test(
t => {
test_feature_availability_with_post_message_result(
return test_feature_availability_with_post_message_result(
t, same_origin_frame_pathname, '#OK');
},
'Default "' + feature_name +
'" permissions policy ["*"] allows same-origin iframes.');

// 3. Allowed in cross-origin iframe.
const cross_origin_frame_url = cross_origin_url(cross_origin, feature_name);
async_test(
promise_test(
t => {
test_feature_availability_with_post_message_result(
return test_feature_availability_with_post_message_result(
t, cross_origin_frame_url, '#OK');
},
'Default "' + feature_name +
'" permissions policy ["*"] allows cross-origin iframes.');

// 4. Blocked in cross-origin iframe with "allow" attribute set to 'none'.
async_test(
promise_test(
t => {
test_feature_availability_with_post_message_result(
t, cross_origin_frame_url, error_name,
feature_name + " 'none'");
return test_feature_availability_with_post_message_result(
t, cross_origin_frame_url, error_name, feature_name + ' \'none\'');
},
'permissions policy "' + feature_name +
'" can be disabled in cross-origin iframes using "allow" attribute.');

// 5. Blocked in same-origin iframe with "allow" attribute set to 'none'.
async_test(
promise_test(
t => {
test_feature_availability_with_post_message_result(
return test_feature_availability_with_post_message_result(
t, same_origin_frame_pathname, error_name,
feature_name + " 'none'");
feature_name + ' \'none\'');
},
'permissions policy "' + feature_name +
'" can be disabled in same-origin iframes using "allow" attribute.');
Expand Down
33 changes: 13 additions & 20 deletions speculation-rules/prerender/resources/screen-capture.https.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,23 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/speculation-rules/prerender/resources/utils.js"></script>
<script src="/speculation-rules/prerender/resources/deferred-promise-utils.js"></script>
<script>

const params = new URLSearchParams(location.search);
assert_true(document.prerendering);

// The main test page (restriction-screen-capture.https.html) loads the
// initiator page, then the initiator page will prerender itself with the
// `prerendering` parameter.
const isPrerendering = params.has('prerendering');
async function invokeScreenCaptureAPI(){
const bc = new PrerenderChannel('prerender-channel');

if (!isPrerendering) {
loadInitiatorPage();
} else {
const prerenderEventCollector = new PrerenderEventCollector();
const promise = new Promise(async (resolve, reject) => {
try {
await navigator.mediaDevices.getDisplayMedia({video: true});
resolve();
} catch (e) {
reject(`navigator.mediaDevices.getDisplayMedia error: ${e.toString()}`);
}
});
prerenderEventCollector.start(
promise, 'navigator.mediaDevices.getDisplayMedia');
try {
await navigator.mediaDevices.getDisplayMedia();
bc.postMessage('unexpected success');
} catch (err){
bc.postMessage(err.name);
} finally {
bc.close();
}
}

invokeScreenCaptureAPI();

</script>
39 changes: 9 additions & 30 deletions speculation-rules/prerender/restriction-screen-capture.https.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<!DOCTYPE html>
<title>Access to the Screen Capture API is deferred</title>
<title>Prerendering cannot invoke the Screen Capture API</title>
<meta name="timeout" content="long">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
Expand All @@ -12,8 +12,7 @@

promise_test(async t => {
const uid = token();
const bc = new PrerenderChannel('test-channel', uid);
t.add_cleanup(_ => bc.close());
const bc = new PrerenderChannel('prerender-channel', uid);

const gotMessage = new Promise(resolve => {
bc.addEventListener('message', e => {
Expand All @@ -22,35 +21,15 @@
once: true
});
});
const url = `resources/screen-capture.https.html?uid=${uid}`;
window.open(url, '_blank', 'noopener');

// Start prerendering a page that attempts to invoke the Screen Capture API.
// This API is activated-gated so it's expected to fail:
// https://wicg.github.io/nav-speculation/prerendering.html#implicitly-restricted
startPrerendering(`resources/screen-capture.https.html?uid=${uid}`);
const result = await gotMessage;
const expected = [
{
event: 'started waiting navigator.mediaDevices.getDisplayMedia',
prerendering: true
},
{
event: 'prerendering change',
prerendering: false
},
{
event: 'finished waiting navigator.mediaDevices.getDisplayMedia',
prerendering: false
},
];
assert_equals(result.length, expected.length);
for (let i = 0; i < result.length; i++) {
assert_equals(result[i].event, expected[i].event, `event[${i}]`);
assert_equals(result[i].prerendering, expected[i].prerendering,
`prerendering[${i}]`);
}

// Send a close signal to PrerenderEventCollector on the prerendered page.
new PrerenderChannel('close', uid).postMessage('');
}, `The access to the Screen Capture API should be deferred until the
prerendered page is activated`);
assert_equals(result, 'InvalidStateError');
bc.close();
}, `prerendering pages should not be able to invoke the Screen Capture API`);

</script>
</body>

0 comments on commit 87866ea

Please sign in to comment.