[iOS] WebContent processes should be marked as "Foreground Running" when their view...
authorcdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 9 Apr 2019 18:08:27 +0000 (18:08 +0000)
committercdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 9 Apr 2019 18:08:27 +0000 (18:08 +0000)
https://bugs.webkit.org/show_bug.cgi?id=196695
<rdar://problem/48073787>

Reviewed by Tim Horton.

In order for WebContent processes to get marked as "Foreground Running" when their view
is visible on iOS, we now construct a _UILayerHostView in the UIProcess and add it as
a subview of the WKContentView. The _UILayerHostView's visibility target is the
WebContent process currently associated with the view.

* Platform/spi/ios/UIKitSPI.h:
* UIProcess/PageClient.h:
(WebKit::PageClient::didCreateContextForVisibilityPropagation):
* UIProcess/WebPageProxy.h:
* UIProcess/WebProcessProxy.h:
(WebKit::WebProcessProxy::contextIDForVisibilityPropagation):
* UIProcess/WebProcessProxy.messages.in:
* UIProcess/ios/PageClientImplIOS.h:
* UIProcess/ios/PageClientImplIOS.mm:
(WebKit::PageClientImpl::didCreateContextForVisibilityPropagation):
* UIProcess/ios/WKContentView.h:
* UIProcess/ios/WKContentView.mm:
(-[WKContentView _commonInitializationWithProcessPool:configuration:]):
(-[WKContentView _setupVisibilityPropagationView]):
(-[WKContentView _processDidExit]):
(-[WKContentView _didRelaunchProcess]):
(-[WKContentView _processDidCreateContextForVisibilityPropagation]):
* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::didCreateContextForVisibilityPropagation):
* UIProcess/ios/WebProcessProxyIOS.mm:
(WebKit::WebProcessProxy::didCreateContextForVisibilityPropagation):
* WebProcess/WebProcess.h:
* WebProcess/cocoa/WebProcessCocoa.mm:
(WebKit::WebProcess::platformInitializeWebProcess):

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

18 files changed:
Source/WTF/wtf/FeatureDefines.h
Source/WebKit/ChangeLog
Source/WebKit/Platform/mac/LayerHostingContext.h
Source/WebKit/Platform/mac/LayerHostingContext.mm
Source/WebKit/Platform/spi/ios/UIKitSPI.h
Source/WebKit/Scripts/webkit/messages.py
Source/WebKit/UIProcess/PageClient.h
Source/WebKit/UIProcess/WebPageProxy.h
Source/WebKit/UIProcess/WebProcessProxy.h
Source/WebKit/UIProcess/WebProcessProxy.messages.in
Source/WebKit/UIProcess/ios/PageClientImplIOS.h
Source/WebKit/UIProcess/ios/PageClientImplIOS.mm
Source/WebKit/UIProcess/ios/WKContentView.h
Source/WebKit/UIProcess/ios/WKContentView.mm
Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm
Source/WebKit/UIProcess/ios/WebProcessProxyIOS.mm
Source/WebKit/WebProcess/WebProcess.h
Source/WebKit/WebProcess/cocoa/WebProcessCocoa.mm

index c4069ac..e76e8dc 100644 (file)
@@ -177,6 +177,12 @@ the public iOS SDK. See <https://webkit.org/b/179167>. */
 #endif
 #endif
 
+#if !defined(HAVE_VISIBILITY_PROPAGATION_VIEW)
+#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 130000
+#define HAVE_VISIBILITY_PROPAGATION_VIEW 1
+#endif
+#endif
+
 #if !defined(HAVE_AVSTREAMSESSION)
 #define HAVE_AVSTREAMSESSION 0
 #endif
