Skip to content

Commit

Permalink
Expose text fragment matching via WebKit SPI
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=244079

Reviewed by Megan Gardner.

Add WKWebView SPI that asynchronously returns the first text fragment directive
match (if any) as a plain text string.

* Source/WebCore/WebCore.xcodeproj/project.pbxproj:
* Source/WebCore/dom/FragmentDirectiveParser.h:
* Source/WebCore/dom/FragmentDirectiveRangeFinder.h:
Expose text fragment directive parser and range computation entry points from WebCore.

* Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _getTextFragmentMatchWithCompletionHandler:]):
* Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h:
Add SPI.

* Source/WebKit/UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::getTextFragmentMatch):
* Source/WebKit/UIProcess/WebPageProxy.h:
* Source/WebKit/WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::getTextFragmentMatch):
* Source/WebKit/WebProcess/WebPage/WebPage.h:
* Source/WebKit/WebProcess/WebPage/WebPage.messages.in:
Compute the range for the first viable text fragment, if any, flatten
it to a plain text string, and return it to the app.

* Tools/TestWebKitAPI/SourcesCocoa.txt:
* Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* Tools/TestWebKitAPI/Tests/WebKitCocoa/TextFragments.mm: Added.
(TEST):
Add a test that ensures that the API works reasonably. This is
not meant to be an exhaustive test of text fragment parsing, just
a basic test of the API.

Canonical link: https://commits.webkit.org/253575@main
  • Loading branch information
