Bug 182855

Summary: The WebContent process should not use NSScreen in the screenAvailableRect/screenRect implementations.
Product: WebKit Reporter: Per Arne Vollan <pvollan>
Component: WebKit Misc.Assignee: Per Arne Vollan <pvollan>
Status: RESOLVED FIXED    
Severity: Normal CC: achristensen, beidson, bfulgham, cdumez, commit-queue, darin, dbates, ews-watchlist, japhet, rniwa, webkit-bug-importer
Priority: P2 Keywords: InRadar
Version: WebKit Nightly Build   
Hardware: Unspecified   
OS: Unspecified   
Bug Depends on:    
Bug Blocks: 182747, 183338    
Attachments:
Description Flags
Patch
none
Patch
none
Patch
none
Patch
none
Archive of layout-test-results from ews101 for mac-sierra
none
Archive of layout-test-results from ews117 for mac-sierra
none
Archive of layout-test-results from ews104 for mac-sierra-wk2
none
Patch
none
Patch
none
Patch
none
Patch
none
Patch
none
Patch
none
Patch
none
Patch
none
Patch
none
Archive of layout-test-results from ews206 for win-future
none
Patch
none
Patch
none
Patch
none
Patch none

Description Per Arne Vollan 2018-02-15 18:09:35 PST
The WebContent process should broker NSScreen method calls to the UIProcess, since these calls will communicate with the WindowServer.
Comment 1 Per Arne Vollan 2018-02-15 18:21:29 PST
Created attachment 333979 [details]
Patch
Comment 2 Per Arne Vollan 2018-02-15 18:48:03 PST
Created attachment 333984 [details]
Patch
Comment 3 Per Arne Vollan 2018-02-15 18:54:52 PST
Created attachment 333987 [details]
Patch
Comment 4 Per Arne Vollan 2018-02-15 19:20:31 PST
Created attachment 333989 [details]
Patch
Comment 5 Chris Dumez 2018-02-15 19:26:59 PST
Comment on attachment 333989 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=333989&action=review

> Source/WebCore/ChangeLog:9
> +        since these calls will communicate with the WindowServer.

