Changeset 260865 in webkit


Ignore:
Timestamp:
Apr 28, 2020 10:16:23 PM (4 years ago)
Author:
Wenson Hsieh
Message:

[Text manipulation] Add a userInfo dictionary to _WKTextManipulationToken
https://bugs.webkit.org/show_bug.cgi?id=211151
<rdar://problem/62329534>

Reviewed by Darin Adler.

Source/WebCore:

Add an extensible mechanism for the text manipulation controller to send additional
metadata for each text manipulation token through to the WebKit client, for debugging
purposes.

Test: TextManipulation.StartTextManipulationExtractsUserInfo

  • editing/TextManipulationController.cpp:

(WebCore::tokenInfo):
(WebCore::TextManipulationController::observeParagraphs):

  • editing/TextManipulationController.h:

Add TextManipulationTokenInfo, and add an optional TextManipulationTokenInfo member to
TextManipulationToken. For now, just send over the document URL, element tag name, and
the value of the role attribute.

(WebCore::TextManipulationController::ManipulationTokenInfo::encode const):
(WebCore::TextManipulationController::ManipulationTokenInfo::decode):
(WebCore::TextManipulationController::ManipulationToken::encode const):
(WebCore::TextManipulationController::ManipulationToken::decode):

Source/WebKit:

  • UIProcess/API/Cocoa/WKWebView.mm:

(createUserInfo):
(-[WKWebView _startTextManipulationsWithConfiguration:completion:]):
(-[WKWebView _completeTextManipulation:completion:]):
(-[WKWebView _completeTextManipulationForItems:completion:]):

  • UIProcess/API/Cocoa/_WKTextManipulationToken.h:
  • UIProcess/API/Cocoa/_WKTextManipulationToken.mm:

(-[_WKTextManipulationToken setUserInfo:]):
(-[_WKTextManipulationToken userInfo]):

Add a new userInfo dictionary to _WKTextManipulationToken, which contains several named
NSString keys.

(-[_WKTextManipulationToken isEqualToTextManipulationToken:includingContentEquality:]):
(-[_WKTextManipulationToken _descriptionPreservingPrivacy:]):

Tools:

Add a new API test to check the userInfo dictionary on text manipulation tokens.

  • TestWebKitAPI/Tests/WebKitCocoa/TextManipulation.mm:
