The WebContent process should not use NSScreen in the screenAvailableRect/screenRect...
authorpvollan@apple.com <pvollan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 22 Feb 2018 00:19:58 +0000 (00:19 +0000)
committerpvollan@apple.com <pvollan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 22 Feb 2018 00:19:58 +0000 (00:19 +0000)
https://bugs.webkit.org/show_bug.cgi?id=182855

Reviewed by Brent Fulgham.

On macOS, the functions screenAvailableRect and screenRect is implemented using NSScreen, which is communicating
with the WindowServer. To avoid this WindowServer communication from the WebContent process when calling
screenAvailableRect and screenRect, it is possible to let the UIProcess send a message to the WebContent
process whenever there is a change in the display properties, and have the WebContent process cache these
display properties. This message should also be sent to a newly started WebContent process.

Source/WebCore:

No new tests, covered by existing tests.

* WebCore.xcodeproj/project.pbxproj:
* platform/PlatformScreen.h:
* platform/mac/PlatformScreenMac.mm:
(WebCore::getScreenProperties):
(WebCore::screenProperties):
(WebCore::setScreenProperties):
(WebCore::screenRect):
(WebCore::screenAvailableRect):
* platform/ScreenProperties.h: Added.
(WebCore::ScreenProperties::encode const):
(WebCore::ScreenProperties::decode):

Source/WebKit:

* UIProcess/WebProcessPool.cpp:
(WebKit::displayReconfigurationCallBack):
(WebKit::registerDisplayConfigurationCallback):
(WebKit::WebProcessPool::initializeNewWebProcess):
(WebKit::WebProcessPool::warmInitialProcess):
* WebProcess/WebProcess.cpp:
(WebKit::WebProcess::setScreenProperties):
* WebProcess/WebProcess.h:
* WebProcess/WebProcess.messages.in:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@228907 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/platform/PlatformScreen.h
Source/WebCore/platform/ScreenProperties.h [new file with mode: 0644]
Source/WebCore/platform/mac/PlatformScreenMac.mm
Source/WebKit/ChangeLog
Source/WebKit/UIProcess/WebProcessPool.cpp
Source/WebKit/WebProcess/WebProcess.cpp
Source/WebKit/WebProcess/WebProcess.h
Source/WebKit/WebProcess/WebProcess.messages.in

index 045a8cc..b6f8fcf 100644 (file)
@@ -1,3 +1,30 @@
+2018-02-21  Per Arne Vollan  <pvollan@apple.com>
+
+        The WebContent process should not use NSScreen in the screenAvailableRect/screenRect implementations.
+        https://bugs.webkit.org/show_bug.cgi?id=182855
+
+        Reviewed by Brent Fulgham.
+
+        On macOS, the functions screenAvailableRect and screenRect is implemented using NSScreen, which is communicating
+        with the WindowServer. To avoid this WindowServer communication from the WebContent process when calling
+        screenAvailableRect and screenRect, it is possible to let the UIProcess send a message to the WebContent
+        process whenever there is a change in the display properties, and have the WebContent process cache these
+        display properties. This message should also be sent to a newly started WebContent process.
+
+        No new tests, covered by existing tests.
+
+        * WebCore.xcodeproj/project.pbxproj:
+        * platform/PlatformScreen.h:
+        * platform/mac/PlatformScreenMac.mm:
+        (WebCore::getScreenProperties):
+        (WebCore::screenProperties):
+        (WebCore::setScreenProperties):
+        (WebCore::screenRect):
+        (WebCore::screenAvailableRect):
+        * platform/ScreenProperties.h: Added.
+        (WebCore::ScreenProperties::encode const):
+        (WebCore::ScreenProperties::decode):
+
 2018-02-21  Christopher Reid  <chris.reid@sony.com>
 
         [Curl] Curl Cookie Database File should be configurable using NetworkProcessCreationParameters
index 9ba7293..11e70b5 100644 (file)
                C0C054CD1118C8E400CE2636 /* IDLParser.pm in Headers */ = {isa = PBXBuildFile; fileRef = 14813BF309EDF88E00F757E1 /* IDLParser.pm */; settings = {ATTRIBUTES = (Private, ); }; };
                C0F2A44113869AAB0066C534 /* preprocessor.pm in Headers */ = {isa = PBXBuildFile; fileRef = C0F2A43F13869A280066C534 /* preprocessor.pm */; settings = {ATTRIBUTES = (Private, ); }; };
                C105DA640F3AA6B8001DD44F /* TextEncodingDetector.h in Headers */ = {isa = PBXBuildFile; fileRef = C105DA630F3AA6B8001DD44F /* TextEncodingDetector.h */; };