index 83feb8d..9faffab 100644 (file)
@@ -1,3 +1,41 @@
+2019-04-09  Chris Dumez  <cdumez@apple.com>
+
+        [iOS] WebContent processes should be marked as "Foreground Running" when their view is visible
+        https://bugs.webkit.org/show_bug.cgi?id=196695
+        <rdar://problem/48073787>
+
+        Reviewed by Tim Horton.
+
+        In order for WebContent processes to get marked as "Foreground Running" when their view
+        is visible on iOS, we now construct a _UILayerHostView in the UIProcess and add it as
+        a subview of the WKContentView. The _UILayerHostView's visibility target is the
+        WebContent process currently associated with the view.
+
+        * Platform/spi/ios/UIKitSPI.h:
+        * UIProcess/PageClient.h:
+        (WebKit::PageClient::didCreateContextForVisibilityPropagation):
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/WebProcessProxy.h:
+        (WebKit::WebProcessProxy::contextIDForVisibilityPropagation):
+        * UIProcess/WebProcessProxy.messages.in:
+        * UIProcess/ios/PageClientImplIOS.h:
+        * UIProcess/ios/PageClientImplIOS.mm:
+        (WebKit::PageClientImpl::didCreateContextForVisibilityPropagation):
+        * UIProcess/ios/WKContentView.h:
+        * UIProcess/ios/WKContentView.mm:
+        (-[WKContentView _commonInitializationWithProcessPool:configuration:]):
+        (-[WKContentView _setupVisibilityPropagationView]):
+        (-[WKContentView _processDidExit]):
+        (-[WKContentView _didRelaunchProcess]):
+        (-[WKContentView _processDidCreateContextForVisibilityPropagation]):
+        * UIProcess/ios/WebPageProxyIOS.mm:
+        (WebKit::WebPageProxy::didCreateContextForVisibilityPropagation):
+        * UIProcess/ios/WebProcessProxyIOS.mm:
+        (WebKit::WebProcessProxy::didCreateContextForVisibilityPropagation):
+        * WebProcess/WebProcess.h:
+        * WebProcess/cocoa/WebProcessCocoa.mm:
+        (WebKit::WebProcess::platformInitializeWebProcess):
+
 2019-04-09  Sihui Liu  <sihui_liu@apple.com>
 
         Remove unnecessary network process assertion for IDB close
index 62c7770..5797793 100644 (file)
@@ -39,6 +39,8 @@ class MachSendRight;
 
 namespace WebKit {
 
+using LayerHostingContextID = uint32_t;
+
 class LayerHostingContext {
     WTF_MAKE_NONCOPYABLE(LayerHostingContext); WTF_MAKE_FAST_ALLOCATED;
 public:
@@ -56,7 +58,7 @@ public:
     void setRootLayer(CALayer *);
     CALayer *rootLayer() const;
 
-    uint32_t contextID() const;
+    LayerHostingContextID contextID() const;
     void invalidate();
 
     LayerHostingMode layerHostingMode() { return m_layerHostingMode; }
index 5ba1fed..910bb3f 100644 (file)
@@ -103,7 +103,7 @@ CALayer *LayerHostingContext::rootLayer() const
     return [m_context layer];
 }
 
-uint32_t LayerHostingContext::contextID() const
+LayerHostingContextID LayerHostingContext::contextID() const
 {
     return [m_context contextId];
 }
index 9a88773..41cb810 100644 (file)
@@ -1119,6 +1119,7 @@ typedef NS_OPTIONS(NSInteger, UIWKDocumentRequestFlags) {
 @end
 
 @interface _UILayerHostView : UIView
+- (instancetype)initWithFrame:(CGRect)frame pid:(pid_t)pid contextID:(uint32_t)contextID;
 @end
 
 @interface _UIRemoteView : _UILayerHostView
index 12fef65..103c46e 100644 (file)
@@ -188,6 +188,10 @@ def forward_declarations_and_headers(receiver):
         '<wtf/Forward.h>',
     ])
 
+    header_conditions = {
+        '"LayerHostingContext.h"': ["PLATFORM(COCOA)", ],
+    }
+
     non_template_wtf_types = frozenset([
         'MachSendRight',
         'String',
@@ -210,6 +214,7 @@ def forward_declarations_and_headers(receiver):
         'WebCore::ServiceWorkerRegistrationIdentifier',
         'WebCore::SWServerConnectionIdentifier',
         'WebKit::ActivityStateChangeID',
+        'WebKit::LayerHostingContextID',
         'WebKit::UserContentControllerIdentifier',
     ])
 
@@ -238,9 +243,18 @@ def forward_declarations_and_headers(receiver):
             headers.update(headers_for_type(type))
 
     forward_declarations = '\n'.join([forward_declarations_for_namespace(namespace, types) for (namespace, types) in sorted(types_by_namespace.items())])
-    headers = ['#include %s\n' % header for header in sorted(headers)]
 
-    return (forward_declarations, headers)
+    header_includes = set()
+    for header in sorted(headers):
+        if header in header_conditions and not None in header_conditions[header]:
+            header_include = '#if %s\n' % ' || '.join(set(header_conditions[header]))
+            header_include += '#include %s\n' % header
+            header_include += '#endif\n'
+            header_includes.add(header_include)
+        else:
+            header_includes.add('#include %s\n' % header)
+
+    return (forward_declarations, header_includes)
 
 
 def generate_messages_header(file):
