Title: [255992] trunk/Source/WebKit
Revision
255992
Author
[email protected]
Date
2020-02-06 16:44:34 -0800 (Thu, 06 Feb 2020)

Log Message

[WK2][iOS] Add WKWebviewConfiguration SPI to run client navigations at foreground priority, even if the view is background
https://bugs.webkit.org/show_bug.cgi?id=207341
<rdar://problem/59227077>

Reviewed by Geoff Garen.

Add WKWebviewConfiguration SPI to run client navigations at foreground priority, even if the view is background,
as long as the application itself is foreground. The new SPI is:
WKWebViewConfiguration._clientNavigationsRunAtForegroundPriority

The use case is that the client may choose to load something in an offscreen view and only show the view once the
load is complete (to avoid flashing for e.g.). In such cases, it makes sense to use foreground priority for the
load since it needs to complete as fast as possible, even though the view is technically background.

* UIProcess/API/APINavigation.h:
(API::Navigation::setForegroundActivity):
* UIProcess/API/APIPageConfiguration.cpp:
(API::PageConfiguration::copy const):
* UIProcess/API/APIPageConfiguration.h:
(API::PageConfiguration::clientNavigationsRunAtForegroundPriority const):
(API::PageConfiguration::setClientNavigationsRunAtForegroundPriority):
(API::PageConfiguration::alwaysRunsAtForegroundPriority const):
(API::PageConfiguration::alwaysRunsAtForegroundPriority): Deleted.
* UIProcess/API/Cocoa/WKWebViewConfiguration.mm:
(-[WKWebViewConfiguration _clientNavigationsRunAtForegroundPriority]):
(-[WKWebViewConfiguration _setClientNavigationsRunAtForegroundPriority:]):
* UIProcess/API/Cocoa/WKWebViewConfigurationPrivate.h:
* UIProcess/PageClient.h:
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::loadRequest):
(WebKit::WebPageProxy::loadFile):
(WebKit::WebPageProxy::loadData):
(WebKit::WebPageProxy::didFailProvisionalLoadForFrameShared):
(WebKit::WebPageProxy::didFinishLoadForFrame):
(WebKit::WebPageProxy::didFailLoadForFrame):
* UIProcess/WebPageProxy.h:
* UIProcess/ios/PageClientImplIOS.h:
* UIProcess/ios/PageClientImplIOS.mm:
(WebKit::PageClientImpl::isApplicationVisible):
* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::shouldUseForegroundPriorityForClientNavigation const):

Modified Paths

Diff

Modified: trunk/Source/WebKit/ChangeLog (255991 => 255992)


--- trunk/Source/WebKit/ChangeLog	2020-02-06 23:42:06 UTC (rev 255991)
+++ trunk/Source/WebKit/ChangeLog	2020-02-07 00:44:34 UTC (rev 255992)
@@ -1,5 +1,49 @@
 2020-02-06  Chris Dumez  <[email protected]>
 