+               C1E1D236203DF15400584665 /* ScreenProperties.h in Headers */ = {isa = PBXBuildFile; fileRef = C1E1D235203DF15400584665 /* ScreenProperties.h */; settings = {ATTRIBUTES = (Private, ); }; };
                C2015C0A1BE6FEB200822389 /* FontVariantBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = C2015C091BE6FE2C00822389 /* FontVariantBuilder.h */; };
                C21DF2EA1D9E4E9900F5B24C /* CSSFontVariationValue.h in Headers */ = {isa = PBXBuildFile; fileRef = C21DF2E81D9E4E9900F5B24C /* CSSFontVariationValue.h */; };
                C2458E631FE897B000594759 /* FontCacheCoreText.h in Headers */ = {isa = PBXBuildFile; fileRef = C2458E611FE8979E00594759 /* FontCacheCoreText.h */; settings = {ATTRIBUTES = (Private, ); }; };
                C0F2A43F13869A280066C534 /* preprocessor.pm */ = {isa = PBXFileReference; lastKnownFileType = text.script.perl; name = preprocessor.pm; path = scripts/preprocessor.pm; sourceTree = "<group>"; };
                C105DA610F3AA68F001DD44F /* TextEncodingDetectorICU.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextEncodingDetectorICU.cpp; sourceTree = "<group>"; };
                C105DA630F3AA6B8001DD44F /* TextEncodingDetector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextEncodingDetector.h; sourceTree = "<group>"; };
+               C1E1D235203DF15400584665 /* ScreenProperties.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ScreenProperties.h; sourceTree = "<group>"; };
                C2015C091BE6FE2C00822389 /* FontVariantBuilder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FontVariantBuilder.h; sourceTree = "<group>"; };
                C21DF2E71D9E4E9900F5B24C /* CSSFontVariationValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSSFontVariationValue.cpp; sourceTree = "<group>"; };
                C21DF2E81D9E4E9900F5B24C /* CSSFontVariationValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSFontVariationValue.h; sourceTree = "<group>"; };
                                293EAE1E1356B2FE0067ACF9 /* RuntimeApplicationChecks.h */,
                                5162C7F211F77EFA00612EFE /* SchemeRegistry.cpp */,
                                5162C7F311F77EFB00612EFE /* SchemeRegistry.h */,
+                               C1E1D235203DF15400584665 /* ScreenProperties.h */,
                                BC8AE34C12EA096A00EB3AE6 /* ScrollableArea.cpp */,
                                BC8AE34D12EA096A00EB3AE6 /* ScrollableArea.h */,
                                CA3BF67B10D99BAE00E6CE53 /* ScrollAnimator.cpp */,
                                5162C7F511F77EFB00612EFE /* SchemeRegistry.h in Headers */,
                                9BD0BF9312A42BF50072FD43 /* ScopedEventQueue.h in Headers */,
                                BCEC01BE0C274DAC009F4EC9 /* Screen.h in Headers */,
+                               C1E1D236203DF15400584665 /* ScreenProperties.h in Headers */,
                                A84D82C111D3474800972990 /* ScriptableDocumentParser.h in Headers */,
                                41F1D21F0EF35C2A00DA8753 /* ScriptCachedFrameData.h in Headers */,
                                93B70D7009EB0C7C009D8468 /* ScriptController.h in Headers */,
index f90915e..88331e3 100644 (file)
@@ -30,6 +30,8 @@
 #endif
 
 #if PLATFORM(MAC)
+#include <wtf/HashMap.h>
+
 OBJC_CLASS NSScreen;
 OBJC_CLASS NSWindow;
 #ifdef NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES
@@ -77,6 +79,7 @@ WEBCORE_EXPORT CGColorSpaceRef screenColorSpace(Widget* = nullptr);
 #endif
 
 #if PLATFORM(MAC)
+struct ScreenProperties;
 
 NSScreen *screen(NSWindow *);
 NSScreen *screen(PlatformDisplayID);
@@ -86,6 +89,11 @@ WEBCORE_EXPORT NSRect toDeviceSpace(const FloatRect&, NSWindow *source);
 
 NSPoint flipScreenPoint(const NSPoint&, NSScreen *);
 
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
+WEBCORE_EXPORT void getScreenProperties(HashMap<PlatformDisplayID, ScreenProperties>&);
+WEBCORE_EXPORT void setScreenProperties(const HashMap<PlatformDisplayID, ScreenProperties>&);
+#endif
+
 #endif
 
 #if PLATFORM(IOS)
