Changeset 261812 in webkit


Ignore:
Timestamp:
May 18, 2020 8:23:09 AM (4 years ago)
Author:
Wenson Hsieh
Message:

[iOS] Unexpected capitalization of next word after repositioning caret
https://bugs.webkit.org/show_bug.cgi?id=211969
<rdar://problem/62605526>

Reviewed by Alex Christensen.

Source/WebKit:

The changes in r242551 refactored synchronous autocorrection context request logic such that it uses
waitForAndDispatchImmediately instead of sendSync, in order to make it interruptible by unbounded sync IPC
sent from the web process. If the UI process receives sync IPC, it will immediately cancel the autocorrection
context request (returning an empty context), before proceeding to handle the incoming sync IPC.

In a more recent version of iOS, other changes around spellchecking have caused the synchronous message
WebPageProxy::checkTextOfParagraph to be sent from the web process in such a way that it now frequently
coincides with the synchronous autocorrection context request being sent from the UI process. The result is that
we now frequently end up cancelling autocorrection requests early by responding with empty contexts. This
manifests in the keyboard sometimes losing information about its autocapitalization context and believing that
it is in an empty text field, which reverts to default autocorrection suggestions and autocapitalizes the
software keyboard.

To fix this, instead of using the InterruptWaitingIfSyncMessageArrives option when waiting for the IPC
response, add and use a new flag that allows us to process an incoming sync IPC message if we're waiting for
the sync message response. We use this new IPC flag when waiting synchronously for HandleAutocorrectionContext.

Test: editing/selection/ios/changing-selection-does-not-trigger-autocapitalization.html

  • Platform/IPC/Connection.cpp:

(IPC::Connection::processIncomingMessage):

If the new IPC flag is set and the incoming message is synchronous, allow it to immediately dispatch the sync
message by enqueueing it and then waking up m_waitForMessageCondition so that it can process the message.

  • Platform/IPC/Connection.h:
  • Platform/spi/ios/UIKitSPI.h:
  • UIProcess/ios/WKContentViewInteraction.mm:

(-[WKContentView requestAutocorrectionContextWithCompletionHandler:]):

Use DispatchIncomingSyncMessagesWhileWaiting instead of InterruptWaitingIfSyncMessageArrives.

Tools:

Add a new UIScriptController hook to query whether or not the software keyboard is in shifted state.

  • TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
  • TestRunnerShared/UIScriptContext/UIScriptController.h:

(WTR::UIScriptController::keyboardIsAutomaticallyShifted const):

  • TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm:

Adjust a couple of API tests that copy and paste back-to-back, so that they wait for the copy to finish before
attempting to paste.

  • WebKitTestRunner/ios/UIScriptControllerIOS.h:
  • WebKitTestRunner/ios/UIScriptControllerIOS.mm:

(WTR::UIScriptControllerIOS::keyboardIsAutomaticallyShifted const):

LayoutTests:

Add a new layout test to verify that the keyboard does not automatically shift (i.e. autocapitalize) when
changing selection quickly inside a text field.

  • editing/selection/ios/changing-selection-does-not-trigger-autocapitalization-expected.txt: Added.
  • editing/selection/ios/changing-selection-does-not-trigger-autocapitalization.html: Added.
  • resources/ui-helper.js:

(window.UIHelper.keyboardIsAutomaticallyShifted):

