Skip to content

Commit

Permalink
Window Placement: Implement Screens and ScreenAdvanced interfaces
Browse files Browse the repository at this point in the history
This CL makes the following changes for a planned API redesign:
docs.google.com/document/d/1lgCentReLlym6j9kBS_Qo3r2HHZ6Ov7cSGjSWyi8cYs

1) Add Screens interface to vend multi-screen info for windowing.
- RuntimeEnabled and permission-gated; designed like window.screen.

2) Add ScreenAdvanced interface, to extend Screen with extra info.
- Make Screen impl non-final; override functions in ScreenAdvanced.

3) Add WindowScreens supplement, to host Window.getScreens().
- Rename the previous API access point to getScreensDeprecated().

4) Add ScreenInfo::is_primary & is_internal to expose in ScreenAdvanced.
- Add ScreenInfo::display_id for internal logic, it is not web-exposed.

5) Propagate multi-screen VisualProperties from browser to renderers:
- Replace the singular ScreenInfo member with a new ScreenInfos struct.
- Encapsulates multi-screen information and a current screen id.
- Add [mutable_]current() for easy/legacy access to the current screen.
- Validate mojo struct traits in [de]serialization; add tests.

6) Update WidgetBase, ChromeClient, tests, and more code accordingly.
- Update RenderWidgetHostViewMac's cached display::Display on changes.
- Add CoreInitializer plumbing to fire Screens.change in modules/.

FOLLOWUP: Refine Screens::ScreenInfosChanged implementation.
FOLLOWUP: Propagate multi-screen info to RemoteFrames.
FOLLOWUP: Update/add tests; remove old API and plumbing.
FOLLOWUP: Add WindowScreens PermissionObserver & set_disconnect_handler?
FOLLOWUP: Use WebContentsImpl's NativeView in RWHI::GetScreenInfo?

