Title: [238826] trunk
Revision
238826
Author
[email protected]
Date
2018-12-03 15:57:41 -0800 (Mon, 03 Dec 2018)

Log Message

[PSON] Request by the client to process-swap is ignored if the window has an opener
https://bugs.webkit.org/show_bug.cgi?id=192267
<rdar://problem/46386886>

Reviewed by Brady Eidson.

Source/WebKit:

If the client forces a process-swap, we should process-swap, even if the browsing
context has an opener (or openees). Previously, we would only bypass the cross-site
check, not the openee / openees checks.

The issue when doing so is that the openee still has a opener link to the window
in the old process. They would see that the window is still there and navigated
to 'about:blank' due to our page suspension logic. To address the issue, we no
longer suspend the old WebPage if the process swap was forced by the client and
we make sure that the old WebPage gets closed.

* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::suspendCurrentPageIfPossible):
(WebKit::WebPageProxy::swapToWebProcess):
(WebKit::WebPageProxy::receivedNavigationPolicyDecision):
(WebKit::WebPageProxy::continueNavigationInNewProcess):
* UIProcess/WebPageProxy.h:
* UIProcess/WebProcessPool.cpp:
(WebKit::WebProcessPool::processForNavigationInternal):

Tools:

Add API test coverage.

* TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:

Modified Paths

Diff

Modified: trunk/Source/WebKit/ChangeLog (238825 => 238826)


--- trunk/Source/WebKit/ChangeLog	2018-12-03 23:16:25 UTC (rev 238825)
+++ trunk/Source/WebKit/ChangeLog	2018-12-03 23:57:41 UTC (rev 238826)
@@ -1,3 +1,30 @@
+2018-12-03  Chris Dumez  <[email protected]>
+
+        [PSON] Request by the client to process-swap is ignored if the window has an opener
+        https://bugs.webkit.org/show_bug.cgi?id=192267
+        <rdar://problem/46386886>
+
+        Reviewed by Brady Eidson.
+
+        If the client forces a process-swap, we should process-swap, even if the browsing
+        context has an opener (or openees). Previously, we would only bypass the cross-site
+        check, not the openee / openees checks.
+
+        The issue when doing so is that the openee still has a opener link to the window
+        in the old process. They would see that the window is still there and navigated
+        to 'about:blank' due to our page suspension logic. To address the issue, we no
+        longer suspend the old WebPage if the process swap was forced by the client and
+        we make sure that the old WebPage gets closed.
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::suspendCurrentPageIfPossible):
+        (WebKit::WebPageProxy::swapToWebProcess):
+        (WebKit::WebPageProxy::receivedNavigationPolicyDecision):
+        (WebKit::WebPageProxy::continueNavigationInNewProcess):
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/WebProcessPool.cpp:
+        (WebKit::WebProcessPool::processForNavigationInternal):
+
 2018-12-03  Keith Rollin  <[email protected]>
 
         Add .xcfilelist files

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (238825 => 238826)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2018-12-03 23:16:25 UTC (rev 238825)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2018-12-03 23:57:41 UTC (rev 238826)
@@ -737,11 +737,15 @@
     finishAttachingToWebProcess();
 }
 
