Title: [253646] trunk
Revision
253646
Author
commit-qu...@webkit.org
Date
2019-12-17 13:42:22 -0800 (Tue, 17 Dec 2019)

Log Message

Navigation from empty page doesn't use cached web process
https://bugs.webkit.org/show_bug.cgi?id=205015
<rdar://problem/57703742>

Patch by Ben Nham <n...@apple.com> on 2019-12-17
Reviewed by Chris Dumez.

When navigating from an empty page to another domain foo.com, we always use the source
WebProcess (which is basically uninitialized) rather than using an already-initialized
cached WebProcess that has navigated to foo.com. The cached WebProcess should probably be
preferred since it has more relevant cached resources available to it (e.g. memory cache, JS
bytecode cache, prewarmed fonts, ...).

Source/WebKit:

Added an API test.

* UIProcess/API/Cocoa/WKWebViewPrivateForTesting.h:
* UIProcess/API/Cocoa/WKWebViewTesting.mm:
(-[WKWebView _ensureRunningProcessForTesting]):
Allows tests to force WebProcess to launch to an empty document for testing purposes. This
matches the behavior of how Safari uses WKWebView.

* UIProcess/WebProcessPool.cpp:
(WebKit::WebProcessPool::processForNavigationInternal): Prefer cached web process over
source process if the source process hasn't committed any loads.

Tools:

* TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:
Verify that a load from an empty document uses the process cache. To actually force the
WebProcess to launch with an empty document loaded, we use the private API
_ensureRunningProcessForTesting.

Modified Paths

Diff

Modified: trunk/Source/WebKit/ChangeLog (253645 => 253646)


--- trunk/Source/WebKit/ChangeLog	2019-12-17 21:36:07 UTC (rev 253645)
+++ trunk/Source/WebKit/ChangeLog	2019-12-17 21:42:22 UTC (rev 253646)
@@ -1,3 +1,29 @@
+2019-12-17  Ben Nham  <n...@apple.com>
+
+        Navigation from empty page doesn't use cached web process
+        https://bugs.webkit.org/show_bug.cgi?id=205015
+        <rdar://problem/57703742>
+
+        Reviewed by Chris Dumez.
+
+        When navigating from an empty page to another domain foo.com, we always use the source
+        WebProcess (which is basically uninitialized) rather than using an already-initialized
+        cached WebProcess that has navigated to foo.com. The cached WebProcess should probably be
+        preferred since it has more relevant cached resources available to it (e.g. memory cache, JS
+        bytecode cache, prewarmed fonts, ...).
+
+        Added an API test.
+
+        * UIProcess/API/Cocoa/WKWebViewPrivateForTesting.h:
+        * UIProcess/API/Cocoa/WKWebViewTesting.mm:
+        (-[WKWebView _ensureRunningProcessForTesting]):
+        Allows tests to force WebProcess to launch to an empty document for testing purposes. This
+        matches the behavior of how Safari uses WKWebView.
+
+        * UIProcess/WebProcessPool.cpp:
+        (WebKit::WebProcessPool::processForNavigationInternal): Prefer cached web process over
+        source process if the source process hasn't committed any loads.
+
 2019-12-17  Benjamin Nham  <n...@apple.com>
 
         Drop support for NSURLCache callbacks in NetworkProcess

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivateForTesting.h (253645 => 253646)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivateForTesting.h	2019-12-17 21:36:07 UTC (rev 253645)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivateForTesting.h	2019-12-17 21:42:22 UTC (rev 253646)
@@ -59,4 +59,6 @@
 @property (nonatomic, readonly) BOOL _hasServiceWorkerForegroundActivityForTesting;
 - (void)_setAssertionStateForTesting:(int)state;
 
+- (void)_ensureRunningProcessForTesting;
+
 @end

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewTesting.mm (253645 => 253646)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewTesting.mm	2019-12-17 21:36:07 UTC (rev 253645)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewTesting.mm	2019-12-17 21:42:22 UTC (rev 253646)
@@ -202,4 +202,9 @@
 #endif
 }
 
+- (void)_ensureRunningProcessForTesting
+{
+    _page->ensureRunningProcess();
+}
+
 @end

Modified: trunk/Source/WebKit/UIProcess/WebProcessPool.cpp (253645 => 253646)


--- trunk/Source/WebKit/UIProcess/WebProcessPool.cpp	2019-12-17 21:36:07 UTC (rev 253645)
+++ trunk/Source/WebKit/UIProcess/WebProcessPool.cpp	2019-12-17 21:42:22 UTC (rev 253646)
@@ -2183,11 +2183,6 @@
     if (m_automationSession)
         return completionHandler(WTFMove(sourceProcess), nullptr, "An automation session is active"_s);
 
-    if (!sourceProcess->hasCommittedAnyProvisionalLoads()) {
-        tryPrewarmWithDomainInformation(sourceProcess, targetRegistrableDomain);
-        return completionHandler(WTFMove(sourceProcess), nullptr, "Process has not yet committed any provisional loads"_s);
-    }
-
     // FIXME: We should support process swap when a window has been opened via window.open() without 'noopener'.
     // The issue is that the opener has a handle to the WindowProxy.
     if (navigation.openedByDOMWithOpener() && !m_configuration->processSwapsOnWindowOpenWithOpener())
@@ -2223,6 +2218,16 @@
     if (navigation.treatAsSameOriginNavigation())
         return completionHandler(WTFMove(sourceProcess), nullptr, "The treatAsSameOriginNavigation flag is set"_s);
 
