Process Swap on Navigation causes many webpages to hang due to attempted process...
authorbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 5 Apr 2018 23:18:01 +0000 (23:18 +0000)
committerbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 5 Apr 2018 23:18:01 +0000 (23:18 +0000)
<rdar://problem/39162236> and https://bugs.webkit.org/show_bug.cgi?id=184318

Reviewed by Andy Estes.

Source/WebKit:

* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::receivedPolicyDecision): Don't consider a swap if the navigation is not in the main frame.

Tools:

* TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:
(-[PSONMessageHandler userContentController:didReceiveScriptMessage:]):
(-[PSONScheme addMappingFromURLString:toData:]):
(-[PSONScheme webView:startURLSchemeTask:]):

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

Source/WebKit/ChangeLog
Source/WebKit/UIProcess/WebPageProxy.cpp
Tools/ChangeLog
Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm

index 18b023c..436217f 100644 (file)
@@ -1,3 +1,13 @@
+2018-04-05  Brady Eidson  <beidson@apple.com>
+
+        Process Swap on Navigation causes many webpages to hang due to attempted process swap for iframe navigations.
+        <rdar://problem/39162236> and https://bugs.webkit.org/show_bug.cgi?id=184318
+
+        Reviewed by Andy Estes.
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::receivedPolicyDecision): Don't consider a swap if the navigation is not in the main frame.
+
 2018-04-05  Ryosuke Niwa  <rniwa@webkit.org>
 
         WebContent process sometimes hangs in WebProcess::ensureNetworkProcessConnection
 2018-04-05  Ryosuke Niwa  <rniwa@webkit.org>
 
         WebContent process sometimes hangs in WebProcess::ensureNetworkProcessConnection