-bool WebPageProxy::suspendCurrentPageIfPossible(API::Navigation& navigation, std::optional<uint64_t> mainFrameID)
+bool WebPageProxy::suspendCurrentPageIfPossible(API::Navigation& navigation, std::optional<uint64_t> mainFrameID, ProcessSwapRequestedByClient processSwapRequestedByClient)
 {
     if (!mainFrameID)
         return false;
 
+    // If the client forced a swap then it may not be Web-compatible to suspend the previous page because other windows may have an opener link to the page.
+    if (processSwapRequestedByClient == ProcessSwapRequestedByClient::Yes)
+        return false;
+
     auto* currentItem = navigation.fromItem();
     if (!currentItem) {
         LOG(ProcessSwapping, "WebPageProxy %" PRIu64 " unable to create suspended page for process pid %i - No current back/forward item", pageID(), m_process->processIdentifier());
@@ -756,7 +760,7 @@
     return true;
 }
 
-void WebPageProxy::swapToWebProcess(Ref<WebProcessProxy>&& process, API::Navigation& navigation, std::optional<uint64_t> mainFrameIDInPreviousProcess, CompletionHandler<void()>&& completionHandler)
+void WebPageProxy::swapToWebProcess(Ref<WebProcessProxy>&& process, API::Navigation& navigation, std::optional<uint64_t> mainFrameIDInPreviousProcess, ProcessSwapRequestedByClient processSwapRequestedByClient, CompletionHandler<void(bool)>&& completionHandler)
 {
     ASSERT(!m_isClosed);
     RELEASE_LOG_IF_ALLOWED(Process, "%p WebPageProxy::swapToWebProcess\n", this);
@@ -770,11 +774,11 @@
     }
 
     auto* destinationSuspendedPagePtr = destinationSuspendedPage.get();
-    auto doSwap = [this, protectedThis = makeRef(*this), navigation = makeRef(navigation), process = WTFMove(process), mainFrameIDInPreviousProcess, destinationSuspendedPage = WTFMove(destinationSuspendedPage), completionHandler = WTFMove(completionHandler)]() mutable {
+    auto doSwap = [this, protectedThis = makeRef(*this), navigation = makeRef(navigation), process = WTFMove(process), mainFrameIDInPreviousProcess, processSwapRequestedByClient, destinationSuspendedPage = WTFMove(destinationSuspendedPage), completionHandler = WTFMove(completionHandler)]() mutable {
         processDidTerminate(ProcessTerminationReason::NavigationSwap);
 
         m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID);
-        bool didSuspendPreviousPage = suspendCurrentPageIfPossible(navigation, mainFrameIDInPreviousProcess);
+        bool didSuspendPreviousPage = suspendCurrentPageIfPossible(navigation, mainFrameIDInPreviousProcess, processSwapRequestedByClient);
         m_process->removeWebPage(*this, m_pageID);
 
         m_process = WTFMove(process);
@@ -792,7 +796,7 @@
         }
 
         finishAttachingToWebProcess(didSuspendPreviousPage ? ShouldDelayAttachingDrawingArea::Yes : ShouldDelayAttachingDrawingArea::No);
-        completionHandler();
+        completionHandler(didSuspendPreviousPage);
     };
 
     if (destinationSuspendedPagePtr)
@@ -2623,7 +2627,7 @@
     receivedPolicyDecision(policyAction, navigation, WTFMove(data), WTFMove(sender));
 
     if (processForNavigation.ptr() != &process())
-        continueNavigationInNewProcess(*navigation, WTFMove(processForNavigation));
+        continueNavigationInNewProcess(*navigation, WTFMove(processForNavigation), processSwapRequestedByClient);
 }
 
 void WebPageProxy::receivedPolicyDecision(PolicyAction action, API::Navigation* navigation, std::optional<WebsitePoliciesData>&& websitePolicies, Ref<PolicyDecisionSender>&& sender)
@@ -2658,7 +2662,7 @@
     sender->send(action, navigation ? navigation->navigationID() : 0, downloadID, WTFMove(websitePolicies));
 }
 
