Changeset 240882 in webkit
- Timestamp:
- Feb 1, 2019 3:12:14 PM (5 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 20 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r240875 r240882 1 2019-02-01 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 [iOS] Consistent 1 sec hang when triggering modal alerts while handling synchronous touch events 4 https://bugs.webkit.org/show_bug.cgi?id=194140 5 <rdar://problem/47728098> 6 7 Reviewed by Tim Horton. 8 9 Add a test that induces sync IPC deadlock by presenting a modal alert while handling touch start. This test 10 forces sync IPC timeouts to be disabled, and passes if we do not time out while handling a touch. 11 12 * fast/events/touch/ios/show-modal-alert-during-touch-start-expected.txt: Added. 13 * fast/events/touch/ios/show-modal-alert-during-touch-start.html: Added. 14 1 15 2019-02-01 Antoine Quint <graouts@apple.com> 2 16 -
trunk/Source/WebKit/ChangeLog
r240881 r240882 1 2019-02-01 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 [iOS] Consistent 1 sec hang when triggering modal alerts while handling synchronous touch events 4 https://bugs.webkit.org/show_bug.cgi?id=194140 5 <rdar://problem/47728098> 6 7 Reviewed by Tim Horton. 8 9 Currently, the UI process hangs when attempting to synchronously present modal UI from the web process while the 10 UI process is waiting for sync IPC in the web process. While we have logic to generally mitigate IPC deadlock in 11 this scenario by dispatching the web process' sync IPC immediately with the intention of allowing the web 12 process to finish processing sync IPC (and consequently unblock the UI process), this fails in the case where 13 the sync IPC message from the web process to the UI process requires main thread execution for an arbitrary 14 amount of time (for instance, modal alert dialogs). In this case, we'll end up in a state where we've handled 15 the web process' sync IPC in the UI process, yet we can't resume execution since the web process is still 16 blocked. 17 18 By far the most egregious scenario in which this manifests is during synchronous gesture recognizer IPC, i.e. 19 grabbing position information from the UI process, and handling touch events synchronously. Luckily, these are 20 also cases where (1) we know sync IPC may safely time out, and (2) the presentation of modal UI from the web 21 process should cause the gesture recognizers to fail anyways. As such, we can mitigate these scenarios in the 22 web process by responding to the these pending sync IPC messages *before* sending our own sync IPC to the UI 23 process. 24 25 Test: fast/events/touch/ios/show-modal-alert-during-touch-start.html 26 27 * Shared/ios/InteractionInformationAtPosition.h: 28 (WebKit::InteractionInformationAtPosition::invalidInformation): 29 * Shared/ios/InteractionInformationAtPosition.mm: 30 (WebKit::InteractionInformationAtPosition::encode const): 31 (WebKit::InteractionInformationAtPosition::decode): 32 33 Add a new flag to indicate whether an interaction information response can be valid. Interaction information 34 cannot be valid in the case where the interaction information request was interrupted by certain sync IPC 35 messages from the web process. 36 37 * UIProcess/API/C/WKContextConfigurationRef.cpp: 38 (WKContextConfigurationIgnoreSynchronousMessagingTimeoutsForTesting): 39 (WKContextConfigurationSetIgnoreSynchronousMessagingTimeoutsForTesting): 40 41 Add some testing SPI to ignore sync IPC timeouts, for the purposes of testing. Rather than use the existing 42 Objective-C SPI in WKWebProcessPoolConfiguration, I decided to add C API plumbing for this flag, so that other 43 non-Cocoa ports may also support the new layout test option to ignore sync IPC timeouts. 44 45 * UIProcess/API/C/WKContextConfigurationRef.h: 46 * UIProcess/ios/WKContentViewInteraction.mm: 47 (-[WKContentView ensurePositionInformationIsUpToDate:]): 48 (-[WKContentView _positionInformationDidChange:]): 49 * WebProcess/WebCoreSupport/WebChromeClient.cpp: 50 (WebKit::WebChromeClient::runBeforeUnloadConfirmPanel): 51 (WebKit::WebChromeClient::runJavaScriptAlert): 52 (WebKit::WebChromeClient::runJavaScriptConfirm): 53 (WebKit::WebChromeClient::runJavaScriptPrompt): 54 (WebKit::WebChromeClient::print): 55 (WebKit::WebChromeClient::exceededDatabaseQuota): 56 (WebKit::WebChromeClient::reachedApplicationCacheOriginQuota): 57 58 Cancel any pending sync IPC replies prior to sending sync IPC messages to the UI process which may result in 59 sync IPC deadlock, by using the new helper method, sendSyncWithDelayedReply, instead of just sendSync. 60 61 * WebProcess/WebPage/WebPage.cpp: 62 (WebKit::WebPage::cancelGesturesBlockedOnSynchronousReplies): 63 64 Add a helper to cancel pending sync messages coming in from the UI process that are being called from within 65 gesture recognizer delegate hooks. 66 67 (WebKit::WebPage::touchEventSync): 68 * WebProcess/WebPage/WebPage.h: 69 70 Add a new helper, sendSyncWithDelayedReply, to be used when sending a sync IPC message to the UI process that 71 cannot be immediately completed upon arrival. Importantly, this cancels pending sync replies, and also passes 72 IPC::SendSyncOption::InformPlatformProcessWillSuspend. 73 74 * WebProcess/WebPage/WebPage.messages.in: 75 76 Change these from LegacySync to Delayed messages. 77 78 * WebProcess/WebPage/ios/WebPageIOS.mm: 79 (WebKit::WebPage::getPositionInformation): 80 81 Make this sync IPC handler (as well as WebPage::touchEventSync) store the IPC reply during the scope of the 82 method, and invoke the stored reply at the end of the method if it wasn't interrupted due to something calling 83 cancelGesturesBlockedOnSynchronousReplies(). 84 85 (WebKit::WebPage::positionInformation): 86 87 Refactor getPositionInformation by pulling out the logic for building an InteractionInformationAtPosition into 88 a separate helper. 89 90 (WebKit::WebPage::requestPositionInformation): 91 1 92 2019-02-01 David Quesada <david_quesada@apple.com> 2 93 -
trunk/Source/WebKit/Shared/ios/InteractionInformationAtPosition.h
r239454 r240882 40 40 41 41 struct InteractionInformationAtPosition { 42 static InteractionInformationAtPosition invalidInformation() 43 { 44 InteractionInformationAtPosition response; 45 response.canBeValid = false; 46 return response; 47 } 48 42 49 InteractionInformationRequest request; 43 50 51 bool canBeValid { true }; 44 52 bool nodeAtPositionIsFocusedElement { false }; 45 53 #if ENABLE(DATA_INTERACTION) -
trunk/Source/WebKit/Shared/ios/InteractionInformationAtPosition.mm
r239454 r240882 44 44 encoder << request; 45 45 46 encoder << canBeValid; 46 47 encoder << nodeAtPositionIsFocusedElement; 47 48 #if ENABLE(DATA_INTERACTION) … … 90 91 return false; 91 92 93 if (!decoder.decode(result.canBeValid)) 94 return false; 95 92 96 if (!decoder.decode(result.nodeAtPositionIsFocusedElement)) 93 97 return false; -
trunk/Source/WebKit/UIProcess/API/C/WKContextConfigurationRef.cpp
r238820 r240882 139 139 } 140 140 141 bool WKContextConfigurationIgnoreSynchronousMessagingTimeoutsForTesting(WKContextConfigurationRef configuration) 142 { 143 return toImpl(configuration)->ignoreSynchronousMessagingTimeoutsForTesting(); 144 } 145 146 void WKContextConfigurationSetIgnoreSynchronousMessagingTimeoutsForTesting(WKContextConfigurationRef configuration, bool ignore) 147 { 148 toImpl(configuration)->setIgnoreSynchronousMessagingTimeoutsForTesting(ignore); 149 } 150 141 151 WKArrayRef WKContextConfigurationCopyOverrideLanguages(WKContextConfigurationRef configuration) 142 152 { -
trunk/Source/WebKit/UIProcess/API/C/WKContextConfigurationRef.h
r238820 r240882 64 64 WK_EXPORT void WKContextConfigurationSetFullySynchronousModeIsAllowedForTesting(WKContextConfigurationRef configuration, bool allowed); 65 65 66 WK_EXPORT bool WKContextConfigurationIgnoreSynchronousMessagingTimeoutsForTesting(WKContextConfigurationRef configuration); 67 WK_EXPORT void WKContextConfigurationSetIgnoreSynchronousMessagingTimeoutsForTesting(WKContextConfigurationRef configuration, bool ignore); 68 66 69 WK_EXPORT WKArrayRef WKContextConfigurationCopyOverrideLanguages(WKContextConfigurationRef configuration); 67 70 WK_EXPORT void WKContextConfigurationSetOverrideLanguages(WKContextConfigurationRef configuration, WKArrayRef overrideLanguages); -
trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm
r240875 r240882 1764 1764 return connection->waitForAndDispatchImmediately<Messages::WebPageProxy::DidReceivePositionInformation>(_page->pageID(), 1_s, IPC::WaitForOption::InterruptWaitingIfSyncMessageArrives); 1765 1765 1766 _hasValidPositionInformation = _page->process().sendSync(Messages::WebPage::GetPositionInformation(request), Messages::WebPage::GetPositionInformation::Reply(_positionInformation), _page->pageID(), 1_s); 1766 bool receivedResponse = _page->process().sendSync(Messages::WebPage::GetPositionInformation(request), Messages::WebPage::GetPositionInformation::Reply(_positionInformation), _page->pageID(), 1_s); 1767 _hasValidPositionInformation = receivedResponse && _positionInformation.canBeValid; 1767 1768 1768 1769 // FIXME: We need to clean up these handlers in the event that we are not able to collect data, or if the WebProcess crashes. … … 2285 2286 2286 2287 _positionInformation = newInfo; 2287 _hasValidPositionInformation = YES;2288 _hasValidPositionInformation = _positionInformation.canBeValid; 2288 2289 if (_actionSheetAssistant) 2289 2290 [_actionSheetAssistant updateSheetPosition]; -
trunk/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp
r240199 r240882 406 406 HangDetectionDisabler hangDetectionDisabler; 407 407 408 if (! WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPageProxy::RunBeforeUnloadConfirmPanel(webFrame->frameID(), SecurityOriginData::fromFrame(&frame), message), Messages::WebPageProxy::RunBeforeUnloadConfirmPanel::Reply(shouldClose), m_page.pageID(), Seconds::infinity(), IPC::SendSyncOption::InformPlatformProcessWillSuspend))408 if (!m_page.sendSyncWithDelayedReply(Messages::WebPageProxy::RunBeforeUnloadConfirmPanel(webFrame->frameID(), SecurityOriginData::fromFrame(&frame), message), Messages::WebPageProxy::RunBeforeUnloadConfirmPanel::Reply(shouldClose))) 409 409 return false; 410 410 … … 452 452 HangDetectionDisabler hangDetectionDisabler; 453 453 454 WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPageProxy::RunJavaScriptAlert(webFrame->frameID(), SecurityOriginData::fromFrame(&frame), alertText), Messages::WebPageProxy::RunJavaScriptAlert::Reply(), m_page.pageID(), Seconds::infinity(), IPC::SendSyncOption::InformPlatformProcessWillSuspend);454 m_page.sendSyncWithDelayedReply(Messages::WebPageProxy::RunJavaScriptAlert(webFrame->frameID(), SecurityOriginData::fromFrame(&frame), alertText), Messages::WebPageProxy::RunJavaScriptAlert::Reply()); 455 455 } 456 456 … … 469 469 470 470 bool result = false; 471 if (! WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPageProxy::RunJavaScriptConfirm(webFrame->frameID(), SecurityOriginData::fromFrame(&frame), message), Messages::WebPageProxy::RunJavaScriptConfirm::Reply(result), m_page.pageID(), Seconds::infinity(), IPC::SendSyncOption::InformPlatformProcessWillSuspend))471 if (!m_page.sendSyncWithDelayedReply(Messages::WebPageProxy::RunJavaScriptConfirm(webFrame->frameID(), SecurityOriginData::fromFrame(&frame), message), Messages::WebPageProxy::RunJavaScriptConfirm::Reply(result))) 472 472 return false; 473 473 … … 488 488 HangDetectionDisabler hangDetectionDisabler; 489 489 490 if (! WebProcess::singleton().parentProcessConnection()->sendSync(Messages::WebPageProxy::RunJavaScriptPrompt(webFrame->frameID(), SecurityOriginData::fromFrame(&frame), message, defaultValue), Messages::WebPageProxy::RunJavaScriptPrompt::Reply(result), m_page.pageID(), Seconds::infinity(), IPC::SendSyncOption::InformPlatformProcessWillSuspend))490 if (!m_page.sendSyncWithDelayedReply(Messages::WebPageProxy::RunJavaScriptPrompt(webFrame->frameID(), SecurityOriginData::fromFrame(&frame), message, defaultValue), Messages::WebPageProxy::RunJavaScriptPrompt::Reply(result))) 491 491 return false; 492 492 … … 715 715 #endif 716 716 717 m_page.sendSync (Messages::WebPageProxy::PrintFrame(webFrame->frameID()), Messages::WebPageProxy::PrintFrame::Reply(), Seconds::infinity(), IPC::SendSyncOption::InformPlatformProcessWillSuspend);717 m_page.sendSyncWithDelayedReply(Messages::WebPageProxy::PrintFrame(webFrame->frameID()), Messages::WebPageProxy::PrintFrame::Reply()); 718 718 } 719 719 … … 732 732 newQuota = m_page.injectedBundleUIClient().didExceedDatabaseQuota(&m_page, securityOrigin.ptr(), databaseName, details.displayName(), currentQuota, currentOriginUsage, details.currentUsage(), details.expectedUsage()); 733 733 734 if (!newQuota) { 735 WebProcess::singleton().parentProcessConnection()->sendSync( 736 Messages::WebPageProxy::ExceededDatabaseQuota(webFrame->frameID(), originData.databaseIdentifier(), databaseName, details.displayName(), currentQuota, currentOriginUsage, details.currentUsage(), details.expectedUsage()), 737 Messages::WebPageProxy::ExceededDatabaseQuota::Reply(newQuota), m_page.pageID(), Seconds::infinity(), IPC::SendSyncOption::InformPlatformProcessWillSuspend); 738 } 734 if (!newQuota) 735 m_page.sendSyncWithDelayedReply(Messages::WebPageProxy::ExceededDatabaseQuota(webFrame->frameID(), originData.databaseIdentifier(), databaseName, details.displayName(), currentQuota, currentOriginUsage, details.currentUsage(), details.expectedUsage()), Messages::WebPageProxy::ExceededDatabaseQuota::Reply(newQuota)); 739 736 740 737 tracker.setQuota(originData, newQuota); … … 758 755 759 756 uint64_t newQuota = 0; 760 WebProcess::singleton().parentProcessConnection()->sendSync( 761 Messages::WebPageProxy::ReachedApplicationCacheOriginQuota(origin.data().databaseIdentifier(), currentQuota, totalBytesNeeded), 762 Messages::WebPageProxy::ReachedApplicationCacheOriginQuota::Reply(newQuota), m_page.pageID(), Seconds::infinity(), IPC::SendSyncOption::InformPlatformProcessWillSuspend); 757 m_page.sendSyncWithDelayedReply(Messages::WebPageProxy::ReachedApplicationCacheOriginQuota(origin.data().databaseIdentifier(), currentQuota, totalBytesNeeded), Messages::WebPageProxy::ReachedApplicationCacheOriginQuota::Reply(newQuota)); 763 758 764 759 cacheStorage.storeUpdatedQuotaForOrigin(&origin, newQuota); -
trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp
r240875 r240882 263 263 264 264 #if PLATFORM(IOS_FAMILY) 265 #include "InteractionInformationAtPosition.h" 266 #include "InteractionInformationRequest.h" 265 267 #include "RemoteLayerTreeDrawingArea.h" 266 268 #include <CoreGraphics/CoreGraphics.h> … … 2726 2728 } 2727 2729 2730 void WebPage::cancelGesturesBlockedOnSynchronousReplies() 2731 { 2732 #if ENABLE(IOS_TOUCH_EVENTS) 2733 if (auto reply = WTFMove(m_pendingSynchronousTouchEventReply)) 2734 reply(true); 2735 #endif 2736 2737 #if PLATFORM(IOS_FAMILY) 2738 if (auto reply = WTFMove(m_pendingSynchronousPositionInformationReply)) 2739 reply(InteractionInformationAtPosition::invalidInformation()); 2740 #endif 2741 } 2742 2728 2743 #if ENABLE(TOUCH_EVENTS) 2729 2744 static bool handleTouchEvent(const WebTouchEvent& touchEvent, Page* page) … … 2747 2762 } 2748 2763 2749 void WebPage::touchEventSync(const WebTouchEvent& touchEvent, bool& handled) 2750 { 2764 void WebPage::touchEventSync(const WebTouchEvent& touchEvent, CompletionHandler<void(bool)>&& reply) 2765 { 2766 m_pendingSynchronousTouchEventReply = WTFMove(reply); 2767 2751 2768 EventDispatcher::TouchEventQueue queuedEvents; 2752 2769 WebProcess::singleton().eventDispatcher().getQueuedTouchEventsForPage(*this, queuedEvents); 2753 2770 dispatchAsynchronousTouchEvents(queuedEvents); 2754 2771 2772 bool handled = true; 2755 2773 dispatchTouchEvent(touchEvent, handled); 2774 2775 if (auto reply = WTFMove(m_pendingSynchronousTouchEventReply)) 2776 reply(handled); 2756 2777 } 2757 2778 -
trunk/Source/WebKit/WebProcess/WebPage/WebPage.h
r240875 r240882 648 648 void requestAutocorrectionContext(CallbackID); 649 649 void getAutocorrectionContext(String& beforeText, String& markedText, String& selectedText, String& afterText, uint64_t& location, uint64_t& length); 650 void getPositionInformation(const InteractionInformationRequest&, InteractionInformationAtPosition&);650 void getPositionInformation(const InteractionInformationRequest&, CompletionHandler<void(InteractionInformationAtPosition&&)>&&); 651 651 void requestPositionInformation(const InteractionInformationRequest&); 652 652 void startInteractionWithElementAtPosition(const WebCore::IntPoint&); … … 1138 1138 void didReceiveWebPageMessage(IPC::Connection&, IPC::Decoder&); 1139 1139 1140 template<typename T> 1141 bool sendSyncWithDelayedReply(T&& message, typename T::Reply&& reply) 1142 { 1143 cancelGesturesBlockedOnSynchronousReplies(); 1144 return sendSync(WTFMove(message), WTFMove(reply), m_pageID, Seconds::infinity(), IPC::SendSyncOption::InformPlatformProcessWillSuspend); 1145 } 1146 1140 1147 private: 1141 1148 WebPage(uint64_t pageID, WebPageCreationParameters&&); … … 1179 1186 WebCore::VisiblePosition visiblePositionInFocusedNodeForPoint(const WebCore::Frame&, const WebCore::IntPoint&, bool isInteractingWithFocusedElement); 1180 1187 RefPtr<WebCore::Range> rangeForGranularityAtPoint(WebCore::Frame&, const WebCore::IntPoint&, uint32_t granularity, bool isInteractingWithFocusedElement); 1188 1189 void sendPositionInformation(InteractionInformationAtPosition&&); 1190 InteractionInformationAtPosition positionInformation(const InteractionInformationRequest&); 1181 1191 #endif 1182 1192 … … 1235 1245 1236 1246 #if ENABLE(IOS_TOUCH_EVENTS) 1237 void touchEventSync(const WebTouchEvent&, bool& handled);1247 void touchEventSync(const WebTouchEvent&, CompletionHandler<void(bool)>&&); 1238 1248 void updatePotentialTapSecurityOrigin(const WebTouchEvent&, bool wasHandled); 1239 1249 #elif ENABLE(TOUCH_EVENTS) … … 1494 1504 bool canShowMIMEType(const String&, const Function<bool(const String&, WebCore::PluginData::AllowedPluginTypes)>& supportsPlugin) const; 1495 1505 1506 void cancelGesturesBlockedOnSynchronousReplies(); 1507 1496 1508 uint64_t m_pageID; 1497 1509 … … 1700 1712 bool m_hasPendingBlurNotification { false }; 1701 1713 bool m_hasPendingEditorStateUpdate { false }; 1714 1715 #if ENABLE(IOS_TOUCH_EVENTS) 1716 CompletionHandler<void(bool)> m_pendingSynchronousTouchEventReply; 1717 #endif 1702 1718 1703 1719 #if PLATFORM(IOS_FAMILY) … … 1745 1761 double m_lastTransactionPageScaleFactor { 0 }; 1746 1762 uint64_t m_lastTransactionIDWithScaleChange { 0 }; 1763 1764 CompletionHandler<void(InteractionInformationAtPosition&&)> m_pendingSynchronousPositionInformationReply; 1747 1765 #endif 1748 1766 -
trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in
r240875 r240882 81 81 RequestAutocorrectionContext(WebKit::CallbackID callbackID) 82 82 GetAutocorrectionContext() -> (String beforeContext, String markedText, String selectedText, String afterContext, uint64_t location, uint64_t length) LegacySync 83 GetPositionInformation(struct WebKit::InteractionInformationRequest request) -> (struct WebKit::InteractionInformationAtPosition information) LegacySync83 GetPositionInformation(struct WebKit::InteractionInformationRequest request) -> (struct WebKit::InteractionInformationAtPosition information) Delayed 84 84 RequestPositionInformation(struct WebKit::InteractionInformationRequest request) 85 85 StartInteractionWithElementAtPosition(WebCore::IntPoint point) … … 122 122 123 123 #if ENABLE(IOS_TOUCH_EVENTS) 124 TouchEventSync(WebKit::WebTouchEvent event) -> (bool handled) LegacySync124 TouchEventSync(WebKit::WebTouchEvent event) -> (bool handled) Delayed 125 125 #endif 126 126 #if !ENABLE(IOS_TOUCH_EVENTS) && ENABLE(TOUCH_EVENTS) -
trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm
r240702 r240882 2086 2086 } 2087 2087 2088 void WebPage::getPositionInformation(const InteractionInformationRequest& request, InteractionInformationAtPosition& info) 2089 { 2088 void WebPage::getPositionInformation(const InteractionInformationRequest& request, CompletionHandler<void(InteractionInformationAtPosition&&)>&& reply) 2089 { 2090 m_pendingSynchronousPositionInformationReply = WTFMove(reply); 2091 2092 auto information = positionInformation(request); 2093 2094 if (auto reply = WTFMove(m_pendingSynchronousPositionInformationReply)) 2095 reply(WTFMove(information)); 2096 } 2097 2098 InteractionInformationAtPosition WebPage::positionInformation(const InteractionInformationRequest& request) 2099 { 2100 InteractionInformationAtPosition info; 2090 2101 info.request = request; 2091 2102 … … 2263 2274 #endif 2264 2275 info.adjustedPointForNodeRespondingToClickEvents = adjustedPoint; 2276 2277 return info; 2265 2278 } 2266 2279 2267 2280 void WebPage::requestPositionInformation(const InteractionInformationRequest& request) 2268 2281 { 2269 InteractionInformationAtPosition info; 2270 2271 getPositionInformation(request, info); 2272 send(Messages::WebPageProxy::DidReceivePositionInformation(info)); 2282 send(Messages::WebPageProxy::DidReceivePositionInformation(positionInformation(request))); 2273 2283 } 2274 2284 -
trunk/Tools/ChangeLog
r240880 r240882 1 2019-02-01 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 [iOS] Consistent 1 sec hang when triggering modal alerts while handling synchronous touch events 4 https://bugs.webkit.org/show_bug.cgi?id=194140 5 <rdar://problem/47728098> 6 7 Reviewed by Tim Horton. 8 9 * WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl: 10 * WebKitTestRunner/InjectedBundle/TestRunner.cpp: 11 (WTR::TestRunner::setShouldDismissJavaScriptAlertsAsynchronously): 12 13 Add a new TestRunner hook to make modal JavaScript alerts dismiss asynchronously. This is used by the new layout 14 test to induce an IPC deadlock when presenting a modal alert during touch start. 15 16 * WebKitTestRunner/InjectedBundle/TestRunner.h: 17 * WebKitTestRunner/TestController.cpp: 18 (WTR::runJavaScriptAlert): 19 20 Add a client callback function for running JavaScript alerts. 21 22 (WTR::TestController::createOtherPage): 23 (WTR::TestController::generateContextConfiguration const): 24 25 Add a test option to disable IPC timeouts for a layout test. This forces the test to reliably time out without 26 the fix in this patch. 27 28 (WTR::TestController::createWebViewWithOptions): 29 30 Plumb TestOptions to generateContextConfiguration. 31 32 (WTR::TestController::resetPreferencesToConsistentValues): 33 (WTR::TestController::resetStateToConsistentValues): 34 (WTR::updateTestOptionsFromTestHeader): 35 (WTR::TestController::setShouldDismissJavaScriptAlertsAsynchronously): 36 (WTR::TestController::handleJavaScriptAlert): 37 * WebKitTestRunner/TestController.h: 38 * WebKitTestRunner/TestInvocation.cpp: 39 (WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle): 40 * WebKitTestRunner/TestOptions.h: 41 (WTR::TestOptions::hasSameInitializationOptions const): 42 1 43 2019-02-01 Chris Dumez <cdumez@apple.com> 2 44 -
trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl
r240689 r240882 330 330 void setOpenPanelFiles(object filesArray); 331 331 332 // Modal alerts 333 void setShouldDismissJavaScriptAlertsAsynchronously(boolean value); 334 332 335 void setWebRTCMDNSICECandidatesEnabled(boolean value); 333 336 void setWebRTCUnifiedPlanEnabled(boolean value); -
trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp
r240689 r240882 2716 2716 } 2717 2717 2718 void TestRunner::setShouldDismissJavaScriptAlertsAsynchronously(bool shouldDismissAsynchronously) 2719 { 2720 WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("ShouldDismissJavaScriptAlertsAsynchronously")); 2721 WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(shouldDismissAsynchronously)); 2722 WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr); 2723 } 2724 2718 2725 } // namespace WTR -
trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h
r240689 r240882 449 449 void setOpenPanelFiles(JSValueRef); 450 450 451 // Modal alerts 452 void setShouldDismissJavaScriptAlertsAsynchronously(bool); 453 451 454 void terminateNetworkProcess(); 452 455 void terminateServiceWorkerProcess(); -
trunk/Tools/WebKitTestRunner/TestController.cpp
r240775 r240882 238 238 { 239 239 TestController::singleton().handleUserMediaPermissionRequest(frame, userMediaDocumentOrigin, topLevelDocumentOrigin, permissionRequest); 240 } 241 242 static void runJavaScriptAlert(WKPageRef page, WKStringRef alertText, WKFrameRef frame, WKSecurityOriginRef securityOrigin, WKPageRunJavaScriptAlertResultListenerRef listener, const void *clientInfo) 243 { 244 TestController::singleton().handleJavaScriptAlert(listener); 240 245 } 241 246 … … 327 332 0, // mediaSessionMetadataDidChange 328 333 createOtherPage, 329 0, // runJavaScriptAlert334 runJavaScriptAlert, 330 335 0, // runJavaScriptConfirm 331 336 0, // runJavaScriptPrompt … … 443 448 } 444 449 445 WKRetainPtr<WKContextConfigurationRef> TestController::generateContextConfiguration( ) const450 WKRetainPtr<WKContextConfigurationRef> TestController::generateContextConfiguration(const TestOptions& options) const 446 451 { 447 452 auto configuration = adoptWK(WKContextConfigurationCreate()); 448 453 WKContextConfigurationSetInjectedBundlePath(configuration.get(), injectedBundlePath()); 449 454 WKContextConfigurationSetFullySynchronousModeIsAllowedForTesting(configuration.get(), true); 455 WKContextConfigurationSetIgnoreSynchronousMessagingTimeoutsForTesting(configuration.get(), options.ignoreSynchronousMessagingTimeoutsForTesting); 450 456 451 457 if (const char* dumpRenderTreeTemp = libraryPathForTesting()) { … … 535 541 void TestController::createWebViewWithOptions(const TestOptions& options) 536 542 { 537 auto contextConfiguration = generateContextConfiguration( );543 auto contextConfiguration = generateContextConfiguration(options); 538 544 539 545 WKRetainPtr<WKMutableArrayRef> overrideLanguages = adoptWK(WKMutableArrayCreate()); … … 615 621 0, // mediaSessionMetadataDidChange 616 622 createOtherPage, 617 0, // runJavaScriptAlert623 runJavaScriptAlert, 618 624 0, // runJavaScriptConfirm 619 625 0, // runJavaScriptPrompt … … 825 831 WKPreferencesSetWebSQLDisabled(preferences, false); 826 832 827 m_serverTrustEvaluationCallbackCallsCount = 0;828 829 833 platformResetPreferencesToConsistentValues(); 830 834 } … … 958 962 959 963 m_didReceiveServerRedirectForProvisionalNavigation = false; 964 m_serverTrustEvaluationCallbackCallsCount = 0; 965 m_shouldDismissJavaScriptAlertsAsynchronously = false; 960 966 961 967 // Reset main page back to about:blank … … 1279 1285 else if (key == "contentInset.top") 1280 1286 testOptions.contentInsetTop = std::stod(value); 1287 else if (key == "ignoreSynchronousMessagingTimeoutsForTesting") 1288 testOptions.ignoreSynchronousMessagingTimeoutsForTesting = parseBooleanTestHeaderValue(value); 1281 1289 pairStart = pairEnd + 1; 1282 1290 } … … 2331 2339 } 2332 2340 2341 void TestController::setShouldDismissJavaScriptAlertsAsynchronously(bool value) 2342 { 2343 m_shouldDismissJavaScriptAlertsAsynchronously = value; 2344 } 2345 2346 void TestController::handleJavaScriptAlert(WKPageRunJavaScriptAlertResultListenerRef listener) 2347 { 2348 if (!m_shouldDismissJavaScriptAlertsAsynchronously) { 2349 WKPageRunJavaScriptAlertResultListenerCall(listener); 2350 return; 2351 } 2352 2353 WKRetain(listener); 2354 callOnMainThread([listener] { 2355 WKPageRunJavaScriptAlertResultListenerCall(listener); 2356 WKRelease(listener); 2357 }); 2358 } 2359 2333 2360 class OriginSettings : public RefCounted<OriginSettings> { 2334 2361 public: -
trunk/Tools/WebKitTestRunner/TestController.h
r240689 r240882 285 285 uint64_t serverTrustEvaluationCallbackCallsCount() const { return m_serverTrustEvaluationCallbackCallsCount; } 286 286 287 void setShouldDismissJavaScriptAlertsAsynchronously(bool); 288 void handleJavaScriptAlert(WKPageRunJavaScriptAlertResultListenerRef); 289 287 290 private: 288 291 WKRetainPtr<WKPageConfigurationRef> generatePageConfiguration(WKContextConfigurationRef); 289 WKRetainPtr<WKContextConfigurationRef> generateContextConfiguration( ) const;292 WKRetainPtr<WKContextConfigurationRef> generateContextConfiguration(const TestOptions&) const; 290 293 void initialize(int argc, const char* argv[]); 291 294 void createWebViewWithOptions(const TestOptions&); … … 540 543 541 544 uint64_t m_serverTrustEvaluationCallbackCallsCount { 0 }; 545 bool m_shouldDismissJavaScriptAlertsAsynchronously { false }; 542 546 }; 543 547 -
trunk/Tools/WebKitTestRunner/TestInvocation.cpp
r240689 r240882 1540 1540 } 1541 1541 1542 if (WKStringIsEqualToUTF8CString(messageName, "ShouldDismissJavaScriptAlertsAsynchronously")) { 1543 ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID()); 1544 WKBooleanRef value = static_cast<WKBooleanRef>(messageBody); 1545 TestController::singleton().setShouldDismissJavaScriptAlertsAsynchronously(WKBooleanGetValue(value)); 1546 return nullptr; 1547 } 1548 1542 1549 ASSERT_NOT_REACHED(); 1543 1550 return nullptr; -
trunk/Tools/WebKitTestRunner/TestOptions.h
r240139 r240882 69 69 bool editable { false }; 70 70 bool enableUndoManagerAPI { false }; 71 bool ignoreSynchronousMessagingTimeoutsForTesting { false }; 71 72 72 73 double contentInsetTop { 0 }; … … 117 118 || editable != options.editable 118 119 || enableUndoManagerAPI != options.enableUndoManagerAPI 119 || contentInsetTop != options.contentInsetTop) 120 || contentInsetTop != options.contentInsetTop 121 || ignoreSynchronousMessagingTimeoutsForTesting != options.ignoreSynchronousMessagingTimeoutsForTesting) 120 122 return false; 121 123
Note: See TracChangeset
for help on using the changeset viewer.