THis introduces new sync IPC, why do we want this? Do we really need sync IPC?
Comment 6 Per Arne Vollan 2018-02-15 19:35:49 PST
(In reply to Chris Dumez from comment #5)
> Comment on attachment 333989 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=333989&action=review
> 
> > Source/WebCore/ChangeLog:9
> > +        since these calls will communicate with the WindowServer.
> 
> THis introduces new sync IPC, why do we want this? Do we really need sync
> IPC?

I also think it would be better with async IPC. I will look into whether we can get the screen size asynchronously.

Thanks for reviewing!
Comment 7 EWS Watchlist 2018-02-15 20:19:40 PST
Comment on attachment 333989 [details]
Patch

Attachment 333989 [details] did not pass mac-ews (mac):
Output: http://webkit-queues.webkit.org/results/6528663

New failing tests:
fast/frames/iframe-access-screen-of-deleted.html
fast/dom/Window/property-access-on-cached-window-after-frame-removed.html
Comment 8 EWS Watchlist 2018-02-15 20:19:41 PST
Created attachment 333992 [details]
Archive of layout-test-results from ews101 for mac-sierra

The attached test failures were seen while running run-webkit-tests on the mac-ews.
Bot: ews101  Port: mac-sierra  Platform: Mac OS X 10.12.6
Comment 9 EWS Watchlist 2018-02-15 20:45:48 PST
Comment on attachment 333989 [details]
Patch

Attachment 333989 [details] did not pass mac-debug-ews (mac):
Output: http://webkit-queues.webkit.org/results/6528759

New failing tests:
fast/frames/iframe-access-screen-of-deleted.html
fast/dom/Window/property-access-on-cached-window-after-frame-removed.html
Comment 10 EWS Watchlist 2018-02-15 20:45:50 PST
Created attachment 333995 [details]
Archive of layout-test-results from ews117 for mac-sierra

The attached test failures were seen while running run-webkit-tests on the mac-debug-ews.
Bot: ews117  Port: mac-sierra  Platform: Mac OS X 10.12.6
Comment 11 EWS Watchlist 2018-02-15 20:48:27 PST
Comment on attachment 333989 [details]
Patch

Attachment 333989 [details] did not pass mac-wk2-ews (mac-wk2):
Output: http://webkit-queues.webkit.org/results/6528979

New failing tests:
fast/frames/iframe-access-screen-of-deleted.html
fast/dom/Window/property-access-on-cached-window-after-frame-removed.html
Comment 12 EWS Watchlist 2018-02-15 20:48:28 PST
Created attachment 333996 [details]
Archive of layout-test-results from ews104 for mac-sierra-wk2

The attached test failures were seen while running run-webkit-tests on the mac-wk2-ews.
Bot: ews104  Port: mac-sierra-wk2  Platform: Mac OS X 10.12.6
Comment 13 Per Arne Vollan 2018-02-15 20:50:19 PST
Created attachment 333997 [details]
Patch
Comment 14 Per Arne Vollan 2018-02-16 10:36:28 PST
I will attempt to do this with async IPC.
Comment 15 Per Arne Vollan 2018-02-19 12:34:12 PST
Created attachment 334176 [details]
Patch
Comment 16 Per Arne Vollan 2018-02-19 12:47:04 PST
Created attachment 334178 [details]
Patch
Comment 17 Radar WebKit Bug Importer 2018-02-19 13:31:22 PST
<rdar://problem/37683058>
Comment 18 Per Arne Vollan 2018-02-19 13:37:43 PST
Created attachment 334181 [details]
Patch
Comment 19 Per Arne Vollan 2018-02-19 13:41:34 PST
(In reply to Per Arne Vollan from comment #14)
> I will attempt to do this with async IPC.

It seems we might not be able to do this with async IPC, since the function is used when e.g. getting the DOM property 'window.screen.availWidth'.
Comment 20 Chris Dumez 2018-02-19 13:44:19 PST
(In reply to Per Arne Vollan from comment #19)
> (In reply to Per Arne Vollan from comment #14)
> > I will attempt to do this with async IPC.
> 
> It seems we might not be able to do this with async IPC, since the function
> is used when e.g. getting the DOM property 'window.screen.availWidth'.

Once way would be to cache those on the WebContent process side and have the UIProcess notify the WebProcesses whenever these values change.
Comment 21 Per Arne Vollan 2018-02-19 13:44:56 PST
Created attachment 334184 [details]
Patch
Comment 22 Per Arne Vollan 2018-02-19 13:53:13 PST
(In reply to Chris Dumez from comment #20)
> (In reply to Per Arne Vollan from comment #19)
> > (In reply to Per Arne Vollan from comment #14)
> > > I will attempt to do this with async IPC.
> > 
> > It seems we might not be able to do this with async IPC, since the function
> > is used when e.g. getting the DOM property 'window.screen.availWidth'.
> 
> Once way would be to cache those on the WebContent process side and have the
> UIProcess notify the WebProcesses whenever these values change.

Right, that is a good idea. Do we get any notifications from the system when these display properties change?
Comment 23 Alex Christensen 2018-02-19 16:16:51 PST
Comment on attachment 334184 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=334184&action=review

> Source/WebKit/UIProcess/WebPageProxy.messages.in:519
> +    ScreenAvailableRect() -> (WebCore::FloatRect screen) Delayed

This is still synchronous IPC.
Comment 24 Per Arne Vollan 2018-02-20 09:58:26 PST
Created attachment 334278 [details]
Patch
Comment 25 Per Arne Vollan 2018-02-20 10:04:06 PST
(In reply to Alex Christensen from comment #23)
> Comment on attachment 334184 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=334184&action=review
> 
> > Source/WebKit/UIProcess/WebPageProxy.messages.in:519
> > +    ScreenAvailableRect() -> (WebCore::FloatRect screen) Delayed
> 
> This is still synchronous IPC.

I have now implemented Chris' proposal in the latest patch, which should send messages async.

Thanks for reviewing!
Comment 26 Per Arne Vollan 2018-02-20 10:17:47 PST
Created attachment 334283 [details]
Patch
Comment 27 Brent Fulgham 2018-02-20 11:10:34 PST
Comment on attachment 334283 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=334283&action=review

> Source/WebCore/platform/mac/PlatformScreenMac.mm:120
> +void getScreenAvailableRects(HashMap<PlatformDisplayID, FloatRect>& rects)

(Not for this bug) All of this should probably be in the "Platform Abstraction Layer" library.
Comment 28 Brent Fulgham 2018-02-20 11:39:23 PST
Comment on attachment 334283 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=334283&action=review

r=me

> Source/WebCore/platform/mac/PlatformScreenMac.mm:142
> +    if (screenRects().contains(WebCore::displayID(screen(widget)))) {

Is the result of WebCore::displayID(screen(widget)) worth capturing in a variable? I'm not sure how costly it is to do this.

> Source/WebCore/platform/mac/PlatformScreenMac.mm:144
> +        return rect;

... then this could just be:

return screenRects().get(displayIDForWidget);
Comment 29 Per Arne Vollan 2018-02-20 11:49:31 PST
(In reply to Brent Fulgham from comment #28)
> Comment on attachment 334283 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=334283&action=review
> 
> r=me
> 
> > Source/WebCore/platform/mac/PlatformScreenMac.mm:142
> > +    if (screenRects().contains(WebCore::displayID(screen(widget)))) {
> 
> Is the result of WebCore::displayID(screen(widget)) worth capturing in a
> variable? I'm not sure how costly it is to do this.
> 
> > Source/WebCore/platform/mac/PlatformScreenMac.mm:144
> > +        return rect;
> 
> ... then this could just be:
> 
> return screenRects().get(displayIDForWidget);

Thanks for reviewing! I will update the patch before landing.
Comment 30 Per Arne Vollan 2018-02-20 11:53:14 PST
Created attachment 334290 [details]
Patch
Comment 31 Per Arne Vollan 2018-02-20 12:05:55 PST
Created attachment 334293 [details]
Patch
Comment 32 EWS Watchlist 2018-02-20 12:40:12 PST
Comment on attachment 334283 [details]
Patch

Attachment 334283 [details] did not pass win-ews (win):
Output: http://webkit-queues.webkit.org/results/6593573

New failing tests:
http/tests/preload/onerror_event.html
Comment 33 EWS Watchlist 2018-02-20 12:40:23 PST
Created attachment 334295 [details]
Archive of layout-test-results from ews206 for win-future

The attached test failures were seen while running run-webkit-tests on the win-ews.
Bot: ews206  Port: win-future  Platform: CYGWIN_NT-6.1-2.9.0-0.318-5-3-x86_64-64bit
Comment 34 Daniel Bates 2018-02-20 18:25:03 PST
Does this patch cover the case where a person attaches a new monitor and hen moves the window to the new monitor? Does it handle the case where a window is moved to another monitor if your disconnect the monitor the monitor it was originally on?
Comment 35 Per Arne Vollan 2018-02-21 12:01:16 PST
Created attachment 334399 [details]
Patch
Comment 36 Per Arne Vollan 2018-02-21 12:05:46 PST
(In reply to Daniel Bates from comment #34)
> Does this patch cover the case where a person attaches a new monitor and hen
> moves the window to the new monitor? Does it handle the case where a window
> is moved to another monitor if your disconnect the monitor the monitor it
> was originally on?

In theory, the behavior should not change, since we still will use the PlatformDisplayID sent from the UI process to find the properties of the screen on the WebProcess side, and the UI process should send new screen properties to the WebProcess on every screen configuration change.

However, I think I will need to test this manually with the new patch.

Thanks for reviewing!
Comment 37 Per Arne Vollan 2018-02-21 12:20:29 PST
Created attachment 334403 [details]
Patch
Comment 38 Per Arne Vollan 2018-02-21 13:06:31 PST
Created attachment 334407 [details]
Patch
Comment 39 Per Arne Vollan 2018-02-21 14:24:56 PST
Created attachment 334414 [details]
Patch
Comment 40 Brent Fulgham 2018-02-21 15:56:23 PST
Comment on attachment 334414 [details]
Patch

r=me
Comment 41 Per Arne Vollan 2018-02-21 15:58:15 PST
Comment on attachment 334414 [details]
Patch

Thanks for reviewing!
Comment 42 WebKit Commit Bot 2018-02-21 16:20:03 PST
Comment on attachment 334414 [details]
Patch

Clearing flags on attachment: 334414

Committed r228907: <https://trac.webkit.org/changeset/228907>
Comment 43 WebKit Commit Bot 2018-02-21 16:20:05 PST
All reviewed patches have been landed.  Closing bug.
Comment 44 Darin Adler 2018-02-25 11:18:40 PST
This change is a good idea for better performance, too, making it possible to eliminate some synchronous messaging from web process to the UI process. If I remember analysis I did earlier correctly, this should boost the speed of Speedometer.
Comment 45 Darin Adler 2018-02-25 11:37:42 PST
Comment on attachment 334414 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=334414&action=review

Some ideas for coding style refinement.

> Source/WebCore/platform/PlatformScreen.h:92
> +#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101400

What here is specific to newer versions of macOS?

> Source/WebCore/platform/PlatformScreen.h:94
> +WEBCORE_EXPORT void getScreenProperties(HashMap<PlatformDisplayID, ScreenProperties>&);
> +WEBCORE_EXPORT void setScreenProperties(const HashMap<PlatformDisplayID, ScreenProperties>&);

I don’t understand why this can only be done on newer versions of macOS.

The getScreenProperties call should use a return value instead of an out argument. There’s no reason not to do that with C++ with modern move semantics.

The setScreenProperties call should take a HashMap&&, because given the way it’s used, we can move the HashMap in, instead of copying it.

These functions are named peculiarly; the two aren’t parallel! The first one computes the properties and would be inefficient to use over and over again; it’s specifically designed to be called in the UI process only. The second one sets cached properties that will be used internally by all the other functions in this header. I think they might need different names.

> Source/WebCore/platform/mac/PlatformScreenMac.mm:142
> +    if (!screenProperties().isEmpty()) {

I don’t think we should be calling through to NSScreen if the screen properties map just happens to be empty because we are early in the initialization process. We could do something else like:

1) returning a fixed rectangle
2) returning an empty rectangle
3) asserting this case never occurs

I think maybe a combination of (1) and (3) is the best policy.

> Source/WebCore/platform/mac/PlatformScreenMac.mm:145
> +        if (displayIDForWidget && screenProperties().contains(displayIDForWidget))
> +            return screenProperties().get(displayIDForWidget).screenRect;

Double hashing here isn’t good. Should use find instead of contains/get.

> Source/WebCore/platform/mac/PlatformScreenMac.mm:146
> +        // Return property of the first screen if the screen is not found in the map.

This comment says that the code will return the property of the "first screen", which is a good idea, but the code below doesn’t actually do that! It returns the property of a random screen. If we want to know which is the first screen, we will need to change the data structure to identify which is the first; a HashMap alone won’t do that. The rule implemented below is based on the first value seen when iterating the hash map, which will be random based on the hash function, and the current state of the hash table, including things like the current number of buckets.

> Source/WebCore/platform/mac/PlatformScreenMac.mm:148
> +        auto iter = screenProperties().begin();
> +        return screenProperties().get(iter->key).screenRect;

This does an unnecessary hash lookup. The efficient way to write it is one of these:

    return screenProperties().begin()->value.screenRect;

    return screenProperties().values().begin()->screenRect;

But those are only good if we want a randomly chosen screen’s result.

> Source/WebCore/platform/mac/PlatformScreenMac.mm:164
> +    if (!screenProperties().isEmpty()) {
> +        auto displayIDForWidget = displayID(widget);
> +        if (displayIDForWidget && screenProperties().contains(displayIDForWidget))
> +            return screenProperties().get(displayIDForWidget).screenAvailableRect;
> +        // Return property of the first screen if the screen is not found in the map.
> +        auto iter = screenProperties().begin();
> +        return screenProperties().get(iter->key).screenAvailableRect;
> +    }

This function and the one above are nearly identical. Should factor them so they can share code. We can make a helper function that returns a const ScreenProperties* or const ScreenProperties& given a Widget*.

> Source/WebKit/UIProcess/WebProcessPool.cpp:891
> +    HashMap<PlatformDisplayID, ScreenProperties> screenProperties;
> +    WebCore::getScreenProperties(screenProperties);
> +    process.send(Messages::WebProcess::SetScreenProperties(screenProperties), 0);

We should consider passing these in as part of the arguments to InitializeWebProcess instead of sending them as a second messages.
Comment 46 Darin Adler 2018-02-25 11:40:10 PST
(In reply to Darin Adler from comment #44)
> This change is a good idea for better performance, too, making it possible
> to eliminate some synchronous messaging from web process to the UI process.
> If I remember analysis I did earlier correctly, this should boost the speed
> of Speedometer.

I guess maybe I was remembering something old. I guess we got rid of the IPC a while back and made the web process do NSScreen calls. But this is a better solution.
Comment 47 Darin Adler 2018-02-25 11:41:42 PST
One more thought: Ideally, I think that the idea that the UI process should compute the rectangles and send them to the web process is something we should implement cross-platform, not just for Mac. The platform-specific part should be how we compute the rectangles. Might require a bit more refactoring to get rid of some of the legacy concepts inside the web process.
Comment 48 Chris Dumez 2018-02-25 11:43:50 PST
(In reply to Darin Adler from comment #46)
> (In reply to Darin Adler from comment #44)
> > This change is a good idea for better performance, too, making it possible
> > to eliminate some synchronous messaging from web process to the UI process.
> > If I remember analysis I did earlier correctly, this should boost the speed
> > of Speedometer.
> 
> I guess maybe I was remembering something old. I guess we got rid of the IPC
> a while back and made the web process do NSScreen calls. But this is a
> better solution.

I seem to remember we fixed that by not computing the screen coordinates for simulated mouse events. We did not introduce NSScreen calls.
Comment 49 Per Arne Vollan 2018-02-26 11:54:21 PST
(In reply to Darin Adler from comment #47)
> One more thought: Ideally, I think that the idea that the UI process should
> compute the rectangles and send them to the web process is something we
> should implement cross-platform, not just for Mac. The platform-specific
> part should be how we compute the rectangles. Might require a bit more
> refactoring to get rid of some of the legacy concepts inside the web process.

Thanks for reviewing, Darin! I will create a follow-up patch addressing these issues.
Comment 50 Per Arne Vollan 2018-03-05 10:42:46 PST
(In reply to Per Arne Vollan from comment #49)
> (In reply to Darin Adler from comment #47)
> > One more thought: Ideally, I think that the idea that the UI process should
> > compute the rectangles and send them to the web process is something we
> > should implement cross-platform, not just for Mac. The platform-specific
> > part should be how we compute the rectangles. Might require a bit more
> > refactoring to get rid of some of the legacy concepts inside the web process.
> 
> Thanks for reviewing, Darin! I will create a follow-up patch addressing
> these issues.

This is tracked in https://bugs.webkit.org/show_bug.cgi?id=183338.