Source/WebKit/ChangeLog

 12018-02-12 Alex Christensen <achristensen@webkit.org>
 2
 3 Make policy decisions asynchronous
 4 https://bugs.webkit.org/show_bug.cgi?id=180568
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 * UIProcess/WebPageProxy.cpp:
 9 (WebKit::WebPageProxy::receivedPolicyDecision):
 10 (WebKit::WebPageProxy::decidePolicyForNavigationAction):
 11 (WebKit::WebPageProxy::decidePolicyForResponse):
 12 (WebKit::WebPageProxy::decidePolicyForResponseSync): Deleted.
 13 * UIProcess/WebPageProxy.h:
 14 * UIProcess/WebPageProxy.messages.in:
 15 * WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
 16 (WebKit::WebFrameLoaderClient::dispatchDecidePolicyForResponse):
 17 (WebKit::WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction):
 18
1192018-03-01 Antti Koivisto <antti@apple.com>
220
321 Crash when updating cache entry after validation in apps that uses class A file protection

Source/WebKit/UIProcess/WebPageProxy.cpp

@@void WebPageProxy::receivedPolicyDecision(PolicyAction action, WebFrameProxy& fr
23252325 DownloadID downloadID = { };
23262326 if (action == PolicyAction::Download) {
23272327 // Create a download proxy.
2328  const ResourceRequest& downloadRequest = m_decidePolicyForResponseRequest ? *m_decidePolicyForResponseRequest : ResourceRequest();
2329  DownloadProxy* download = m_process->processPool().createDownloadProxy(downloadRequest, this);
 2328 auto* download = m_process->processPool().createDownloadProxy(m_decidePolicyForResponseRequest, this);
23302329 if (navigation) {
23312330 download->setWasUserInitiated(navigation->wasUserInitiated());
23322331 download->setRedirectChain(navigation->takeRedirectChain());

@@void WebPageProxy::receivedPolicyDecision(PolicyAction action, WebFrameProxy& fr
23342333
23352334 downloadID = download->downloadID();
23362335 handleDownloadRequest(download);
 2336 m_decidePolicyForResponseRequest = { };
23372337 }
23382338
2339  // If we received a policy decision while in decidePolicyForResponse the decision will
2340  // be sent back to the web process by decidePolicyForResponse.
2341  if (m_inDecidePolicyForResponseSync) {
2342  m_syncMimeTypePolicyActionIsValid = true;
2343  m_syncMimeTypePolicyAction = action;
2344  m_syncMimeTypePolicyDownloadID = downloadID;
2345  return;
2346  }
2347 
2348  // If we received a policy decision while in decidePolicyForNavigationAction the decision will
2349  // be sent back to the web process by decidePolicyForNavigationAction.
2350  if (m_inDecidePolicyForNavigationAction) {
2351  m_syncNavigationActionPolicyActionIsValid = true;
2352  m_syncNavigationActionPolicyAction = action;
2353  m_syncNavigationActionPolicyDownloadID = downloadID;
2354  m_syncNavigationActionPolicyWebsitePolicies = WTFMove(websitePolicies);
2355  return;
2356  }
2357 
23582339 m_process->send(Messages::WebPage::DidReceivePolicyDecision(frame.frameID(), listenerID, action, navigation ? navigation->navigationID() : 0, downloadID, websitePolicies), m_pageID);
23592340}
23602341

@@void WebPageProxy::frameDidBecomeFrameSet(uint64_t frameID, bool value)
37483729 m_frameSetLargestFrame = value ? m_mainFrame : 0;
37493730}
37503731
3751 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, bool& receivedPolicyAction, uint64_t& newNavigationID, WebCore::PolicyAction& policyAction, DownloadID& downloadID, std::optional<WebsitePoliciesData>& websitePolicies)
 3732void 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)