Location:
trunk
Files:
2 added
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r261809 r261812  
     12020-05-18  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        [iOS] Unexpected capitalization of next word after repositioning caret
     4        https://bugs.webkit.org/show_bug.cgi?id=211969
     5        <rdar://problem/62605526>
     6
     7        Reviewed by Alex Christensen.
     8
     9        Add a new layout test to verify that the keyboard does not automatically shift (i.e. autocapitalize) when
     10        changing selection quickly inside a text field.
     11
     12        * editing/selection/ios/changing-selection-does-not-trigger-autocapitalization-expected.txt: Added.
     13        * editing/selection/ios/changing-selection-does-not-trigger-autocapitalization.html: Added.
     14        * resources/ui-helper.js:
     15        (window.UIHelper.keyboardIsAutomaticallyShifted):
     16
    1172020-05-18  Diego Pino Garcia  <dpino@igalia.com>
    218
  • trunk/LayoutTests/resources/ui-helper.js

    r261056 r261812  
    306306        return new Promise((resolve) => {
    307307            testRunner.runUIScript(`uiController.toggleCapsLock(() => uiController.uiScriptComplete());`, resolve);
     308        });
     309    }
     310
     311    static keyboardIsAutomaticallyShifted()
     312    {
     313        return new Promise(resolve => {
     314            testRunner.runUIScript(`uiController.keyboardIsAutomaticallyShifted`, result => resolve(result === "true"));
    308315        });
    309316    }
  • trunk/Source/WebKit/ChangeLog

    r261811 r261812  
     12020-05-18  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        [iOS] Unexpected capitalization of next word after repositioning caret
     4        https://bugs.webkit.org/show_bug.cgi?id=211969
     5        <rdar://problem/62605526>
     6
     7        Reviewed by Alex Christensen.
     8
     9        The changes in r242551 refactored synchronous autocorrection context request logic such that it uses
     10        `waitForAndDispatchImmediately` instead of `sendSync`, in order to make it interruptible by unbounded sync IPC
     11        sent from the web process. If the UI process receives sync IPC, it will immediately cancel the autocorrection
     12        context request (returning an empty context), before proceeding to handle the incoming sync IPC.
     13
     14        In a more recent version of iOS, other changes around spellchecking have caused the synchronous message
     15        `WebPageProxy::checkTextOfParagraph` to be sent from the web process in such a way that it now frequently
     16        coincides with the synchronous autocorrection context request being sent from the UI process. The result is that
     17        we now frequently end up cancelling autocorrection requests early by responding with empty contexts. This
     18        manifests in the keyboard sometimes losing information about its autocapitalization context and believing that
     19        it is in an empty text field, which reverts to default autocorrection suggestions and autocapitalizes the
     20        software keyboard.
     21
     22        To fix this, instead of using the `InterruptWaitingIfSyncMessageArrives` option when waiting for the IPC
     23        response, add and use a new flag that allows us to process an incoming sync IPC message if we're waiting for
     24        the sync message response. We use this new IPC flag when waiting synchronously for HandleAutocorrectionContext.
     25
     26        Test: editing/selection/ios/changing-selection-does-not-trigger-autocapitalization.html
     27
     28        * Platform/IPC/Connection.cpp:
     29        (IPC::Connection::processIncomingMessage):
     30
     31        If the new IPC flag is set and the incoming message is synchronous, allow it to immediately dispatch the sync
     32        message by enqueueing it and then waking up `m_waitForMessageCondition` so that it can process the message.
     33
     34        * Platform/IPC/Connection.h:
     35        * Platform/spi/ios/UIKitSPI.h:
     36        * UIProcess/ios/WKContentViewInteraction.mm:
     37        (-[WKContentView requestAutocorrectionContextWithCompletionHandler:]):
     38
     39        Use `DispatchIncomingSyncMessagesWhileWaiting` instead of `InterruptWaitingIfSyncMessageArrives`.
     40
    1412020-05-18  Lauro Moura  <lmoura@igalia.com>
    242
  • trunk/Source/WebKit/Platform/IPC/Connection.cpp

    r261254 r261812  
    755755            }
    756756
     757            if (m_waitingForMessage->waitForOptions.contains(WaitForOption::DispatchIncomingSyncMessagesWhileWaiting) && message->isSyncMessage() && SyncMessageState::singleton().processIncomingMessage(*this, message)) {
     758                m_waitForMessageCondition.notifyOne();
     759                return;
     760            }
     761
    757762            if (m_waitingForMessage->waitForOptions.contains(WaitForOption::InterruptWaitingIfSyncMessageArrives) && message->isSyncMessage()) {
    758763                m_waitingForMessage->messageWaitingInterrupted = true;
  • trunk/Source/WebKit/Platform/IPC/Connection.h

    r261254 r261812  
    7575    // Use this to make waitForMessage be interrupted immediately by any incoming sync messages.
    7676    InterruptWaitingIfSyncMessageArrives = 1 << 0,
     77    DispatchIncomingSyncMessagesWhileWaiting = 1 << 1,
    7778};
    7879
  • trunk/Source/WebKit/Platform/spi/ios/UIKitSPI.h

    r261658 r261812  
    322322- (void)addInputString:(NSString *)string withFlags:(NSUInteger)flags withInputManagerHint:(NSString *)hint;
    323323- (BOOL)autocorrectSpellingEnabled;
     324- (BOOL)isAutoShifted;
    324325- (void)deleteFromInput;
    325326- (void)deleteFromInputWithFlags:(NSUInteger)flags;
  • trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm

    r261776 r261812  
    42394239
    42404240    if (useSyncRequest) {
    4241         _page->process().connection()->waitForAndDispatchImmediately<Messages::WebPageProxy::HandleAutocorrectionContext>(_page->webPageID(), 1_s, IPC::WaitForOption::InterruptWaitingIfSyncMessageArrives);
     4241        _page->process().connection()->waitForAndDispatchImmediately<Messages::WebPageProxy::HandleAutocorrectionContext>(_page->webPageID(), 1_s, IPC::WaitForOption::DispatchIncomingSyncMessagesWhileWaiting);
    42424242        [self _cancelPendingAutocorrectionContextHandler];
    42434243    }
  • trunk/Tools/ChangeLog

    r261800 r261812  
     12020-05-18  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        [iOS] Unexpected capitalization of next word after repositioning caret
     4        https://bugs.webkit.org/show_bug.cgi?id=211969
     5        <rdar://problem/62605526>
     6
     7        Reviewed by Alex Christensen.
     8
     9        Add a new UIScriptController hook to query whether or not the software keyboard is in shifted state.
     10
     11        * TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
     12        * TestRunnerShared/UIScriptContext/UIScriptController.h:
     13        (WTR::UIScriptController::keyboardIsAutomaticallyShifted const):
     14        * TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm:
     15
     16        Adjust a couple of API tests that copy and paste back-to-back, so that they wait for the copy to finish before
     17        attempting to paste.
     18
     19        * WebKitTestRunner/ios/UIScriptControllerIOS.h:
     20        * WebKitTestRunner/ios/UIScriptControllerIOS.mm:
     21        (WTR::UIScriptControllerIOS::keyboardIsAutomaticallyShifted const):
     22
    1232020-05-18  Carlos Garcia Campos  <cgarcia@igalia.com>
    224
  • trunk/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl

    r260402 r261812  
    8080    void toggleCapsLock(object callback);
    8181    void setContinuousSpellCheckingEnabled(boolean enabled);
     82
     83    readonly attribute boolean keyboardIsAutomaticallyShifted;
    8284
    8385    void rawKeyDown(DOMString key);
  • trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.h

    r260402 r261812  
    164164    virtual void toggleCapsLock(JSValueRef callback) { notImplemented(); }
    165165    virtual void setContinuousSpellCheckingEnabled(bool) { notImplemented(); }
     166    virtual bool keyboardIsAutomaticallyShifted() const
     167    {
     168        notImplemented();
     169        return false;
     170    }
    166171
    167172    virtual void rawKeyDown(JSStringRef) { notImplemented(); }
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm

    r261638 r261812  
    11551155    }
    11561156    [webView selectAll:nil];
    1157     [webView _executeEditCommand:@"Copy" argument:nil completion:nil];
     1157    [webView _synchronouslyExecuteEditCommand:@"Copy" argument:nil];
    11581158    [webView evaluateJavaScript:@"getSelection().collapseToEnd()" completionHandler:nil];
    11591159    {
     
    11971197    }
    11981198    [webView selectAll:nil];
    1199     [webView _executeEditCommand:@"Copy" argument:nil completion:nil];
     1199    [webView _synchronouslyExecuteEditCommand:@"Copy" argument:nil];
    12001200    [webView evaluateJavaScript:@"getSelection().collapseToEnd()" completionHandler:nil];
    12011201    {
  • trunk/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.h

    r260402 r261812  
    137137    void setKeyboardInputModeIdentifier(JSStringRef) override;
    138138    void toggleCapsLock(JSValueRef) override;
     139    bool keyboardIsAutomaticallyShifted() const override;
    139140    JSObjectRef attachmentInfo(JSStringRef) override;
    140141    UIView *platformContentView() const override;
  • trunk/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm

    r261658 r261812  
    12061206}
    12071207
     1208bool UIScriptControllerIOS::keyboardIsAutomaticallyShifted() const
     1209{
     1210    return UIKeyboardImpl.activeInstance.isAutoShifted;
     1211}
     1212
    12081213JSObjectRef UIScriptControllerIOS::attachmentInfo(JSStringRef jsAttachmentIdentifier)
    12091214{
Note: See TracChangeset for help on using the changeset viewer.