Diff
Modified: trunk/Source/WebCore/ChangeLog (277315 => 277316)
--- trunk/Source/WebCore/ChangeLog 2021-05-11 02:14:57 UTC (rev 277315)
+++ trunk/Source/WebCore/ChangeLog 2021-05-11 04:31:16 UTC (rev 277316)
@@ -1,3 +1,34 @@
+2021-05-10 Wenson Hsieh <[email protected]>
+
+ [macOS] Allow immediate action gestures to begin when force clicking text inside image overlays
+ https://bugs.webkit.org/show_bug.cgi?id=225600
+ <rdar://problem/77792365>
+
+ Reviewed by Tim Horton.
+
+ Allow immediate action hit-testing to descend into image overlay content. Currently, this uses the
+ `DisallowsUserAgentShadowContent` hit-testing option, causing us to ignore image overlays (which exist inside
+ the UA shadow root). To fix this, we introduce a `DisallowsUserAgentShadowContentExceptForImageOverlays` option
+ that behaves like the existing `DisallowsUserAgentShadowContent` option, with the exception that we allow hit-
+ testing to pierce the UA shadow root to find nodes inside image overlays.
+
+ Tests: ImmediateActionTests.ImmediateActionOverText
+ ImmediateActionTests.ImmediateActionOverBody
+ ImmediateActionTests.ImmediateActionOverImageOverlay
+
+ * page/EventHandler.cpp:
+ (WebCore::EventHandler::hitTestResultAtPoint const):
+ * rendering/HitTestRequest.h:
+
+ Add support for the new hit-test option, which allows hit-testing to descend into image overlays (and is
+ intended to be mutually exclusive with the existing `DisallowsUserAgentShadowContent` option). Specifying both
+ options will lead to an assertion on debug builds, and `DisallowsUserAgentShadowContent` takes precedence on
+ release builds.
+
+ (WebCore::HitTestRequest::disallowsUserAgentShadowContentExceptForImageOverlays const):
+ * rendering/HitTestResult.cpp:
+ (WebCore::HitTestResult::addNodeToListBasedTestResultCommon):
+
2021-05-10 Sam Weinig <[email protected]>
Use PixelBuffer rather than ImageData in platform/ code to fix layering violation
Modified: trunk/Source/WebCore/PAL/ChangeLog (277315 => 277316)
--- trunk/Source/WebCore/PAL/ChangeLog 2021-05-11 02:14:57 UTC (rev 277315)
+++ trunk/Source/WebCore/PAL/ChangeLog 2021-05-11 04:31:16 UTC (rev 277316)
@@ -1,3 +1,13 @@
+2021-05-10 Wenson Hsieh <[email protected]>
+
+ [macOS] Allow immediate action gestures to begin when force clicking text inside image overlays
+ https://bugs.webkit.org/show_bug.cgi?id=225600
+ <rdar://problem/77792365>
+
+ Reviewed by Tim Horton.
+
+ * pal/spi/mac/NSImmediateActionGestureRecognizerSPI.h:
+
2021-04-29 Jean-Yves Avenard <[email protected]>
Adopt AVSampleBufferAudioRendererWasFlushedAutomaticallyNotification
Modified: trunk/Source/WebCore/PAL/pal/spi/mac/NSImmediateActionGestureRecognizerSPI.h (277315 => 277316)
--- trunk/Source/WebCore/PAL/pal/spi/mac/NSImmediateActionGestureRecognizerSPI.h 2021-05-11 02:14:57 UTC (rev 277315)
+++ trunk/Source/WebCore/PAL/pal/spi/mac/NSImmediateActionGestureRecognizerSPI.h 2021-05-11 04:31:16 UTC (rev 277316)
@@ -56,6 +56,7 @@
@interface NSImmediateActionGestureRecognizer : NSGestureRecognizer
+@property (weak) id <NSImmediateActionGestureRecognizerDelegate> delegate;
@property (strong) id<NSImmediateActionAnimationController> animationController;
@property (readonly) CGFloat animationProgress;
Modified: trunk/Source/WebCore/page/EventHandler.cpp (277315 => 277316)
--- trunk/Source/WebCore/page/EventHandler.cpp 2021-05-11 02:14:57 UTC (rev 277315)
+++ trunk/Source/WebCore/page/EventHandler.cpp 2021-05-11 04:31:16 UTC (rev 277316)
@@ -1190,7 +1190,9 @@
if (!request.readOnly())
m_frame.document()->updateHoverActiveState(request, result.targetElement());
- if (request.disallowsUserAgentShadowContent())
+ auto innerNode = makeRefPtr(result.innerNode());
+ if (request.disallowsUserAgentShadowContent()
+ || (request.disallowsUserAgentShadowContentExceptForImageOverlays() && innerNode && !HTMLElement::isInsideImageOverlay(*innerNode)))
result.setToNonUserAgentShadowAncestor();
return result;
Modified: trunk/Source/WebCore/rendering/HitTestRequest.h (277315 => 277316)
--- trunk/Source/WebCore/rendering/HitTestRequest.h 2021-05-11 02:14:57 UTC (rev 277315)
+++ trunk/Source/WebCore/rendering/HitTestRequest.h 2021-05-11 04:31:16 UTC (rev 277316)
@@ -39,20 +39,22 @@
SVGClipContent = 1 << 6,
TouchEvent = 1 << 7,
DisallowUserAgentShadowContent = 1 << 8,
- AllowFrameScrollbars = 1 << 9,
- AllowChildFrameContent = 1 << 10,
- AllowVisibleChildFrameContentOnly = 1 << 11,
- ChildFrameHitTest = 1 << 12,
- AccessibilityHitTest = 1 << 13,
+ DisallowUserAgentShadowContentExceptForImageOverlays = 1 << 9,
+ AllowFrameScrollbars = 1 << 10,
+ AllowChildFrameContent = 1 << 11,
+ AllowVisibleChildFrameContentOnly = 1 << 12,
+ ChildFrameHitTest = 1 << 13,
+ AccessibilityHitTest = 1 << 14,
// Collect a list of nodes instead of just one. Used for elementsFromPoint and rect-based tests.
- CollectMultipleElements = 1 << 14,
+ CollectMultipleElements = 1 << 15,
// When using list-based testing, continue hit testing even after a hit has been found.
- IncludeAllElementsUnderPoint = 1 << 15,
+ IncludeAllElementsUnderPoint = 1 << 16,
};
HitTestRequest(OptionSet<Type> type = { Type::ReadOnly, Type::Active, Type::DisallowUserAgentShadowContent })
: m_type { type }
{
+ ASSERT(!type.containsAll({ Type::DisallowUserAgentShadowContentExceptForImageOverlays, Type::DisallowUserAgentShadowContent }));
ASSERT_IMPLIES(type.contains(Type::IncludeAllElementsUnderPoint), type.contains(Type::CollectMultipleElements));
}
@@ -66,6 +68,7 @@
bool touchEvent() const { return m_type.contains(Type::TouchEvent); }
bool mouseEvent() const { return !touchEvent(); }
bool disallowsUserAgentShadowContent() const { return m_type.contains(Type::DisallowUserAgentShadowContent); }
+ bool disallowsUserAgentShadowContentExceptForImageOverlays() const { return m_type.contains(Type::DisallowUserAgentShadowContentExceptForImageOverlays); }
bool allowsFrameScrollbars() const { return m_type.contains(Type::AllowFrameScrollbars); }
bool allowsChildFrameContent() const { return m_type.contains(Type::AllowChildFrameContent); }
bool allowsVisibleChildFrameContent() const { return m_type.contains(Type::AllowVisibleChildFrameContentOnly); }
Modified: trunk/Source/WebCore/rendering/HitTestResult.cpp (277315 => 277316)
--- trunk/Source/WebCore/rendering/HitTestResult.cpp 2021-05-11 02:14:57 UTC (rev 277315)
+++ trunk/Source/WebCore/rendering/HitTestResult.cpp 2021-05-11 04:31:16 UTC (rev 277316)
@@ -656,7 +656,8 @@
if (!node)
return HitTestProgress::Continue;
- if (request.disallowsUserAgentShadowContent() && node->isInUserAgentShadowTree())
+ if ((request.disallowsUserAgentShadowContent() && node->isInUserAgentShadowTree())
+ || (request.disallowsUserAgentShadowContentExceptForImageOverlays() && !HTMLElement::isInsideImageOverlay(*node) && node->isInUserAgentShadowTree()))
node = node->document().ancestorNodeInThisScope(node);
mutableListBasedTestResult().add(*node);
Modified: trunk/Source/WebKit/ChangeLog (277315 => 277316)
--- trunk/Source/WebKit/ChangeLog 2021-05-11 02:14:57 UTC (rev 277315)
+++ trunk/Source/WebKit/ChangeLog 2021-05-11 04:31:16 UTC (rev 277316)
@@ -1,3 +1,17 @@
+2021-05-10 Wenson Hsieh <[email protected]>
+
+ [macOS] Allow immediate action gestures to begin when force clicking text inside image overlays
+ https://bugs.webkit.org/show_bug.cgi?id=225600
+ <rdar://problem/77792365>
+
+ Reviewed by Tim Horton.
+
+ Adopt the new hit-test option. See WebCore/ChangeLog for more details.
+
+ * WebProcess/WebPage/mac/WebPageMac.mm:
+ (WebKit::WebPage::performImmediateActionHitTestAtLocation):
+ (WebKit::WebPage::lookupTextAtLocation):
+
2021-05-10 Sam Weinig <[email protected]>
Use PixelBuffer rather than ImageData in platform/ code to fix layering violation
Modified: trunk/Source/WebKit/WebProcess/WebPage/mac/WebPageMac.mm (277315 => 277316)
--- trunk/Source/WebKit/WebProcess/WebPage/mac/WebPageMac.mm 2021-05-11 02:14:57 UTC (rev 277315)
+++ trunk/Source/WebKit/WebProcess/WebPage/mac/WebPageMac.mm 2021-05-11 04:31:16 UTC (rev 277316)
@@ -858,9 +858,13 @@
return;
}
- IntPoint locationInContentCoordinates = mainFrame.view()->rootViewToContents(roundedIntPoint(locationInViewCoordinates));
- constexpr OptionSet<HitTestRequest::Type> hitType { HitTestRequest::Type::ReadOnly, HitTestRequest::Type::Active, HitTestRequest::Type::DisallowUserAgentShadowContent, HitTestRequest::Type::AllowChildFrameContent };
- HitTestResult hitTestResult = mainFrame.eventHandler().hitTestResultAtPoint(locationInContentCoordinates, hitType);
+ auto locationInContentCoordinates = mainFrame.view()->rootViewToContents(roundedIntPoint(locationInViewCoordinates));
+ auto hitTestResult = mainFrame.eventHandler().hitTestResultAtPoint(locationInContentCoordinates, {
+ HitTestRequest::Type::ReadOnly,
+ HitTestRequest::Type::Active,
+ HitTestRequest::Type::DisallowUserAgentShadowContentExceptForImageOverlays,
+ HitTestRequest::Type::AllowChildFrameContent,
+ });
bool immediateActionHitTestPreventsDefault = false;
Element* element = hitTestResult.targetElement();
@@ -958,10 +962,12 @@
if (!mainFrame.view() || !mainFrame.view()->renderView())
return WTF::nullopt;
- auto point = roundedIntPoint(locationInViewCoordinates);
- constexpr OptionSet<HitTestRequest::Type> hitType { HitTestRequest::Type::ReadOnly, HitTestRequest::Type::Active, HitTestRequest::Type::DisallowUserAgentShadowContent, HitTestRequest::Type::AllowChildFrameContent };
- auto result = mainFrame.eventHandler().hitTestResultAtPoint(m_page->mainFrame().view()->windowToContents(point), hitType);
- return DictionaryLookup::rangeAtHitTestResult(result);
+ return DictionaryLookup::rangeAtHitTestResult(mainFrame.eventHandler().hitTestResultAtPoint(m_page->mainFrame().view()->windowToContents(roundedIntPoint(locationInViewCoordinates)), {
+ HitTestRequest::Type::ReadOnly,
+ HitTestRequest::Type::Active,
+ HitTestRequest::Type::DisallowUserAgentShadowContentExceptForImageOverlays,
+ HitTestRequest::Type::AllowChildFrameContent,
+ }));
}
void WebPage::immediateActionDidUpdate()
Modified: trunk/Tools/ChangeLog (277315 => 277316)
--- trunk/Tools/ChangeLog 2021-05-11 02:14:57 UTC (rev 277315)
+++ trunk/Tools/ChangeLog 2021-05-11 04:31:16 UTC (rev 277316)
@@ -1,3 +1,25 @@
+2021-05-10 Wenson Hsieh <[email protected]>
+
+ [macOS] Allow immediate action gestures to begin when force clicking text inside image overlays
+ https://bugs.webkit.org/show_bug.cgi?id=225600
+ <rdar://problem/77792365>
+
+ Reviewed by Tim Horton.
+
+ Add new API tests to exercise these changes by grabbing the immediate action `NSGestureRecognizer` from
+ `WKWebView` and calling into its delegate. This patch adds two basic immediate action tests by simulating the
+ immediate action over text and the body element, and includes a third test that installs an image overlay using
+ an injected `internals` object, and verifies that the immediate action in an image overlay matches that of
+ regular text on the page.
+
+ * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+ * TestWebKitAPI/Tests/mac/ImmediateActionTests.mm: Added.
+ (swizzledImmediateActionLocationInView):
+ (-[WKWebViewForTestingImmediateActions _immediateActionAnimationControllerForHitTestResult:withType:userData:]):
+ (-[WKWebViewForTestingImmediateActions immediateActionGesture]):
+ (-[WKWebViewForTestingImmediateActions simulateImmediateAction:]):
+ (TestWebKitAPI::TEST):
+
2021-05-10 Kate Cheney <[email protected]>
Preflight requests not properly attributed as app-bound
Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (277315 => 277316)
--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2021-05-11 02:14:57 UTC (rev 277315)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2021-05-11 04:31:16 UTC (rev 277316)
@@ -868,8 +868,8 @@
93F56DA71E5F9174003EDE84 /* libicucore.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 7C83E0331D0A5F2700FEBCF3 /* libicucore.dylib */; };
93F56DA91E5F919D003EDE84 /* WKWebViewSnapshot.mm in Sources */ = {isa = PBXBuildFile; fileRef = 93F56DA81E5F9181003EDE84 /* WKWebViewSnapshot.mm */; };
93F7E86F14DC8E5C00C84A99 /* NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93F7E86E14DC8E5B00C84A99 /* NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp */; };
+ 93FCDB34263631560046DD7D /* SortedArrayMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93FCDB33263631560046DD7D /* SortedArrayMap.cpp */; };
95095F20262FFFA50000D920 /* SampledPageTopColor.mm in Sources */ = {isa = PBXBuildFile; fileRef = 95095F1F262FFFA50000D920 /* SampledPageTopColor.mm */; };
- 93FCDB34263631560046DD7D /* SortedArrayMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93FCDB33263631560046DD7D /* SortedArrayMap.cpp */; };
950E4CC1252E75240071659F /* iOSStylusSupport.mm in Sources */ = {isa = PBXBuildFile; fileRef = 950E4CC0252E75230071659F /* iOSStylusSupport.mm */; };
953ABB3525C0D682004C8B73 /* PageExtendedBackgroundColor.mm in Sources */ = {isa = PBXBuildFile; fileRef = 953ABB3425C0D681004C8B73 /* PageExtendedBackgroundColor.mm */; };
95A524952581A10D00461FE9 /* WKWebViewThemeColor.mm in Sources */ = {isa = PBXBuildFile; fileRef = 95A524942581A10D00461FE9 /* WKWebViewThemeColor.mm */; };
@@ -1179,6 +1179,7 @@
F442851D2140DF2900CCDA22 /* NSFontPanelTesting.mm in Sources */ = {isa = PBXBuildFile; fileRef = F442851C2140DF2900CCDA22 /* NSFontPanelTesting.mm */; };
F4451C761EB8FD890020C5DA /* two-paragraph-contenteditable.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4451C751EB8FD7C0020C5DA /* two-paragraph-contenteditable.html */; };
F44A531121B8990300DBB99C /* InstanceMethodSwizzler.mm in Sources */ = {isa = PBXBuildFile; fileRef = F44A531021B8976900DBB99C /* InstanceMethodSwizzler.mm */; };
+ F44A9AF72649BBDD00E7CB16 /* ImmediateActionTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = F44A9AF62649BBDD00E7CB16 /* ImmediateActionTests.mm */; };
F44C79FF20F9E8710014478C /* ParserYieldTokenTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = F44C79FE20F9E8710014478C /* ParserYieldTokenTests.mm */; };
F44C7A0020F9EEBF0014478C /* ParserYieldTokenPlugIn.mm in Sources */ = {isa = PBXBuildFile; fileRef = F44C79FB20F9E50C0014478C /* ParserYieldTokenPlugIn.mm */; };
F44C7A0520FAAE3C0014478C /* text-with-deferred-script.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F44C7A0420FAAE320014478C /* text-with-deferred-script.html */; };
@@ -2565,8 +2566,8 @@
93F56DA81E5F9181003EDE84 /* WKWebViewSnapshot.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKWebViewSnapshot.mm; sourceTree = "<group>"; };
93F7E86B14DC8E4D00C84A99 /* NewFirstVisuallyNonEmptyLayoutFrames.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NewFirstVisuallyNonEmptyLayoutFrames.cpp; sourceTree = "<group>"; };
93F7E86E14DC8E5B00C84A99 /* NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp; sourceTree = "<group>"; };
+ 93FCDB33263631560046DD7D /* SortedArrayMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SortedArrayMap.cpp; sourceTree = "<group>"; };
95095F1F262FFFA50000D920 /* SampledPageTopColor.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SampledPageTopColor.mm; sourceTree = "<group>"; };
- 93FCDB33263631560046DD7D /* SortedArrayMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SortedArrayMap.cpp; sourceTree = "<group>"; };
950E4CC0252E75230071659F /* iOSStylusSupport.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = iOSStylusSupport.mm; sourceTree = "<group>"; };
953ABB3425C0D681004C8B73 /* PageExtendedBackgroundColor.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PageExtendedBackgroundColor.mm; sourceTree = "<group>"; };
95A524942581A10D00461FE9 /* WKWebViewThemeColor.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKWebViewThemeColor.mm; sourceTree = "<group>"; };
@@ -2997,6 +2998,8 @@
F44A530E21B8976900DBB99C /* ClassMethodSwizzler.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ClassMethodSwizzler.mm; path = ../TestRunnerShared/cocoa/ClassMethodSwizzler.mm; sourceTree = "<group>"; };
F44A530F21B8976900DBB99C /* ClassMethodSwizzler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClassMethodSwizzler.h; path = ../TestRunnerShared/cocoa/ClassMethodSwizzler.h; sourceTree = "<group>"; };
F44A531021B8976900DBB99C /* InstanceMethodSwizzler.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = InstanceMethodSwizzler.mm; path = ../TestRunnerShared/cocoa/InstanceMethodSwizzler.mm; sourceTree = "<group>"; };
+ F44A9AF52649BBDD00E7CB16 /* ImmediateActionTests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ImmediateActionTests.h; sourceTree = "<group>"; };
+ F44A9AF62649BBDD00E7CB16 /* ImmediateActionTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ImmediateActionTests.mm; sourceTree = "<group>"; };
F44C79FB20F9E50C0014478C /* ParserYieldTokenPlugIn.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ParserYieldTokenPlugIn.mm; sourceTree = "<group>"; };
F44C79FD20F9E8710014478C /* ParserYieldTokenTests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ParserYieldTokenTests.h; sourceTree = "<group>"; };
F44C79FE20F9E8710014478C /* ParserYieldTokenTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ParserYieldTokenTests.mm; sourceTree = "<group>"; };
@@ -4680,6 +4683,8 @@
51EB125824C68589000CB030 /* HIDGamepads.mm */,
9B4F8FA3159D52B1002D9F94 /* HTMLCollectionNamedItem.mm */,
9B26FC6B159D061000CC3765 /* HTMLFormCollectionNamedItem.mm */,
+ F44A9AF52649BBDD00E7CB16 /* ImmediateActionTests.h */,
+ F44A9AF62649BBDD00E7CB16 /* ImmediateActionTests.mm */,
C507E8A614C6545B005D6B3B /* InspectorBar.mm */,
57F10D921C7E7B3800ECDF30 /* IsNavigationActionTrusted.mm */,
51820A4C22F4EE7700DF0A01 /* _javascript_URLNavigation.mm */,
@@ -5467,6 +5472,7 @@
510477781D29923B009747EB /* IDBDeleteRecovery.mm in Sources */,
5110FCFA1E01CDB8006F8D0B /* IDBIndexUpgradeToV2.mm in Sources */,
93BCBC8323CC6F2A00CA2221 /* IDBObjectStoreInfoUpgradeToV2.mm in Sources */,
+ F44A9AF72649BBDD00E7CB16 /* ImmediateActionTests.mm in Sources */,
49AEEF6D2407359D00C87E4C /* InAppBrowserPrivacy.mm in Sources */,
51A587861D273AA9004BA9AF /* IndexedDBDatabaseProcessKill.mm in Sources */,
CAB0FF5522332C57006CA5B0 /* IndexedDBFileName.mm in Sources */,
Added: trunk/Tools/TestWebKitAPI/Tests/mac/ImmediateActionTests.mm (0 => 277316)
--- trunk/Tools/TestWebKitAPI/Tests/mac/ImmediateActionTests.mm (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/mac/ImmediateActionTests.mm 2021-05-11 04:31:16 UTC (rev 277316)
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2021 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 "Test.h"
+
+#if PLATFORM(MAC)
+
+#import "InstanceMethodSwizzler.h"
+#import "PlatformUtilities.h"
+#import "TestWKWebView.h"
+#import "WKWebViewConfigurationExtras.h"
+#import <WebKit/WKWebViewPrivate.h>
+#import <WebKit/_WKHitTestResult.h>
+#import <pal/spi/mac/NSImmediateActionGestureRecognizerSPI.h>
+#import <wtf/RetainPtr.h>
+
+static NSPoint gSwizzledImmediateActionLocation = NSZeroPoint;
+static NSPoint swizzledImmediateActionLocationInView(id, SEL, NSView *)
+{
+ return gSwizzledImmediateActionLocation;
+}
+
+using ImmediateActionHitTestResult = std::pair<RetainPtr<_WKHitTestResult>, _WKImmediateActionType>;
+
+@interface WKWebViewForTestingImmediateActions : TestWKWebView
+
+@property (nonatomic, readonly) NSImmediateActionGestureRecognizer *immediateActionGesture;
+
+- (ImmediateActionHitTestResult)simulateImmediateAction:(NSPoint)location;
+
+@end
+
+@implementation WKWebViewForTestingImmediateActions {
+ bool _hasReturnedImmediateActionController;
+ RetainPtr<_WKHitTestResult> _hitTestResult;
+ _WKImmediateActionType _actionType;
+}
+
+- (id)_immediateActionAnimationControllerForHitTestResult:(_WKHitTestResult *)hitTestResult withType:(_WKImmediateActionType)type userData:(id <NSSecureCoding>)userData
+{
+ _hasReturnedImmediateActionController = true;
+ _hitTestResult = hitTestResult;
+ _actionType = type;
+ return [super _immediateActionAnimationControllerForHitTestResult:hitTestResult withType:type userData:userData];
+}
+
+- (NSImmediateActionGestureRecognizer *)immediateActionGesture
+{
+ for (NSGestureRecognizer *gesture in [self gestureRecognizers]) {
+ if ([gesture isKindOfClass:NSImmediateActionGestureRecognizer.class])
+ return static_cast<NSImmediateActionGestureRecognizer *>(gesture);
+ }
+ return nil;
+}
+
+- (ImmediateActionHitTestResult)simulateImmediateAction:(NSPoint)location
+{
+ auto immediateActionGesture = self.immediateActionGesture;
+ if (!immediateActionGesture.delegate)
+ return ImmediateActionHitTestResult { nil, _WKImmediateActionNone };
+
+ _hasReturnedImmediateActionController = false;
+
+ InstanceMethodSwizzler swizzleLocationInView {
+ NSImmediateActionGestureRecognizer.class,
+ @selector(locationInView:),
+ reinterpret_cast<IMP>(swizzledImmediateActionLocationInView),
+ };
+
+ gSwizzledImmediateActionLocation = location;
+ [immediateActionGesture.delegate immediateActionRecognizerWillPrepare:immediateActionGesture];
+
+ TestWebKitAPI::Util::run(&_hasReturnedImmediateActionController);
+
+ _hasReturnedImmediateActionController = false;
+ return { std::exchange(_hitTestResult, nil), std::exchange(_actionType, _WKImmediateActionNone) };
+}
+
+@end
+
+namespace TestWebKitAPI {
+
+TEST(ImmediateActionTests, ImmediateActionOverText)
+{
+ auto webView = adoptNS([[WKWebViewForTestingImmediateActions alloc] initWithFrame:NSMakeRect(0, 0, 500, 500)]);
+ [webView synchronouslyLoadHTMLString:@"<div style='font-size: 32px;'>Foobar</div>"];
+
+ auto [hitTestResult, actionType] = [webView simulateImmediateAction:NSMakePoint(16, 16)];
+ EXPECT_NOT_NULL([webView immediateActionGesture].animationController);
+ EXPECT_EQ(actionType, _WKImmediateActionLookupText);
+ EXPECT_WK_STREQ([hitTestResult lookupText], "Foobar");
+}
+
+TEST(ImmediateActionTests, ImmediateActionOverBody)
+{
+ auto webView = adoptNS([[WKWebViewForTestingImmediateActions alloc] initWithFrame:NSMakeRect(0, 0, 500, 500)]);
+ [webView synchronouslyLoadHTMLString:@"<div style='font-size: 32px;'>Foobar</div>"];
+
+ auto [hitTestResult, actionType] = [webView simulateImmediateAction:NSMakePoint(490, 490)];
+ EXPECT_NULL([webView immediateActionGesture].animationController);
+ EXPECT_EQ(actionType, _WKImmediateActionNone);
+ EXPECT_EQ([hitTestResult lookupText].length, 0U);
+}
+
+#if ENABLE(IMAGE_EXTRACTION)
+
+TEST(ImmediateActionTests, ImmediateActionOverImageOverlay)
+{
+ auto configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
+ auto webView = adoptNS([[WKWebViewForTestingImmediateActions alloc] initWithFrame:NSMakeRect(0, 0, 500, 500) configuration:configuration]);
+ [webView synchronouslyLoadTestPageNamed:@"simple-image-overlay"];
+
+ auto [hitTestResult, actionType] = [webView simulateImmediateAction:NSMakePoint(50, 50)];
+ EXPECT_NOT_NULL([webView immediateActionGesture].animationController);
+ EXPECT_EQ(actionType, _WKImmediateActionLookupText);
+ EXPECT_WK_STREQ([hitTestResult lookupText], "foobar");
+}
+
+#endif // ENABLE(IMAGE_EXTRACTION)
+
+} // namespace TestWebKitAPI
+
+#endif // PLATFORM(MAC)