@@ -451,6 +465,7 @@ def headers_for_type(type):
         'WebCore::SelectionRect': ['"EditorState.h"'],
         'WebKit::ActivityStateChangeID': ['"DrawingAreaInfo.h"'],
         'WebKit::BackForwardListItemState': ['"SessionState.h"'],
+        'WebKit::LayerHostingContextID': ['"LayerHostingContext.h"'],
         'WebKit::LayerHostingMode': ['"LayerTreeContext.h"'],
         'WebKit::PageState': ['"SessionState.h"'],
         'WebKit::WebGestureEvent': ['"WebEvent.h"'],
index 7df54c3..db36757 100644 (file)
@@ -157,6 +157,10 @@ class InstallMissingMediaPluginsPermissionRequest;
 struct ColorSpaceData;
 #endif
 
+#if HAVE(VISIBILITY_PROPAGATION_VIEW)
+using LayerHostingContextID = uint32_t;
+#endif
+
 class PageClient : public CanMakeWeakPtr<PageClient> {
 public:
     virtual ~PageClient() { }
@@ -281,6 +285,10 @@ public:
     virtual void didNotHandleTapAsClick(const WebCore::IntPoint&) = 0;
     virtual void didCompleteSyntheticClick() = 0;
 #endif
+
+#if HAVE(VISIBILITY_PROPAGATION_VIEW)
+    virtual void didCreateContextForVisibilityPropagation(LayerHostingContextID) { }
+#endif
     
     virtual void doneWithKeyEvent(const NativeWebKeyboardEvent&, bool wasEventHandled) = 0;
 #if ENABLE(TOUCH_EVENTS)
index 460a193..41a4322 100644 (file)
@@ -302,6 +302,10 @@ typedef GenericCallback<const String&> StringCallback;
 typedef GenericCallback<API::SerializedScriptValue*, bool, const WebCore::ExceptionDetails&> ScriptValueCallback;
 typedef GenericCallback<const WebCore::FontAttributes&> FontAttributesCallback;
 
+#if HAVE(VISIBILITY_PROPAGATION_VIEW)
+using LayerHostingContextID = uint32_t;
+#endif
+
 #if PLATFORM(GTK)
 typedef GenericCallback<API::Error*> PrintFinishedCallback;
 #endif
@@ -1054,6 +1058,10 @@ public:
     void processWillBecomeForeground();
 #endif
 
+#if HAVE(VISIBILITY_PROPAGATION_VIEW)
+    void didCreateContextForVisibilityPropagation(LayerHostingContextID);
+#endif
+
     virtual void enterAcceleratedCompositingMode(const LayerTreeContext&);
     virtual void exitAcceleratedCompositingMode();
     virtual void updateAcceleratedCompositingMode(const LayerTreeContext&);
index 67bc7f5..a9a993d 100644 (file)
@@ -297,6 +297,10 @@ public:
     void unblockAccessibilityServerIfNeeded();
 #endif
 
+#if HAVE(VISIBILITY_PROPAGATION_VIEW)
+    LayerHostingContextID contextIDForVisibilityPropagation() { return m_contextIDForVisibilityPropagation; }
+#endif
+
 protected:
     static uint64_t generatePageID();
     WebProcessProxy(WebProcessPool&, WebsiteDataStore*, IsPrewarmed);
@@ -337,6 +341,10 @@ private:
     void didDeliverMessagePortMessages(uint64_t messageBatchIdentifier);
     void didCheckProcessLocalPortForActivity(uint64_t callbackIdentifier, bool isLocallyReachable);
 
+#if HAVE(VISIBILITY_PROPAGATION_VIEW)
+    void didCreateContextForVisibilityPropagation(LayerHostingContextID);
+#endif
+
     bool hasProvisionalPageWithID(uint64_t pageID) const;
     bool isAllowedToUpdateBackForwardItem(WebBackForwardListItem&) const;
 
@@ -442,6 +450,10 @@ private:
     bool m_hasSentMessageToUnblockAccessibilityServer { false };
 #endif
 
+#if HAVE(VISIBILITY_PROPAGATION_VIEW)
+    LayerHostingContextID m_contextIDForVisibilityPropagation { 0 };
+#endif
+
     HashMap<String, uint64_t> m_pageURLRetainCountMap;
 
     Optional<WebCore::RegistrableDomain> m_registrableDomain;
index c424c18..86cf19a 100644 (file)
@@ -79,4 +79,8 @@ messages -> WebProcessProxy LegacyReceiver {
     StartDisplayLink(unsigned observerID, uint32_t displayID)
     StopDisplayLink(unsigned observerID, uint32_t displayID)
 #endif
+
+#if HAVE(VISIBILITY_PROPAGATION_VIEW)
+    DidCreateContextForVisibilityPropagation(WebKit::LayerHostingContextID contextID);
+#endif
 }
index 4792c2a..f40fd3f 100644 (file)
@@ -68,6 +68,9 @@ private:
     void processDidExit() override;
     void processWillSwap() override;
     void didRelaunchProcess() override;
+#if HAVE(VISIBILITY_PROPAGATION_VIEW)
+    void didCreateContextForVisibilityPropagation(LayerHostingContextID) override;
+#endif
     void pageClosed() override;
     void preferencesDidChange() override;
     void toolTipChanged(const String&, const String&) override;
index 41b4776..ff1de0e 100644 (file)
@@ -175,6 +175,13 @@ void PageClientImpl::didRelaunchProcess()
     [m_webView _didRelaunchProcess];
 }
 
