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

Changeset 282247 in webkit


Ignore:
Timestamp:
Sep 9, 2021, 5:15:44 PM (5 years ago)
Author:
Wenson Hsieh
Message:

[Mac Catalyst] Korean characters do not combine correctly in editable fields in WKWebView
​https://bugs.webkit.org/show_bug.cgi?id=230122
rdar://79062204

Reviewed by Devin Rousso.

Source/WebKit:

When using Korean input method (e.g. 2-set Korean) to type into editable input fields in WKWebView on Catalyst,
character combination is broken. While this is partly due to a WebKit-specific UIKit bug (see rdar://82938391),
this is also broken due to the fact that WKContentView reports a UIWKAutocorrectionContext with a
contextBeforeSelection that starts with a newline (\n); this causes UIKit to believe that the text selection
range when a single character has been typed is NSRange { 2, 0 } instead of NSRange { 1, 0 }, due to the
extra newline. This subsequently causes character combination logic to proceed with a range that is off by one
character, which leads to characters not being combined (or the wrong characters being combined).

To address this, we simply avoid including the leading newline in the case where the starting position for the
"context before selection" is exactly at the first position inside the editable root.

Test: AutocorrectionTests.AutocorrectionContextDoesNotIncludeNewlineInTextField

  • WebProcess/WebPage/ios/WebPageIOS.mm:

(WebKit::WebPage::autocorrectionContext):

Also drive-by fix a typo in "minContextLenght" while I'm here, and rename currentPosition to
contextStartPosition, to better describe the purpose of this local variable.

Tools:

Add a new API test to exercise the change. See WebKit/ChangeLog for more information.

  • TestWebKitAPI/Tests/ios/AutocorrectionTestsIOS.mm:

(-[TestWKWebView synchronouslyRequestAutocorrectionContext]):
(TEST):

  • TestWebKitAPI/ios/UIKitSPI.h:
Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r282236 r282247  
     12021-09-09  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        [Mac Catalyst] Korean characters do not combine correctly in editable fields in WKWebView
     4        https://bugs.webkit.org/show_bug.cgi?id=230122
     5        rdar://79062204
     6
     7        Reviewed by Devin Rousso.
     8
     9        When using Korean input method (e.g. 2-set Korean) to type into editable input fields in WKWebView on Catalyst,
     10        character combination is broken. While this is partly due to a WebKit-specific UIKit bug (see rdar://82938391),
     11        this is also broken due to the fact that WKContentView reports a UIWKAutocorrectionContext with a
     12        `contextBeforeSelection` that starts with a newline (\n); this causes UIKit to believe that the text selection
     13        range when a single character has been typed is `NSRange { 2, 0 }` instead of `NSRange { 1, 0 }`, due to the
     14        extra newline. This subsequently causes character combination logic to proceed with a range that is off by one
     15        character, which leads to characters not being combined (or the wrong characters being combined).
     16
     17        To address this, we simply avoid including the leading newline in the case where the starting position for the
     18        "context before selection" is exactly at the first position inside the editable root.
     19
     20        Test: AutocorrectionTests.AutocorrectionContextDoesNotIncludeNewlineInTextField
     21
     22        * WebProcess/WebPage/ios/WebPageIOS.mm:
     23        (WebKit::WebPage::autocorrectionContext):
     24
     25        Also drive-by fix a typo in "minContextLenght" while I'm here, and rename `currentPosition` to
     26        `contextStartPosition`, to better describe the purpose of this local variable.
     27
    1282021-09-09  Fujii Hironori  <Hironori.Fujii@sony.com>
    229
  • trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm

    r282191 r282247  
    25012501    VisiblePosition endPosition = frame->selection().selection().end();
    25022502    const unsigned minContextWordCount = 3;
    2503     const unsigned minContextLenght = 12;
     2503    const unsigned minContextLength = 12;
    25042504    const unsigned maxContextLength = 30;
    25052505
    … …  
    25162516        }
    25172517    } else {
    2518         if (startPosition != startOfEditableContent(startPosition)) {
    2519             VisiblePosition currentPosition = startPosition;
     2518        auto firstPositionInEditableContent = startOfEditableContent(startPosition);
     2519        if (startPosition != firstPositionInEditableContent) {
     2520            VisiblePosition contextStartPosition = startPosition;
    25202521            VisiblePosition previousPosition;
    25212522            unsigned totalContextLength = 0;
    25222523            for (unsigned i = 0; i < minContextWordCount; ++i) {
    2523                 if (contextBefore.length() >= minContextLenght)
     2524                if (contextBefore.length() >= minContextLength)
    25242525                    break;
    2525                 previousPosition = startOfWord(positionOfNextBoundaryOfGranularity(currentPosition, TextGranularity::WordGranularity, SelectionDirection::Backward));
     2526                previousPosition = startOfWord(positionOfNextBoundaryOfGranularity(contextStartPosition, TextGranularity::WordGranularity, SelectionDirection::Backward));
    25262527                if (previousPosition.isNull())
    25272528                    break;
    2528                 String currentWord = plainTextForContext(makeSimpleRange(previousPosition, currentPosition));
     2529                String currentWord = plainTextForContext(makeSimpleRange(previousPosition, contextStartPosition));
    25292530                totalContextLength += currentWord.length();
    25302531                if (totalContextLength >= maxContextLength)
    25312532                    break;
    2532                 currentPosition = previousPosition;
     2533                contextStartPosition = previousPosition;
    25332534            }
    2534             if (currentPosition.isNotNull() && currentPosition != startPosition) {
    2535                 contextBefore = plainTextForContext(makeSimpleRange(currentPosition, startPosition));
    2536                 if (atBoundaryOfGranularity(currentPosition, TextGranularity::ParagraphGranularity, SelectionDirection::Backward))
     2535            if (contextStartPosition.isNotNull() && contextStartPosition != startPosition) {
     2536                contextBefore = plainTextForContext(makeSimpleRange(contextStartPosition, startPosition));
     2537                if (atBoundaryOfGranularity(contextStartPosition, TextGranularity::ParagraphGranularity, SelectionDirection::Backward) && firstPositionInEditableContent != contextStartPosition)
    25372538                    contextBefore = makeString("\n "_s, contextBefore);
    25382539            }
  • trunk/Tools/ChangeLog

    r282218 r282247  
     12021-09-09  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        [Mac Catalyst] Korean characters do not combine correctly in editable fields in WKWebView
     4        https://bugs.webkit.org/show_bug.cgi?id=230122
     5        rdar://79062204
     6
     7        Reviewed by Devin Rousso.
     8
     9        Add a new API test to exercise the change. See WebKit/ChangeLog for more information.
     10
     11        * TestWebKitAPI/Tests/ios/AutocorrectionTestsIOS.mm:
     12        (-[TestWKWebView synchronouslyRequestAutocorrectionContext]):
     13        (TEST):
     14        * TestWebKitAPI/ios/UIKitSPI.h:
     15
    1162021-09-09  Chris Dumez  <cdumez@apple.com>
    217
  • trunk/Tools/TestWebKitAPI/Tests/ios/AutocorrectionTestsIOS.mm

    r260367 r282247  
    3737@interface TestWKWebView (AutocorrectionTests)
    3838- (UIWKAutocorrectionRects *)autocorrectionRectsForString:(NSString *)string;
     39- (UIWKAutocorrectionContext *)synchronouslyRequestAutocorrectionContext;
    3940@end
    4041
    … …  
    4748    [self.textInputContentView requestAutocorrectionRectsForString:string withCompletionHandler:[&] (UIWKAutocorrectionRects *rects) {
    4849        result = rects;
     50        done = true;
     51    }];
     52    TestWebKitAPI::Util::run(&done);
     53    return result.autorelease();
     54}
     55
     56- (UIWKAutocorrectionContext *)synchronouslyRequestAutocorrectionContext
     57{
     58    RetainPtr<UIWKAutocorrectionContext> result;
     59    bool done = false;
     60    [self.textInputContentView requestAutocorrectionContextWithCompletionHandler:[&] (UIWKAutocorrectionContext *context) {
     61        result = context;
    4962        done = true;
    5063    }];
    … …  
    105118    [webView _close];
    106119
    107     bool done = false;
    108     [contentView requestAutocorrectionContextWithCompletionHandler:[&] (UIWKAutocorrectionContext *) {
    109         done = true;
    110     }];
    111     TestWebKitAPI::Util::run(&done);
     120    // This test just verifies that attempting to request an autocorrection context in this state
     121    // does not trigger a crash or hang, and also still invokes the given completion handler.
     122    [webView synchronouslyRequestAutocorrectionContext];
     123}
     124
     125TEST(AutocorrectionTests, AutocorrectionContextDoesNotIncludeNewlineInTextField)
     126{
     127    auto webView = adoptNS([[TestWKWebView alloc] init]);
     128    [webView synchronouslyLoadTestPageNamed:@"autofocused-text-input"];
     129
     130    RetainPtr contextBeforeTyping = [webView synchronouslyRequestAutocorrectionContext];
     131    EXPECT_EQ(0U, [contextBeforeTyping contextBeforeSelection].length);
     132    EXPECT_EQ(0U, [contextBeforeTyping selectedText].length);
     133    EXPECT_EQ(0U, [contextBeforeTyping contextAfterSelection].length);
     134
     135    [[webView textInputContentView] insertText:@"a"];
     136    [webView waitForNextPresentationUpdate];
     137
     138    RetainPtr contextAfterTyping = [webView synchronouslyRequestAutocorrectionContext];
     139    EXPECT_WK_STREQ(@"a", [contextAfterTyping contextBeforeSelection]);
     140    EXPECT_EQ(0U, [contextAfterTyping selectedText].length);
     141    EXPECT_EQ(0U, [contextAfterTyping contextAfterSelection].length);
    112142}
    113143
  • trunk/Tools/TestWebKitAPI/ios/UIKitSPI.h

    r281468 r282247  
    184184
    185185@interface UIWKAutocorrectionContext : NSObject
     186@property (nonatomic, copy) NSString *contextBeforeSelection;
     187@property (nonatomic, copy) NSString *selectedText;
     188@property (nonatomic, copy) NSString *contextAfterSelection;
    186189@end
    187190
Note: See TracChangeset for help on using the changeset viewer.