⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 279310 in webkit


Ignore:
Timestamp:
Jun 26, 2021, 7:06:45 PM (5 years ago)
Author:
Wenson Hsieh
Message:

[iOS] Safari sometimes hangs under sync IPC in -[WKWebView _setSuppressSoftwareKeyboard:]
​https://bugs.webkit.org/show_bug.cgi?id=227424
rdar://79745385

Reviewed by Tim Horton.

When activating streamlined AutoFill, Safari calls UIKit SPI (-_setSuppressSoftwareKeyboard:) on WKWebView to
ensure that the normal software keyboard doesn't briefly appear instead of the AutoFill input view; after
requesting AutoFill credentials, Safari then stops suppressing the software keyboard by setting the SPI property
back to NO. In WebKit, we override -[WKWebView _setSuppressSoftwareKeyboard:], such that WKContentView's
keyboard suppression state follows the web view's state (this is necessary, since WKContentView is the actual
-firstResponder when editing focused text inputs). However, when changing software keyboard suppression from
YES to NO, UIKit reloads input views and (in the process) calls into
-requestAutocorrectionContextWithCompletionHandler:, which then makes a sync IPC call into the web process.

To avoid this sync IPC call, we refactor the implementation of -[WKWebView _setSuppressSoftwareKeyboard:],
such that we don't immediately attempt to unsuppress the software keyboard by calling into WKContentView.
Instead, we asynchronously request an autocorrection context from the web process, and then call
-[WKContentView _setSuppressSoftwareKeyboard:NO] after the autocorrection context request completes (using
the last known autocorrection context data in the UI process rather than making a sync IPC call).

  • UIProcess/API/ios/WKWebViewIOS.mm:

(-[WKWebView _setSuppressSoftwareKeyboard:]):

Call into -updateSoftwareKeyboardSuppressionStateFromWebView below.

  • UIProcess/ios/WKContentViewInteraction.h:
  • UIProcess/ios/WKContentViewInteraction.mm:

(-[WKContentView cleanUpInteraction]):

Invoke -unsuppressSoftwareKeyboardUsingLastAutocorrectionContextIfNeeded to ensure that we stop software
keyboard suppression if the web process terminates while we're waiting for autocorrection context data to
arrive.

(-[WKContentView requestAutocorrectionContextWithCompletionHandler:]):
(-[WKContentView _handleAutocorrectionContext:]):
(-[WKContentView updateSoftwareKeyboardSuppressionStateFromWebView]):

Add a new helper that keeps WKContentView's software keyboard suppression state in sync with the WKWebView's
software keyboard suppression state. In the case where we're supressing the software keyboard, we can simply
call into -[WKContentView _setSuppressSoftwareKeyboard:] right away, since UIKit won't try to request an
autocorrection context.

However, in the case where we're unsuppressing the software keyboard, set a new flag, don't immediately forward
the call to WKContentView. Instead, set the _unsuppressSoftwareKeyboardAfterNextAutocorrectionContextUpdate
flag to YES and call into WebPageProxy to request an updated autocorrection context. Upon receiving the response
in -[WKContentView _handleAutocorrectionContext:], we then unset the flag and unsuppress the software keyboard
(crucially, using _lastAutocorrectionContext instead of making a synchronous call back to the web content
process).

(-[WKContentView unsuppressSoftwareKeyboardUsingLastAutocorrectionContextIfNeeded]):