+        [WK2][iOS] Add WKWebviewConfiguration SPI to run client navigations at foreground priority, even if the view is background
+        https://bugs.webkit.org/show_bug.cgi?id=207341
+        <rdar://problem/59227077>
+
+        Reviewed by Geoff Garen.
+
+        Add WKWebviewConfiguration SPI to run client navigations at foreground priority, even if the view is background,
+        as long as the application itself is foreground. The new SPI is:
+        WKWebViewConfiguration._clientNavigationsRunAtForegroundPriority
+
+        The use case is that the client may choose to load something in an offscreen view and only show the view once the
+        load is complete (to avoid flashing for e.g.). In such cases, it makes sense to use foreground priority for the
+        load since it needs to complete as fast as possible, even though the view is technically background.
+
+        * UIProcess/API/APINavigation.h:
+        (API::Navigation::setForegroundActivity):
+        * UIProcess/API/APIPageConfiguration.cpp:
+        (API::PageConfiguration::copy const):
+        * UIProcess/API/APIPageConfiguration.h:
+        (API::PageConfiguration::clientNavigationsRunAtForegroundPriority const):
+        (API::PageConfiguration::setClientNavigationsRunAtForegroundPriority):
+        (API::PageConfiguration::alwaysRunsAtForegroundPriority const):
+        (API::PageConfiguration::alwaysRunsAtForegroundPriority): Deleted.
+        * UIProcess/API/Cocoa/WKWebViewConfiguration.mm:
+        (-[WKWebViewConfiguration _clientNavigationsRunAtForegroundPriority]):
+        (-[WKWebViewConfiguration _setClientNavigationsRunAtForegroundPriority:]):
+        * UIProcess/API/Cocoa/WKWebViewConfigurationPrivate.h:
+        * UIProcess/PageClient.h:
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::loadRequest):
+        (WebKit::WebPageProxy::loadFile):
+        (WebKit::WebPageProxy::loadData):
+        (WebKit::WebPageProxy::didFailProvisionalLoadForFrameShared):
+        (WebKit::WebPageProxy::didFinishLoadForFrame):
+        (WebKit::WebPageProxy::didFailLoadForFrame):
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/ios/PageClientImplIOS.h:
+        * UIProcess/ios/PageClientImplIOS.mm:
+        (WebKit::PageClientImpl::isApplicationVisible):
+        * UIProcess/ios/WebPageProxyIOS.mm:
+        (WebKit::WebPageProxy::shouldUseForegroundPriorityForClientNavigation const):
+
+2020-02-06  Chris Dumez  <[email protected]>
+
         REGRESSION (r254706): Crash under WebProcessPool::terminateServiceWorkerProcess()
         https://bugs.webkit.org/show_bug.cgi?id=207354
         <rdar://problem/59184818>

Modified: trunk/Source/WebKit/UIProcess/API/APINavigation.h (255991 => 255992)


--- trunk/Source/WebKit/UIProcess/API/APINavigation.h	2020-02-06 23:42:06 UTC (rev 255991)
+++ trunk/Source/WebKit/UIProcess/API/APINavigation.h	2020-02-07 00:44:34 UTC (rev 255992)
@@ -29,6 +29,7 @@
 #include "DataReference.h"
 #include "FrameInfoData.h"
 #include "NavigationActionData.h"
+#include "ProcessThrottler.h"
 #include "WebBackForwardListItem.h"
 #include "WebContentMode.h"
 #include <WebCore/AdClickAttribution.h>
@@ -153,6 +154,8 @@
 
     const Optional<WebCore::AdClickAttribution>& adClickAttribution() const { return m_lastNavigationAction.adClickAttribution; }
 
+    void setForegroundActivity(std::unique_ptr<WebKit::ProcessThrottler::ForegroundActivity>&& activity) { m_foregroundActivity = WTFMove(activity); }
+
 private:
     explicit Navigation(WebKit::WebNavigationState&);
     Navigation(WebKit::WebNavigationState&, WebCore::ResourceRequest&&, WebKit::WebBackForwardListItem* fromItem);
@@ -174,6 +177,7 @@
     WebCore::SecurityOriginData m_destinationFrameSecurityOrigin;
     bool m_userContentExtensionsEnabled { true };
     WebKit::WebContentMode m_effectiveContentMode { WebKit::WebContentMode::Recommended };
+    std::unique_ptr<WebKit::ProcessThrottler::ForegroundActivity> m_foregroundActivity;
 };
 
 } // namespace API

Modified: trunk/Source/WebKit/UIProcess/API/APIPageConfiguration.cpp (255991 => 255992)


--- trunk/Source/WebKit/UIProcess/API/APIPageConfiguration.cpp	2020-02-06 23:42:06 UTC (rev 255991)
+++ trunk/Source/WebKit/UIProcess/API/APIPageConfiguration.cpp	2020-02-07 00:44:34 UTC (rev 255992)
@@ -73,6 +73,7 @@
     copy->m_visitedLinkStore = this->m_visitedLinkStore;
     copy->m_websiteDataStore = this->m_websiteDataStore;
 #if PLATFORM(IOS_FAMILY)
