Diff
Modified: trunk/Source/WebCore/ChangeLog (238470 => 238471)
--- trunk/Source/WebCore/ChangeLog 2018-11-24 18:37:14 UTC (rev 238470)
+++ trunk/Source/WebCore/ChangeLog 2018-11-24 21:06:09 UTC (rev 238471)
@@ -1,3 +1,18 @@
+2018-11-24 Wenson Hsieh <wenson_hs...@apple.com>
+
+ [Cocoa] Add WKWebView SPI to trigger and remove data detection
+ https://bugs.webkit.org/show_bug.cgi?id=191918
+ <rdar://problem/36185051>
+
+ Reviewed by Tim Horton.
+
+ Add a helper method on DataDetection to remove all data detected links in the given document. See WebKit changes
+ for more detail.
+
+ * editing/cocoa/DataDetection.h:
+ * editing/cocoa/DataDetection.mm:
+ (WebCore::DataDetection::removeDataDetectedLinksInDocument):
+
2018-11-24 Andy Estes <aes...@apple.com>
[Cocoa] SOFT_LINK_CLASS_FOR_{HEADER,SOURCE} should generate a more concise getter function
Modified: trunk/Source/WebCore/editing/cocoa/DataDetection.h (238470 => 238471)
--- trunk/Source/WebCore/editing/cocoa/DataDetection.h 2018-11-24 18:37:14 UTC (rev 238470)
+++ trunk/Source/WebCore/editing/cocoa/DataDetection.h 2018-11-24 21:06:09 UTC (rev 238471)
@@ -37,6 +37,7 @@
namespace WebCore {
+class Document;
class Element;
class FloatRect;
class HitTestResult;
@@ -61,6 +62,7 @@
WEBCORE_EXPORT static RetainPtr<DDActionContext> detectItemAroundHitTestResult(const HitTestResult&, FloatRect& detectedDataBoundingBox, RefPtr<Range>& detectedDataRange);
#endif
WEBCORE_EXPORT static NSArray *detectContentInRange(RefPtr<Range>& contextRange, DataDetectorTypes, NSDictionary *context);
+ WEBCORE_EXPORT static void removeDataDetectedLinksInDocument(Document&);
#if PLATFORM(IOS_FAMILY)
WEBCORE_EXPORT static bool canBePresentedByDataDetectors(const URL&);
WEBCORE_EXPORT static bool isDataDetectorLink(Element&);
Modified: trunk/Source/WebCore/editing/cocoa/DataDetection.mm (238470 => 238471)
--- trunk/Source/WebCore/editing/cocoa/DataDetection.mm 2018-11-24 18:37:14 UTC (rev 238470)
+++ trunk/Source/WebCore/editing/cocoa/DataDetection.mm 2018-11-24 21:06:09 UTC (rev 238471)
@@ -429,6 +429,16 @@
return kCFCompareEqualTo;
}
+void DataDetection::removeDataDetectedLinksInDocument(Document& document)
+{
+ Vector<Ref<HTMLAnchorElement>> allAnchorElements;
+ for (auto& anchor : descendantsOfType<HTMLAnchorElement>(document))
+ allAnchorElements.append(anchor);
+
+ for (auto& anchor : allAnchorElements)
+ removeResultLinksFromAnchor(anchor.get());
+}
+
NSArray *DataDetection::detectContentInRange(RefPtr<Range>& contextRange, DataDetectorTypes types, NSDictionary *context)
{
RetainPtr<DDScannerRef> scanner = adoptCF(softLink_DataDetectorsCore_DDScannerCreate(DDScannerTypeStandard, 0, nullptr));
@@ -647,10 +657,16 @@
}
#else
+
NSArray *DataDetection::detectContentInRange(RefPtr<Range>&, DataDetectorTypes, NSDictionary *)
{
return nil;
}
+
+void DataDetection::removeDataDetectedLinksInDocument(Document&)
+{
+}
+
#endif
const String& DataDetection::dataDetectorURLProtocol()
Modified: trunk/Source/WebKit/ChangeLog (238470 => 238471)
--- trunk/Source/WebKit/ChangeLog 2018-11-24 18:37:14 UTC (rev 238470)
+++ trunk/Source/WebKit/ChangeLog 2018-11-24 21:06:09 UTC (rev 238471)
@@ -1,3 +1,42 @@
+2018-11-24 Wenson Hsieh <wenson_hs...@apple.com>
+
+ [Cocoa] Add WKWebView SPI to trigger and remove data detection
+ https://bugs.webkit.org/show_bug.cgi?id=191918
+ <rdar://problem/36185051>
+
+ Reviewed by Tim Horton.
+
+ Adds support for two new WKWebView SPI methods, `-_detectDataWithTypes:completionHandler:` and
+ `-_removeAllDataDetectedLinks:`, to allow internal WebKit clients to run data detection and add links to data
+ detected content, or remove all data detected links from the document.
+
+ Test: WebKit.AddAndRemoveDataDetectors
+
+ * Shared/Cocoa/DataDetectionResult.h:
+ * Shared/Cocoa/DataDetectionResult.mm:
+ (WebKit::DataDetectionResult::decode):
+
+ Modernize DataDetectionResult's IPC decoding, so that it can be used with reply-based async IPC.
+
+ * UIProcess/API/Cocoa/WKWebView.mm:
+ (-[WKWebView _removeDataDetectedLinks:]):
+ (-[WKWebView _detectDataWithTypes:completionHandler:]):
+ * UIProcess/API/Cocoa/WKWebViewPrivate.h:
+ * UIProcess/WebPageProxy.cpp:
+ (WebKit::WebPageProxy::detectDataInAllFrames):
+ (WebKit::WebPageProxy::removeDataDetectedLinks):
+
+ Add or remove data detected links from each frame in the page, and then propagate the new data detector
+ results of the main frame to the UI process (this matches current behavior, where the results of -[WKWebView
+ _dataDetectionResults] only reflects data detection results in the main frame of the page).
+
+ * UIProcess/WebPageProxy.h:
+ * WebProcess/WebPage/WebPage.cpp:
+ (WebKit::WebPage::removeDataDetectedLinks):
+ (WebKit::WebPage::detectDataInAllFrames):
+ * WebProcess/WebPage/WebPage.h:
+ * WebProcess/WebPage/WebPage.messages.in:
+
2018-11-24 Andy Estes <aes...@apple.com>
[Cocoa] SOFT_LINK_CLASS_FOR_{HEADER,SOURCE} should generate a more concise getter function
Modified: trunk/Source/WebKit/Shared/Cocoa/DataDetectionResult.h (238470 => 238471)
--- trunk/Source/WebKit/Shared/Cocoa/DataDetectionResult.h 2018-11-24 18:37:14 UTC (rev 238470)
+++ trunk/Source/WebKit/Shared/Cocoa/DataDetectionResult.h 2018-11-24 21:06:09 UTC (rev 238471)
@@ -38,7 +38,7 @@
RetainPtr<NSArray> results;
void encode(IPC::Encoder&) const;
- static bool decode(IPC::Decoder&, DataDetectionResult&);
+ static std::optional<DataDetectionResult> decode(IPC::Decoder&);
};
}
Modified: trunk/Source/WebKit/Shared/Cocoa/DataDetectionResult.mm (238470 => 238471)
--- trunk/Source/WebKit/Shared/Cocoa/DataDetectionResult.mm 2018-11-24 18:37:14 UTC (rev 238470)
+++ trunk/Source/WebKit/Shared/Cocoa/DataDetectionResult.mm 2018-11-24 21:06:09 UTC (rev 238471)
@@ -46,22 +46,23 @@
IPC::encode(encoder, (__bridge CFDataRef)archiver.get().encodedData);
}
-bool DataDetectionResult::decode(IPC::Decoder& decoder, DataDetectionResult& result)
+std::optional<DataDetectionResult> DataDetectionResult::decode(IPC::Decoder& decoder)
{
RetainPtr<CFDataRef> data;
if (!IPC::decode(decoder, data))
- return false;
+ return std::nullopt;
+ DataDetectionResult result;
auto unarchiver = secureUnarchiverFromData((__bridge NSData *)data.get());
@try {
result.results = [unarchiver decodeObjectOfClasses:[NSSet setWithArray:@[ [NSArray class], getDDScannerResultClass()] ] forKey:@"dataDetectorResults"];
} @catch (NSException *exception) {
LOG_ERROR("Failed to decode NSArray of DDScanResult: %@", exception);
- return false;
+ return std::nullopt;
}
[unarchiver finishDecoding];
- return true;
+ return { WTFMove(result) };
}
#endif
Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm (238470 => 238471)
--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm 2018-11-24 18:37:14 UTC (rev 238470)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm 2018-11-24 21:06:09 UTC (rev 238471)
@@ -5423,10 +5423,39 @@
_page->setMuted(coreState);
}
+- (void)_removeDataDetectedLinks:(dispatch_block_t)completion
+{
+#if ENABLE(DATA_DETECTION)
+ _page->removeDataDetectedLinks([completion = makeBlockPtr(completion), page = makeWeakPtr(_page.get())] (auto& result) {
+ if (page)
+ page->setDataDetectionResult(result);
+ if (completion)
+ completion();
+ });
+#else
+ UNUSED_PARAM(completion);
+#endif
+}
+
#pragma mark iOS-specific methods
#if PLATFORM(IOS_FAMILY)
+- (void)_detectDataWithTypes:(WKDataDetectorTypes)types completionHandler:(dispatch_block_t)completion
+{
+#if ENABLE(DATA_DETECTION)
+ _page->detectDataInAllFrames(fromWKDataDetectorTypes(types), [completion = makeBlockPtr(completion), page = makeWeakPtr(_page.get())] (auto& result) {
+ if (page)
+ page->setDataDetectionResult(result);
+ if (completion)
+ completion();
+ });
+#else
+ UNUSED_PARAM(types);
+ UNUSED_PARAM(completion);
+#endif
+}
+
#if ENABLE(FULLSCREEN_API)
- (void)removeFromSuperview
{
Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h (238470 => 238471)
--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h 2018-11-24 18:37:14 UTC (rev 238470)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h 2018-11-24 21:06:09 UTC (rev 238471)
@@ -27,6 +27,7 @@
#if WK_API_ENABLED
+#import <WebKit/WKDataDetectorTypes.h>
#import <WebKit/_WKActivatedElementInfo.h>
#import <WebKit/_WKAttachment.h>
#import <WebKit/_WKFindOptions.h>
@@ -193,6 +194,8 @@
- (void)_showSafeBrowsingWarningWithTitle:(NSString *)title warning:(NSString *)warning details:(NSAttributedString *)details completionHandler:(void(^)(BOOL))completionHandler WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
- (void)_isJITEnabled:(void(^)(BOOL))completionHandler WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
+- (void)_removeDataDetectedLinks:(dispatch_block_t)completion WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
+
- (IBAction)_alignCenter:(id)sender WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
- (IBAction)_alignJustified:(id)sender WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
- (IBAction)_alignLeft:(id)sender WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
@@ -216,6 +219,8 @@
- (void)_setFontSize:(CGFloat)fontSize sender:(id)sender WK_API_AVAILABLE(ios(WK_IOS_TBA));
- (void)_setTextColor:(UIColor *)color sender:(id)sender WK_API_AVAILABLE(ios(WK_IOS_TBA));
+- (void)_detectDataWithTypes:(WKDataDetectorTypes)types completionHandler:(dispatch_block_t)completion WK_API_AVAILABLE(ios(WK_IOS_TBA));
+
// DERECATED: The setters of the three following function are deprecated, please use overrideLayoutParameters.
// Define the smallest size a page take with a regular viewport.
@property (nonatomic, readonly) CGSize _minimumLayoutSizeOverride;
Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (238470 => 238471)
--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp 2018-11-24 18:37:14 UTC (rev 238470)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp 2018-11-24 21:06:09 UTC (rev 238471)
@@ -8243,6 +8243,20 @@
#endif
}
+#if ENABLE(DATA_DETECTION)
+
+void WebPageProxy::detectDataInAllFrames(WebCore::DataDetectorTypes types, CompletionHandler<void(const DataDetectionResult&)>&& completionHandler)
+{
+ m_process->connection()->sendWithAsyncReply(Messages::WebPage::DetectDataInAllFrames(static_cast<uint64_t>(types)), WTFMove(completionHandler), m_pageID);
+}
+
+void WebPageProxy::removeDataDetectedLinks(CompletionHandler<void(const DataDetectionResult&)>&& completionHandler)
+{
+ m_process->connection()->sendWithAsyncReply(Messages::WebPage::RemoveDataDetectedLinks(), WTFMove(completionHandler), m_pageID);
+}
+
+#endif
+
} // namespace WebKit
#undef MERGE_WHEEL_EVENTS
Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (238470 => 238471)
--- trunk/Source/WebKit/UIProcess/WebPageProxy.h 2018-11-24 18:37:14 UTC (rev 238470)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h 2018-11-24 21:06:09 UTC (rev 238471)
@@ -362,6 +362,8 @@
#if ENABLE(DATA_DETECTION)
NSArray *dataDetectionResults() { return m_dataDetectionResults.get(); }
+ void detectDataInAllFrames(WebCore::DataDetectorTypes, CompletionHandler<void(const DataDetectionResult&)>&&);
+ void removeDataDetectedLinks(CompletionHandler<void(const DataDetectionResult&)>&&);
#endif
#if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA)
Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp (238470 => 238471)
--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp 2018-11-24 18:37:14 UTC (rev 238470)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp 2018-11-24 21:06:09 UTC (rev 238471)
@@ -3385,6 +3385,7 @@
}
#if ENABLE(DATA_DETECTION)
+
void WebPage::setDataDetectionResults(NSArray *detectionResults)
{
DataDetectionResult dataDetectionResult;
@@ -3391,8 +3392,36 @@
dataDetectionResult.results = detectionResults;
send(Messages::WebPageProxy::SetDataDetectionResult(dataDetectionResult));
}
-#endif
+void WebPage::removeDataDetectedLinks(Messages::WebPage::RemoveDataDetectedLinks::AsyncReply&& reply)
+{
+ for (auto frame = makeRefPtr(&m_page->mainFrame()); frame; frame = frame->tree().traverseNext()) {
+ auto document = makeRefPtr(frame->document());
+ if (!document)
+ continue;
+
+ DataDetection::removeDataDetectedLinksInDocument(*document);
+ frame->setDataDetectionResults(nullptr);
+ }
+ reply({ m_page->mainFrame().dataDetectionResults() });
+}
+
+void WebPage::detectDataInAllFrames(uint64_t types, Messages::WebPage::DetectDataInAllFrames::AsyncReply&& reply)
+{
+ auto dataDetectorTypes = static_cast<WebCore::DataDetectorTypes>(types);
+ for (auto frame = makeRefPtr(&m_page->mainFrame()); frame; frame = frame->tree().traverseNext()) {
+ auto document = makeRefPtr(frame->document());
+ if (!document)
+ continue;
+
+ RefPtr<Range> range = Range::create(*document, Position { document.get(), Position::PositionIsBeforeChildren }, Position { document.get(), Position::PositionIsAfterChildren });
+ frame->setDataDetectionResults(DataDetection::detectContentInRange(range, dataDetectorTypes, m_dataDetectionContext.get()));
+ }
+ reply({ m_page->mainFrame().dataDetectionResults() });
+}
+
+#endif // ENABLE(DATA_DETECTION)
+
#if PLATFORM(COCOA)
void WebPage::willCommitLayerTree(RemoteLayerTreeTransaction& layerTransaction)
{
Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.h (238470 => 238471)
--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.h 2018-11-24 18:37:14 UTC (rev 238470)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.h 2018-11-24 21:06:09 UTC (rev 238471)
@@ -48,6 +48,7 @@
#include "SharedMemory.h"
#include "UserData.h"
#include "WebBackForwardListProxy.h"
+#include "WebPageMessages.h"
#include "WebURLSchemeHandler.h"
#include "WebUserContentController.h"
#include <_javascript_Core/InspectorFrontendChannel.h>
@@ -92,7 +93,6 @@
#if PLATFORM(IOS_FAMILY)
#include "GestureTypes.h"
-#include "WebPageMessages.h"
#include <WebCore/IntPointHash.h>
#include <WebCore/ViewportConfiguration.h>
#endif
@@ -107,6 +107,10 @@
#include <WebCore/PlatformTouchEvent.h>
#endif
+#if ENABLE(DATA_DETECTION)
+#include <WebCore/DataDetection.h>
+#endif
+
#if ENABLE(MAC_GESTURE_EVENTS)
#include <WebKitAdditions/PlatformGestureEventMac.h>
#endif
@@ -992,6 +996,8 @@
#if ENABLE(DATA_DETECTION)
void setDataDetectionResults(NSArray *);
+ void detectDataInAllFrames(uint64_t, Messages::WebPage::DetectDataInAllFrames::AsyncReply&&);
+ void removeDataDetectedLinks(Messages::WebPage::RemoveDataDetectedLinks::AsyncReply&&);
#endif
unsigned extendIncrementalRenderingSuppression();
Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in (238470 => 238471)
--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in 2018-11-24 18:37:14 UTC (rev 238470)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in 2018-11-24 21:06:09 UTC (rev 238471)
@@ -193,6 +193,11 @@
PerformDictionaryLookupAtLocation(WebCore::FloatPoint point)
#endif
+#if ENABLE(DATA_DETECTION)
+ DetectDataInAllFrames(uint64_t types) -> (struct WebKit::DataDetectionResult result) Async
+ RemoveDataDetectedLinks() -> (struct WebKit::DataDetectionResult result) Async
+#endif
+
#if PLATFORM(MAC)
PerformDictionaryLookupOfCurrentSelection()
#endif
Modified: trunk/Tools/ChangeLog (238470 => 238471)
--- trunk/Tools/ChangeLog 2018-11-24 18:37:14 UTC (rev 238470)
+++ trunk/Tools/ChangeLog 2018-11-24 21:06:09 UTC (rev 238471)
@@ -1,3 +1,52 @@
+2018-11-24 Wenson Hsieh <wenson_hs...@apple.com>
+
+ [Cocoa] Add WKWebView SPI to trigger and remove data detection
+ https://bugs.webkit.org/show_bug.cgi?id=191918
+ <rdar://problem/36185051>
+
+ Reviewed by Tim Horton.
+
+ Add an API test to exercise the new WebKit SPI.
+
+ * TestWebKitAPI/DataDetectorsCoreSPI.h: Added.
+ * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+ * TestWebKitAPI/Tests/WebKitCocoa/DataDetection.mm:
+ (-[WKWebView synchronouslyDetectDataWithTypes:]):
+ (-[WKWebView synchronouslyRemoveDataDetectedLinks]):
+ (TEST):
+ * TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm:
+ (TestWebKitAPI::TEST):
+ (-[TestWKWebView tagsInBody]): Deleted.
+ (-[TestWKWebView expectElementTagsInOrder:]): Deleted.
+ (-[TestWKWebView expectElementCount:tagName:]): Deleted.
+ (-[TestWKWebView expectElementTag:toComeBefore:]): Deleted.
+
+ Rename this from `-expectElementCount:tagName:` to `-expectElementCount:querySelector:`.
+
+ * TestWebKitAPI/Tests/WebKitCocoa/data-detectors.html: Added.
+
+ Add a new test page containing some content that can be data detected.
+
+ * TestWebKitAPI/cocoa/TestWKWebView.h:
+ * TestWebKitAPI/cocoa/TestWKWebView.mm:
+ (-[WKWebView tagsInBody]):
+ (-[WKWebView expectElementTagsInOrder:]):
+ (-[WKWebView expectElementCount:querySelector:]):
+ (-[WKWebView expectElementTag:toComeBefore:]):
+
+ Move some testing helper functions from WKAttachmentTests to a testing category on WKWebView. This allows us to
+ use `-expectElementCount:querySelector:` in tests outside of WKAttachmentTests.
+
+ (-[WKWebView objectByEvaluatingJavaScript:]):
+ (-[WKWebView objectByEvaluatingJavaScriptWithUserGesture:]):
+ (-[WKWebView stringByEvaluatingJavaScript:]):
+
+ Move some common helper functions from TestWKWebView to a testing category on WKWebView.
+
+ (-[TestWKWebView objectByEvaluatingJavaScript:]): Deleted.
+ (-[TestWKWebView objectByEvaluatingJavaScriptWithUserGesture:]): Deleted.
+ (-[TestWKWebView stringByEvaluatingJavaScript:]): Deleted.
+
2018-11-23 Sam Weinig <s...@webkit.org>
Add raw pointer overloads to ListHashSet via SmartPtr specialized functions
Copied: trunk/Tools/TestWebKitAPI/DataDetectorsCoreSPI.h (from rev 238470, trunk/Source/WebKit/Shared/Cocoa/DataDetectionResult.h) (0 => 238471)
--- trunk/Tools/TestWebKitAPI/DataDetectorsCoreSPI.h (rev 0)
+++ trunk/Tools/TestWebKitAPI/DataDetectorsCoreSPI.h 2018-11-24 21:06:09 UTC (rev 238471)
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#pragma once
+
+#if ENABLE(DATA_DETECTION)
+
+#import <pal/spi/cocoa/DataDetectorsCoreSPI.h>
+
+#if !USE(APPLE_INTERNAL_SDK)
+
+@interface DDScannerResult (Private)
+@property (readonly, nonatomic) NSString *value;
+@property (readonly, nonatomic) NSString *type;
+@property (readonly, nonatomic) DDResultCategory category;
+@end
+
+#endif // !USE(APPLE_INTERNAL_SDK)
+
+#endif // ENABLE(DATA_DETECTION)
Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (238470 => 238471)
--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2018-11-24 18:37:14 UTC (rev 238470)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2018-11-24 21:06:09 UTC (rev 238471)
@@ -852,6 +852,7 @@
F46A095A1ED8A6E600D4AA55 /* apple.gif in Copy Resources */ = {isa = PBXBuildFile; fileRef = F47D30EB1ED28619000482E1 /* apple.gif */; };
F46A095B1ED8A6E600D4AA55 /* gif-and-file-input.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F47D30ED1ED28A6C000482E1 /* gif-and-file-input.html */; };
F47728991E4AE3C1007ABF6A /* full-page-contenteditable.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F47728981E4AE3AD007ABF6A /* full-page-contenteditable.html */; };
+ F47DFB2621A878DF00021FB6 /* data-detectors.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F47DFB2421A8704A00021FB6 /* data-detectors.html */; };
F4811E5921940BDE00A5E0FD /* WKWebViewEditActions.mm in Sources */ = {isa = PBXBuildFile; fileRef = F4811E5821940B4400A5E0FD /* WKWebViewEditActions.mm */; };
F4856CA31E649EA8009D7EE7 /* attachment-element.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4856CA21E6498A8009D7EE7 /* attachment-element.html */; };
F486B1D01F67952300F34BDD /* DataTransfer-setDragImage.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F486B1CF1F6794FF00F34BDD /* DataTransfer-setDragImage.html */; };
@@ -1019,6 +1020,7 @@
7AEAD4811E20122700416EFE /* CrossPartitionFileSchemeAccess.html in Copy Resources */,
F4AB578A1F65165400DB0DA1 /* custom-draggable-div.html in Copy Resources */,
290F4275172A221C00939FF0 /* custom-protocol-sync-xhr.html in Copy Resources */,
+ F47DFB2621A878DF00021FB6 /* data-detectors.html in Copy Resources */,
F486B1D01F67952300F34BDD /* DataTransfer-setDragImage.html in Copy Resources */,
F457A9D6202D68AF00F7E9D5 /* DataTransfer.html in Copy Resources */,
F4512E131F60C44600BB369E /* DataTransferItem-getAsEntry.html in Copy Resources */,
@@ -2147,6 +2149,8 @@
F47728981E4AE3AD007ABF6A /* full-page-contenteditable.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "full-page-contenteditable.html"; sourceTree = "<group>"; };
F47D30EB1ED28619000482E1 /* apple.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = apple.gif; sourceTree = "<group>"; };
F47D30ED1ED28A6C000482E1 /* gif-and-file-input.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "gif-and-file-input.html"; sourceTree = "<group>"; };
+ F47DFB2421A8704A00021FB6 /* data-detectors.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "data-detectors.html"; sourceTree = "<group>"; };
+ F47DFB2721A885E700021FB6 /* DataDetectorsCoreSPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DataDetectorsCoreSPI.h; sourceTree = "<group>"; };
F4811E5821940B4400A5E0FD /* WKWebViewEditActions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKWebViewEditActions.mm; sourceTree = "<group>"; };
F4856CA21E6498A8009D7EE7 /* attachment-element.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "attachment-element.html"; sourceTree = "<group>"; };
F486B1CF1F6794FF00F34BDD /* DataTransfer-setDragImage.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "DataTransfer-setDragImage.html"; sourceTree = "<group>"; };
@@ -2311,6 +2315,7 @@
A13EBB441B87332B00097110 /* WebProcessPlugIn */,
F4517B682054E0AC00C26721 /* ClassMethodSwizzler.h */,
F4517B692054E0AC00C26721 /* ClassMethodSwizzler.mm */,
+ F47DFB2721A885E700021FB6 /* DataDetectorsCoreSPI.h */,
F46128B4211C861A00D9FADB /* DragAndDropSimulator.h */,
F44D06481F3962E3001A0E29 /* EditingTestHarness.h */,
F44D06491F3962E3001A0E29 /* EditingTestHarness.mm */,
@@ -2740,6 +2745,7 @@
9B1056421F9047CC00D5583F /* copy-html.html */,
9B62630B1F8C2510007EE29B /* copy-url.html */,
F4AB57891F65164B00DB0DA1 /* custom-draggable-div.html */,
+ F47DFB2421A8704A00021FB6 /* data-detectors.html */,
F486B1CF1F6794FF00F34BDD /* DataTransfer-setDragImage.html */,
F457A9B3202D535300F7E9D5 /* DataTransfer.html */,
F4512E121F60C43400BB369E /* DataTransferItem-getAsEntry.html */,
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/DataDetection.mm (238470 => 238471)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/DataDetection.mm 2018-11-24 18:37:14 UTC (rev 238470)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/DataDetection.mm 2018-11-24 21:06:09 UTC (rev 238471)
@@ -25,14 +25,43 @@
#include "config.h"
+#import "DataDetectorsCoreSPI.h"
#import "PlatformUtilities.h"
#import "Test.h"
#import "TestNavigationDelegate.h"
+#import "TestWKWebView.h"
#import <WebKit/WebKit.h>
#import <wtf/RetainPtr.h>
#if WK_API_ENABLED && PLATFORM(IOS_FAMILY)
+@interface WKWebView (DataDetection)
+- (void)synchronouslyDetectDataWithTypes:(WKDataDetectorTypes)types;
+- (void)synchronouslyRemoveDataDetectedLinks;
+@end
+
+@implementation WKWebView (DataDetection)
+
+- (void)synchronouslyDetectDataWithTypes:(WKDataDetectorTypes)types
+{
+ __block bool done = false;
+ [self _detectDataWithTypes:types completionHandler:^{
+ done = true;
+ }];
+ TestWebKitAPI::Util::run(&done);
+}
+
+- (void)synchronouslyRemoveDataDetectedLinks
+{
+ __block bool done = false;
+ [self _removeDataDetectedLinks:^{
+ done = true;
+ }];
+ TestWebKitAPI::Util::run(&done);
+}
+
+@end
+
static bool ranScript;
@interface DataDetectionUIDelegate : NSObject <WKUIDelegate>
@@ -97,4 +126,39 @@
expectLinkCount(webView.get(), @"yesterday at 6PM", 1);
}
+TEST(WebKit, AddAndRemoveDataDetectors)
+{
+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
+ [webView synchronouslyLoadTestPageNamed:@"data-detectors"];
+ [webView expectElementCount:0 querySelector:@"a[x-apple-data-detectors=true]"];
+ EXPECT_EQ(0U, [webView _dataDetectionResults].count);
+
+ auto checkDataDetectionResults = [] (NSArray<DDScannerResult *> *results) {
+ EXPECT_EQ(3U, results.count);
+ EXPECT_EQ(DDResultCategoryUnknown, results[0].category);
+ EXPECT_TRUE([results[0].value containsString:@"+1-234-567-8900"]);
+ EXPECT_TRUE([results[0].value containsString:@"https://www.apple.com"]);
+ EXPECT_TRUE([results[0].value containsString:@"2 Apple Park Way, Cupertino 95014"]);
+ EXPECT_WK_STREQ("SignatureBlock", results[0].type);
+ EXPECT_EQ(DDResultCategoryCalendarEvent, results[1].category);
+ EXPECT_WK_STREQ("Date", results[1].type);
+ EXPECT_WK_STREQ("December 21, 2021", results[1].value);
+ EXPECT_EQ(DDResultCategoryMisc, results[2].category);
+ EXPECT_WK_STREQ("FlightInformation", results[2].type);
+ EXPECT_WK_STREQ("AC780", results[2].value);
+ };
+
+ [webView synchronouslyDetectDataWithTypes:WKDataDetectorTypeAll];
+ [webView expectElementCount:5 querySelector:@"a[x-apple-data-detectors=true]"];
+ checkDataDetectionResults([webView _dataDetectionResults]);
+
+ [webView synchronouslyRemoveDataDetectedLinks];
+ [webView expectElementCount:0 querySelector:@"a[x-apple-data-detectors=true]"];
+ EXPECT_EQ(0U, [webView _dataDetectionResults].count);
+
+ [webView synchronouslyDetectDataWithTypes:WKDataDetectorTypeAddress | WKDataDetectorTypePhoneNumber];
+ [webView expectElementCount:2 querySelector:@"a[x-apple-data-detectors=true]"];
+ checkDataDetectionResults([webView _dataDetectionResults]);
+}
+
#endif
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm (238470 => 238471)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm 2018-11-24 18:37:14 UTC (rev 238470)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm 2018-11-24 21:06:09 UTC (rev 238471)
@@ -215,37 +215,6 @@
@implementation TestWKWebView (AttachmentTesting)
-- (NSArray<NSString *> *)tagsInBody
-{
- return [self objectByEvaluatingJavaScript:@"Array.from(document.body.getElementsByTagName('*')).map(e => e.tagName)"];
-}
-
-- (void)expectElementTagsInOrder:(NSArray<NSString *> *)tagNames
-{
- auto remainingTags = adoptNS([tagNames mutableCopy]);
- NSArray<NSString *> *tagsInBody = self.tagsInBody;
- for (NSString *tag in tagsInBody.reverseObjectEnumerator) {
- if ([tag isEqualToString:[remainingTags lastObject]])
- [remainingTags removeLastObject];
- if (![remainingTags count])
- break;
- }
- EXPECT_EQ([remainingTags count], 0U);
- if ([remainingTags count])
- NSLog(@"Expected to find ordered tags: %@ in: %@", tagNames, tagsInBody);
-}
-
-- (void)expectElementCount:(NSInteger)count tagName:(NSString *)tagName
-{
- NSString *script = [NSString stringWithFormat:@"document.querySelectorAll('%@').length", tagName];
- EXPECT_EQ(count, [self stringByEvaluatingJavaScript:script].integerValue);
-}
-
-- (void)expectElementTag:(NSString *)tagName toComeBefore:(NSString *)otherTagName
-{
- [self expectElementTagsInOrder:@[tagName, otherTagName]];
-}
-
- (_WKAttachment *)synchronouslyInsertAttachmentWithFileWrapper:(NSFileWrapper *)fileWrapper contentType:(NSString *)contentType
{
__block bool done = false;
@@ -831,7 +800,7 @@
}
auto checkAttachmentConsistency = [webView, file, folder] (_WKAttachment *expectedFileAttachment, _WKAttachment *expectedFolderAttachment) {
- [webView expectElementCount:2 tagName:@"ATTACHMENT"];
+ [webView expectElementCount:2 querySelector:@"ATTACHMENT"];
EXPECT_TRUE(UTTypeConformsTo((__bridge CFStringRef)[webView valueOfAttribute:@"type" forQuerySelector:@"attachment[title=folder]"], kUTTypeDirectory));
EXPECT_TRUE(UTTypeConformsTo((__bridge CFStringRef)[webView valueOfAttribute:@"type" forQuerySelector:@"attachment[title^=test]"], kUTTypeData));
EXPECT_WK_STREQ(expectedFileAttachment.uniqueIdentifier, [webView stringByEvaluatingJavaScript:@"document.querySelector('attachment[title^=test]').uniqueIdentifier"]);
@@ -928,7 +897,7 @@
[webView _synchronouslyExecuteEditCommand:@"DeleteBackward" argument:nil];
[webView _synchronouslyExecuteEditCommand:@"DeleteBackward" argument:nil];
observer.expectAttachmentUpdates(@[ ], @[ ]);
- [webView expectElementCount:0 tagName:@"BR"];
+ [webView expectElementCount:0 querySelector:@"BR"];
}
}
@@ -971,13 +940,13 @@
[webView _executeEditCommand:@"InsertHTML" argument:@"<strong>text</strong>" completion:nil];
[webView _synchronouslyExecuteEditCommand:@"InsertParagraph" argument:nil];
[webView expectElementTag:@"IMG" toComeBefore:@"STRONG"];
- [webView expectElementCount:1 tagName:@"IMG"];
+ [webView expectElementCount:1 querySelector:@"IMG"];
// Drag the attachment element to somewhere below the strong text.
[simulator runFrom:CGPointMake(50, 50) to:CGPointMake(50, 350)];
[webView expectElementTag:@"STRONG" toComeBefore:@"IMG"];
- [webView expectElementCount:1 tagName:@"IMG"];
+ [webView expectElementCount:1 querySelector:@"IMG"];
EXPECT_EQ([simulator insertedAttachments].count, [simulator removedAttachments].count);
[simulator endDataTransfer];
@@ -1034,8 +1003,8 @@
}
EXPECT_TRUE(zipAttachment && imageAttachment && pdfAttachment);
- [webView expectElementCount:2 tagName:@"ATTACHMENT"];
- [webView expectElementCount:1 tagName:@"IMG"];
+ [webView expectElementCount:2 querySelector:@"ATTACHMENT"];
+ [webView expectElementCount:1 querySelector:@"IMG"];
EXPECT_WK_STREQ("application/pdf", [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[0].getAttribute('type')"]);
NSString *zipAttachmentType = [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[1].getAttribute('type')"];
@@ -1338,7 +1307,7 @@
ObserveAttachmentUpdatesForScope observer(webView.get());
[webView _synchronouslyExecuteEditCommand:@"Paste" argument:nil];
- [webView expectElementCount:2 tagName:@"IMG"];
+ [webView expectElementCount:2 querySelector:@"IMG"];
for (_WKAttachment *attachment in observer.observer().inserted) {
if ([attachment.info.contentType isEqualToString:@"image/png"])
@@ -1473,7 +1442,7 @@
auto secondWebView = webViewForTestingAttachments();
ObserveAttachmentUpdatesForScope observer(secondWebView.get());
[secondWebView paste:nil];
- [secondWebView expectElementCount:3 tagName:@"attachment"];
+ [secondWebView expectElementCount:3 querySelector:@"attachment"];
EXPECT_EQ(3U, observer.observer().inserted.count);
NSString *plainFileIdentifier = [secondWebView stringByEvaluatingJavaScript:@"document.querySelector('attachment[title^=test]').uniqueIdentifier"];
@@ -1516,8 +1485,8 @@
EXPECT_EQ(2U, [insertedAttachments count]);
}
- [webView expectElementCount:1 tagName:@"ATTACHMENT"];
- [webView expectElementCount:1 tagName:@"IMG"];
+ [webView expectElementCount:1 querySelector:@"ATTACHMENT"];
+ [webView expectElementCount:1 querySelector:@"IMG"];
EXPECT_WK_STREQ("application/pdf", [webView stringByEvaluatingJavaScript:@"document.querySelector('attachment').getAttribute('type')"]);
EXPECT_WK_STREQ("test.pdf", [webView stringByEvaluatingJavaScript:@"document.querySelector('attachment').getAttribute('title')"]);
@@ -1552,8 +1521,8 @@
[simulator runFrom:CGPointMake(0, 0) to:CGPointMake(50, 50)];
- [webView expectElementCount:1 tagName:@"ATTACHMENT"];
- [webView expectElementCount:1 tagName:@"IMG"];
+ [webView expectElementCount:1 querySelector:@"ATTACHMENT"];
+ [webView expectElementCount:1 querySelector:@"IMG"];
EXPECT_EQ(2U, [simulator insertedAttachments].count);
auto insertedAttachments = retainPtr([simulator insertedAttachments]);
@@ -1573,8 +1542,8 @@
[webView _synchronouslyExecuteEditCommand:@"DeleteBackward" argument:nil];
auto removedAttachments = retainPtr([simulator removedAttachments]);
EXPECT_EQ(2U, [removedAttachments count]);
- [webView expectElementCount:0 tagName:@"ATTACHMENT"];
- [webView expectElementCount:0 tagName:@"IMG"];
+ [webView expectElementCount:0 querySelector:@"ATTACHMENT"];
+ [webView expectElementCount:0 querySelector:@"IMG"];
EXPECT_TRUE([removedAttachments containsObject:[insertedAttachments firstObject]]);
EXPECT_TRUE([removedAttachments containsObject:[insertedAttachments lastObject]]);
}
@@ -1681,7 +1650,7 @@
for (_WKAttachment *attachment in [dragAndDropSimulator insertedAttachments])
EXPECT_GT([attachment info].data.length, 0U);
- [webView expectElementCount:2 tagName:@"ATTACHMENT"];
+ [webView expectElementCount:2 querySelector:@"ATTACHMENT"];
EXPECT_WK_STREQ("hello.rtf", [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[0].getAttribute('title')"]);
EXPECT_WK_STREQ("text/rtf", [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[0].getAttribute('type')"]);
EXPECT_WK_STREQ("world.txt", [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[1].getAttribute('title')"]);
@@ -1706,7 +1675,7 @@
EXPECT_EQ(1U, [dragAndDropSimulator insertedAttachments].count);
EXPECT_EQ(0U, [dragAndDropSimulator removedAttachments].count);
[[dragAndDropSimulator insertedAttachments].firstObject expectRequestedDataToBe:data];
- [webView expectElementCount:1 tagName:@"ATTACHMENT"];
+ [webView expectElementCount:1 querySelector:@"ATTACHMENT"];
EXPECT_WK_STREQ("archive.zip", [webView valueOfAttribute:@"title" forQuerySelector:@"attachment"]);
EXPECT_WK_STREQ("application/zip", [webView valueOfAttribute:@"type" forQuerySelector:@"attachment"]);
}
Added: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/data-detectors.html (0 => 238471)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/data-detectors.html (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/data-detectors.html 2018-11-24 21:06:09 UTC (rev 238471)
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<body>
+<table>
+<tbody>
+<tr>
+ <td>Telephone number</td>
+ <td>+1-234-567-8900</td>
+</tr>
+<tr>
+ <td>Link</td>
+ <td>https://www.apple.com</td>
+</tr>
+<tr>
+ <td>Address</td>
+ <td>2 Apple Park Way, Cupertino 95014</td>
+</tr>
+<tr>
+ <td>Calendar event</td>
+ <td>December 21, 2021</td>
+</tr>
+<tr>
+ <td>Flight number</td>
+ <td>AC780</td>
+</tr>
+</tbody>
+</table>
+</body>
+</html>
Modified: trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.h (238470 => 238471)
--- trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.h 2018-11-24 18:37:14 UTC (rev 238470)
+++ trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.h 2018-11-24 21:06:09 UTC (rev 238471)
@@ -48,7 +48,14 @@
@end
@interface WKWebView (TestWebKitAPI)
+@property (nonatomic, readonly) NSArray<NSString *> *tagsInBody;
- (BOOL)_synchronouslyExecuteEditCommand:(NSString *)command argument:(NSString *)argument;
+- (void)expectElementTagsInOrder:(NSArray<NSString *> *)tagNames;
+- (void)expectElementCount:(NSInteger)count querySelector:(NSString *)querySelector;
+- (void)expectElementTag:(NSString *)tagName toComeBefore:(NSString *)otherTagName;
+- (NSString *)stringByEvaluatingJavaScript:(NSString *)script;
+- (id)objectByEvaluatingJavaScriptWithUserGesture:(NSString *)script;
+- (id)objectByEvaluatingJavaScript:(NSString *)script;
@end
@interface TestMessageHandler : NSObject <WKScriptMessageHandler>
@@ -64,9 +71,6 @@
- (void)synchronouslyLoadHTMLString:(NSString *)html;
- (void)synchronouslyLoadHTMLString:(NSString *)html baseURL:(NSURL *)url;
- (void)synchronouslyLoadTestPageNamed:(NSString *)pageName;
-- (id)objectByEvaluatingJavaScript:(NSString *)script;
-- (id)objectByEvaluatingJavaScriptWithUserGesture:(NSString *)script;
-- (NSString *)stringByEvaluatingJavaScript:(NSString *)script;
- (void)waitForMessage:(NSString *)message;
- (void)performAfterLoading:(dispatch_block_t)actions;
- (void)waitForNextPresentationUpdate;
Modified: trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm (238470 => 238471)
--- trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm 2018-11-24 18:37:14 UTC (rev 238470)
+++ trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm 2018-11-24 21:06:09 UTC (rev 238471)
@@ -78,6 +78,72 @@
return success;
}
+- (NSArray<NSString *> *)tagsInBody
+{
+ return [self objectByEvaluatingJavaScript:@"Array.from(document.body.getElementsByTagName('*')).map(e => e.tagName)"];
+}
+
+- (void)expectElementTagsInOrder:(NSArray<NSString *> *)tagNames
+{
+ auto remainingTags = adoptNS([tagNames mutableCopy]);
+ NSArray<NSString *> *tagsInBody = self.tagsInBody;
+ for (NSString *tag in tagsInBody.reverseObjectEnumerator) {
+ if ([tag isEqualToString:[remainingTags lastObject]])
+ [remainingTags removeLastObject];
+ if (![remainingTags count])
+ break;
+ }
+ EXPECT_EQ([remainingTags count], 0U);
+ if ([remainingTags count])
+ NSLog(@"Expected to find ordered tags: %@ in: %@", tagNames, tagsInBody);
+}
+
+- (void)expectElementCount:(NSInteger)count querySelector:(NSString *)querySelector
+{
+ NSString *script = [NSString stringWithFormat:@"document.querySelectorAll('%@').length", querySelector];
+ EXPECT_EQ(count, [self stringByEvaluatingJavaScript:script].integerValue);
+}
+
+- (void)expectElementTag:(NSString *)tagName toComeBefore:(NSString *)otherTagName
+{
+ [self expectElementTagsInOrder:@[tagName, otherTagName]];
+}
+
+- (id)objectByEvaluatingJavaScript:(NSString *)script
+{
+ bool isWaitingForJavaScript = false;
+ RetainPtr<id> evalResult;
+ [self _evaluateJavaScriptWithoutUserGesture:script completionHandler:[&] (id result, NSError *error) {
+ evalResult = result;
+ isWaitingForJavaScript = true;
+ EXPECT_TRUE(!error);
+ if (error)
+ NSLog(@"Encountered error: %@ while evaluating script: %@", error, script);
+ }];
+ TestWebKitAPI::Util::run(&isWaitingForJavaScript);
+ return evalResult.autorelease();
+}
+
+- (id)objectByEvaluatingJavaScriptWithUserGesture:(NSString *)script
+{
+ bool isWaitingForJavaScript = false;
+ RetainPtr<id> evalResult;
+ [self evaluateJavaScript:script completionHandler:[&] (id result, NSError *error) {
+ evalResult = result;
+ isWaitingForJavaScript = true;
+ EXPECT_TRUE(!error);
+ if (error)
+ NSLog(@"Encountered error: %@ while evaluating script: %@", error, script);
+ }];
+ TestWebKitAPI::Util::run(&isWaitingForJavaScript);
+ return evalResult.autorelease();
+}
+
+- (NSString *)stringByEvaluatingJavaScript:(NSString *)script
+{
+ return [NSString stringWithFormat:@"%@", [self objectByEvaluatingJavaScript:script]];
+}
+
@end
@implementation TestMessageHandler {
@@ -289,41 +355,6 @@
[self _test_waitForDidFinishNavigation];
}
-- (id)objectByEvaluatingJavaScript:(NSString *)script
-{
- bool isWaitingForJavaScript = false;
- RetainPtr<id> evalResult;
- [self _evaluateJavaScriptWithoutUserGesture:script completionHandler:[&] (id result, NSError *error) {
- evalResult = result;
- isWaitingForJavaScript = true;
- EXPECT_TRUE(!error);
- if (error)
- NSLog(@"Encountered error: %@ while evaluating script: %@", error, script);
- }];
- TestWebKitAPI::Util::run(&isWaitingForJavaScript);
- return evalResult.autorelease();
-}
-
-- (id)objectByEvaluatingJavaScriptWithUserGesture:(NSString *)script
-{
- bool isWaitingForJavaScript = false;
- RetainPtr<id> evalResult;
- [self evaluateJavaScript:script completionHandler:[&] (id result, NSError *error) {
- evalResult = result;
- isWaitingForJavaScript = true;
- EXPECT_TRUE(!error);
- if (error)
- NSLog(@"Encountered error: %@ while evaluating script: %@", error, script);
- }];
- TestWebKitAPI::Util::run(&isWaitingForJavaScript);
- return evalResult.autorelease();
-}
-
-- (NSString *)stringByEvaluatingJavaScript:(NSString *)script
-{
- return [NSString stringWithFormat:@"%@", [self objectByEvaluatingJavaScript:script]];
-}
-
- (void)waitForMessage:(NSString *)message
{
__block bool isDoneWaiting = false;