37523733{
37533734 PageClientProtector protector(m_pageClient);
37543735

@@void WebPageProxy::decidePolicyForNavigationAction(uint64_t frameID, const Secur
37633744 MESSAGE_CHECK_URL(request.url());
37643745 MESSAGE_CHECK_URL(originalRequest.url());
37653746
 3747 uint64_t newNavigationID { 0 };
37663748 Ref<WebFramePolicyListenerProxy> listener = frame->setUpPolicyListenerProxy(listenerID);
37673749 if (!navigationID) {
37683750 auto navigation = m_navigationState->createLoadRequestNavigation(ResourceRequest(request));

@@void WebPageProxy::decidePolicyForNavigationAction(uint64_t frameID, const Secur
37723754 listener->setNavigation(WTFMove(navigation));
37733755 } else {
37743756 auto& navigation = m_navigationState->navigation(navigationID);
 3757 newNavigationID = navigationID;
37753758 navigation.setWasUserInitiated(!!navigationActionData.userGestureTokenIdentifier);
37763759 navigation.setShouldForceDownload(!navigationActionData.downloadAttribute.isNull());
37773760 listener->setNavigation(navigation);
37783761 }
37793762
37803763#if ENABLE(CONTENT_FILTERING)
3781  if (frame->didHandleContentFilterUnblockNavigation(request)) {
3782  receivedPolicyAction = true;
3783  policyAction = PolicyAction::Ignore;
3784  return;
3785  }
 3764 if (frame->didHandleContentFilterUnblockNavigation(request))
 3765 return receivedPolicyDecision(PolicyAction::Ignore, *frame, listenerID, &m_navigationState->navigation(newNavigationID), { });
37863766#endif
37873767
3788  ASSERT(!m_inDecidePolicyForNavigationAction);
3789 
3790  m_inDecidePolicyForNavigationAction = true;
3791  m_syncNavigationActionPolicyActionIsValid = false;
3792 
37933768 WebFrameProxy* originatingFrame = m_process->webFrame(originatingFrameInfoData.frameID);
37943769
37953770 if (m_navigationClient) {

@@void WebPageProxy::decidePolicyForNavigationAction(uint64_t frameID, const Secur
38103785 m_policyClient->decidePolicyForNavigationAction(*this, frame, WTFMove(navigationActionData), originatingFrame, originalRequest, WTFMove(request), WTFMove(listener), m_process->transformHandlesToObjects(userData.object()).get());
38113786
38123787 m_shouldSuppressAppLinksInNextNavigationPolicyDecision = false;
3813  m_inDecidePolicyForNavigationAction = false;
3814 
3815  // Check if we received a policy decision already. If we did, we can just pass it back.
3816  receivedPolicyAction = m_syncNavigationActionPolicyActionIsValid;
3817  if (m_syncNavigationActionPolicyActionIsValid) {
3818  policyAction = m_syncNavigationActionPolicyAction;
3819  downloadID = m_syncNavigationActionPolicyDownloadID;
3820  websitePolicies = WTFMove(m_syncNavigationActionPolicyWebsitePolicies);
3821  }
38223788}
38233789
38243790void WebPageProxy::decidePolicyForNewWindowAction(uint64_t frameID, const SecurityOriginData& frameSecurityOrigin, NavigationActionData&& navigationActionData, ResourceRequest&& request, const String& frameName, uint64_t listenerID, const UserData& userData)

@@void WebPageProxy::decidePolicyForResponse(uint64_t frameID, const SecurityOrigi
38503816{
38513817 PageClientProtector protector(m_pageClient);
38523818
 3819 m_decidePolicyForResponseRequest = request;
 3820
38533821 WebFrameProxy* frame = m_process->webFrame(frameID);
38543822 MESSAGE_CHECK(frame);
38553823 MESSAGE_CHECK_URL(request.url());

@@void WebPageProxy::decidePolicyForResponse(uint64_t frameID, const SecurityOrigi
38663834 m_policyClient->decidePolicyForResponse(*this, *frame, response, request, canShowMIMEType, WTFMove(listener), m_process->transformHandlesToObjects(userData.object()).get());
38673835}
38683836
3869 void WebPageProxy::decidePolicyForResponseSync(uint64_t frameID, const SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, const ResourceResponse& response, const ResourceRequest& request, bool canShowMIMEType, uint64_t listenerID, const UserData& userData, bool& receivedPolicyAction, WebCore::PolicyAction& policyAction, DownloadID& downloadID)
3870 {
3871  PageClientProtector protector(m_pageClient);
3872 
3873  ASSERT(!m_inDecidePolicyForResponseSync);
3874 
3875  m_inDecidePolicyForResponseSync = true;
3876  m_decidePolicyForResponseRequest = &request;
3877  m_syncMimeTypePolicyActionIsValid = false;
3878 
3879  decidePolicyForResponse(frameID, frameSecurityOrigin, navigationID, response, request, canShowMIMEType, listenerID, userData);
3880 
3881  m_inDecidePolicyForResponseSync = false;
3882  m_decidePolicyForResponseRequest = nullptr;
3883 
3884  // Check if we received a policy decision already. If we did, we can just pass it back.
3885  receivedPolicyAction = m_syncMimeTypePolicyActionIsValid;
3886  if (m_syncMimeTypePolicyActionIsValid) {
3887  policyAction = m_syncMimeTypePolicyAction;
3888  downloadID = m_syncMimeTypePolicyDownloadID;
3889  }
3890 }
3891 
38923837void WebPageProxy::unableToImplementPolicy(uint64_t frameID, const ResourceError& error, const UserData& userData)
38933838{
38943839 PageClientProtector protector(m_pageClient);

Source/WebKit/UIProcess/WebPageProxy.h

@@private:
13541354
13551355 void didDestroyNavigation(uint64_t navigationID);
13561356
1357  void decidePolicyForNavigationAction(uint64_t frameID, const WebCore::SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, NavigationActionData&&, const FrameInfoData&, uint64_t originatingPageID, const WebCore::ResourceRequest& originalRequest, WebCore::ResourceRequest&&, uint64_t listenerID, const UserData&, bool& receivedPolicyAction, uint64_t& newNavigationID, WebCore::PolicyAction&, DownloadID&, std::optional<WebsitePoliciesData>&);
 1357 void decidePolicyForNavigationAction(uint64_t frameID, const WebCore::SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, NavigationActionData&&, const FrameInfoData&, uint64_t originatingPageID, const WebCore::ResourceRequest& originalRequest, WebCore::ResourceRequest&&, uint64_t listenerID, const UserData&);
13581358 void decidePolicyForNewWindowAction(uint64_t frameID, const WebCore::SecurityOriginData& frameSecurityOrigin, NavigationActionData&&, WebCore::ResourceRequest&&, const String& frameName, uint64_t listenerID, const UserData&);
13591359 void decidePolicyForResponse(uint64_t frameID, const WebCore::SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, const WebCore::ResourceResponse&, const WebCore::ResourceRequest&, bool canShowMIMEType, uint64_t listenerID, const UserData&);
1360  void decidePolicyForResponseSync(uint64_t frameID, const WebCore::SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, const WebCore::ResourceResponse&, const WebCore::ResourceRequest&, bool canShowMIMEType, uint64_t listenerID, const UserData&, bool& receivedPolicyAction, WebCore::PolicyAction&, DownloadID&);
13611360 void unableToImplementPolicy(uint64_t frameID, const WebCore::ResourceError&, const UserData&);
13621361
13631362 void willSubmitForm(uint64_t frameID, uint64_t sourceFrameID, const Vector<std::pair<String, String>>& textFieldValues, uint64_t listenerID, const UserData&);

@@private:
18911890 bool m_isInPrintingMode { false };
18921891 bool m_isPerformingDOMPrintOperation { false };
18931892
1894  bool m_inDecidePolicyForResponseSync { false };
1895  const WebCore::ResourceRequest* m_decidePolicyForResponseRequest { nullptr };
1896  bool m_syncMimeTypePolicyActionIsValid { false };
1897  WebCore::PolicyAction m_syncMimeTypePolicyAction { WebCore::PolicyAction::Use };
1898  DownloadID m_syncMimeTypePolicyDownloadID { 0 };
1899  bool m_inDecidePolicyForNavigationAction { false };
1900  bool m_syncNavigationActionPolicyActionIsValid { false };
1901  WebCore::PolicyAction m_syncNavigationActionPolicyAction { WebCore::PolicyAction::Use };
1902  DownloadID m_syncNavigationActionPolicyDownloadID { 0 };
1903  std::optional<WebsitePoliciesData> m_syncNavigationActionPolicyWebsitePolicies;
1904 
 1893 WebCore::ResourceRequest m_decidePolicyForResponseRequest;
19051894 bool m_shouldSuppressAppLinksInNextNavigationPolicyDecision { false };
19061895
19071896 Deque<NativeWebKeyboardEvent> m_keyEventQueue;

Source/WebKit/UIProcess/WebPageProxy.messages.in

@@messages -> WebPageProxy {
9898#endif
9999
100100 # Policy messages
101  DecidePolicyForResponseSync(uint64_t frameID, struct WebCore::SecurityOriginData frameSecurityOrigin, uint64_t navigationID, WebCore::ResourceResponse response, WebCore::ResourceRequest request, bool canShowMIMEType, uint64_t listenerID, WebKit::UserData userData) -> (bool receivedPolicyAction, enum WebCore::PolicyAction policyAction, WebKit::DownloadID downloadID)
102  DecidePolicyForNavigationAction(uint64_t frameID, struct WebCore::SecurityOriginData frameSecurityOrigin, uint64_t navigationID, struct WebKit::NavigationActionData navigationActionData, struct WebKit::FrameInfoData originatingFrameInfoData, uint64_t originatingPageID, WebCore::ResourceRequest originalRequest, WebCore::ResourceRequest request, uint64_t listenerID, WebKit::UserData userData) -> (bool receivedPolicyAction, uint64_t newNavigationID, enum WebCore::PolicyAction policyAction, WebKit::DownloadID downloadID, std::optional<WebKit::WebsitePoliciesData> websitePolicies)
 101 DecidePolicyForResponse(uint64_t frameID, struct WebCore::SecurityOriginData frameSecurityOrigin, uint64_t navigationID, WebCore::ResourceResponse response, WebCore::ResourceRequest request, bool canShowMIMEType, uint64_t listenerID, WebKit::UserData userData)
 102 DecidePolicyForNavigationAction(uint64_t frameID, struct WebCore::SecurityOriginData frameSecurityOrigin, uint64_t navigationID, struct WebKit::NavigationActionData navigationActionData, struct WebKit::FrameInfoData originatingFrameInfoData, uint64_t originatingPageID, WebCore::ResourceRequest originalRequest, WebCore::ResourceRequest request, uint64_t listenerID, WebKit::UserData userData)
103103 DecidePolicyForNewWindowAction(uint64_t frameID, struct WebCore::SecurityOriginData frameSecurityOrigin, struct WebKit::NavigationActionData navigationActionData, WebCore::ResourceRequest request, String frameName, uint64_t listenerID, WebKit::UserData userData)
104104 UnableToImplementPolicy(uint64_t frameID, WebCore::ResourceError error, WebKit::UserData userData)
105105

Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp

@@void WebFrameLoaderClient::dispatchDecidePolicyForResponse(const ResourceRespons
748748
749749 Ref<WebFrame> protector(*m_frame);
750750 uint64_t listenerID = m_frame->setUpPolicyListener(WTFMove(function), WebFrame::ForNavigationAction::No);
751  bool receivedPolicyAction;
752  PolicyAction policyAction;
753  DownloadID downloadID;
754 
755751 auto navigationID = static_cast<WebDocumentLoader&>(*policyDocumentLoader).navigationID();
756  if (!webPage->sendSync(Messages::WebPageProxy::DecidePolicyForResponseSync(m_frame->frameID(), SecurityOriginData::fromFrame(coreFrame), navigationID, response, request, canShowMIMEType, listenerID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())), Messages::WebPageProxy::DecidePolicyForResponseSync::Reply(receivedPolicyAction, policyAction, downloadID), Seconds::infinity(), IPC::SendSyncOption::InformPlatformProcessWillSuspend)) {
 752 if (!webPage->send(Messages::WebPageProxy::DecidePolicyForResponse(m_frame->frameID(), SecurityOriginData::fromFrame(coreFrame), navigationID, response, request, canShowMIMEType, listenerID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get()))))
757753 m_frame->didReceivePolicyDecision(listenerID, PolicyAction::Ignore, 0, { }, { });
758  return;
759  }
760 
761  // We call this synchronously because CFNetwork can only convert a loading connection to a download from its didReceiveResponse callback.
762  if (receivedPolicyAction)
763  m_frame->didReceivePolicyDecision(listenerID, policyAction, 0, downloadID, { });
764754}
765755
766756void WebFrameLoaderClient::dispatchDecidePolicyForNewWindowAction(const NavigationAction& navigationAction, const ResourceRequest& request, FormState* formState, const String& frameName, FramePolicyFunction&& function)

@@void WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction(const Navigat
843833 }
844834
845835 uint64_t listenerID = m_frame->setUpPolicyListener(WTFMove(function), WebFrame::ForNavigationAction::Yes);
846  bool receivedPolicyAction;
847  uint64_t newNavigationID;
848  PolicyAction policyAction;
849  DownloadID downloadID;
850836
851837 ASSERT(navigationAction.sourceDocument());
852838 const Document& sourceDocument = *navigationAction.sourceDocument();

@@void WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction(const Navigat
885871
886872 // Notify the UIProcess.
887873 Ref<WebFrame> protect(*m_frame);
888  std::optional<WebsitePoliciesData> websitePolicies;
889  if (!webPage->sendSync(Messages::WebPageProxy::DecidePolicyForNavigationAction(m_frame->frameID(), SecurityOriginData::fromFrame(coreFrame), documentLoader->navigationID(), navigationActionData, originatingFrameInfoData, originatingFrame && originatingFrame->page() ? originatingFrame->page()->pageID() : 0, navigationAction.resourceRequest(), request, listenerID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())), Messages::WebPageProxy::DecidePolicyForNavigationAction::Reply(receivedPolicyAction, newNavigationID, policyAction, downloadID, websitePolicies))) {
 874 if (!webPage->send(Messages::WebPageProxy::DecidePolicyForNavigationAction(m_frame->frameID(), SecurityOriginData::fromFrame(coreFrame), documentLoader->navigationID(), navigationActionData, originatingFrameInfoData, originatingFrame && originatingFrame->page() ? originatingFrame->page()->pageID() : 0, navigationAction.resourceRequest(), request, listenerID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get()))))
890875 m_frame->didReceivePolicyDecision(listenerID, PolicyAction::Ignore, 0, { }, { });
891  return;
892  }
893 
894  // We call this synchronously because WebCore cannot gracefully handle a frame load without a synchronous navigation policy reply.
895  if (receivedPolicyAction)
896  m_frame->didReceivePolicyDecision(listenerID, policyAction, newNavigationID, downloadID, WTFMove(websitePolicies));
897876}
898877
899878void WebFrameLoaderClient::cancelPolicyCheck()