index 0b41249..5ca1bd2 100644 (file)
@@ -2350,7 +2350,7 @@ void WebPageProxy::receivedPolicyDecision(PolicyAction action, WebFrameProxy& fr
     if (activePolicyListener && activePolicyListener->policyListenerType() == PolicyListenerType::NavigationAction) {
         ASSERT(activePolicyListener->listenerID() == listenerID);
 
     if (activePolicyListener && activePolicyListener->policyListenerType() == PolicyListenerType::NavigationAction) {
         ASSERT(activePolicyListener->listenerID() == listenerID);
 
-        if (action == PolicyAction::Use && navigation) {
+        if (action == PolicyAction::Use && navigation && frame.isMainFrame()) {
             auto proposedProcess = process().processPool().processForNavigation(*this, *navigation, action);
 
             if (proposedProcess.ptr() != &process()) {
             auto proposedProcess = process().processPool().processForNavigation(*this, *navigation, action);
 
             if (proposedProcess.ptr() != &process()) {
index 53da09a..64ea2b2 100644 (file)
@@ -1,3 +1,15 @@
+2018-04-05  Brady Eidson  <beidson@apple.com>
+
+        Process Swap on Navigation causes many webpages to hang due to attempted process swap for iframe navigations.
+        <rdar://problem/39162236> and https://bugs.webkit.org/show_bug.cgi?id=184318
+
+        Reviewed by Andy Estes.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:
+        (-[PSONMessageHandler userContentController:didReceiveScriptMessage:]):
+        (-[PSONScheme addMappingFromURLString:toData:]):
+        (-[PSONScheme webView:startURLSchemeTask:]):
+
 2018-04-05  Yusuke Suzuki  <utatane.tea@gmail.com>
 
         [WTF] Remove StaticLock
 2018-04-05  Yusuke Suzuki  <utatane.tea@gmail.com>
 
         [WTF] Remove StaticLock
index 2f51b15..772bdb2 100644 (file)
@@ -73,6 +73,7 @@ static HashSet<pid_t> seenPIDs;
         [receivedMessages addObject:@""];
 
     receivedMessage = true;
         [receivedMessages addObject:@""];
 
     receivedMessage = true;
+    seenPIDs.add([message.webView _webProcessIdentifier]);
 }
 @end
 
 }
 @end
 
@@ -134,9 +135,11 @@ static RetainPtr<WKWebView> createdWebView;
 @interface PSONScheme : NSObject <WKURLSchemeHandler> {
     const char* _bytes;
     HashMap<String, String> _redirects;
 @interface PSONScheme : NSObject <WKURLSchemeHandler> {
     const char* _bytes;
     HashMap<String, String> _redirects;
+    HashMap<String, RetainPtr<NSData *>> _dataMappings;
 }
 - (instancetype)initWithBytes:(const char*)bytes;
 - (void)addRedirectFromURLString:(NSString *)sourceURLString toURLString:(NSString *)destinationURLString;
 }
 - (instancetype)initWithBytes:(const char*)bytes;
 - (void)addRedirectFromURLString:(NSString *)sourceURLString toURLString:(NSString *)destinationURLString;
+- (void)addMappingFromURLString:(NSString *)urlString toData:(const char*)data;
 @end
 
 @implementation PSONScheme
 @end
 
 @implementation PSONScheme
@@ -153,6 +156,11 @@ static RetainPtr<WKWebView> createdWebView;
     _redirects.set(sourceURLString, destinationURLString);
 }
 
     _redirects.set(sourceURLString, destinationURLString);
 }
 
+- (void)addMappingFromURLString:(NSString *)urlString toData:(const char*)data
+{
+    _dataMappings.set(urlString, [NSData dataWithBytesNoCopy:(void*)data length:strlen(data) freeWhenDone:NO]);
+}
+
 - (void)webView:(WKWebView *)webView startURLSchemeTask:(id <WKURLSchemeTask>)task
 {
     NSURL *finalURL = task.request.URL;
 - (void)webView:(WKWebView *)webView startURLSchemeTask:(id <WKURLSchemeTask>)task
 {
     NSURL *finalURL = task.request.URL;
@@ -169,7 +177,9 @@ static RetainPtr<WKWebView> createdWebView;
     RetainPtr<NSURLResponse> response = adoptNS([[NSURLResponse alloc] initWithURL:finalURL MIMEType:@"text/html" expectedContentLength:1 textEncodingName:nil]);
     [task didReceiveResponse:response.get()];
 
     RetainPtr<NSURLResponse> response = adoptNS([[NSURLResponse alloc] initWithURL:finalURL MIMEType:@"text/html" expectedContentLength:1 textEncodingName:nil]);
     [task didReceiveResponse:response.get()];
 
-    if (_bytes) {
+    if (auto data = _dataMappings.get([finalURL absoluteString]))
+        [task didReceiveData:data.get()];
+    else if (_bytes) {
         RetainPtr<NSData> data = adoptNS([[NSData alloc] initWithBytesNoCopy:(void *)_bytes length:strlen(_bytes) freeWhenDone:NO]);
         [task didReceiveData:data.get()];
     } else
         RetainPtr<NSData> data = adoptNS([[NSData alloc] initWithBytesNoCopy:(void *)_bytes length:strlen(_bytes) freeWhenDone:NO]);
         [task didReceiveData:data.get()];
     } else
@@ -687,4 +697,58 @@ TEST(ProcessSwap, SessionStorage)
     EXPECT_TRUE([receivedMessages.get()[1] isEqualToString:@"I exist!"]);
 }
 
     EXPECT_TRUE([receivedMessages.get()[1] isEqualToString:@"I exist!"]);
 }
 
+static const char* mainFramesOnlyMainFrame = R"PSONRESOURCE(
+<script>
+function loaded() {
+    setTimeout('window.frames[0].location.href = "pson2://host2/main.html"', 0);
+}
+</script>
+<body onload="loaded();">
+Some text
+<iframe src="pson1://host/iframe.html"></iframe>
+</body>
+)PSONRESOURCE";
+
+static const char* mainFramesOnlySubframe = R"PSONRESOURCE(
+Some content
+)PSONRESOURCE";
+
+
+static const char* mainFramesOnlySubframe2 = R"PSONRESOURCE(
+<script>
+    window.webkit.messageHandlers.pson.postMessage("Done");
+</script>
+)PSONRESOURCE";
+
+TEST(ProcessSwap, MainFramesOnly)
+{
+    auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
+    [processPoolConfiguration setProcessSwapsOnNavigation:YES];
+    auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
+
+    auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    [webViewConfiguration setProcessPool:processPool.get()];
+    auto handler = adoptNS([[PSONScheme alloc] init]);
+    [handler addMappingFromURLString:@"pson1://host/main.html" toData:mainFramesOnlyMainFrame];
+    [handler addMappingFromURLString:@"pson1://host/iframe" toData:mainFramesOnlySubframe];
+    [handler addMappingFromURLString:@"pson2://host2/main.html" toData:mainFramesOnlySubframe2];
+    [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON1"];
+    [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON2"];
+
+    auto messageHandler = adoptNS([[PSONMessageHandler alloc] init]);
+    [[webViewConfiguration userContentController] addScriptMessageHandler:messageHandler.get() name:@"pson"];
+
+    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
+    auto delegate = adoptNS([[PSONNavigationDelegate alloc] init]);
+    [webView setNavigationDelegate:delegate.get()];
+
+    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson1://host/main.html"]];
+    [webView loadRequest:request];
+
+    TestWebKitAPI::Util::run(&receivedMessage);
+    receivedMessage = false;
+
+    EXPECT_EQ(1u, seenPIDs.size());
+}
+
 #endif // WK_API_ENABLED
 #endif // WK_API_ENABLED