Bug: 897300, 1116528, 1138596, 1169312, 1116528, 1179876, 1179945
Test: New API roughly WAI w/ --enable-blink-features=WindowPlacement
Change-Id: I1d67cfabda62796274992e3e650d5209dd7bb857
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2669359
Commit-Queue: Michael Wasserman <msw@chromium.org>
Reviewed-by: John Abd-El-Malek <jam@chromium.org>
Reviewed-by: danakj <danakj@chromium.org>
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
Reviewed-by: Victor Costan <pwnall@chromium.org>
Cr-Commit-Position: refs/heads/master@{#858379}
  • Loading branch information
Mike Wasserman authored and chromium-wpt-export-bot committed Feb 27, 2021
1 parent 48af5d4 commit bb119ab
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 18 deletions.
31 changes: 24 additions & 7 deletions screen_enumeration/getScreens.tentative.https.window.js
Expand Up @@ -9,8 +9,10 @@ promise_test(async t => {

promise_test(async t => {
await test_driver.set_permission({name: 'window-placement'}, 'granted');
const screens = await self.getScreens();
const screensInterface = await self.getScreens();
const screens = screensInterface.screens;
assert_greater_than(screens.length, 0);
assert_true(screens.includes(screensInterface.currentScreen));

assert_equals(typeof screens[0].availWidth, 'number');
assert_equals(typeof screens[0].availHeight, 'number');
Expand All @@ -25,24 +27,26 @@ promise_test(async t => {
assert_equals(typeof screens[0].top, 'number');
assert_equals(typeof screens[0].orientation, 'object');

assert_equals(typeof screens[0].primary, 'boolean');
assert_equals(typeof screens[0].internal, 'boolean');
assert_equals(typeof screens[0].scaleFactor, 'number');
assert_equals(typeof screens[0].isExtended, 'boolean');
assert_equals(typeof screens[0].isPrimary, 'boolean');
assert_equals(typeof screens[0].isInternal, 'boolean');
assert_equals(typeof screens[0].devicePixelRatio, 'number');
assert_equals(typeof screens[0].id, 'string');
assert_equals(typeof screens[0].touchSupport, 'boolean');
assert_equals(typeof screens[0].pointerTypes, 'object');
assert_equals(typeof screens[0].label, 'string');
}, 'getScreens() returns at least 1 Screen with permission granted');

promise_test(async t => {
await test_driver.set_permission({name: 'window-placement'}, 'granted');
assert_greater_than((await self.getScreens()).length, 0);
assert_greater_than((await self.getScreens()).screens.length, 0);
await test_driver.set_permission({name: 'window-placement'}, 'denied');
await promise_rejects_dom(t, 'NotAllowedError', self.getScreens());
}, 'getScreens() rejects the promise with permission denied');

promise_test(async t => {
await test_driver.set_permission({name: 'window-placement'}, 'granted');
let iframe = document.body.appendChild(document.createElement('iframe'));
assert_greater_than((await iframe.contentWindow.getScreens()).length, 0);
assert_greater_than((await iframe.contentWindow.getScreens()).screens.length, 0);

let iframeGetScreens;
let constructor;
Expand All @@ -62,3 +66,16 @@ promise_test(async t => {
assert_equals(iframe.contentWindow, null);
await promise_rejects_dom(t, 'InvalidStateError', constructor, iframeGetScreens());
}, "getScreens() resolves for attached iframe; rejects for detached iframe");

promise_test(async t => {
await test_driver.set_permission({name: 'window-placement'}, 'granted');
let iframe = document.body.appendChild(document.createElement('iframe'));
const screensInterface = await iframe.contentWindow.getScreens();
assert_greater_than(screensInterface.screens.length, 0);
assert_equals(screensInterface.currentScreen, screensInterface.screens[0]);
iframe.remove();
await t.step_wait(() => !iframe.contentWindow, "execution context invalid");
assert_equals(iframe.contentWindow, null);
assert_equals(screensInterface.screens.length, 0);
assert_equals(screensInterface.currentScreen, null);
}, "Cached Screens interface from detached iframe doesn't crash, behaves okay");
22 changes: 11 additions & 11 deletions screen_enumeration/getScreens.values.https.html
@@ -1,6 +1,6 @@
<!DOCTYPE html>
<meta charset='utf-8'>
<title>Window Placement: getScreens() tentative</title>
<title>Window Placement: getScreensDeprecated() tentative</title>
<!-- TODO: update link to W3C whenever specifications are ready -->
<link rel='help' href='https://github.com/webscreens/window-placement'/>
<script src='/resources/testharness.js'></script>
Expand All @@ -25,8 +25,8 @@
screen_enumeration_test(async (t, mockScreenEnum) => {
mockScreenEnum.setSuccess(true);
await test_driver.set_permission({name: 'window-placement'}, 'granted');
assert_equals((await self.getScreens()).length, 0);
}, 'getScreens() supports an empty set of mocked screens');
assert_equals((await self.getScreensDeprecated()).length, 0);
}, 'getScreensDeprecated() supports an empty set of mocked screens');

screen_enumeration_test(async (t, mockScreenEnum) => {
let display1 = makeDisplay(10,
Expand All @@ -41,13 +41,13 @@

await test_driver.set_permission({name: 'window-placement'}, 'granted');

const screens = await self.getScreens();
const screens = await self.getScreensDeprecated();
assert_equals(screens.length, 1);
check_screen_matches_display(screens[0], display1);
assert_equals(screens[0].primary, true);
assert_equals(screens[0].internal, true);
assert_equals(screens[0].id, '0');
}, 'getScreens() supports a single mocked screen');
}, 'getScreensDeprecated() supports a single mocked screen');

screen_enumeration_test(async (t, mockScreenEnum) => {
let display1 = makeDisplay(10,
Expand All @@ -74,7 +74,7 @@

await test_driver.set_permission({name: 'window-placement'}, 'granted');

let screens = await self.getScreens();
let screens = await self.getScreensDeprecated();
assert_equals(screens.length, 3);
check_screen_matches_display(screens[0], display1);
assert_equals(screens[0].primary, true);
Expand All @@ -90,24 +90,24 @@
assert_equals(screens[2].id, '2');

mockScreenEnum.removeDisplay(display2.id);
screens = await self.getScreens();
screens = await self.getScreensDeprecated();
assert_equals(screens.length, 2);
check_screen_matches_display(screens[0], display1);
assert_equals(screens[0].id, '0');
check_screen_matches_display(screens[1], display3);
assert_equals(screens[1].id, '1');

mockScreenEnum.removeDisplay(display1.id);
screens = await self.getScreens();
screens = await self.getScreensDeprecated();
assert_equals(screens.length, 1);
check_screen_matches_display(screens[0], display3);
assert_equals(screens[0].id, '0');
}, 'getScreens() supports multiple mocked screens');
}, 'getScreensDeprecated() supports multiple mocked screens');

screen_enumeration_test(async (t, mockScreenEnum) => {
mockScreenEnum.setSuccess(false);
await test_driver.set_permission({name: 'window-placement'}, 'granted');
promise_rejects_dom(t, 'NotAllowedError', self.getScreens());
}, 'getScreens() rejects when the mock success value is set to false');
promise_rejects_dom(t, 'NotAllowedError', self.getScreensDeprecated());
}, 'getScreensDeprecated() rejects when the mock success value is set false');

</script>

0 comments on commit bb119ab

Please sign in to comment.