+#if HAVE(VISIBILITY_PROPAGATION_VIEW)
+void PageClientImpl::didCreateContextForVisibilityPropagation(LayerHostingContextID)
+{
+    [m_contentView _processDidCreateContextForVisibilityPropagation];
+}
+#endif
+
 void PageClientImpl::pageClosed()
 {
     notImplemented();
index 4b290a7..daa3910 100644 (file)
@@ -93,6 +93,9 @@ class WebProcessPool;
 - (void)_processDidExit;
 - (void)_processWillSwap;
 - (void)_didRelaunchProcess;
+#if HAVE(VISIBILITY_PROPAGATION_VIEW)
+- (void)_processDidCreateContextForVisibilityPropagation;
+#endif
 - (void)_setAcceleratedCompositingRootView:(UIView *)rootView;
 
 - (void)_showInspectorHighlight:(const WebCore::Highlight&)highlight;
index ff163da..6b2d9f9 100644 (file)
@@ -183,6 +183,10 @@ private:
     RetainPtr<WKInspectorIndicationView> _inspectorIndicationView;
     RetainPtr<WKInspectorHighlightView> _inspectorHighlightView;
 
+#if HAVE(VISIBILITY_PROPAGATION_VIEW)
+    RetainPtr<_UILayerHostView> _visibilityPropagationView;
+#endif
+
     WebKit::HistoricalVelocityData _historicalKinematicData;
 
     RetainPtr<NSUndoManager> _undoManager;
@@ -226,12 +230,38 @@ private:
 
     self.layer.hitTestsAsOpaque = YES;
 
+#if HAVE(VISIBILITY_PROPAGATION_VIEW)
+    [self _setupVisibilityPropagationView];
+#endif
+
     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_applicationWillResignActive:) name:UIApplicationWillResignActiveNotification object:[UIApplication sharedApplication]];
     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_applicationDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:[UIApplication sharedApplication]];
 
     return self;
 }
 