+    copy->m_clientNavigationsRunAtForegroundPriority = this->m_clientNavigationsRunAtForegroundPriority;
     copy->m_alwaysRunsAtForegroundPriority = this->m_alwaysRunsAtForegroundPriority;
     copy->m_canShowWhileLocked = this->m_canShowWhileLocked;
     copy->m_clickInteractionDriverForTesting = this->m_clickInteractionDriverForTesting;

Modified: trunk/Source/WebKit/UIProcess/API/APIPageConfiguration.h (255991 => 255992)


--- trunk/Source/WebKit/UIProcess/API/APIPageConfiguration.h	2020-02-06 23:42:06 UTC (rev 255991)
+++ trunk/Source/WebKit/UIProcess/API/APIPageConfiguration.h	2020-02-07 00:44:34 UTC (rev 255992)
@@ -92,7 +92,9 @@
     void setDefaultWebsitePolicies(WebsitePolicies*);
 
 #if PLATFORM(IOS_FAMILY)
-    bool alwaysRunsAtForegroundPriority() { return m_alwaysRunsAtForegroundPriority; }
+    bool clientNavigationsRunAtForegroundPriority() const { return m_clientNavigationsRunAtForegroundPriority; }
+    void setClientNavigationsRunAtForegroundPriority(bool value) { m_clientNavigationsRunAtForegroundPriority = value; }
+    bool alwaysRunsAtForegroundPriority() const { return m_alwaysRunsAtForegroundPriority; }
     void setAlwaysRunsAtForegroundPriority(bool alwaysRunsAtForegroundPriority) { m_alwaysRunsAtForegroundPriority = alwaysRunsAtForegroundPriority; }
     
     bool canShowWhileLocked() const { return m_canShowWhileLocked; }
@@ -153,6 +155,7 @@
     RefPtr<WebsitePolicies> m_defaultWebsitePolicies;
 
 #if PLATFORM(IOS_FAMILY)
+    bool m_clientNavigationsRunAtForegroundPriority { false };
     bool m_alwaysRunsAtForegroundPriority { false };
     bool m_canShowWhileLocked { false };
     RetainPtr<_UIClickInteractionDriving> m_clickInteractionDriverForTesting;

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewConfiguration.mm (255991 => 255992)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewConfiguration.mm	2020-02-06 23:42:06 UTC (rev 255991)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewConfiguration.mm	2020-02-07 00:44:34 UTC (rev 255992)
@@ -705,6 +705,16 @@
 }
 
 #if PLATFORM(IOS_FAMILY)