Location:
trunk/Source/WebKit
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r279305 r279310  
     12021-06-26  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        [iOS] Safari sometimes hangs under sync IPC in `-[WKWebView _setSuppressSoftwareKeyboard:]`
     4        https://bugs.webkit.org/show_bug.cgi?id=227424
     5        rdar://79745385
     6
     7        Reviewed by Tim Horton.
     8
     9        When activating streamlined AutoFill, Safari calls UIKit SPI (`-_setSuppressSoftwareKeyboard:`) on WKWebView to
     10        ensure that the normal software keyboard doesn't briefly appear instead of the AutoFill input view; after
     11        requesting AutoFill credentials, Safari then stops suppressing the software keyboard by setting the SPI property
     12        back to NO. In WebKit, we override `-[WKWebView _setSuppressSoftwareKeyboard:]`, such that WKContentView's
     13        keyboard suppression state follows the web view's state (this is necessary, since WKContentView is the actual
     14        `-firstResponder` when editing focused text inputs). However, when changing software keyboard suppression from
     15        YES to NO, UIKit reloads input views and (in the process) calls into
     16        `-requestAutocorrectionContextWithCompletionHandler:`, which then makes a sync IPC call into the web process.
     17
     18        To avoid this sync IPC call, we refactor the implementation of `-[WKWebView _setSuppressSoftwareKeyboard:]`,
     19        such that we don't immediately attempt to unsuppress the software keyboard by calling into WKContentView.
     20        Instead, we asynchronously request an autocorrection context from the web process, and then call
     21        `-[WKContentView _setSuppressSoftwareKeyboard:NO]` after the autocorrection context request completes (using
     22        the last known autocorrection context data in the UI process rather than making a sync IPC call).
     23
     24        * UIProcess/API/ios/WKWebViewIOS.mm:
     25        (-[WKWebView _setSuppressSoftwareKeyboard:]):
     26
     27        Call into `-updateSoftwareKeyboardSuppressionStateFromWebView` below.
     28
     29        * UIProcess/ios/WKContentViewInteraction.h:
     30        * UIProcess/ios/WKContentViewInteraction.mm:
     31        (-[WKContentView cleanUpInteraction]):
     32
     33        Invoke `-unsuppressSoftwareKeyboardUsingLastAutocorrectionContextIfNeeded` to ensure that we stop software
     34        keyboard suppression if the web process terminates while we're waiting for autocorrection context data to
     35        arrive.
     36
     37        (-[WKContentView requestAutocorrectionContextWithCompletionHandler:]):
     38        (-[WKContentView _handleAutocorrectionContext:]):
     39        (-[WKContentView updateSoftwareKeyboardSuppressionStateFromWebView]):
     40
     41        Add a new helper that keeps WKContentView's software keyboard suppression state in sync with the WKWebView's
     42        software keyboard suppression state. In the case where we're supressing the software keyboard, we can simply
     43        call into `-[WKContentView _setSuppressSoftwareKeyboard:]` right away, since UIKit won't try to request an
     44        autocorrection context.
     45
     46        However, in the case where we're unsuppressing the software keyboard, set a new flag, don't immediately forward
     47        the call to WKContentView. Instead, set the `_unsuppressSoftwareKeyboardAfterNextAutocorrectionContextUpdate`
     48        flag to YES and call into WebPageProxy to request an updated autocorrection context. Upon receiving the response
     49        in `-[WKContentView _handleAutocorrectionContext:]`, we then unset the flag and unsuppress the software keyboard
     50        (crucially, using `_lastAutocorrectionContext` instead of making a synchronous call back to the web content
     51        process).
     52
     53        (-[WKContentView unsuppressSoftwareKeyboardUsingLastAutocorrectionContextIfNeeded]):
     54
    1552021-06-25  Brent Fulgham  <bfulgham@apple.com>
    256
  • trunk/Source/WebKit/UIProcess/API/ios/WKWebViewIOS.mm

    r279245 r279310  
    30843084- (void)_setSuppressSoftwareKeyboard:(BOOL)suppressSoftwareKeyboard
    30853085{
    3086     [super _setSuppressSoftwareKeyboard:suppressSoftwareKeyboard];
    3087     [_contentView _setSuppressSoftwareKeyboard:suppressSoftwareKeyboard];
     3086    super._suppressSoftwareKeyboard = suppressSoftwareKeyboard;
     3087    [_contentView updateSoftwareKeyboardSuppressionStateFromWebView];
    30883088}
    30893089
  • trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h

    r278997 r279310  
    442442    BOOL _isBlurringFocusedElement;
    443443    BOOL _isRelinquishingFirstResponderToFocusedElement;
     444    BOOL _unsuppressSoftwareKeyboardAfterNextAutocorrectionContextUpdate;
     445    BOOL _isUnsuppressingSoftwareKeyboardUsingLastAutocorrectionContext;
    444446
    445447    BOOL _focusRequiresStrongPasswordAssistance;
    … …  
    710712- (void)setContinuousSpellCheckingEnabled:(BOOL)enabled;
    711713
     714- (void)updateSoftwareKeyboardSuppressionStateFromWebView;
     715
    712716#if USE(UICONTEXTMENU)
    713717- (UIView *)textEffectsWindow;
  • trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm

    r279197 r279310  
    11811181    [self _removeContainerForDragPreviews];
    11821182    [self _removeContainerForDropPreviews];
     1183    [self unsuppressSoftwareKeyboardUsingLastAutocorrectionContextIfNeeded];
    11831184
    11841185    _hasSetUpInteractions = NO;
    … …  
    46244625    }
    46254626
    4626     if (_page->isRunningModalJavaScriptDialog() || _domPasteRequestHandler) {
     4627    bool respondWithLastKnownAutocorrectionContext = ([&] {
     4628        if (_page->isRunningModalJavaScriptDialog())
     4629            return true;
     4630
     4631        if (_domPasteRequestHandler)
     4632            return true;
     4633
     4634        if (_isUnsuppressingSoftwareKeyboardUsingLastAutocorrectionContext)
     4635            return true;
     4636
     4637        return false;
     4638    })();
     4639
     4640    if (respondWithLastKnownAutocorrectionContext) {
    46274641        completionHandler([WKAutocorrectionContext autocorrectionContextWithWebContext:_lastAutocorrectionContext]);
    46284642        return;
    … …  
    46504664    _lastAutocorrectionContext = context;
    46514665    [self _invokePendingAutocorrectionContextHandler:[WKAutocorrectionContext autocorrectionContextWithWebContext:context]];
     4666    [self unsuppressSoftwareKeyboardUsingLastAutocorrectionContextIfNeeded];
     4667}
     4668
     4669- (void)updateSoftwareKeyboardSuppressionStateFromWebView
     4670{
     4671    BOOL webViewIsSuppressingSoftwareKeyboard = [_webView _suppressSoftwareKeyboard];
     4672    if (webViewIsSuppressingSoftwareKeyboard) {
     4673        _unsuppressSoftwareKeyboardAfterNextAutocorrectionContextUpdate = NO;
     4674        self._suppressSoftwareKeyboard = webViewIsSuppressingSoftwareKeyboard;
     4675        return;
     4676    }
     4677
     4678    if (self._suppressSoftwareKeyboard == webViewIsSuppressingSoftwareKeyboard)
     4679        return;
     4680
     4681    if (!std::exchange(_unsuppressSoftwareKeyboardAfterNextAutocorrectionContextUpdate, YES))
     4682        _page->requestAutocorrectionContext();
     4683}
     4684
     4685- (void)unsuppressSoftwareKeyboardUsingLastAutocorrectionContextIfNeeded
     4686{
     4687    if (!std::exchange(_unsuppressSoftwareKeyboardAfterNextAutocorrectionContextUpdate, NO))
     4688        return;
     4689
     4690    SetForScope<BOOL> unsuppressSoftwareKeyboardScope { _isUnsuppressingSoftwareKeyboardUsingLastAutocorrectionContext, YES };
     4691    self._suppressSoftwareKeyboard = NO;
    46524692}
    46534693
Note: See TracChangeset for help on using the changeset viewer.