Location:
trunk
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r260862 r260865  
     12020-04-28  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        [Text manipulation] Add a userInfo dictionary to _WKTextManipulationToken
     4        https://bugs.webkit.org/show_bug.cgi?id=211151
     5        <rdar://problem/62329534>
     6
     7        Reviewed by Darin Adler.
     8
     9        Add an extensible mechanism for the text manipulation controller to send additional
     10        metadata for each text manipulation token through to the WebKit client, for debugging
     11        purposes.
     12
     13        Test: TextManipulation.StartTextManipulationExtractsUserInfo
     14
     15        * editing/TextManipulationController.cpp:
     16        (WebCore::tokenInfo):
     17        (WebCore::TextManipulationController::observeParagraphs):
     18        * editing/TextManipulationController.h:
     19
     20        Add TextManipulationTokenInfo, and add an optional TextManipulationTokenInfo member to
     21        TextManipulationToken. For now, just send over the document URL, element tag name, and
     22        the value of the role attribute.
     23
     24        (WebCore::TextManipulationController::ManipulationTokenInfo::encode const):
     25        (WebCore::TextManipulationController::ManipulationTokenInfo::decode):
     26        (WebCore::TextManipulationController::ManipulationToken::encode const):
     27        (WebCore::TextManipulationController::ManipulationToken::decode):
     28
    1292020-04-28  Simon Fraser  <simon.fraser@apple.com>
    230
  • trunk/Source/WebCore/editing/TextManipulationController.cpp

    r260783 r260865  
    259259}
    260260
     261static Optional<TextManipulationController::ManipulationTokenInfo> tokenInfo(Node* node)
     262{
     263    if (!node)
     264        return WTF::nullopt;
     265
     266    TextManipulationController::ManipulationTokenInfo result;
     267    result.documentURL = node->document().url();
     268    if (auto element = is<Element>(node) ? makeRefPtr(downcast<Element>(*node)) : makeRefPtr(node->parentElement())) {
     269        result.tagName = element->tagName();
     270        if (element->hasAttributeWithoutSynchronization(HTMLNames::roleAttr))
     271            result.roleAttribute = element->attributeWithoutSynchronization(HTMLNames::roleAttr);
     272    }
     273    return result;
     274}
     275
    261276void TextManipulationController::observeParagraphs(const Position& start, const Position& end)
    262277{
     
    322337                if (!content.isTextContent && canPerformTextManipulationByReplacingEntireTextContent(currentElement)) {
    323338                    addItem(ManipulationItemData { Position(), Position(), makeWeakPtr(currentElement), nullQName(),
    324                         { ManipulationToken { m_tokenIdentifier.generate(), currentElement.textContent() } } });
     339                        { ManipulationToken { m_tokenIdentifier.generate(), currentElement.textContent(), tokenInfo(&currentElement) } } });
    325340                }
    326341                if (currentElement.hasAttributes()) {
     
    328343                        if (isAttributeForTextManipulation(attribute.name())) {
    329344                            addItem(ManipulationItemData { Position(), Position(), makeWeakPtr(currentElement), attribute.name(),
    330                                 { ManipulationToken { m_tokenIdentifier.generate(), attribute.value() } } });
     345                                { ManipulationToken { m_tokenIdentifier.generate(), attribute.value(), tokenInfo(&currentElement) } } });
    331346                        }
    332347                    }
     
    347362
    348363            endOfCurrentParagraph = currentEndOfCurrentParagraph;
    349             tokensInCurrentParagraph.append(ManipulationToken { m_tokenIdentifier.generate(), "[]", true });
     364            tokensInCurrentParagraph.append(ManipulationToken { m_tokenIdentifier.generate(), "[]", tokenInfo(content.node.get()), true });
    350365
    351366            continue;
     
    366381                    startOfCurrentParagraph = Position(&textNode, startOfCurrentLine);
    367382
    368                 tokensInCurrentParagraph.append(ManipulationToken { m_tokenIdentifier.generate(), stringUntilEndOfLine, exclusionRuleMatcher.isExcluded(content.node.get()) });
     383                tokensInCurrentParagraph.append(ManipulationToken { m_tokenIdentifier.generate(), stringUntilEndOfLine, tokenInfo(&textNode), exclusionRuleMatcher.isExcluded(content.node.get()) });
    369384            }
    370385
     
    386401            }
    387402            endOfCurrentParagraph = iterator.endPosition();
    388             tokensInCurrentParagraph.append(ManipulationToken { m_tokenIdentifier.generate(), remainingText.toString(), exclusionRuleMatcher.isExcluded(content.node.get()) });
     403            tokensInCurrentParagraph.append(ManipulationToken { m_tokenIdentifier.generate(), remainingText.toString(), tokenInfo(content.node.get()), exclusionRuleMatcher.isExcluded(content.node.get()) });
    389404        }
    390405    }
  • trunk/Source/WebCore/editing/TextManipulationController.h

    r260609 r260865  
    4949    using TokenIdentifier = ObjectIdentifier<TokenIdentifierType>;
    5050
     51    struct ManipulationTokenInfo {
     52        String tagName;
     53        String roleAttribute;
     54        URL documentURL;
     55
     56        template<class Encoder> void encode(Encoder&) const;
     57        template<class Decoder> static Optional<ManipulationTokenInfo> decode(Decoder&);
     58    };
     59
    5160    struct ManipulationToken {
    5261        TokenIdentifier identifier;
    5362        String content;
     63        Optional<ManipulationTokenInfo> info;
    5464        bool isExcluded { false };
    5565
     
    159169
    160170template<class Encoder>
     171void TextManipulationController::ManipulationTokenInfo::encode(Encoder& encoder) const
     172{
     173    encoder << tagName;
     174    encoder << roleAttribute;
     175    encoder << documentURL;
     176}
     177
     178template<class Decoder>
     179Optional<TextManipulationController::ManipulationTokenInfo> TextManipulationController::ManipulationTokenInfo::decode(Decoder& decoder)
     180{
     181    ManipulationTokenInfo result;
     182    if (!decoder.decode(result.tagName))
     183        return WTF::nullopt;
     184
     185    if (!decoder.decode(result.roleAttribute))
     186        return WTF::nullopt;
     187
     188    if (!decoder.decode(result.documentURL))
     189        return WTF::nullopt;
     190
     191    return result;
     192}
     193
     194template<class Encoder>
    161195void TextManipulationController::ManipulationToken::encode(Encoder& encoder) const
    162196{
    163     encoder << identifier << content << isExcluded;
     197    encoder << identifier << content << info << isExcluded;
    164198}
    165199
     
    171205        return WTF::nullopt;
    172206    if (!decoder.decode(result.content))
     207        return WTF::nullopt;
     208    if (!decoder.decode(result.info))
    173209        return WTF::nullopt;
    174210    if (!decoder.decode(result.isExcluded))
  • trunk/Source/WebKit/ChangeLog

    r260864 r260865  
     12020-04-28  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        [Text manipulation] Add a userInfo dictionary to _WKTextManipulationToken
     4        https://bugs.webkit.org/show_bug.cgi?id=211151
     5        <rdar://problem/62329534>
     6
     7        Reviewed by Darin Adler.
     8
     9        * UIProcess/API/Cocoa/WKWebView.mm:
     10        (createUserInfo):
     11        (-[WKWebView _startTextManipulationsWithConfiguration:completion:]):
     12        (-[WKWebView _completeTextManipulation:completion:]):
     13        (-[WKWebView _completeTextManipulationForItems:completion:]):
     14        * UIProcess/API/Cocoa/_WKTextManipulationToken.h:
     15        * UIProcess/API/Cocoa/_WKTextManipulationToken.mm:
     16        (-[_WKTextManipulationToken setUserInfo:]):
     17        (-[_WKTextManipulationToken userInfo]):
     18
     19        Add a new `userInfo` dictionary to `_WKTextManipulationToken`, which contains several named
     20        `NSString` keys.
     21
     22        (-[_WKTextManipulationToken isEqualToTextManipulationToken:includingContentEquality:]):
     23        (-[_WKTextManipulationToken _descriptionPreservingPrivacy:]):
     24
    1252020-04-28  David Kilzer  <ddkilzer@apple.com>
    226
  • trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm

    r260787 r260865  
    16071607}
    16081608
     1609static RetainPtr<NSDictionary<NSString *, id>> createUserInfo(const Optional<WebCore::TextManipulationController::ManipulationTokenInfo>& info)
     1610{
     1611    if (!info)
     1612        return { };
     1613
     1614    auto result = adoptNS([[NSMutableDictionary alloc] initWithCapacity:3]);
     1615    if (!info->documentURL.isNull())
     1616        [result setObject:(NSURL *)info->documentURL forKey:_WKTextManipulationTokenUserInfoDocumentURLKey];
     1617    if (!info->tagName.isNull())
     1618        [result setObject:(NSString *)info->tagName forKey:_WKTextManipulationTokenUserInfoTagNameKey];
     1619    if (!info->roleAttribute.isNull())
     1620        [result setObject:(NSString *)info->roleAttribute forKey:_WKTextManipulationTokenUserInfoRoleAttributeKey];
     1621
     1622    return result;
     1623}
     1624
    16091625- (void)_startTextManipulationsWithConfiguration:(_WKTextManipulationConfiguration *)configuration completion:(void(^)())completionHandler
    16101626{
     
    16441660                [wkToken setContent:token.content];
    16451661                [wkToken setExcluded:token.isExcluded];
     1662                [wkToken setUserInfo:createUserInfo(token.info).get()];
    16461663                return wkToken;
    16471664            });
     
    16811698    Vector<WebCore::TextManipulationController::ManipulationToken> tokens;
    16821699    for (_WKTextManipulationToken *wkToken in item.tokens)
    1683         tokens.append(WebCore::TextManipulationController::ManipulationToken { coreTextManipulationTokenIdentifierFromString(wkToken.identifier), wkToken.content });
     1700        tokens.append(WebCore::TextManipulationController::ManipulationToken { coreTextManipulationTokenIdentifierFromString(wkToken.identifier), wkToken.content, WTF::nullopt });
    16841701
    16851702    Vector<WebCore::TextManipulationController::ManipulationItem> coreItems;
     
    17401757        coreTokens.reserveInitialCapacity(wkItem.tokens.count);
    17411758        for (_WKTextManipulationToken *wkToken in wkItem.tokens)
    1742             coreTokens.uncheckedAppend(WebCore::TextManipulationController::ManipulationToken { coreTextManipulationTokenIdentifierFromString(wkToken.identifier), wkToken.content });
     1759            coreTokens.uncheckedAppend(WebCore::TextManipulationController::ManipulationToken { coreTextManipulationTokenIdentifierFromString(wkToken.identifier), wkToken.content, WTF::nullopt });
    17431760        coreItems.uncheckedAppend(WebCore::TextManipulationController::ManipulationItem { coreTextManipulationItemIdentifierFromString(wkItem.identifier), WTFMove(coreTokens) });
    17441761    }
  • trunk/Source/WebKit/UIProcess/API/Cocoa/_WKTextManipulationToken.h

    r260334 r260865  
    2929NS_ASSUME_NONNULL_BEGIN
    3030
     31WK_EXTERN NSString * const _WKTextManipulationTokenUserInfoDocumentURLKey WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
     32WK_EXTERN NSString * const _WKTextManipulationTokenUserInfoTagNameKey WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
     33WK_EXTERN NSString * const _WKTextManipulationTokenUserInfoRoleAttributeKey WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
     34
    3135WK_CLASS_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA))
    3236@interface _WKTextManipulationToken : NSObject
     
    3943@property (nonatomic, copy, readonly) NSString *debugDescription;
    4044
     45@property (nonatomic, nullable, copy) NSDictionary<NSString *, id> *userInfo;
     46
    4147@end
    4248
  • trunk/Source/WebKit/UIProcess/API/Cocoa/_WKTextManipulationToken.mm

    r259280 r260865  
    2727#import "_WKTextManipulationToken.h"
    2828
    29 @implementation _WKTextManipulationToken
     29#import <wtf/RetainPtr.h>
     30
     31NSString * const _WKTextManipulationTokenUserInfoDocumentURLKey = @"_WKTextManipulationTokenUserInfoDocumentURLKey";
     32NSString * const _WKTextManipulationTokenUserInfoTagNameKey = @"_WKTextManipulationTokenUserInfoTagNameKey";
     33NSString * const _WKTextManipulationTokenUserInfoRoleAttributeKey = @"_WKTextManipulationTokenUserInfoRoleAttributeKey";
     34
     35@implementation _WKTextManipulationToken {
     36    RetainPtr<NSDictionary<NSString *, id>> _userInfo;
     37}
    3038
    3139- (void)dealloc
     
    3745
    3846    [super dealloc];
     47}
     48
     49- (void)setUserInfo:(NSDictionary<NSString *, id> *)userInfo
     50{
     51    if (userInfo == _userInfo || [_userInfo isEqual:userInfo])
     52        return;
     53
     54    _userInfo = adoptNS(userInfo.copy);
     55}
     56
     57- (NSDictionary<NSString *, id> *)userInfo
     58{
     59    return _userInfo.get();
    3960}
    4061
     
    6687    BOOL equalExclusion = self.isExcluded == otherToken.isExcluded;
    6788    BOOL equalContent = !includingContentEquality || isEqualOrBothNil(self.content, otherToken.content);
     89    BOOL equalUserInfo = isEqualOrBothNil(self.userInfo, otherToken.userInfo);
    6890
    69     return equalIdentifiers && equalExclusion && equalContent;
     91    return equalIdentifiers && equalExclusion && equalContent && equalUserInfo;
    7092}
    7193
     
    86108        [description appendFormat:@"; content length = %lu", (unsigned long)self.content.length];
    87109    else
    88         [description appendFormat:@"; content = %@", self.content];
     110        [description appendFormat:@"; content = %@; user info = %@", self.content, self.userInfo];
    89111
    90112    [description appendString:@">"];
  • trunk/Tools/ChangeLog

    r260860 r260865  
     12020-04-28  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        [Text manipulation] Add a userInfo dictionary to _WKTextManipulationToken
     4        https://bugs.webkit.org/show_bug.cgi?id=211151
     5        <rdar://problem/62329534>
     6
     7        Reviewed by Darin Adler.
     8
     9        Add a new API test to check the userInfo dictionary on text manipulation tokens.
     10
     11        * TestWebKitAPI/Tests/WebKitCocoa/TextManipulation.mm:
     12
    1132020-04-28  David Kilzer  <ddkilzer@apple.com>
    214
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/TextManipulation.mm

    r260783 r260865  
    705705}
    706706
     707TEST(TextManipulation, StartTextManipulationExtractsUserInfo)
     708{
     709    auto delegate = adoptNS([[TextManipulationDelegate alloc] init]);
     710    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 400, 400)]);
     711    [webView _setTextManipulationDelegate:delegate.get()];
     712
     713    [webView synchronouslyLoadHTMLString:@"<!DOCTYPE html>"
     714        "<body>"
     715        "    <title>This is a test</title>"
     716        "    <p>First</p>"
     717        "    <div role='button'>Second</div>"
     718        "    <span>Third</span>"
     719        "</body>"];
     720
     721    done = false;
     722    [webView _startTextManipulationsWithConfiguration:nil completion:^{
     723        done = true;
     724    }];
     725    TestWebKitAPI::Util::run(&done);
     726
     727    auto items = [delegate items];
     728    EXPECT_EQ(items.count, 4UL);
     729    EXPECT_EQ(items[0].tokens.count, 1UL);
     730    EXPECT_EQ(items[1].tokens.count, 1UL);
     731    EXPECT_EQ(items[2].tokens.count, 1UL);
     732    EXPECT_EQ(items[3].tokens.count, 1UL);
     733    EXPECT_WK_STREQ("This is a test", items[0].tokens[0].content);
     734    EXPECT_WK_STREQ("First", items[1].tokens[0].content);
     735    EXPECT_WK_STREQ("Second", items[2].tokens[0].content);
     736    EXPECT_WK_STREQ("Third", items[3].tokens[0].content);
     737    {
     738        auto userInfo = items[0].tokens[0].userInfo;
     739        EXPECT_WK_STREQ("TestWebKitAPI.resources", [(NSURL *)userInfo[_WKTextManipulationTokenUserInfoDocumentURLKey] lastPathComponent]);
     740        EXPECT_WK_STREQ("TITLE", (NSString *)userInfo[_WKTextManipulationTokenUserInfoTagNameKey]);
     741    }
     742    {
     743        auto userInfo = items[1].tokens[0].userInfo;
     744        EXPECT_WK_STREQ("TestWebKitAPI.resources", [(NSURL *)userInfo[_WKTextManipulationTokenUserInfoDocumentURLKey] lastPathComponent]);
     745        EXPECT_WK_STREQ("P", (NSString *)userInfo[_WKTextManipulationTokenUserInfoTagNameKey]);
     746    }
     747    {
     748        auto userInfo = items[2].tokens[0].userInfo;
     749        EXPECT_WK_STREQ("TestWebKitAPI.resources", [(NSURL *)userInfo[_WKTextManipulationTokenUserInfoDocumentURLKey] lastPathComponent]);
     750        EXPECT_WK_STREQ("DIV", (NSString *)userInfo[_WKTextManipulationTokenUserInfoTagNameKey]);
     751        EXPECT_WK_STREQ("button", (NSString *)userInfo[_WKTextManipulationTokenUserInfoRoleAttributeKey]);
     752    }
     753    {
     754        auto userInfo = items[3].tokens[0].userInfo;
     755        EXPECT_WK_STREQ("TestWebKitAPI.resources", [(NSURL *)userInfo[_WKTextManipulationTokenUserInfoDocumentURLKey] lastPathComponent]);
     756        EXPECT_WK_STREQ("SPAN", (NSString *)userInfo[_WKTextManipulationTokenUserInfoTagNameKey]);
     757    }
     758}
     759
    707760struct Token {
    708761    NSString *identifier;
Note: See TracChangeset for help on using the changeset viewer.