+    if (!sourceProcess->hasCommittedAnyProvisionalLoads()) {
+        if (auto process = webProcessCache().takeProcess(targetRegistrableDomain, dataStore)) {
+            RELEASE_LOG(ProcessSwapping, "(ProcessSwapping) Reusing a previously cached process with pid %i in place of pid %i that hasn't committed any provisional loads", process->processIdentifier(), sourceProcess->processIdentifier());
+            return completionHandler(process.releaseNonNull(), nullptr, "Reusing cached process in place of process that hasn't committed any loads"_s);
+        }
+
+        tryPrewarmWithDomainInformation(sourceProcess, targetRegistrableDomain);
+        return completionHandler(WTFMove(sourceProcess), nullptr, "Process has not yet committed any provisional loads"_s);
+    }
+
     URL sourceURL;
     if (page.isPageOpenedByDOMShowingInitialEmptyDocument() && !navigation.requesterOrigin().isEmpty())
         sourceURL = URL { URL(), navigation.requesterOrigin().toString() };

Modified: trunk/Tools/ChangeLog (253645 => 253646)


--- trunk/Tools/ChangeLog	2019-12-17 21:36:07 UTC (rev 253645)
+++ trunk/Tools/ChangeLog	2019-12-17 21:42:22 UTC (rev 253646)
@@ -1,3 +1,22 @@
+2019-12-17  Ben Nham  <n...@apple.com>
+
+        Navigation from empty page doesn't use cached web process
+        https://bugs.webkit.org/show_bug.cgi?id=205015
+        <rdar://problem/57703742>
+
+        Reviewed by Chris Dumez.
+
+        When navigating from an empty page to another domain foo.com, we always use the source
+        WebProcess (which is basically uninitialized) rather than using an already-initialized
+        cached WebProcess that has navigated to foo.com. The cached WebProcess should probably be
+        preferred since it has more relevant cached resources available to it (e.g. memory cache, JS
+        bytecode cache, prewarmed fonts, ...).
+
+        * TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:
+        Verify that a load from an empty document uses the process cache. To actually force the
+        WebProcess to launch with an empty document loaded, we use the private API
+        _ensureRunningProcessForTesting.
+
 2019-12-17  Megan Gardner  <megan_gard...@apple.com>
 
         Update Check webkit style to allow for auto with pairs in c++

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm (253645 => 253646)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm	2019-12-17 21:36:07 UTC (rev 253645)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm	2019-12-17 21:42:22 UTC (rev 253646)
@@ -58,10 +58,6 @@
 #import <wtf/text/StringHash.h>
 #import <wtf/text/WTFString.h>
 
-@interface WKProcessPool ()
-- (WKContextRef)_contextForTesting;
-@end
-
 static bool done;
 static bool didStartProvisionalLoad;
 static bool failed;
@@ -3561,6 +3557,72 @@
     EXPECT_EQ(1U, [processPool _webProcessCountIgnoringPrewarmed]);
 }
 
+TEST(ProcessSwap, UseWebProcessCacheForLoadInEmptyDocument)
+{
+    auto processPoolConfiguration = psonProcessPoolConfiguration();
+    auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
+
+    auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    [webViewConfiguration setProcessPool:processPool.get()];
+    auto handler = adoptNS([[PSONScheme alloc] init]);
+    [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
+
+    pid_t pid1 = 0;
+    pid_t pid2 = 0;
+    pid_t pid3 = 0;
+
+    auto delegate = adoptNS([[PSONNavigationDelegate alloc] init]);
+
+    @autoreleasepool {
+        auto webView1 = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
+        [webView1 setNavigationDelegate:delegate.get()];
+
+        NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main1.html"]];
+        [webView1 loadRequest:request];
+
+        TestWebKitAPI::Util::run(&done);
+        done = false;
+
+        pid1 = [webView1 _webProcessIdentifier];
+        EXPECT_NE(pid1, 0);
+
+        request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.apple.com/main.html"]];
+        [webView1 loadRequest:request];
+
+        TestWebKitAPI::Util::run(&done);
+        done = false;
+
+        pid2 = [webView1 _webProcessIdentifier];
+        EXPECT_NE(pid2, 0);
+    }
+
+    auto webView2 = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
+    [webView2 setNavigationDelegate:delegate.get()];
+
+    // Force webView2 to eagerly launch a WebProcess that loads the empty document. (Safari
+    // implicitly launches WebProcess to the empty document because it immediately posts a message
+    // to its injected bundle after creating its WKWebView. Here we launch WebProcess explicitly.)
+    [webView2 _ensureRunningProcessForTesting];
+
+    // Wait for webkit.org and apple.com from webView1 to enter cached process pool.
+    while ([processPool _processCacheSize] != 2)
+        TestWebKitAPI::Util::sleep(0.1);
+
+    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main2.html"]];
+    [webView2 loadRequest:request];
+
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+
+    pid3 = [webView2 _webProcessIdentifier];
+    EXPECT_NE(pid3, 0);
+
+    EXPECT_EQ(3u, seenPIDs.size());
+    EXPECT_NE(pid1, pid2);
+    EXPECT_NE(pid2, pid3);
+    EXPECT_EQ(pid1, pid3);
+}
+
 TEST(ProcessSwap, UseWebProcessCacheForLoadInNewView)
 {
     auto processPoolConfiguration = psonProcessPoolConfiguration();
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to