+#if HAVE(VISIBILITY_PROPAGATION_VIEW)
+- (void)_setupVisibilityPropagationView
+{
+    auto processIdentifier = _page->process().processIdentifier();
+    auto contextID = _page->process().contextIDForVisibilityPropagation();
+    if (!processIdentifier || !contextID)
+        return;
+
+    ASSERT(!_visibilityPropagationView);
+    // Propagate the view's visibility state to the WebContent process so that it is marked as "Foreground Running" when necessary.
+    _visibilityPropagationView = adoptNS([[_UILayerHostView alloc] initWithFrame:CGRectZero pid:processIdentifier contextID:contextID]);
+    RELEASE_LOG(Process, "Created visibility propagation view %p for WebContent process with PID %d", _visibilityPropagationView.get(), processIdentifier);
+    [self addSubview:_visibilityPropagationView.get()];
+}
+
+- (void)_removeVisibilityPropagationView
+{
+    [_visibilityPropagationView removeFromSuperview];
+    _visibilityPropagationView = nullptr;
+}
+#endif
+
 - (instancetype)initWithFrame:(CGRect)frame processPool:(WebKit::WebProcessPool&)processPool configuration:(Ref<API::PageConfiguration>&&)configuration webView:(WKWebView *)webView
 {
     if (!(self = [super initWithFrame:frame webView:webView]))
@@ -538,6 +568,10 @@ static void storeAccessibilityRemoteConnectionInformation(id element, pid_t pid,
 
     [self setShowingInspectorIndication:NO];
     [self _hideInspectorHighlight];
+
+#if HAVE(VISIBILITY_PROPAGATION_VIEW)
+    [self _removeVisibilityPropagationView];
+#endif
 }
 
 - (void)_processWillSwap
@@ -550,8 +584,18 @@ static void storeAccessibilityRemoteConnectionInformation(id element, pid_t pid,
 {
     [self _accessibilityRegisterUIProcessTokens];
     [self setupInteraction];
+#if HAVE(VISIBILITY_PROPAGATION_VIEW)
+    [self _setupVisibilityPropagationView];
+#endif
 }
 
+#if HAVE(VISIBILITY_PROPAGATION_VIEW)
+- (void)_processDidCreateContextForVisibilityPropagation
+{
+    [self _setupVisibilityPropagationView];
+}
+#endif
+
 - (void)_didCommitLoadForMainFrame
 {
     [self _elementDidBlur];
index ff8bf69..1018e0e 100644 (file)
@@ -81,6 +81,13 @@ String WebPageProxy::standardUserAgent(const String& applicationNameForUserAgent
     return standardUserAgentWithApplicationName(applicationNameForUserAgent);
 }
 
+#if HAVE(VISIBILITY_PROPAGATION_VIEW)
+void WebPageProxy::didCreateContextForVisibilityPropagation(LayerHostingContextID contextID)
+{
+    pageClient().didCreateContextForVisibilityPropagation(contextID);
+}
+#endif
+
 void WebPageProxy::getIsSpeaking(CompletionHandler<void(bool)>&& completionHandler)
 {
     notImplemented();
index 4388087..70ba162 100644 (file)
@@ -62,6 +62,15 @@ void WebProcessProxy::unblockAccessibilityServerIfNeeded()
     m_hasSentMessageToUnblockAccessibilityServer = true;
 }
 
+#if HAVE(VISIBILITY_PROPAGATION_VIEW)
+void WebProcessProxy::didCreateContextForVisibilityPropagation(LayerHostingContextID contextID)
+{
+    m_contextIDForVisibilityPropagation = contextID;
+    for (auto& page : copyToVectorOf<RefPtr<WebPageProxy>>(m_pageMap.values()))
+        page->didCreateContextForVisibilityPropagation(contextID);
+}
+#endif
+
 } // namespace WebKit
 
 #endif // PLATFORM(IOS_FAMILY)
index ee781a0..4d986a8 100644 (file)
@@ -112,6 +112,10 @@ class WebSQLiteDatabaseTracker;
 struct WebsiteData;
 struct WebsiteDataStoreParameters;
 
+#if PLATFORM(IOS_FAMILY)
+class LayerHostingContext;
+#endif
+
 class WebProcess : public AuxiliaryProcess {
 public:
     static WebProcess& singleton();
@@ -498,6 +502,9 @@ private:
 #if PLATFORM(IOS_FAMILY)
     std::unique_ptr<WebSQLiteDatabaseTracker> m_webSQLiteDatabaseTracker;
 #endif
+#if HAVE(VISIBILITY_PROPAGATION_VIEW)
+    std::unique_ptr<LayerHostingContext> m_contextForVisibilityPropagation;
+#endif
 
     enum PageMarkingLayersAsVolatileCounterType { };
     using PageMarkingLayersAsVolatileCounter = RefCounter<PageMarkingLayersAsVolatileCounterType>;
index 24ac5e0..a174811 100644 (file)
@@ -171,6 +171,12 @@ void WebProcess::platformInitializeWebProcess(WebProcessCreationParameters& para
 
     m_compositingRenderServerPort = WTFMove(parameters.acceleratedCompositingPort);
 
+#if HAVE(VISIBILITY_PROPAGATION_VIEW)
+    m_contextForVisibilityPropagation = LayerHostingContext::createForExternalHostingProcess();
+    RELEASE_LOG(Process, "Created context with ID %d for visibility propagation from UIProcess", m_contextForVisibilityPropagation->contextID());
+    parentProcessConnection()->send(Messages::WebProcessProxy::DidCreateContextForVisibilityPropagation(m_contextForVisibilityPropagation->contextID()), 0);
+#endif
+
     WebCore::registerMemoryReleaseNotifyCallbacks();
     MemoryPressureHandler::ReliefLogger::setLoggingEnabled(parameters.shouldEnableMemoryPressureReliefLogging);