+- (BOOL)_clientNavigationsRunAtForegroundPriority
+{
+    return _pageConfiguration->clientNavigationsRunAtForegroundPriority();
+}
+
+- (void)_setClientNavigationsRunAtForegroundPriority:(BOOL)clientNavigationsRunAtForegroundPriority
+{
+    _pageConfiguration->setClientNavigationsRunAtForegroundPriority(clientNavigationsRunAtForegroundPriority);
+}
+
 - (BOOL)_alwaysRunsAtForegroundPriority
 {
     return _pageConfiguration->alwaysRunsAtForegroundPriority();

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewConfigurationPrivate.h (255991 => 255992)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewConfigurationPrivate.h	2020-02-06 23:42:06 UTC (rev 255991)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewConfigurationPrivate.h	2020-02-07 00:44:34 UTC (rev 255992)
@@ -85,6 +85,7 @@
 @property (nonatomic, copy, setter=_setCORSDisablingPatterns:) NSArray<NSString *> *_corsDisablingPatterns WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
 
 #if TARGET_OS_IPHONE
+@property (nonatomic, setter=_setClientNavigationsRunAtForegroundPriority:) BOOL _clientNavigationsRunAtForegroundPriority WK_API_AVAILABLE(ios(WK_IOS_TBA));
 @property (nonatomic, setter=_setAlwaysRunsAtForegroundPriority:) BOOL _alwaysRunsAtForegroundPriority WK_API_AVAILABLE(ios(9_0));
 @property (nonatomic, setter=_setInlineMediaPlaybackRequiresPlaysInlineAttribute:) BOOL _inlineMediaPlaybackRequiresPlaysInlineAttribute WK_API_AVAILABLE(ios(10.0));
 @property (nonatomic, setter=_setAllowsInlineMediaPlaybackAfterFullscreen:) BOOL _allowsInlineMediaPlaybackAfterFullscreen  WK_API_AVAILABLE(ios(10.0));

Modified: trunk/Source/WebKit/UIProcess/ApplicationStateTracker.h (255991 => 255992)


--- trunk/Source/WebKit/UIProcess/ApplicationStateTracker.h	2020-02-06 23:42:06 UTC (rev 255991)
+++ trunk/Source/WebKit/UIProcess/ApplicationStateTracker.h	2020-02-07 00:44:34 UTC (rev 255992)
@@ -34,6 +34,7 @@
 
 OBJC_CLASS BKSApplicationStateMonitor;
 OBJC_CLASS UIView;
+OBJC_CLASS UIWindow;
 
 namespace WebKit {
 
@@ -64,6 +65,14 @@
     id m_willEnterForegroundObserver;
 };
 
+enum class ApplicationType {
+    Application,
+    ViewService,
+    Extension,
+};
+
+ApplicationType applicationType(UIWindow *);
+
 }
 
 #endif

Modified: trunk/Source/WebKit/UIProcess/ApplicationStateTracker.mm (255991 => 255992)


--- trunk/Source/WebKit/UIProcess/ApplicationStateTracker.mm	2020-02-06 23:42:06 UTC (rev 255991)
+++ trunk/Source/WebKit/UIProcess/ApplicationStateTracker.mm	2020-02-07 00:44:34 UTC (rev 255992)
@@ -50,13 +50,7 @@
 
 namespace WebKit {
 
-enum class ApplicationType {
-    Application,
-    ViewService,
-    Extension,
-};
-
-static ApplicationType applicationType(UIWindow *window)
+ApplicationType applicationType(UIWindow *window)
 {
     ASSERT(window);
 

Modified: trunk/Source/WebKit/UIProcess/PageClient.h (255991 => 255992)


--- trunk/Source/WebKit/UIProcess/PageClient.h	2020-02-06 23:42:06 UTC (rev 255991)
+++ trunk/Source/WebKit/UIProcess/PageClient.h	2020-02-07 00:44:34 UTC (rev 255992)
@@ -196,6 +196,11 @@
     // Return whether the view is visible.
     virtual bool isViewVisible() = 0;
 
+#if PLATFORM(IOS_FAMILY)
+    // Return whether the application is visible.
+    virtual bool isApplicationVisible() = 0;
+#endif
+
     // Return whether the view is visible, or occluded by another window.
     virtual bool isViewVisibleOrOccluded() { return isViewVisible(); }
 

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (255991 => 255992)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2020-02-06 23:42:06 UTC (rev 255991)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2020-02-07 00:44:34 UTC (rev 255992)
@@ -1255,6 +1255,10 @@
         launchProcess(RegistrableDomain { request.url() }, ProcessLaunchReason::InitialProcess);
 
     auto navigation = m_navigationState->createLoadRequestNavigation(ResourceRequest(request), m_backForwardList->currentItem());
+
+    if (shouldUseForegroundPriorityForClientNavigation())
+        navigation->setForegroundActivity(process().throttler().foregroundActivity("Client navigation"_s).moveToUniquePtr());
+
     loadRequestWithNavigationShared(m_process.copyRef(), m_webPageID, navigation.get(), WTFMove(request), shouldOpenExternalURLsPolicy, userData, ShouldTreatAsContinuingLoad::No);
     return navigation;
 }
@@ -1327,6 +1331,9 @@
 
     auto navigation = m_navigationState->createLoadRequestNavigation(ResourceRequest(fileURL), m_backForwardList->currentItem());
 
+    if (shouldUseForegroundPriorityForClientNavigation())
+        navigation->setForegroundActivity(process().throttler().foregroundActivity("Client navigation"_s).moveToUniquePtr());
+
     auto transaction = m_pageLoadState.transaction();
 
     m_pageLoadState.setPendingAPIRequest(transaction, { navigation->navigationID(), fileURLString }, resourceDirectoryURL);
@@ -1366,6 +1373,10 @@
         launchProcess({ }, ProcessLaunchReason::InitialProcess);
 
     auto navigation = m_navigationState->createLoadDataNavigation(makeUnique<API::SubstituteData>(data.vector(), MIMEType, encoding, baseURL, userData));
+
+    if (shouldUseForegroundPriorityForClientNavigation())
+        navigation->setForegroundActivity(process().throttler().foregroundActivity("Client navigation"_s).moveToUniquePtr());
+
     loadDataWithNavigationShared(m_process.copyRef(), m_webPageID, navigation, data, MIMEType, encoding, baseURL, userData, ShouldTreatAsContinuingLoad::No, WTF::nullopt, shouldOpenExternalURLsPolicy);
     return navigation;
 }
