Changeset 252035 in webkit
- Timestamp:
- Nov 4, 2019 8:05:07 PM (4 years ago)
- Location:
- trunk
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebKit/ChangeLog
r252030 r252035 1 2019-11-04 Jiewen Tan <jiewen_tan@apple.com> 2 3 [WebAuthn] Guard against unexpected -[_WKWebAuthenticationPanel cancel] 4 https://bugs.webkit.org/show_bug.cgi?id=203830 5 <rdar://problem/56797134> 6 7 Reviewed by Brent Fulgham . 8 9 -[_WKWebAuthenticationPanel cancel] was only expected to be called on behalf of an 10 explicit user cancel from the UI. However, clients may call it in different other 11 unexpected scenarios as well. We should guard against that. 12 13 To do so, two counter ways are implemented: 14 1) AuthenticatorManager::cancelRequest is changed to invoke the pending request if there 15 is no GlobalFrameID. This case can only be reached via calling -[_WKWebAuthenticationPanel cancel] 16 before AuthenticatorManager::cancelRequest. 17 2) WebAuthenticationPanelClient::updatePanel and WebAuthenticationPanelClient::dismissPanel 18 will call delegate methods in the next run loop to prevent -[_WKWebAuthenticationPanel cancel] 19 being called in the delegates. 20 21 Covered by new API tests. 22 23 * UIProcess/WebAuthentication/AuthenticatorManager.cpp: 24 (WebKit::AuthenticatorManager::cancelRequest): 25 (WebKit::AuthenticatorManager::createService const): 26 (WebKit::AuthenticatorManager::invokePendingCompletionHandler): 27 * UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.mm: 28 (WebKit::WebAuthenticationPanelClient::updatePanel const): 29 (WebKit::WebAuthenticationPanelClient::dismissPanel const): 30 1 31 2019-11-04 Ross Kirsling <ross.kirsling@sony.com> 2 32 -
trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp
r251762 r252035 176 176 } 177 177 178 void AuthenticatorManager::cancelRequest(const WebCore::PageIdentifier& pageID, const Optional<FrameIdentifier>& frameID)178 void AuthenticatorManager::cancelRequest(const PageIdentifier& pageID, const Optional<FrameIdentifier>& frameID) 179 179 { 180 180 if (!m_pendingCompletionHandler) 181 181 return; 182 ASSERT(m_pendingRequestData.frameID); 183 if (m_pendingRequestData.frameID->pageID != pageID) 184 return; 185 if (frameID && frameID != m_pendingRequestData.frameID->frameID) 186 return; 182 if (auto pendingFrameID = m_pendingRequestData.frameID) { 183 if (pendingFrameID->pageID != pageID) 184 return; 185 if (frameID && frameID != pendingFrameID->frameID) 186 return; 187 } 187 188 invokePendingCompletionHandler(ExceptionData { NotAllowedError, "Operation timed out."_s }); 188 189 clearState(); … … 195 196 void AuthenticatorManager::cancelRequest(const API::WebAuthenticationPanel& panel) 196 197 { 198 RELEASE_ASSERT(RunLoop::isMain()); 197 199 if (!m_pendingCompletionHandler || m_pendingRequestData.panel.get() != &panel) 198 200 return; … … 268 270 } 269 271 270 UniqueRef<AuthenticatorTransportService> AuthenticatorManager::createService( WebCore::AuthenticatorTransport transport, AuthenticatorTransportService::Observer& observer) const272 UniqueRef<AuthenticatorTransportService> AuthenticatorManager::createService(AuthenticatorTransport transport, AuthenticatorTransportService::Observer& observer) const 271 273 { 272 274 return AuthenticatorTransportService::create(transport, observer); … … 344 346 { 345 347 if (auto *panel = m_pendingRequestData.panel.get()) { 346 WTF::switchOn(respond, [&](const WebCore::PublicKeyCredentialData&) {348 WTF::switchOn(respond, [&](const PublicKeyCredentialData&) { 347 349 panel->client().dismissPanel(WebAuthenticationResult::Succeeded); 348 }, [&](const WebCore::ExceptionData&) {350 }, [&](const ExceptionData&) { 349 351 panel->client().dismissPanel(WebAuthenticationResult::Failed); 350 352 }); … … 352 354 m_pendingCompletionHandler(WTFMove(respond)); 353 355 } 354 355 356 356 357 void AuthenticatorManager::resetState() -
trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.mm
r251317 r252035 31 31 #import "WebAuthenticationFlags.h" 32 32 #import "_WKWebAuthenticationPanel.h" 33 #import <wtf/RunLoop.h> 33 34 34 35 namespace WebKit { … … 59 60 void WebAuthenticationPanelClient::updatePanel(WebAuthenticationStatus status) const 60 61 { 61 if (!m_delegateMethods.panelUpdateWebAuthenticationPanel) 62 return; 62 // Call delegates in the next run loop to prevent clients' reentrance that would potentially modify the state 63 // of the current run loop in unexpected ways. 64 RunLoop::main().dispatch([weakThis = makeWeakPtr(*this), this, status] { 65 if (!weakThis) 66 return; 63 67 64 auto delegate = m_delegate.get(); 65 if (!delegate) 66 return; 68 if (!m_delegateMethods.panelUpdateWebAuthenticationPanel) 69 return; 67 70 68 [delegate panel:m_panel updateWebAuthenticationPanel:wkWebAuthenticationPanelUpdate(status)]; 71 auto delegate = m_delegate.get(); 72 if (!delegate) 73 return; 74 75 [delegate panel:m_panel updateWebAuthenticationPanel:wkWebAuthenticationPanelUpdate(status)]; 76 }); 69 77 } 70 78 … … 83 91 void WebAuthenticationPanelClient::dismissPanel(WebAuthenticationResult result) const 84 92 { 85 if (!m_delegateMethods.panelDismissWebAuthenticationPanelWithResult) 86 return; 93 // Call delegates in the next run loop to prevent clients' reentrance that would potentially modify the state 94 // of the current run loop in unexpected ways. 95 RunLoop::main().dispatch([weakThis = makeWeakPtr(*this), this, result] { 96 if (!weakThis) 97 return; 87 98 88 auto delegate = m_delegate.get(); 89 if (!delegate) 90 return; 99 if (!m_delegateMethods.panelDismissWebAuthenticationPanelWithResult) 100 return; 91 101 92 [delegate panel:m_panel dismissWebAuthenticationPanelWithResult:wkWebAuthenticationResult(result)]; 102 auto delegate = m_delegate.get(); 103 if (!delegate) 104 return; 105 106 [delegate panel:m_panel dismissWebAuthenticationPanelWithResult:wkWebAuthenticationResult(result)]; 107 }); 93 108 } 94 109 -
trunk/Tools/ChangeLog
r252031 r252035 1 2019-11-04 Jiewen Tan <jiewen_tan@apple.com> 2 3 [WebAuthn] Guard against unexpected -[_WKWebAuthenticationPanel cancel] 4 https://bugs.webkit.org/show_bug.cgi?id=203830 5 <rdar://problem/56797134> 6 7 Reviewed by Brent Fulgham . 8 9 * TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm: 10 (-[TestWebAuthenticationPanelDelegate panel:updateWebAuthenticationPanel:]): 11 (-[TestWebAuthenticationPanelDelegate panel:dismissWebAuthenticationPanelWithResult:]): 12 (TestWebKitAPI::TEST): 13 1 14 2019-11-04 Jonathan Bedard <jbedard@apple.com> 2 15 -
trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm
r251762 r252035 45 45 static bool webAuthenticationPanelUpdateMultipleNFCTagsPresent = false; 46 46 static bool webAuthenticationPanelUpdateNoCredentialsFound = false; 47 static bool webAuthenticationPanelCancelImmediately = false; 47 48 48 49 @interface TestWebAuthenticationPanelDelegate : NSObject <_WKWebAuthenticationPanelDelegate> … … 54 55 { 55 56 ASSERT_NE(panel, nil); 57 if (webAuthenticationPanelCancelImmediately) 58 [panel cancel]; 59 56 60 if (update == _WKWebAuthenticationPanelUpdateMultipleNFCTagsPresent) { 57 61 webAuthenticationPanelUpdateMultipleNFCTagsPresent = true; … … 67 71 { 68 72 ASSERT_NE(panel, nil); 73 if (webAuthenticationPanelCancelImmediately) 74 [panel cancel]; 75 69 76 if (result == _WKWebAuthenticationResultFailed) { 70 77 webAuthenticationPanelFailed = true; … … 190 197 webAuthenticationPanelFailed = false; 191 198 webAuthenticationPanelSucceded = false; 199 webAuthenticationPanelCancelImmediately = false; 192 200 } 193 201 … … 681 689 #endif 682 690 691 TEST(WebAuthenticationPanel, PanelHidCancelReloadNoCrash) 692 { 693 reset(); 694 RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-get-assertion-hid-cancel" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; 695 696 auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES]; 697 [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()]; 698 699 auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]); 700 auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]); 701 [webView setUIDelegate:delegate.get()]; 702 703 [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; 704 Util::run(&webAuthenticationPanelRan); 705 [[delegate panel] cancel]; 706 [webView reload]; 707 [webView waitForMessage:@"Operation timed out."]; 708 } 709 710 TEST(WebAuthenticationPanel, PanelHidSuccessCancelNoCrash) 711 { 712 reset(); 713 RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-get-assertion-hid" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; 714 715 auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES]; 716 [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()]; 717 718 auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]); 719 auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]); 720 [webView setUIDelegate:delegate.get()]; 721 webAuthenticationPanelCancelImmediately = true; 722 723 [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; 724 [webView waitForMessage:@"Succeeded!"]; 725 } 726 727 TEST(WebAuthenticationPanel, PanelHidCtapNoCredentialsFoundCancelNoCrash) 728 { 729 reset(); 730 RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-get-assertion-hid-no-credentials" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; 731 732 auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES]; 733 [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()]; 734 735 auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]); 736 auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]); 737 [webView setUIDelegate:delegate.get()]; 738 webAuthenticationPanelCancelImmediately = true; 739 740 [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; 741 Util::run(&webAuthenticationPanelUpdateNoCredentialsFound); 742 } 743 683 744 } // namespace TestWebKitAPI 684 745
Note: See TracChangeset
for help on using the changeset viewer.