Changeset 230195 in webkit
- Timestamp:
- Apr 2, 2018 6:03:46 PM (6 years ago)
- Location:
- trunk
- Files:
-
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebKit/ChangeLog
r230194 r230195 1 2018-04-02 Brady Eidson <beidson@apple.com> 2 3 Process swapping on navigation needs to handle server redirects. 4 <rdar://problem/38690465> and https://bugs.webkit.org/show_bug.cgi?id=184142 5 6 Reviewed by Alex Christensen. 7 8 The same rules we apply to process swapping for basic navigations need to apply 9 to server redirects as well. 10 11 There's three interesting cases we need to support that are covered by new API tests: 12 1 - The initial load in a WKWebView redirects cross-origin. 13 2 - A WKWebView is showing content from a.com, we start a load to b.com, and that redirects to c.com 14 3 - A WKWebView is showing content from a.com, we start a load to a.com, that that redirects to b.com. 15 16 Supporting all 3 of these brought their own little challenges. 17 18 By teaching Navigation objects more about redirects I was able to support all 3 cases. 19 20 * UIProcess/API/APINavigation.cpp: 21 (API::Navigation::Navigation): 22 (API::Navigation::setCurrentRequest): 23 (API::Navigation::appendRedirectionURL): 24 (API::Navigation::loggingString const): 25 (API::Navigation::loggingURL const): Deleted. 26 * UIProcess/API/APINavigation.h: 27 (API::Navigation::originalRequest const): 28 (API::Navigation::currentRequest const): 29 (API::Navigation::currentRequestProcessIdentifier const): 30 (API::Navigation::setCurrentRequestIsRedirect): 31 (API::Navigation::currentRequestIsRedirect const): 32 (API::Navigation::request const): Deleted. 33 34 * UIProcess/API/Cocoa/WKNavigation.mm: 35 (-[WKNavigation _request]): 36 37 * UIProcess/WebPageProxy.cpp: 38 (WebKit::WebPageProxy::receivedPolicyDecision): 39 (WebKit::WebPageProxy::continueNavigationInNewProcess): If this continued navigation is currently in a server 40 redirect, save off a lambda to synthesize a "did receive server redirect" callback once the new WebProcess is running. 41 (WebKit::WebPageProxy::didCreateMainFrame): 42 (WebKit::WebPageProxy::didStartProvisionalLoadForFrame): Possibly ignore this notification if it is really a 43 cross-origin redirect that is just starting back up in a new WebProcess. 44 (WebKit::WebPageProxy::didReceiveServerRedirectForProvisionalLoadForFrame): 45 (WebKit::WebPageProxy::didCommitLoadForFrame): 46 (WebKit::WebPageProxy::decidePolicyForNavigationAction): 47 (WebKit::WebPageProxy::resetStateAfterProcessExited): Do not clear pageLoadState if the process is exitting for 48 a navigation swap, as we will need to pick up where we left off when the load continues in a new WebProcess. 49 * UIProcess/WebPageProxy.h: 50 * UIProcess/WebPageProxy.messages.in: 51 52 * UIProcess/WebProcessPool.cpp: 53 (WebKit::WebProcessPool::processForNavigation): If a process has never committed any provisional load, it can always 54 be used to continue a navigation. 55 * UIProcess/WebProcessPool.h: 56 57 * UIProcess/WebProcessProxy.h: 58 (WebKit::WebProcessProxy::didCommitProvisionalLoad): 59 (WebKit::WebProcessProxy::hasCommittedAnyProvisionalLoads const): 60 61 * WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp: 62 (WebKit::WebFrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad): 63 (WebKit::WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction): 64 1 65 2018-04-02 Eric Carlson <eric.carlson@apple.com> 2 66 -
trunk/Source/WebKit/UIProcess/API/APINavigation.cpp
r230191 r230195 42 42 Navigation::Navigation(WebNavigationState& state, WebCore::ResourceRequest&& request) 43 43 : m_navigationID(state.generateNavigationID()) 44 , m_request(WTFMove(request)) 44 , m_originalRequest(WTFMove(request)) 45 , m_currentRequest(m_originalRequest) 45 46 { 46 m_redirectChain.append(m_ request.url());47 m_redirectChain.append(m_originalRequest.url()); 47 48 } 48 49 49 50 Navigation::Navigation(WebNavigationState& state, WebBackForwardListItem& item, FrameLoadType backForwardFrameLoadType) 50 51 : m_navigationID(state.generateNavigationID()) 52 , m_originalRequest(item.url()) 53 , m_currentRequest(m_originalRequest) 51 54 , m_backForwardListItem(&item) 52 55 , m_backForwardFrameLoadType(backForwardFrameLoadType) … … 58 61 } 59 62 60 void Navigation::appendRedirectionURL(const WebCore::URL& url) 63 void Navigation::setCurrentRequest(ResourceRequest&& request, ProcessIdentifier processIdentifier) 64 { 65 m_currentRequest = WTFMove(request); 66 m_currentRequestProcessIdentifier = processIdentifier; 67 } 68 69 void Navigation::appendRedirectionURL(const URL& url) 61 70 { 62 71 if (m_redirectChain.isEmpty() || m_redirectChain.last() != url) … … 65 74 66 75 #if !LOG_DISABLED 67 WTF::String Navigation::logging URL() const76 WTF::String Navigation::loggingString() const 68 77 { 69 return m _backForwardListItem ? m_backForwardListItem->url() : m_request.url().string();78 return makeString("Most recent URL: ", m_currentRequest.url().string(), " Back/forward list item URL: '", m_backForwardListItem ? m_backForwardListItem->url() : String { }, String::format("' (%p)", m_backForwardListItem.get())); 70 79 } 71 80 #endif -
trunk/Source/WebKit/UIProcess/API/APINavigation.h
r230191 r230195 27 27 28 28 #include "APIObject.h" 29 #include <WebCore/Process.h> 29 30 #include <WebCore/ResourceRequest.h> 30 31 #include <wtf/Ref.h> … … 63 64 uint64_t navigationID() const { return m_navigationID; } 64 65 65 const WebCore::ResourceRequest& request() const { return m_request; } 66 const WebCore::ResourceRequest& originalRequest() const { return m_originalRequest; } 67 void setCurrentRequest(WebCore::ResourceRequest&&, WebCore::ProcessIdentifier); 68 const WebCore::ResourceRequest& currentRequest() const { return m_currentRequest; } 69 std::optional<WebCore::ProcessIdentifier> currentRequestProcessIdentifier() const { return m_currentRequestProcessIdentifier; } 70 71 void setCurrentRequestIsRedirect(bool isRedirect) { m_isRedirect = isRedirect; } 72 bool currentRequestIsRedirect() const { return m_isRedirect; } 73 66 74 WebKit::WebBackForwardListItem* backForwardListItem() { return m_backForwardListItem.get(); } 67 75 std::optional<WebCore::FrameLoadType> backForwardFrameLoadType() const { return m_backForwardFrameLoadType; } … … 83 91 84 92 #if !LOG_DISABLED 85 WTF::String logging URL() const;93 WTF::String loggingString() const; 86 94 #endif 87 95 … … 92 100 93 101 uint64_t m_navigationID; 94 WebCore::ResourceRequest m_request; 102 WebCore::ResourceRequest m_originalRequest; 103 WebCore::ResourceRequest m_currentRequest; 104 std::optional<WebCore::ProcessIdentifier> m_currentRequestProcessIdentifier; 95 105 Vector<WebCore::URL> m_redirectChain; 96 106 bool m_wasUserInitiated { true }; 97 107 bool m_shouldForceDownload { false }; 108 bool m_isRedirect { false }; 98 109 99 110 RefPtr<WebKit::WebBackForwardListItem> m_backForwardListItem; -
trunk/Source/WebKit/UIProcess/API/Cocoa/WKNavigation.mm
r230191 r230195 44 44 - (NSURLRequest *)_request 45 45 { 46 return _navigation-> request().nsURLRequest(WebCore::DoNotUpdateHTTPBody);46 return _navigation->originalRequest().nsURLRequest(WebCore::DoNotUpdateHTTPBody); 47 47 } 48 48 -
trunk/Source/WebKit/UIProcess/WebPageProxy.cpp
r230191 r230195 2353 2353 if (action == PolicyAction::Use && navigation) { 2354 2354 auto proposedProcess = process().processPool().processForNavigation(*this, *navigation, action); 2355 2355 2356 if (proposedProcess.ptr() != &process()) { 2356 LOG(Loading, "Switching to new process for navigation %" PRIu64 " to url '%s' (WebBackForwardListItem %p)", navigation->navigationID(), navigation->loggingURL().utf8().data(), navigation->backForwardListItem());2357 LOG(Loading, "Switching from process %i to new process for navigation %" PRIu64 " '%s'", processIdentifier(), navigation->navigationID(), navigation->loggingString().utf8().data()); 2357 2358 2358 2359 RunLoop::main().dispatch([this, protectedThis = makeRef(*this), navigation = makeRef(*navigation), proposedProcess = WTFMove(proposedProcess)]() mutable { … … 2368 2369 void WebPageProxy::continueNavigationInNewProcess(API::Navigation& navigation, Ref<WebProcessProxy>&& process) 2369 2370 { 2370 LOG(Loading, "Continuing navigation %" PRIu64 " to URL %s in a new web process", navigation.navigationID(), navigation.loggingURL().utf8().data()); 2371 2371 LOG(Loading, "Continuing navigation %" PRIu64 " '%s' in a new web process", navigation.navigationID(), navigation.loggingString().utf8().data()); 2372 2373 ASSERT(m_process.ptr() != process.ptr()); 2372 2374 attachToProcessForNavigation(WTFMove(process)); 2373 2375 … … 2385 2387 2386 2388 // FIXME: Work out timing of responding with the last policy delegate, etc 2387 loadRequestWithNavigation(navigation, ResourceRequest { navigation.request() }, WebCore::ShouldOpenExternalURLsPolicy::ShouldAllowExternalSchemes, nullptr, NavigationPolicyCheck::Bypass); 2389 ASSERT(!navigation.currentRequest().isEmpty()); 2390 loadRequestWithNavigation(navigation, ResourceRequest { navigation.currentRequest() }, WebCore::ShouldOpenExternalURLsPolicy::ShouldAllowExternalSchemes, nullptr, NavigationPolicyCheck::Bypass); 2391 2392 // Normally, notification of a server redirect comes from the WebContent process. 2393 // If we are process swapping in response to a server redirect then that notification will not come from the new WebContent process. 2394 // In this case we have the UIProcess synthesize the redirect notification at the appropriate time. 2395 if (navigation.currentRequestIsRedirect()) { 2396 ASSERT(!m_mainFrame); 2397 m_mainFrameCreationHandler = [this, protectedThis = makeRef(*this), navigation = makeRef(navigation), request = navigation.currentRequest()]() mutable { 2398 ASSERT(m_mainFrame); 2399 m_mainFrame->frameLoadState().didStartProvisionalLoad(request.url()); 2400 didReceiveServerRedirectForProvisionalLoadForFrame(m_mainFrame->frameID(), navigation->navigationID(), WTFMove(request), { }); 2401 }; 2402 } 2388 2403 } 2389 2404 … … 3194 3209 // Add the frame to the process wide map. 3195 3210 m_process->frameCreated(frameID, m_mainFrame.get()); 3211 3212 if (m_mainFrameCreationHandler) { 3213 m_mainFrameCreationHandler(); 3214 m_mainFrameCreationHandler = nullptr; 3215 } 3196 3216 } 3197 3217 … … 3270 3290 PageClientProtector protector(m_pageClient); 3271 3291 3272 auto transaction = m_pageLoadState.transaction();3273 3274 m_pageLoadState.clearPendingAPIRequestURL(transaction);3275 3276 3292 WebFrameProxy* frame = m_process->webFrame(frameID); 3277 3293 MESSAGE_CHECK(frame); … … 3282 3298 if (frame->isMainFrame() && navigationID) 3283 3299 navigation = &navigationState().navigation(navigationID); 3300 3301 // If this seemingly new load is actually continuing a server redirect for a previous navigation in a new process, 3302 // then we ignore this notification. 3303 if (navigation && navigation->currentRequestIsRedirect()) { 3304 auto navigationProcessIdentifier = navigation->currentRequestProcessIdentifier(); 3305 if (navigationProcessIdentifier && *navigationProcessIdentifier != m_process->coreProcessIdentifier()) 3306 return; 3307 } 3308 3309 LOG(Loading, "WebPageProxy::didStartProvisionalLoadForFrame to frameID %" PRIu64 ", navigationID %" PRIu64 ", url %s", frameID, navigationID, url.string().utf8().data()); 3310 3311 auto transaction = m_pageLoadState.transaction(); 3312 3313 m_pageLoadState.clearPendingAPIRequestURL(transaction); 3284 3314 3285 3315 if (frame->isMainFrame()) { … … 3303 3333 } 3304 3334 3305 void WebPageProxy::didReceiveServerRedirectForProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, WebCore::URL&& url, const UserData& userData) 3306 { 3335 void WebPageProxy::didReceiveServerRedirectForProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, ResourceRequest&& request, const UserData& userData) 3336 { 3337 LOG(Loading, "WebPageProxy::didReceiveServerRedirectForProvisionalLoadForFrame to frameID %" PRIu64 ", navigationID %" PRIu64 ", url %s", frameID, navigationID, request.url().string().utf8().data()); 3338 3307 3339 PageClientProtector protector(m_pageClient); 3308 3340 3309 3341 WebFrameProxy* frame = m_process->webFrame(frameID); 3310 3342 MESSAGE_CHECK(frame); 3311 MESSAGE_CHECK_URL( url);3343 MESSAGE_CHECK_URL(request.url()); 3312 3344 3313 3345 // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache. … … 3315 3347 if (navigationID) { 3316 3348 navigation = &navigationState().navigation(navigationID); 3317 navigation->appendRedirectionURL( url);3349 navigation->appendRedirectionURL(request.url()); 3318 3350 } 3319 3351 … … 3321 3353 3322 3354 if (frame->isMainFrame()) 3323 m_pageLoadState.didReceiveServerRedirectForProvisionalLoad(transaction, url);3324 3325 frame->didReceiveServerRedirectForProvisionalLoad( url);3355 m_pageLoadState.didReceiveServerRedirectForProvisionalLoad(transaction, request.url()); 3356 3357 frame->didReceiveServerRedirectForProvisionalLoad(request.url()); 3326 3358 3327 3359 m_pageLoadState.commitChanges(); … … 3443 3475 if (frame->isMainFrame() && navigationID) 3444 3476 navigation = &navigationState().navigation(navigationID); 3477 3478 m_process->didCommitProvisionalLoad(); 3445 3479 3446 3480 #if PLATFORM(IOS) … … 3792 3826 void WebPageProxy::decidePolicyForNavigationAction(uint64_t frameID, const SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, NavigationActionData&& navigationActionData, const FrameInfoData& originatingFrameInfoData, uint64_t originatingPageID, const WebCore::ResourceRequest& originalRequest, ResourceRequest&& request, uint64_t listenerID, const UserData& userData) 3793 3827 { 3794 LOG(Loading, "WebPageProxy::d idStartProvisionalLoadForFrame - Target url %s", originalRequest.url().string().utf8().data());3828 LOG(Loading, "WebPageProxy::decidePolicyForNavigationAction - Original URL %s, current target URL %s", originalRequest.url().string().utf8().data(), request.url().string().utf8().data()); 3795 3829 3796 3830 PageClientProtector protector(m_pageClient); … … 3807 3841 MESSAGE_CHECK_URL(originalRequest.url()); 3808 3842 3809 uint64_t newNavigationID { 0 };3810 Ref<WebFramePolicyListenerProxy> listener = frame->setUpPolicyListenerProxy(listenerID, PolicyListenerType::NavigationAction);3811 3843 Ref<API::Navigation> navigation = navigationID ? makeRef(m_navigationState->navigation(navigationID)) : m_navigationState->createLoadRequestNavigation(ResourceRequest(request)); 3812 3844 3813 newNavigationID = navigation->navigationID();3845 uint64_t newNavigationID = navigation->navigationID(); 3814 3846 navigation->setWasUserInitiated(!!navigationActionData.userGestureTokenIdentifier); 3815 3847 navigation->setShouldForceDownload(!navigationActionData.downloadAttribute.isNull()); 3848 navigation->setCurrentRequest(ResourceRequest(request), m_process->coreProcessIdentifier()); 3849 navigation->setCurrentRequestIsRedirect(navigationActionData.isRedirect); 3816 3850 navigation->setIsCrossOriginWindowOpenNavigation(navigationActionData.isCrossOriginWindowOpenNavigation); 3817 3851 navigation->setOpener(navigationActionData.opener); 3852 3853 auto listener = makeRef(frame->setUpPolicyListenerProxy(listenerID, PolicyListenerType::NavigationAction)); 3818 3854 listener->setNavigation(WTFMove(navigation)); 3819 3855 … … 5804 5840 #endif 5805 5841 5806 PageLoadState::Transaction transaction = m_pageLoadState.transaction(); 5807 m_pageLoadState.reset(transaction); 5808 5842 if (terminationReason != ProcessTerminationReason::NavigationSwap) { 5843 PageLoadState::Transaction transaction = m_pageLoadState.transaction(); 5844 m_pageLoadState.reset(transaction); 5845 } 5846 5847 // FIXME: <rdar://problem/38676604> In case of process swaps, the old process should gracefully suspend instead of terminating. 5809 5848 m_process->processTerminated(); 5810 5849 } -
trunk/Source/WebKit/UIProcess/WebPageProxy.h
r230191 r230195 1340 1340 1341 1341 void didStartProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, WebCore::URL&&, WebCore::URL&& unreachableURL, const UserData&); 1342 void didReceiveServerRedirectForProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, WebCore:: URL&&, const UserData&);1342 void didReceiveServerRedirectForProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, WebCore::ResourceRequest&&, const UserData&); 1343 1343 void willPerformClientRedirectForFrame(uint64_t frameID, const String& url, double delay); 1344 1344 void didCancelClientRedirectForFrame(uint64_t frameID); … … 1778 1778 1779 1779 RefPtr<WebFrameProxy> m_mainFrame; 1780 Function<void()> m_mainFrameCreationHandler; 1781 1780 1782 RefPtr<WebFrameProxy> m_focusedFrame; 1781 1783 RefPtr<WebFrameProxy> m_frameSetLargestFrame; -
trunk/Source/WebKit/UIProcess/WebPageProxy.messages.in
r230191 r230195 117 117 # Frame load messages 118 118 DidStartProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, WebCore::URL url, WebCore::URL unreachableURL, WebKit::UserData userData) 119 DidReceiveServerRedirectForProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, WebCore:: URL url, WebKit::UserData userData)119 DidReceiveServerRedirectForProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, WebCore::ResourceRequest request, WebKit::UserData userData) 120 120 WillPerformClientRedirectForFrame(uint64_t frameID, String url, double delay) 121 121 DidCancelClientRedirectForFrame(uint64_t frameID) -
trunk/Source/WebKit/UIProcess/WebProcessPool.cpp
r230191 r230195 1986 1986 return page.process(); 1987 1987 1988 if (!page.process().hasCommittedAnyProvisionalLoads()) 1989 return page.process(); 1990 1988 1991 // FIXME: We should support process swap when a window has an opener. 1989 1992 if (navigation.opener()) … … 1995 1998 } 1996 1999 1997 auto targetURL = navigation. request().url();2000 auto targetURL = navigation.currentRequest().url(); 1998 2001 auto url = URL { ParsedURLString, page.pageLoadState().url() }; 1999 if (!url.isValid() || url.is BlankURL() || protocolHostAndPortAreEqual(url, targetURL))2002 if (!url.isValid() || url.isEmpty() || url.isBlankURL() || protocolHostAndPortAreEqual(url, targetURL)) 2000 2003 return page.process(); 2001 2004 -
trunk/Source/WebKit/UIProcess/WebProcessPool.h
r230191 r230195 79 79 class InjectedBundleClient; 80 80 class LegacyContextHistoryClient; 81 class Navigation; 81 82 class PageConfiguration; 82 83 } -
trunk/Source/WebKit/UIProcess/WebProcessProxy.h
r230191 r230195 206 206 void checkProcessLocalPortForActivity(const WebCore::MessagePortIdentifier&, CompletionHandler<void(WebCore::MessagePortChannelProvider::HasActivity)>&&); 207 207 208 void didCommitProvisionalLoad() { m_hasCommittedAnyProvisionalLoads = true; } 209 bool hasCommittedAnyProvisionalLoads() const { return m_hasCommittedAnyProvisionalLoads; } 210 208 211 protected: 209 212 static uint64_t generatePageID(); … … 330 333 HashMap<uint64_t, Function<void()>> m_messageBatchDeliveryCompletionHandlers; 331 334 HashMap<uint64_t, CompletionHandler<void(WebCore::MessagePortChannelProvider::HasActivity)>> m_localPortActivityCompletionHandlers; 335 336 bool m_hasCommittedAnyProvisionalLoads { false }; 332 337 }; 333 338 -
trunk/Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp
r230191 r230195 36 36 #include "InjectedBundleDOMWindowExtension.h" 37 37 #include "InjectedBundleNavigationAction.h" 38 #include "Logging.h" 38 39 #include "NavigationActionData.h" 39 40 #include "NetworkConnectionToWebProcessMessages.h" … … 307 308 RefPtr<API::Object> userData; 308 309 310 LOG(Loading, "WebProcess %i - dispatchDidReceiveServerRedirectForProvisionalLoad to request url %s", getpid(), documentLoader.request().url().string().utf8().data()); 311 309 312 // Notify the bundle client. 310 313 webPage->injectedBundleLoaderClient().didReceiveServerRedirectForProvisionalLoadForFrame(*webPage, *m_frame, userData); 311 314 312 315 // Notify the UIProcess. 313 webPage->send(Messages::WebPageProxy::DidReceiveServerRedirectForProvisionalLoadForFrame(m_frame->frameID(), documentLoader.navigationID(), documentLoader. url(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));316 webPage->send(Messages::WebPageProxy::DidReceiveServerRedirectForProvisionalLoadForFrame(m_frame->frameID(), documentLoader.navigationID(), documentLoader.request(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get()))); 314 317 } 315 318 … … 818 821 return; 819 822 } 823 824 LOG(Loading, "WebProcess %i - dispatchDecidePolicyForNavigationAction to request url %s", getpid(), request.url().string().utf8().data()); 820 825 821 826 m_isDecidingNavigationPolicyDecision = true; -
trunk/Tools/ChangeLog
r230192 r230195 1 2018-04-02 Brady Eidson <beidson@apple.com> 2 3 Process swapping on navigation needs to handle server redirects. 4 <rdar://problem/38690465> and https://bugs.webkit.org/show_bug.cgi?id=184142 5 6 Reviewed by Alex Christensen. 7 8 * TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm: 9 (-[PSONNavigationDelegate webView:didFinishNavigation:]): 10 (-[PSONNavigationDelegate webView:decidePolicyForNavigationAction:decisionHandler:]): 11 (-[PSONNavigationDelegate webView:didReceiveServerRedirectForProvisionalNavigation:]): 12 (-[PSONScheme addRedirectFromURLString:toURLString:]): 13 (-[PSONScheme webView:startURLSchemeTask:]): 14 1 15 2018-04-02 Daniel Bates <dabates@apple.com> 2 16 -
trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm
r230191 r230195 29 29 #import "Test.h" 30 30 #import <WebKit/WKNavigationDelegate.h> 31 #import <WebKit/WKNavigationPrivate.h> 31 32 #import <WebKit/WKPreferencesPrivate.h> 32 33 #import <WebKit/WKProcessPoolPrivate.h> … … 45 46 #import <wtf/Deque.h> 46 47 #import <wtf/HashMap.h> 48 #import <wtf/HashSet.h> 47 49 #import <wtf/RetainPtr.h> 48 50 #import <wtf/Vector.h> … … 58 60 static RetainPtr<NSMutableArray> receivedMessages = adoptNS([@[] mutableCopy]); 59 61 static bool receivedMessage; 62 static bool serverRedirected; 63 static HashSet<pid_t> seenPIDs; 60 64 @interface PSONMessageHandler : NSObject <WKScriptMessageHandler> 61 65 @end … … 76 80 - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation 77 81 { 82 seenPIDs.add([webView _webProcessIdentifier]); 78 83 done = true; 79 84 } … … 82 87 { 83 88 ++numberOfDecidePolicyCalls; 89 seenPIDs.add([webView _webProcessIdentifier]); 84 90 decisionHandler(WKNavigationActionPolicyAllow); 91 } 92 93 - (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation 94 { 95 seenPIDs.add([webView _webProcessIdentifier]); 96 serverRedirected = true; 85 97 } 86 98 … … 118 130 @interface PSONScheme : NSObject <WKURLSchemeHandler> { 119 131 const char* _bytes; 132 HashMap<String, String> _redirects; 120 133 } 121 134 - (instancetype)initWithBytes:(const char*)bytes; 135 - (void)addRedirectFromURLString:(NSString *)sourceURLString toURLString:(NSString *)destinationURLString; 122 136 @end 123 137 … … 131 145 } 132 146 147 - (void)addRedirectFromURLString:(NSString *)sourceURLString toURLString:(NSString *)destinationURLString 148 { 149 _redirects.set(sourceURLString, destinationURLString); 150 } 151 133 152 - (void)webView:(WKWebView *)webView startURLSchemeTask:(id <WKURLSchemeTask>)task 134 153 { 135 RetainPtr<NSURLResponse> response = adoptNS([[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:1 textEncodingName:nil]); 154 NSURL *finalURL = task.request.URL; 155 auto target = _redirects.get(task.request.URL.absoluteString); 156 if (!target.isEmpty()) { 157 auto redirectResponse = adoptNS([[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:nil expectedContentLength:0 textEncodingName:nil]); 158 159 finalURL = [NSURL URLWithString:(NSString *)target]; 160 auto request = adoptNS([[NSURLRequest alloc] initWithURL:finalURL]); 161 162 [(id<WKURLSchemeTaskPrivate>)task _didPerformRedirection:redirectResponse.get() newRequest:request.get()]; 163 } 164 165 RetainPtr<NSURLResponse> response = adoptNS([[NSURLResponse alloc] initWithURL:finalURL MIMEType:@"text/html" expectedContentLength:1 textEncodingName:nil]); 136 166 [task didReceiveResponse:response.get()]; 137 167 … … 445 475 #endif // PLATFORM(MAC) 446 476 477 TEST(ProcessSwap, ServerRedirectFromNewWebView) 478 { 479 auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]); 480 processPoolConfiguration.get().processSwapsOnNavigation = YES; 481 auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]); 482 483 auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]); 484 [webViewConfiguration setProcessPool:processPool.get()]; 485 RetainPtr<PSONScheme> handler = adoptNS([[PSONScheme alloc] init]); 486 [handler addRedirectFromURLString:@"pson://host/main1.html" toURLString:@"psonredirected://host/main1.html"]; 487 [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"pson"]; 488 489 auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]); 490 auto delegate = adoptNS([[PSONNavigationDelegate alloc] init]); 491 [webView setNavigationDelegate:delegate.get()]; 492 493 NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://host/main1.html"]]; 494 [webView loadRequest:request]; 495 496 TestWebKitAPI::Util::run(&serverRedirected); 497 serverRedirected = false; 498 499 seenPIDs.add([webView _webProcessIdentifier]); 500 501 TestWebKitAPI::Util::run(&done); 502 done = false; 503 504 seenPIDs.add([webView _webProcessIdentifier]); 505 506 EXPECT_FALSE(serverRedirected); 507 EXPECT_EQ(2, numberOfDecidePolicyCalls); 508 EXPECT_EQ(1u, seenPIDs.size()); 509 } 510 511 TEST(ProcessSwap, ServerRedirect) 512 { 513 auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]); 514 processPoolConfiguration.get().processSwapsOnNavigation = YES; 515 auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]); 516 517 auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]); 518 [webViewConfiguration setProcessPool:processPool.get()]; 519 RetainPtr<PSONScheme> handler1 = adoptNS([[PSONScheme alloc] init]); 520 [handler1 addRedirectFromURLString:@"pson://host/main1.html" toURLString:@"psonredirected://host/main1.html"]; 521 [webViewConfiguration setURLSchemeHandler:handler1.get() forURLScheme:@"pson"]; 522 RetainPtr<PSONScheme> handler2 = adoptNS([[PSONScheme alloc] init]); 523 [webViewConfiguration setURLSchemeHandler:handler2.get() forURLScheme:@"originalload"]; 524 525 auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]); 526 auto delegate = adoptNS([[PSONNavigationDelegate alloc] init]); 527 [webView setNavigationDelegate:delegate.get()]; 528 529 NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"originalload://host/main1.html"]]; 530 [webView loadRequest:request]; 531 532 TestWebKitAPI::Util::run(&done); 533 done = false; 534 535 auto pidAfterFirstLoad = [webView _webProcessIdentifier]; 536 537 EXPECT_EQ(1, numberOfDecidePolicyCalls); 538 EXPECT_EQ(1u, seenPIDs.size()); 539 EXPECT_TRUE(*seenPIDs.begin() == pidAfterFirstLoad); 540 541 request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://host/main1.html"]]; 542 [webView loadRequest:request]; 543 544 TestWebKitAPI::Util::run(&serverRedirected); 545 serverRedirected = false; 546 547 seenPIDs.add([webView _webProcessIdentifier]); 548 549 TestWebKitAPI::Util::run(&done); 550 done = false; 551 552 seenPIDs.add([webView _webProcessIdentifier]); 553 554 EXPECT_FALSE(serverRedirected); 555 EXPECT_EQ(3, numberOfDecidePolicyCalls); 556 EXPECT_EQ(2u, seenPIDs.size()); 557 } 558 559 TEST(ProcessSwap, ServerRedirect2) 560 { 561 // This tests a load that *starts out* to the same origin as the previous load, but then redirects to a new origin. 562 auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]); 563 processPoolConfiguration.get().processSwapsOnNavigation = YES; 564 auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]); 565 566 auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]); 567 [webViewConfiguration setProcessPool:processPool.get()]; 568 RetainPtr<PSONScheme> handler1 = adoptNS([[PSONScheme alloc] init]); 569 [handler1 addRedirectFromURLString:@"pson://host/main2.html" toURLString:@"psonredirected://host/main1.html"]; 570 [webViewConfiguration setURLSchemeHandler:handler1.get() forURLScheme:@"pson"]; 571 RetainPtr<PSONScheme> handler2 = adoptNS([[PSONScheme alloc] init]); 572 [webViewConfiguration setURLSchemeHandler:handler2.get() forURLScheme:@"psonredirected"]; 573 574 auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]); 575 auto delegate = adoptNS([[PSONNavigationDelegate alloc] init]); 576 [webView setNavigationDelegate:delegate.get()]; 577 578 NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://host/main1.html"]]; 579 [webView loadRequest:request]; 580 581 TestWebKitAPI::Util::run(&done); 582 done = false; 583 584 auto pidAfterFirstLoad = [webView _webProcessIdentifier]; 585 586 EXPECT_FALSE(serverRedirected); 587 EXPECT_EQ(1, numberOfDecidePolicyCalls); 588 EXPECT_EQ(1u, seenPIDs.size()); 589 EXPECT_TRUE(*seenPIDs.begin() == pidAfterFirstLoad); 590 591 request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://host/main2.html"]]; 592 [webView loadRequest:request]; 593 594 TestWebKitAPI::Util::run(&serverRedirected); 595 serverRedirected = false; 596 597 seenPIDs.add([webView _webProcessIdentifier]); 598 599 TestWebKitAPI::Util::run(&done); 600 done = false; 601 602 seenPIDs.add([webView _webProcessIdentifier]); 603 604 EXPECT_FALSE(serverRedirected); 605 EXPECT_EQ(3, numberOfDecidePolicyCalls); 606 EXPECT_EQ(2u, seenPIDs.size()); 607 } 608 609 447 610 #endif // WK_API_ENABLED
Note: See TracChangeset
for help on using the changeset viewer.