@@ -4429,6 +4440,8 @@
         reportPageLoadResult(error);
         m_pageLoadState.didFailProvisionalLoad(transaction);
         pageClient().didFailProvisionalLoadForMainFrame();
+        if (navigation)
+            navigation->setForegroundActivity(nullptr);
     }
 
     frame->didFailProvisionalLoad();
@@ -4661,6 +4674,9 @@
         reportPageLoadResult();
         pageClient().didFinishLoadForMainFrame();
 
+        if (navigation)
+            navigation->setForegroundActivity(nullptr);
+
         resetRecentCrashCountSoon();
 
         notifyProcessPoolToPrewarm();
@@ -4708,6 +4724,8 @@
     if (isMainFrame) {
         reportPageLoadResult(error);
         pageClient().didFailLoadForMainFrame();
+        if (navigation)
+            navigation->setForegroundActivity(nullptr);
     }
 }
 
@@ -9815,6 +9833,13 @@
     send(Messages::WebPage::SetOverriddenMediaType(mediaType));
 }
 
+#if !PLATFORM(IOS_FAMILY)
+bool WebPageProxy::shouldUseForegroundPriorityForClientNavigation() const
+{
+    return false;
+}
+#endif
+
 void WebPageProxy::setOrientationForMediaCapture(uint64_t orientation)
 {
 #if PLATFORM(COCOA) && ENABLE(MEDIA_STREAM)

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (255991 => 255992)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.h	2020-02-06 23:42:06 UTC (rev 255991)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h	2020-02-07 00:44:34 UTC (rev 255992)
@@ -1692,6 +1692,8 @@
     void notifyProcessPoolToPrewarm();
     bool shouldUseBackForwardCache() const;
 
+    bool shouldUseForegroundPriorityForClientNavigation() const;
+
     RefPtr<API::Navigation> goToBackForwardItem(WebBackForwardListItem&, WebCore::FrameLoadType);
 
     void updateActivityState(OptionSet<WebCore::ActivityState::Flag> flagsToUpdate = WebCore::ActivityState::allFlags());

Modified: trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.h (255991 => 255992)


--- trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.h	2020-02-06 23:42:06 UTC (rev 255991)
+++ trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.h	2020-02-07 00:44:34 UTC (rev 255992)
@@ -63,6 +63,7 @@
     bool isViewWindowActive() override;
     bool isViewFocused() override;
     bool isViewVisible() override;
+    bool isApplicationVisible() override;
     bool isViewInWindow() override;
     bool isViewVisibleOrOccluded() override;
     bool isVisuallyIdle() override;

Modified: trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm (255991 => 255992)


--- trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm	2020-02-06 23:42:06 UTC (rev 255991)
+++ trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm	2020-02-07 00:44:34 UTC (rev 255992)
@@ -29,6 +29,8 @@
 #if PLATFORM(IOS_FAMILY)
 
 #import "APIData.h"
+#import "ApplicationStateTracker.h"
+#import "AssertionServicesSPI.h"
 #import "DataReference.h"
 #import "DownloadProxy.h"
 #import "DrawingAreaProxy.h"
@@ -68,9 +70,14 @@
 #import <WebCore/TextIndicator.h>
 #import <WebCore/ValidationBubble.h>
 #import <wtf/BlockPtr.h>
+#import <wtf/cocoa/Entitlements.h>
 
 #define MESSAGE_CHECK(assertion) MESSAGE_CHECK_BASE(assertion, m_webView.get()->_page->process().connection())
 
+@interface UIWindow ()
+- (BOOL)_isHostedInAnotherProcess;
+@end
+
 namespace WebKit {
 using namespace WebCore;
 
@@ -141,6 +148,34 @@
     return false;
 }
 
+bool PageClientImpl::isApplicationVisible()
+{
+    switch (applicationType([m_webView window])) {
+    case ApplicationType::Application:
+        return [[UIApplication sharedApplication] applicationState] != UIApplicationStateBackground;
+    case ApplicationType::ViewService:
+    case ApplicationType::Extension:
+        break;
+    }
+
+    UIViewController *serviceViewController = nil;
+    for (UIView *view = m_webView.get().get(); view; view = view.superview) {
+        UIViewController *viewController = [UIViewController viewControllerForView:view];
+        if (viewController._hostProcessIdentifier) {
+            serviceViewController = viewController;
+            break;
+        }
+    }
+    ASSERT(serviceViewController);
+    pid_t applicationPID = serviceViewController._hostProcessIdentifier;
+    ASSERT(applicationPID);
+
+    auto applicationStateMonitor = adoptNS([[BKSApplicationStateMonitor alloc] init]);
+    auto applicationState = [applicationStateMonitor mostElevatedApplicationStateForPID:applicationPID];
+    [applicationStateMonitor invalidate];
+    return applicationState != BKSApplicationStateBackgroundRunning && applicationState != BKSApplicationStateBackgroundTaskSuspended;
+}
+
 bool PageClientImpl::isViewInWindow()
 {
     // FIXME: in WebKitTestRunner, m_webView is nil, so check the content view instead.

Modified: trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm (255991 => 255992)


--- trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm	2020-02-06 23:42:06 UTC (rev 255991)
+++ trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm	2020-02-07 00:44:34 UTC (rev 255992)
@@ -29,6 +29,7 @@
 #if PLATFORM(IOS_FAMILY)
 
 #import "APINavigationAction.h"
+#import "APIPageConfiguration.h"
 #import "APIUIClient.h"
 #import "APIWebsitePolicies.h"
 #import "Connection.h"
@@ -1500,6 +1501,19 @@
     return WebContentMode::Desktop;
 }
 
+bool WebPageProxy::shouldUseForegroundPriorityForClientNavigation() const
+{
+    // The client may request that we do client navigations at foreground priority, even if the
+    // view is not visible, as long as the application is foreground.
+    if (!configuration().clientNavigationsRunAtForegroundPriority())
+        return false;
+
+    if (isViewVisible())
+        return false;
+
+    return pageClient().isApplicationVisible();
+}
+
 #if PLATFORM(IOS)
 void WebPageProxy::grantAccessToAssetServices()
 {
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to