diff --git a/Source/WebCore/platform/ScreenProperties.h b/Source/WebCore/platform/ScreenProperties.h
new file mode 100644 (file)
index 0000000..ea3e4db
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "FloatRect.h"
+
+namespace WebCore {
+
+struct ScreenProperties {
+    FloatRect screenAvailableRect;
+    FloatRect screenRect;
+
+    template<class Encoder> void encode(Encoder&) const;
+    template<class Decoder> static std::optional<ScreenProperties> decode(Decoder&);
+};
+
+template<class Encoder>
+void ScreenProperties::encode(Encoder& encoder) const
+{
+    encoder << screenAvailableRect << screenRect;
+}
+
+template<class Decoder>
+std::optional<ScreenProperties> ScreenProperties::decode(Decoder& decoder)
+{
+    std::optional<FloatRect> screenAvailableRect;
+    decoder >> screenAvailableRect;
+    if (!screenAvailableRect)
+        return std::nullopt;
+
+    std::optional<FloatRect> screenRect;
+    decoder >> screenRect;
+    if (!screenRect)
+        return std::nullopt;
+
+    return { { WTFMove(*screenAvailableRect), WTFMove(*screenRect) } };
+}
+
+} // namespace WebCore
index 76c7aaa..9ef0e73 100644 (file)
@@ -31,6 +31,7 @@
 #import "FloatRect.h"
 #import "FrameView.h"
 #import "HostWindow.h"
+#import "ScreenProperties.h"
 #import <ColorSync/ColorSync.h>
 #import <pal/spi/cg/CoreGraphicsSPI.h>
 
@@ -112,13 +113,56 @@ bool screenHasInvertedColors()
     return CGDisplayUsesInvertedPolarity();
 }
 
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
+void getScreenProperties(HashMap<PlatformDisplayID, ScreenProperties>& screenProperties)
+{
+    for (NSScreen *screen in [NSScreen screens]) {
+        FloatRect screenAvailableRect = [screen visibleFrame];
+        screenAvailableRect.setY(NSMaxY([screen frame]) - (screenAvailableRect.y() + screenAvailableRect.height())); // flip
+        FloatRect screenRect = [screen frame];
+        screenProperties.set(WebCore::displayID(screen), ScreenProperties { screenAvailableRect, screenRect});
+    }
+}
+
+static HashMap<PlatformDisplayID, ScreenProperties>& screenProperties()
+{
+    static NeverDestroyed<HashMap<PlatformDisplayID, ScreenProperties>> screenProperties;
+    return screenProperties;
+}
+
+void setScreenProperties(const HashMap<PlatformDisplayID, ScreenProperties>& properties)
+{
+    screenProperties() = properties;
+}
+#endif
+
 FloatRect screenRect(Widget* widget)
 {
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
+    if (!screenProperties().isEmpty()) {
+        auto displayIDForWidget = displayID(widget);
+        if (displayIDForWidget && screenProperties().contains(displayIDForWidget))
+            return screenProperties().get(displayIDForWidget).screenRect;
+        // Return property of the first screen if the screen is not found in the map.
+        auto iter = screenProperties().begin();
+        return screenProperties().get(iter->key).screenRect;
+    }
+#endif
     return toUserSpace([screen(widget) frame], window(widget));
 }
 
 FloatRect screenAvailableRect(Widget* widget)
 {
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
+    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;
+    }
+#endif
     return toUserSpace([screen(widget) visibleFrame], window(widget));
 }
 
index 89ae4e8..3d3e1b2 100644 (file)
@@ -1,3 +1,26 @@
+2018-02-21  Per Arne Vollan  <pvollan@apple.com>
+
+        The WebContent process should not use NSScreen in the screenAvailableRect/screenRect implementations.
+        https://bugs.webkit.org/show_bug.cgi?id=182855
+
+        Reviewed by Brent Fulgham.
+
+        On macOS, the functions screenAvailableRect and screenRect is implemented using NSScreen, which is communicating
+        with the WindowServer. To avoid this WindowServer communication from the WebContent process when calling
+        screenAvailableRect and screenRect, it is possible to let the UIProcess send a message to the WebContent
+        process whenever there is a change in the display properties, and have the WebContent process cache these
+        display properties. This message should also be sent to a newly started WebContent process.
+
+        * UIProcess/WebProcessPool.cpp:
+        (WebKit::displayReconfigurationCallBack):
+        (WebKit::registerDisplayConfigurationCallback):
+        (WebKit::WebProcessPool::initializeNewWebProcess):
+        (WebKit::WebProcessPool::warmInitialProcess):
+        * WebProcess/WebProcess.cpp:
+        (WebKit::WebProcess::setScreenProperties):
+        * WebProcess/WebProcess.h:
+        * WebProcess/WebProcess.messages.in:
+
 2018-02-21  Christopher Reid  <chris.reid@sony.com>
 
         [Curl] Curl Cookie Database File should be configurable using NetworkProcessCreationParameters