-void WebPageProxy::continueNavigationInNewProcess(API::Navigation& navigation, Ref<WebProcessProxy>&& process)
+void WebPageProxy::continueNavigationInNewProcess(API::Navigation& navigation, Ref<WebProcessProxy>&& process, ProcessSwapRequestedByClient processSwapRequestedByClient)
 {
     LOG(Loading, "Continuing navigation %" PRIu64 " '%s' in a new web process", navigation.navigationID(), navigation.loggingString());
 
@@ -2668,7 +2672,7 @@
 
     ASSERT(m_process.ptr() != process.ptr());
 
-    swapToWebProcess(WTFMove(process), navigation, mainFrameIDInPreviousProcess, [this, protectedThis = makeRef(*this), navigation = makeRef(navigation), previousProcess = WTFMove(previousProcess), mainFrameIDInPreviousProcess, mainFrameURL = WTFMove(mainFrameURL)]() mutable {
+    swapToWebProcess(WTFMove(process), navigation, mainFrameIDInPreviousProcess, processSwapRequestedByClient, [this, protectedThis = makeRef(*this), navigation = makeRef(navigation), previousProcess = WTFMove(previousProcess), mainFrameIDInPreviousProcess, mainFrameURL = WTFMove(mainFrameURL)](bool didSuspendPreviousPage) mutable {
         if (auto* item = navigation->targetItem()) {
             LOG(Loading, "WebPageProxy %p continueNavigationInNewProcess to back item URL %s", this, item->url().utf8().data());
 
@@ -2726,8 +2730,12 @@
         };
 
         bool isInitialNavigationInNewWindow = openedByDOM() && !hasCommittedAnyProvisionalLoads();
-        if (!isInitialNavigationInNewWindow || !mainFrameIDInPreviousProcess)
+        if (!m_process->processPool().configuration().processSwapsOnWindowOpenWithOpener() || !isInitialNavigationInNewWindow || !mainFrameIDInPreviousProcess) {
+            // There is no way we'll be able to return to the page in the previous page so close it.
+            if (!didSuspendPreviousPage)
+                previousProcess->send(Messages::WebPage::Close(), m_pageID);
             return;
+        }
 
         m_mainFrameWindowCreationHandler = [this, previousProcess = WTFMove(previousProcess), mainFrameIDInPreviousProcess = *mainFrameIDInPreviousProcess](const GlobalWindowIdentifier& windowIdentifier) {
             ASSERT(m_mainFrame);

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (238825 => 238826)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.h	2018-12-03 23:16:25 UTC (rev 238825)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h	2018-12-03 23:57:41 UTC (rev 238826)
@@ -1411,7 +1411,7 @@
     void updateThrottleState();
     void updateHiddenPageThrottlingAutoIncreases();
 
-    bool suspendCurrentPageIfPossible(API::Navigation&, std::optional<uint64_t> mainFrameID);
+    bool suspendCurrentPageIfPossible(API::Navigation&, std::optional<uint64_t> mainFrameID, ProcessSwapRequestedByClient);
 
     enum class ResetStateReason {
         PageInvalidated,
@@ -1559,7 +1559,7 @@
     void setCanShortCircuitHorizontalWheelEvents(bool canShortCircuitHorizontalWheelEvents) { m_canShortCircuitHorizontalWheelEvents = canShortCircuitHorizontalWheelEvents; }
 
     void reattachToWebProcess();
-    void swapToWebProcess(Ref<WebProcessProxy>&&, API::Navigation&, std::optional<uint64_t> mainFrameIDInPreviousProcess, CompletionHandler<void()>&&);
+    void swapToWebProcess(Ref<WebProcessProxy>&&, API::Navigation&, std::optional<uint64_t> mainFrameIDInPreviousProcess, ProcessSwapRequestedByClient, CompletionHandler<void(bool)>&&);
 
     void finishAttachingToWebProcess(ShouldDelayAttachingDrawingArea = ShouldDelayAttachingDrawingArea::No);
 
@@ -1878,7 +1878,7 @@
 
     void reportPageLoadResult(const WebCore::ResourceError& = { });
 
-    void continueNavigationInNewProcess(API::Navigation&, Ref<WebProcessProxy>&&);
+    void continueNavigationInNewProcess(API::Navigation&, Ref<WebProcessProxy>&&, ProcessSwapRequestedByClient);
 
     void setNeedsFontAttributes(bool);
     void updateFontAttributesAfterEditorStateChange();

Modified: trunk/Source/WebKit/UIProcess/WebProcessPool.cpp (238825 => 238826)


--- trunk/Source/WebKit/UIProcess/WebProcessPool.cpp	2018-12-03 23:16:25 UTC (rev 238825)
+++ trunk/Source/WebKit/UIProcess/WebProcessPool.cpp	2018-12-03 23:57:41 UTC (rev 238826)
@@ -2138,7 +2138,21 @@
 {
     auto& targetURL = navigation.currentRequest().url();
 
-    if (!m_configuration->processSwapsOnNavigation() && processSwapRequestedByClient == ProcessSwapRequestedByClient::No) {
+    auto createNewProcess = [&] () -> Ref<WebProcessProxy> {
+        if (RefPtr<WebProcessProxy> process = tryTakePrewarmedProcess(page.websiteDataStore())) {
+            tryPrewarmWithDomainInformation(*process, targetURL);
+            return process.releaseNonNull();
+        }
+
+        return createNewWebProcess(page.websiteDataStore());
+    };
+
+    if (processSwapRequestedByClient == ProcessSwapRequestedByClient::Yes) {
+        reason = "Process swap was requested by the client"_s;
+        return createNewProcess();
+    }
+
+    if (!m_configuration->processSwapsOnNavigation()) {
         reason = "Feature is disabled"_s;
         return page.process();
     }
@@ -2186,31 +2200,28 @@
         }
     }
 
-    if (processSwapRequestedByClient == ProcessSwapRequestedByClient::No) {
-        if (navigation.treatAsSameOriginNavigation()) {
-            reason = "The treatAsSameOriginNavigation flag is set"_s;
-            return page.process();
-        }
+    if (navigation.treatAsSameOriginNavigation()) {
+        reason = "The treatAsSameOriginNavigation flag is set"_s;
+        return page.process();
+    }
 
-        bool isInitialLoadInNewWindowOpenedByDOM = page.openedByDOM() && !page.hasCommittedAnyProvisionalLoads();
-        URL sourceURL;
-        if (isInitialLoadInNewWindowOpenedByDOM && !navigation.requesterOrigin().isEmpty())
-            sourceURL = URL { URL(), navigation.requesterOrigin().toString() };
-        else
-            sourceURL = URL { { }, page.pageLoadState().url() };
+    bool isInitialLoadInNewWindowOpenedByDOM = page.openedByDOM() && !page.hasCommittedAnyProvisionalLoads();
+    URL sourceURL;
+    if (isInitialLoadInNewWindowOpenedByDOM && !navigation.requesterOrigin().isEmpty())
+        sourceURL = URL { URL(), navigation.requesterOrigin().toString() };
+    else
+        sourceURL = URL { { }, page.pageLoadState().url() };
 
-        if (sourceURL.isEmpty() && page.configuration().relatedPage()) {
-            sourceURL = URL { { }, page.configuration().relatedPage()->pageLoadState().url() };
-            RELEASE_LOG(ProcessSwapping, "Using related page %p's URL as source URL for process swap decision", page.configuration().relatedPage());
-        }
+    if (sourceURL.isEmpty() && page.configuration().relatedPage()) {
+        sourceURL = URL { { }, page.configuration().relatedPage()->pageLoadState().url() };
+        RELEASE_LOG(ProcessSwapping, "Using related page %p's URL as source URL for process swap decision", page.configuration().relatedPage());
+    }
 
-        if (!sourceURL.isValid() || !targetURL.isValid() || sourceURL.isEmpty() || sourceURL.protocolIsAbout() || registrableDomainsAreEqual(sourceURL, targetURL)) {
-            reason = "Navigation is same-site"_s;
-            return page.process();
-        }
-        reason = "Navigation is cross-site"_s;
-    } else
-        reason = "Process swap was requested by the client"_s;
+    if (!sourceURL.isValid() || !targetURL.isValid() || sourceURL.isEmpty() || sourceURL.protocolIsAbout() || registrableDomainsAreEqual(sourceURL, targetURL)) {
+        reason = "Navigation is same-site"_s;
+        return page.process();
+    }
+    reason = "Navigation is cross-site"_s;
     
     auto registrableDomain = toRegistrableDomain(targetURL);
     if (m_configuration->alwaysKeepAndReuseSwappedProcesses()) {
@@ -2251,12 +2262,7 @@
         return process;
     }
 
-    if (RefPtr<WebProcessProxy> process = tryTakePrewarmedProcess(page.websiteDataStore())) {
-        tryPrewarmWithDomainInformation(*process, targetURL);
-        return process.releaseNonNull();
-    }
-
-    return createNewWebProcess(page.websiteDataStore());
+    return createNewProcess();
 }
 
 void WebProcessPool::addSuspendedPage(std::unique_ptr<SuspendedPageProxy>&& suspendedPage)

Modified: trunk/Tools/ChangeLog (238825 => 238826)


--- trunk/Tools/ChangeLog	2018-12-03 23:16:25 UTC (rev 238825)
+++ trunk/Tools/ChangeLog	2018-12-03 23:57:41 UTC (rev 238826)
@@ -1,3 +1,15 @@
+2018-12-03  Chris Dumez  <[email protected]>
+
+        [PSON] Request by the client to process-swap is ignored if the window has an opener
+        https://bugs.webkit.org/show_bug.cgi?id=192267
+        <rdar://problem/46386886>
+
+        Reviewed by Brady Eidson.
+
+        Add API test coverage.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:
+
 2018-12-03  Keith Rollin  <[email protected]>
 
         Add .xcfilelist files

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm (238825 => 238826)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm	2018-12-03 23:16:25 UTC (rev 238825)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm	2018-12-03 23:57:41 UTC (rev 238826)
@@ -2601,6 +2601,141 @@
     EXPECT_NE(pid1, pid3);
 }
 
+#if PLATFORM(MAC)
+
+static const char* saveOpenerTestBytes = R"PSONRESOURCE(
+<script>
+window._onload_ = function() {
+    savedOpener = opener;
+}
+</script>
+)PSONRESOURCE";
+
+TEST(ProcessSwap, OpenerLinkAfterAPIControlledProcessSwappingOfOpener)
+{
+    auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    auto handler = adoptNS([[PSONScheme alloc] init]);
+    [handler addMappingFromURLString:@"pson://www.webkit.org/main1.html" toData:windowOpenSameSiteWithOpenerTestBytes]; // Opens "pson://www.webkit.org/main2.html".
+    [handler addMappingFromURLString:@"pson://www.webkit.org/main2.html" toData:saveOpenerTestBytes];
+    [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
+
+    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
+    auto navigationDelegate = adoptNS([[PSONNavigationDelegate alloc] init]);
+    [webView setNavigationDelegate:navigationDelegate.get()];
+
+    auto uiDelegate = adoptNS([[PSONUIDelegate alloc] initWithNavigationDelegate:navigationDelegate.get()]);
+    [webView setUIDelegate:uiDelegate.get()];
+
+    [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main1.html"]]];
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+    auto pid1 = [webView _webProcessIdentifier];
+
+    TestWebKitAPI::Util::run(&didCreateWebView);
+    didCreateWebView = false;
+
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+
+    EXPECT_EQ(pid1, [createdWebView _webProcessIdentifier]);
+
+    // Auxiliary window should have an opener.
+    [createdWebView evaluateJavaScript:@"window.opener.location.href" completionHandler: [&] (id hasOpener, NSError *error) {
+        EXPECT_WK_STREQ(@"pson://www.webkit.org/main1.html", hasOpener);
+        done = true;
+    }];
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+
+    // We force a proces-swap via client API.
+    navigationDelegate->decidePolicyForNavigationAction = ^(WKNavigationAction *, void (^decisionHandler)(WKNavigationActionPolicy)) {
+        decisionHandler(_WKNavigationActionPolicyAllowInNewProcess);
+    };
+
+    // Navigating from the above URL to this URL normally should not process swap.
+    [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main3.html"]]];
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+
+    auto pid2 = [webView _webProcessIdentifier];
+    EXPECT_NE(pid1, pid2);
+
+    // Auxiliary window's opener should no longer have an opener.
+    [createdWebView evaluateJavaScript:@"window.opener ? 'true' : 'false'" completionHandler: [&] (id hasOpener, NSError *error) {
+        EXPECT_WK_STREQ(@"false", hasOpener);
+        done = true;
+    }];
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+
+    [createdWebView evaluateJavaScript:@"savedOpener.closed ? 'true' : 'false'" completionHandler: [&] (id savedOpenerIsClosed, NSError *error) {
+        EXPECT_WK_STREQ(@"true", savedOpenerIsClosed);
+        done = true;
+    }];
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+}
+
+TEST(ProcessSwap, OpenerLinkAfterAPIControlledProcessSwappingOfOpenee)
+{
+    auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    auto handler = adoptNS([[PSONScheme alloc] init]);
+    [handler addMappingFromURLString:@"pson://www.webkit.org/main1.html" toData:windowOpenSameSiteWithOpenerTestBytes]; // Opens "pson://www.webkit.org/main2.html".
+    [handler addMappingFromURLString:@"pson://www.webkit.org/main2.html" toData:saveOpenerTestBytes];
+    [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
+
+    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
+    auto navigationDelegate = adoptNS([[PSONNavigationDelegate alloc] init]);
+    [webView setNavigationDelegate:navigationDelegate.get()];
+
+    auto uiDelegate = adoptNS([[PSONUIDelegate alloc] initWithNavigationDelegate:navigationDelegate.get()]);
+    [webView setUIDelegate:uiDelegate.get()];
+
+    [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main1.html"]]];
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+    auto pid1 = [webView _webProcessIdentifier];
+
+    TestWebKitAPI::Util::run(&didCreateWebView);
+    didCreateWebView = false;
+
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+
+    EXPECT_EQ(pid1, [createdWebView _webProcessIdentifier]);
+
+    // Auxiliary window should have an opener.
+    [webView evaluateJavaScript:@"w.opener.location.href" completionHandler: [&] (id hasOpener, NSError *error) {
+        EXPECT_WK_STREQ(@"pson://www.webkit.org/main1.html", hasOpener);
+        done = true;
+    }];
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+
+    // We force a proces-swap via client API.
+    navigationDelegate->decidePolicyForNavigationAction = ^(WKNavigationAction *, void (^decisionHandler)(WKNavigationActionPolicy)) {
+        decisionHandler(_WKNavigationActionPolicyAllowInNewProcess);
+    };
+
+    // Navigating from the above URL to this URL normally should not process swap.
+    [createdWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main3.html"]]];
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+
+    auto pid2 = [createdWebView _webProcessIdentifier];
+    EXPECT_NE(pid1, pid2);
+
+    // Auxiliary window's opener should no longer have an opener.
+    [webView evaluateJavaScript:@"w.opener ? 'true' : 'false'" completionHandler: [&] (id hasOpener, NSError *error) {
+        EXPECT_WK_STREQ(@"false", hasOpener);
+        done = true;
+    }];
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+}
+
+#endif // PLATFORM(MAC)
+
 enum class ExpectSwap { No, Yes };
 static void runProcessSwapDueToRelatedWebViewTest(NSURL* relatedViewURL, NSURL* targetURL, ExpectSwap expectSwap)
 {
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to