hortont424 committed Aug 18, 2022
1 parent b237a7c commit c2b3ade
Show file tree
Hide file tree
Showing 14 changed files with 127 additions and 6 deletions.
2 changes: 2 additions & 0 deletions Source/WebCore/Headers.cmake
Expand Up @@ -693,6 +693,8 @@ set(WebCore_PRIVATE_FRAMEWORK_HEADERS
dom/ExceptionData.h
dom/ExceptionOr.h
dom/FocusOptions.h
dom/FragmentDirectiveParser.h
dom/FragmentDirectiveRangeFinder.h
dom/FragmentScriptingPermission.h
dom/FullscreenManager.h
dom/GCReachableRef.h
Expand Down
10 changes: 7 additions & 3 deletions Source/WebCore/WebCore.xcodeproj/project.pbxproj
Expand Up @@ -870,6 +870,8 @@
2D8B92FF203D13E1009C868F /* UnifiedSource530.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE5F85D31FA23859006DB63B /* UnifiedSource530.cpp */; };
2D8FEBDD143E3EF70072502B /* CSSCrossfadeValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D8FEBDB143E3EF70072502B /* CSSCrossfadeValue.h */; };
2D9066070BE141D400956998 /* RenderLayoutState.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D9066050BE141D400956998 /* RenderLayoutState.h */; settings = {ATTRIBUTES = (Private, ); }; };
2D9153EF28AE0E280073A385 /* FragmentDirectiveParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 445612AB270F6F3800758C97 /* FragmentDirectiveParser.h */; settings = {ATTRIBUTES = (Private, ); }; };
2D9153F028AE0E330073A385 /* FragmentDirectiveRangeFinder.h in Headers */ = {isa = PBXBuildFile; fileRef = 442E7BEE27BC56EC00C69AC1 /* FragmentDirectiveRangeFinder.h */; settings = {ATTRIBUTES = (Private, ); }; };
2D93AEE319DF5641002A86C3 /* ServicesOverlayController.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D93AEE119DF5641002A86C3 /* ServicesOverlayController.h */; };
2D97F04719DD413C001EE9C3 /* MockPageOverlayClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2DAAE32C19DCAF6000E002D2 /* MockPageOverlayClient.cpp */; };
2D97F04819DD4140001EE9C3 /* MockPageOverlayClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DAAE32D19DCAF6000E002D2 /* MockPageOverlayClient.h */; };
Expand Down Expand Up @@ -1271,8 +1273,8 @@
436708C312D9CA4B00044234 /* LegacyRenderSVGContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4367088412D9CA4A00044234 /* LegacyRenderSVGContainer.h */; };
436708C433F8CA4C10044234 /* RenderSVGContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4367077412D9BC4A00044234 /* RenderSVGContainer.h */; };
436708C512D9CA4B00044234 /* RenderSVGGradientStop.h in Headers */ = {isa = PBXBuildFile; fileRef = 4367088612D9CA4A00044234 /* RenderSVGGradientStop.h */; };
436708C713E8CB3B000355F1 /* LegacyRenderSVGHiddenContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4367088813E8CA3B00055F14 /* LegacyRenderSVGHiddenContainer.h */; };
436708C712D9CA4B00044234 /* RenderSVGHiddenContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4367088812D9CA4A00044234 /* RenderSVGHiddenContainer.h */; };
436708C713E8CB3B000355F1 /* LegacyRenderSVGHiddenContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4367088813E8CA3B00055F14 /* LegacyRenderSVGHiddenContainer.h */; };
436708C912D9CA4B00044234 /* RenderSVGImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 4367088A12D9CA4A00044234 /* RenderSVGImage.h */; };
436708CB12D9CA4B00044234 /* LegacyRenderSVGModelObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 4367088C12D9CA4A00044234 /* LegacyRenderSVGModelObject.h */; };
436708CD12D9CA4B00044234 /* RenderSVGResource.h in Headers */ = {isa = PBXBuildFile; fileRef = 4367088E12D9CA4A00044234 /* RenderSVGResource.h */; };
Expand Down Expand Up @@ -9196,10 +9198,10 @@
4367088442A9AC3B10044234 /* RenderSVGContainer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderSVGContainer.cpp; sourceTree = "<group>"; };
4367088512D9CA4A00044234 /* RenderSVGGradientStop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderSVGGradientStop.cpp; sourceTree = "<group>"; };
4367088612D9CA4A00044234 /* RenderSVGGradientStop.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderSVGGradientStop.h; sourceTree = "<group>"; };
4367088713E8CA3B00055F14 /* LegacyRenderSVGHiddenContainer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LegacyRenderSVGHiddenContainer.cpp; sourceTree = "<group>"; };
4367088813E8CA3B00055F14 /* LegacyRenderSVGHiddenContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LegacyRenderSVGHiddenContainer.h; sourceTree = "<group>"; };
4367088712D9CA4A00044234 /* RenderSVGHiddenContainer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderSVGHiddenContainer.cpp; sourceTree = "<group>"; };
4367088713E8CA3B00055F14 /* LegacyRenderSVGHiddenContainer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LegacyRenderSVGHiddenContainer.cpp; sourceTree = "<group>"; };
4367088812D9CA4A00044234 /* RenderSVGHiddenContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderSVGHiddenContainer.h; sourceTree = "<group>"; };
4367088813E8CA3B00055F14 /* LegacyRenderSVGHiddenContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LegacyRenderSVGHiddenContainer.h; sourceTree = "<group>"; };
4367088912D9CA4A00044234 /* RenderSVGImage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderSVGImage.cpp; sourceTree = "<group>"; };
4367088A12D9CA4A00044234 /* RenderSVGImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderSVGImage.h; sourceTree = "<group>"; };
4367088B12D9CA4A00044234 /* LegacyRenderSVGModelObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LegacyRenderSVGModelObject.cpp; sourceTree = "<group>"; };
Expand Down Expand Up @@ -35329,6 +35331,8 @@
656D373A0ADBA5DE00A4554D /* FormState.h in Headers */,
41885B9311B6FDA6003383BB /* FormSubmission.h in Headers */,
CD525BA41EE0B10700788DF5 /* FourCC.h in Headers */,
2D9153EF28AE0E280073A385 /* FragmentDirectiveParser.h in Headers */,
2D9153F028AE0E330073A385 /* FragmentDirectiveRangeFinder.h in Headers */,
A853123D11D0471B00D4D077 /* FragmentScriptingPermission.h in Headers */,
65BF022F0974816300C43196 /* Frame.h in Headers */,
974A862314B7ADBB003FDC76 /* FrameDestructionObserver.h in Headers */,
Expand Down
2 changes: 1 addition & 1 deletion Source/WebCore/dom/FragmentDirectiveParser.h
Expand Up @@ -39,7 +39,7 @@ struct ParsedTextDirective {

class FragmentDirectiveParser {
public:
explicit FragmentDirectiveParser(const URL&);
WEBCORE_EXPORT explicit FragmentDirectiveParser(const URL&);

const Vector<ParsedTextDirective>& parsedTextDirectives() const { return m_parsedTextDirectives; };
StringView fragmentDirective() const { return m_fragmentDirective; };
Expand Down
2 changes: 1 addition & 1 deletion Source/WebCore/dom/FragmentDirectiveRangeFinder.h
Expand Up @@ -34,7 +34,7 @@ namespace WebCore {

namespace FragmentDirectiveRangeFinder {

const Vector<SimpleRange> findRangesFromTextDirectives(Vector<ParsedTextDirective>& parsedTextDirectives, Document&);
WEBCORE_EXPORT const Vector<SimpleRange> findRangesFromTextDirectives(Vector<ParsedTextDirective>& parsedTextDirectives, Document&);
std::optional<SimpleRange> findRangeFromTextDirective(ParsedTextDirective, Document&);

}
Expand Down
8 changes: 8 additions & 0 deletions Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm
Expand Up @@ -3197,6 +3197,14 @@ - (void)_getApplicationManifestWithCompletionHandler:(void (^)(_WKApplicationMan
#endif
}

- (void)_getTextFragmentMatchWithCompletionHandler:(void (^)(NSString *))completionHandler
{
THROW_IF_SUSPENDED;
_page->getTextFragmentMatch([completionHandler = makeBlockPtr(completionHandler)](const String& textFragmentMatch) {
completionHandler(textFragmentMatch);
});
}

- (_WKPaginationMode)_paginationMode
{
switch (_page->paginationMode()) {
Expand Down
2 changes: 2 additions & 0 deletions Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h
Expand Up @@ -310,6 +310,8 @@ for this property.

- (void)_getApplicationManifestWithCompletionHandler:(void (^)(_WKApplicationManifest *))completionHandler WK_API_AVAILABLE(macos(10.13.4), ios(11.3));

- (void)_getTextFragmentMatchWithCompletionHandler:(void (^)(NSString *))completionHandler WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));

@property (nonatomic, setter=_setPaginationMode:) _WKPaginationMode _paginationMode;
// Whether the column-break-{before,after} properties are respected instead of the
// page-break-{before,after} properties.
Expand Down
5 changes: 5 additions & 0 deletions Source/WebKit/UIProcess/WebPageProxy.cpp
Expand Up @@ -10717,6 +10717,11 @@ void WebPageProxy::getApplicationManifest(CompletionHandler<void(const std::opti
}
#endif

void WebPageProxy::getTextFragmentMatch(CompletionHandler<void(const String&)>&& callback)
{
sendWithAsyncReply(Messages::WebPage::GetTextFragmentMatch(), WTFMove(callback));
}

#if ENABLE(APP_HIGHLIGHTS)
void WebPageProxy::storeAppHighlight(const WebCore::AppHighlight& highlight)
{
Expand Down
2 changes: 2 additions & 0 deletions Source/WebKit/UIProcess/WebPageProxy.h
Expand Up @@ -1807,6 +1807,8 @@ class WebPageProxy final : public API::ObjectImpl<API::Object::Type::Page>
void getApplicationManifest(CompletionHandler<void(const std::optional<WebCore::ApplicationManifest>&)>&&);
#endif

void getTextFragmentMatch(CompletionHandler<void(const String&)>&&);

WebPreferencesStore preferencesStore() const;

void setDefersLoadingForTesting(bool);
Expand Down
31 changes: 31 additions & 0 deletions Source/WebKit/WebProcess/WebPage/WebPage.cpp
Expand Up @@ -184,6 +184,8 @@
#include <WebCore/FontAttributeChanges.h>
#include <WebCore/FontAttributes.h>
#include <WebCore/FormState.h>
#include <WebCore/FragmentDirectiveParser.h>
#include <WebCore/FragmentDirectiveRangeFinder.h>
#include <WebCore/Frame.h>
#include <WebCore/FrameLoadRequest.h>
#include <WebCore/FrameLoaderTypes.h>
Expand Down Expand Up @@ -7557,6 +7559,35 @@ void WebPage::getApplicationManifest(CompletionHandler<void(const std::optional<

#endif // ENABLE(APPLICATION_MANIFEST)

void WebPage::getTextFragmentMatch(CompletionHandler<void(const String&)>&& completionHandler)
{
if (!m_mainFrame->coreFrame()) {
completionHandler({ });
return;
}

Document* document = m_mainFrame->coreFrame()->document();
if (!document) {
completionHandler({ });
return;
}

FragmentDirectiveParser fragmentDirectiveParser(mainWebFrame().url());
if (!fragmentDirectiveParser.isValid()) {
completionHandler({ });
return;
}

auto parsedTextDirectives = fragmentDirectiveParser.parsedTextDirectives();
auto highlightRanges = FragmentDirectiveRangeFinder::findRangesFromTextDirectives(parsedTextDirectives, *document);
if (highlightRanges.isEmpty()) {
completionHandler({ });
return;
}

completionHandler(plainText(highlightRanges.first()));
}

void WebPage::updateCurrentModifierState(OptionSet<PlatformEvent::Modifier> modifiers)
{
PlatformKeyboardEvent::setCurrentModifierState(modifiers);
Expand Down
2 changes: 2 additions & 0 deletions Source/WebKit/WebProcess/WebPage/WebPage.h
Expand Up @@ -1349,6 +1349,8 @@ class WebPage : public API::ObjectImpl<API::Object::Type::BundlePage>, public IP
void getApplicationManifest(CompletionHandler<void(const std::optional<WebCore::ApplicationManifest>&)>&&);
#endif

void getTextFragmentMatch(CompletionHandler<void(const String&)>&&);

#if USE(WPE_RENDERER)
int hostFileDescriptor() const { return m_hostFileDescriptor.fd().value(); }
#endif
Expand Down
2 changes: 2 additions & 0 deletions Source/WebKit/WebProcess/WebPage/WebPage.messages.in
Expand Up @@ -616,6 +616,8 @@ GenerateSyntheticEditingCommand(enum:uint8_t WebKit::SyntheticEditingCommandType
GetApplicationManifest() -> (std::optional<WebCore::ApplicationManifest> manifest)
#endif

GetTextFragmentMatch() -> (String match)

SetDefersLoading(bool defersLoading)

#if ENABLE(UI_PROCESS_PDF_HUD)
Expand Down
1 change: 1 addition & 0 deletions Tools/TestWebKitAPI/SourcesCocoa.txt
Expand Up @@ -238,6 +238,7 @@ Tests/WebKitCocoa/TabOutOfWebView.mm
Tests/WebKitCocoa/TestAwakener.mm
Tests/WebKitCocoa/TestSOAuthorization.mm
Tests/WebKitCocoa/TestURLSchemeHandler.mm
Tests/WebKitCocoa/TextFragments.mm
Tests/WebKitCocoa/TextManipulation.mm
Tests/WebKitCocoa/TextSize.mm
Tests/WebKitCocoa/TextWidth.mm
Expand Down
4 changes: 3 additions & 1 deletion Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
Expand Up @@ -1997,6 +1997,7 @@
2D7FD19222419087007887F1 /* DocumentEditingContext.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DocumentEditingContext.mm; sourceTree = "<group>"; };
2D8104CB1BEC13E70020DA46 /* FindInPage.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FindInPage.mm; sourceTree = "<group>"; };
2D838B1E1EEF3A5B009B980E /* WKContentViewEditingActions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKContentViewEditingActions.mm; sourceTree = "<group>"; };
2D9846FB28AE0F2F00CBA70C /* TextFragments.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = TextFragments.mm; sourceTree = "<group>"; };
2D9A53AE1B31FA8D0074D5AA /* ShrinkToFit.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ShrinkToFit.mm; sourceTree = "<group>"; };
2DA2586E225C67DC00B45C1C /* OverrideViewportArguments.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = OverrideViewportArguments.mm; sourceTree = "<group>"; };
2DADF26221CB8F32003D3E3A /* GetResourceData.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = GetResourceData.mm; sourceTree = "<group>"; };
Expand Down Expand Up @@ -3835,6 +3836,7 @@
5774AA6721FBBF7800AF2A1B /* TestSOAuthorization.mm */,
F4CD74C720FDB49600DE3794 /* TestURLSchemeHandler.h */,
F4CD74C820FDB49600DE3794 /* TestURLSchemeHandler.mm */,
2D9846FB28AE0F2F00CBA70C /* TextFragments.mm */,
9B02E0D5235FA47D004044B2 /* TextManipulation.mm */,
5C16F8FB230C942B0074C4A8 /* TextSize.mm */,
C22FA32A228F8708009D7988 /* TextWidth.mm */,
Expand Down Expand Up @@ -5943,11 +5945,11 @@
7CCE7EC21A411A7E00447C4C /* HTMLFormCollectionNamedItem.mm in Sources */,
7C83E0501D0A641800FEBCF3 /* HTMLParserIdioms.cpp in Sources */,
5CA1DEC81F71F70100E71BD3 /* HTTPHeaderField.cpp in Sources */,
41EBA9F228ABA06700953013 /* ImageRotationSessionVT.cpp in Sources */,
46FA2FEE23846CA5000CCB0C /* HTTPHeaderMap.cpp in Sources */,
6B9ABE122086952F00D75DE6 /* HTTPParsers.cpp in Sources */,
5C7C24FC237C975400599C91 /* HTTPServer.mm in Sources */,
7B18417C2673860200ED4F8D /* ImageBufferTests.cpp in Sources */,
41EBA9F228ABA06700953013 /* ImageRotationSessionVT.cpp in Sources */,
F44A9AF72649BBDD00E7CB16 /* ImmediateActionTests.mm in Sources */,
7A95BDE11E9BEC5F00865498 /* InjectedBundleAppleEvent.cpp in Sources */,
7CCE7EFB1A411AE600447C4C /* InjectedBundleBasic.cpp in Sources */,
Expand Down
60 changes: 60 additions & 0 deletions Tools/TestWebKitAPI/Tests/WebKitCocoa/TextFragments.mm
@@ -0,0 +1,60 @@
/*
* Copyright (C) 2022 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/

#import "config.h"

#import "PlatformUtilities.h"
#import "Test.h"
#import "TestNavigationDelegate.h"
#import "TestWKWebView.h"
#import <WebKit/WKFoundation.h>
#import <WebKit/WKWebViewPrivate.h>
#import <wtf/RetainPtr.h>

TEST(WebKit, GetTextFragmentMatch)
{
auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 100, 100) configuration:configuration.get() addToWindow:YES]);

auto testTextFragment = ^(NSString *pageContent, NSString *textFragment, NSString *expectedResult) {
// Load an empty baseURL-less string, otherwise using the same baseURL (modulo the fragment) does a same-document navigation.
[webView synchronouslyLoadHTMLString:@""];
[webView synchronouslyLoadHTMLString:pageContent baseURL:[NSURL URLWithString:[@"http://example.com/" stringByAppendingString:textFragment]]];

__block bool isDone;
[webView _getTextFragmentMatchWithCompletionHandler:^(NSString *string) {
EXPECT_WK_STREQ(string, expectedResult);
isDone = true;
}];

TestWebKitAPI::Util::run(&isDone);
};

testTextFragment(@"hello world", @"#:~:text=hello%20world", @"hello world");
testTextFragment(@"<span id='the'>The</span> quick brown fox <span id='jumps'>jumps</span> over the lazy <span id='dog'>dog.</span>", @"#:~:text=quick,jumps", @"quick brown fox jumps");
testTextFragment(@"a the first match b the second match c", @"#:~:text=a-,the,match,-b", @"the first match");
testTextFragment(@"a the first match b the second match c", @"#:~:text=b-,the,match,-c", @"the second match");
testTextFragment(@"no match", @"#:~:text=hello%20world", nil);
}

0 comments on commit c2b3ade

Please sign in to comment.