index 8a57332..b6f90a5 100644 (file)
@@ -78,6 +78,7 @@
 #include <JavaScriptCore/JSCInlines.h>
 #include <WebCore/ApplicationCacheStorage.h>
 #include <WebCore/LogInitialization.h>
+#include <WebCore/PlatformScreen.h>
 #include <WebCore/ResourceRequest.h>
 #include <WebCore/URLParser.h>
 #include <pal/SessionID.h>
@@ -714,6 +715,27 @@ WebProcessProxy& WebProcessPool::createNewWebProcess(WebsiteDataStore& websiteDa
     return process;
 }
 
+#if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
+static void displayReconfigurationCallBack(CGDirectDisplayID display, CGDisplayChangeSummaryFlags flags, void *userInfo)
+{
+    HashMap<PlatformDisplayID, ScreenProperties> screenProperties;
+    WebCore::getScreenProperties(screenProperties);
+
+    for (auto& processPool : WebProcessPool::allProcessPools())
+        processPool->sendToAllProcesses(Messages::WebProcess::SetScreenProperties(screenProperties));
+}
+
+static void registerDisplayConfigurationCallback()
+{
+    static std::once_flag onceFlag;
+    std::call_once(
+        onceFlag,
+        [] {
+            CGDisplayRegisterReconfigurationCallback(displayReconfigurationCallBack, nullptr);
+        });
+}
+#endif
+
 void WebProcessPool::initializeNewWebProcess(WebProcessProxy& process, WebsiteDataStore& websiteDataStore)
 {
     ensureNetworkProcess();
@@ -860,9 +882,17 @@ void WebProcessPool::initializeNewWebProcess(WebProcessProxy& process, WebsiteDa
     // Initialize remote inspector connection now that we have a sub-process that is hosting one of our web views.
     Inspector::RemoteInspector::singleton(); 
 #endif
+
+#if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
+    registerDisplayConfigurationCallback();
+
+    HashMap<PlatformDisplayID, ScreenProperties> screenProperties;
+    WebCore::getScreenProperties(screenProperties);
+    process.send(Messages::WebProcess::SetScreenProperties(screenProperties), 0);
+#endif
 }
 
-void WebProcessPool::warmInitialProcess()  
+void WebProcessPool::warmInitialProcess()
 {
     if (m_haveInitialEmptyProcess) {
         ASSERT(!m_processes.isEmpty());
index 1a7f743..85ef3f9 100644 (file)
@@ -1678,4 +1678,11 @@ void WebProcess::registerServiceWorkerClients(PAL::SessionID sessionID)
 
 #endif
 
+#if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
+void WebProcess::setScreenProperties(const HashMap<uint32_t, WebCore::ScreenProperties>& properties)
+{
+    WebCore::setScreenProperties(properties);
+}
+#endif
+
 } // namespace WebKit
index 6a59998..52b9d3f 100644 (file)
@@ -34,6 +34,9 @@
 #include "ViewUpdateDispatcher.h"
 #include "WebInspectorInterruptDispatcher.h"
 #include <WebCore/ActivityState.h>
+#if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
+#include <WebCore/ScreenProperties.h>
+#endif
 #include <WebCore/Timer.h>
 #include <pal/HysteresisActivity.h>
 #include <pal/SessionID.h>
@@ -367,6 +370,10 @@ private:
     void didReceiveWebProcessMessage(IPC::Connection&, IPC::Decoder&);
     void didReceiveSyncWebProcessMessage(IPC::Connection&, IPC::Decoder&, std::unique_ptr<IPC::Encoder>&);
 
+#if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
+    void setScreenProperties(const HashMap<uint32_t, WebCore::ScreenProperties>&);
+#endif
+
     RefPtr<WebConnectionToUIProcess> m_webConnection;
 
     HashMap<uint64_t, RefPtr<WebPage>> m_pageMap;
index b2e681c..5798d7d 100644 (file)
@@ -124,4 +124,8 @@ messages -> WebProcess LegacyReceiver {
     DidCheckRemotePortForActivity(uint64_t callbackIdentifier, bool hasActivity)
     CheckProcessLocalPortForActivity(struct WebCore::MessagePortIdentifier port, uint64_t callbackIdentifier)
     MessagesAvailableForPort(struct WebCore::MessagePortIdentifier port)
+
+#if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
+    SetScreenProperties(HashMap<uint32_t, WebCore::ScreenProperties> screenProperties);
+#endif
 }