Diff
Modified: trunk/Source/WebCore/ChangeLog (219540 => 219541)
--- trunk/Source/WebCore/ChangeLog 2017-07-16 03:45:04 UTC (rev 219540)
+++ trunk/Source/WebCore/ChangeLog 2017-07-16 04:01:30 UTC (rev 219541)
@@ -1,3 +1,34 @@
+2017-07-15 Wenson Hsieh <[email protected]>
+
+ [iOS WK2] Presenting an action sheet on an image map prevents selection UI from updating
+ https://bugs.webkit.org/show_bug.cgi?id=174539
+ <rdar://problem/33307395>
+
+ Reviewed by Darin Adler.
+
+ Currently, if TextIndicator fails to take a snapshot in TextIndicator::createWithRange, we will enter an
+ inconsistent state in the web process where Editor will continue to ignore selection changes until the next time
+ Editor::setIgnoreSelectionChanges(false) is called. This causes us to indefinitely defer EditorState updates to
+ the UI process, which leads to selection UI appearing unresponsive.
+
+ To fix this, we introduce a new TemporarySelectionChange object to simplify selection changes and/or
+ EditorState-update-ignoring behaviors within the scope of a single function. The constructor applies these
+ temporary changes, and the destructor reverts them as needed to their prior values.
+
+ This patch only adopts TemporarySelectionChange in order to fix this bug, but future patches will replace the
+ remaining places where we temporarily change selection and/or ignore selection with this helper.
+
+ Test: ActionSheetTests.ImageMapDoesNotDestroySelection.
+
+ * editing/Editor.cpp:
+ (WebCore::TemporarySelectionChange::TemporarySelectionChange):
+ (WebCore::TemporarySelectionChange::~TemporarySelectionChange):
+ * editing/Editor.h:
+ * editing/FrameSelection.h:
+ (WebCore::FrameSelection::isUpdateAppearanceEnabled):
+ * page/TextIndicator.cpp:
+ (WebCore::TextIndicator::createWithRange):
+
2017-07-15 Myles C. Maxfield <[email protected]>
Clean up line-height and minimumFontSize functions
Modified: trunk/Source/WebCore/editing/Editor.cpp (219540 => 219541)
--- trunk/Source/WebCore/editing/Editor.cpp 2017-07-16 03:45:04 UTC (rev 219540)
+++ trunk/Source/WebCore/editing/Editor.cpp 2017-07-16 04:01:30 UTC (rev 219541)
@@ -184,6 +184,44 @@
using namespace WTF;
using namespace Unicode;
+TemporarySelectionChange::TemporarySelectionChange(Frame& frame, std::optional<VisibleSelection> temporarySelection, TemporarySelectionOptions options)
+ : m_frame(frame)
+ , m_options(options)
+ , m_wasIgnoringSelectionChanges(frame.editor().ignoreSelectionChanges())
+#if PLATFORM(IOS)
+ , m_appearanceUpdatesWereEnabled(frame.selection().isUpdateAppearanceEnabled())
+#endif
+{
+#if PLATFORM(IOS)
+ if (options & TemporarySelectionOptionEnableAppearanceUpdates)
+ frame.selection().setUpdateAppearanceEnabled(true);
+#endif
+
+ if (options & TemporarySelectionOptionIgnoreSelectionChanges)
+ frame.editor().setIgnoreSelectionChanges(true);
+
+ if (temporarySelection) {
+ m_selectionToRestore = frame.selection().selection();
+ frame.selection().setSelection(temporarySelection.value());
+ }
+}
+
+TemporarySelectionChange::~TemporarySelectionChange()
+{
+ if (m_selectionToRestore)
+ m_frame->selection().setSelection(m_selectionToRestore.value());
+
+ if (m_options & TemporarySelectionOptionIgnoreSelectionChanges) {
+ auto revealSelection = m_options & TemporarySelectionOptionRevealSelection ? Editor::RevealSelection::Yes : Editor::RevealSelection::No;
+ m_frame->editor().setIgnoreSelectionChanges(m_wasIgnoringSelectionChanges, revealSelection);
+ }
+
+#if PLATFORM(IOS)
+ if (m_options & TemporarySelectionOptionEnableAppearanceUpdates)
+ m_frame->selection().setUpdateAppearanceEnabled(m_appearanceUpdatesWereEnabled);
+#endif
+}
+
// When an event handler has moved the selection outside of a text control
// we should use the target control's selection for this editing operation.
VisibleSelection Editor::selectionForCommand(Event* event)
Modified: trunk/Source/WebCore/editing/Editor.h (219540 => 219541)
--- trunk/Source/WebCore/editing/Editor.h 2017-07-16 03:45:04 UTC (rev 219540)
+++ trunk/Source/WebCore/editing/Editor.h 2017-07-16 04:01:30 UTC (rev 219541)
@@ -102,6 +102,37 @@
#endif
+enum TemporarySelectionOption : uint8_t {
+ // By default, no additional options are enabled.
+ TemporarySelectionOptionDefault = 0,
+
+ // Scroll to reveal the selection.
+ TemporarySelectionOptionRevealSelection = 1 << 0,
+
+ // Don't propagate selection changes to the UI process.
+ TemporarySelectionOptionIgnoreSelectionChanges = 1 << 1,
+
+ // Force the render tree to update selection state. Only respected on iOS.
+ TemporarySelectionOptionEnableAppearanceUpdates = 1 << 2
+};
+
+using TemporarySelectionOptions = uint8_t;
+
+class TemporarySelectionChange {
+public:
+ TemporarySelectionChange(Frame&, std::optional<VisibleSelection> = std::nullopt, TemporarySelectionOptions = TemporarySelectionOptionDefault);
+ ~TemporarySelectionChange();
+
+private:
+ Ref<Frame> m_frame;
+ TemporarySelectionOptions m_options;
+ bool m_wasIgnoringSelectionChanges;
+#if PLATFORM(IOS)
+ bool m_appearanceUpdatesWereEnabled;
+#endif
+ std::optional<VisibleSelection> m_selectionToRestore;
+};
+
class Editor {
WTF_MAKE_FAST_ALLOCATED;
public:
Modified: trunk/Source/WebCore/editing/FrameSelection.h (219540 => 219541)
--- trunk/Source/WebCore/editing/FrameSelection.h 2017-07-16 03:45:04 UTC (rev 219540)
+++ trunk/Source/WebCore/editing/FrameSelection.h 2017-07-16 04:01:30 UTC (rev 219541)
@@ -236,6 +236,7 @@
void setCaretBlinks(bool caretBlinks = true);
WEBCORE_EXPORT void setCaretColor(const Color&);
WEBCORE_EXPORT static VisibleSelection wordSelectionContainingCaretSelection(const VisibleSelection&);
+ bool isUpdateAppearanceEnabled() const { return m_updateAppearanceEnabled; }
void setUpdateAppearanceEnabled(bool enabled) { m_updateAppearanceEnabled = enabled; }
void suppressScrolling() { ++m_scrollingSuppressCount; }
void restoreScrolling()
Modified: trunk/Source/WebCore/page/TextIndicator.cpp (219540 => 219541)
--- trunk/Source/WebCore/page/TextIndicator.cpp 2017-07-16 03:45:04 UTC (rev 219540)
+++ trunk/Source/WebCore/page/TextIndicator.cpp 2017-07-16 04:01:30 UTC (rev 219541)
@@ -78,14 +78,14 @@
Ref<Frame> protector(*frame);
+ VisibleSelection oldSelection = frame->selection().selection();
+ TemporarySelectionOptions temporarySelectionOptions = TemporarySelectionOptionDefault;
#if PLATFORM(IOS)
- frame->editor().setIgnoreSelectionChanges(true);
- frame->selection().setUpdateAppearanceEnabled(true);
+ temporarySelectionOptions |= TemporarySelectionOptionIgnoreSelectionChanges;
+ temporarySelectionOptions |= TemporarySelectionOptionEnableAppearanceUpdates;
#endif
+ TemporarySelectionChange selectionChange(*frame, { range }, temporarySelectionOptions);
- VisibleSelection oldSelection = frame->selection().selection();
- frame->selection().setSelection(range);
-
TextIndicatorData data;
data.presentationTransition = presentationTransition;
@@ -96,16 +96,7 @@
if (!initializeIndicator(data, *frame, range, margin, indicatesCurrentSelection))
return nullptr;
- RefPtr<TextIndicator> indicator = TextIndicator::create(data);
-
- frame->selection().setSelection(oldSelection);
-
-#if PLATFORM(IOS)
- frame->editor().setIgnoreSelectionChanges(false, Editor::RevealSelection::No);
- frame->selection().setUpdateAppearanceEnabled(false);
-#endif
-
- return indicator;
+ return TextIndicator::create(data);
}
RefPtr<TextIndicator> TextIndicator::createWithSelectionInFrame(Frame& frame, TextIndicatorOptions options, TextIndicatorPresentationTransition presentationTransition, FloatSize margin)
Modified: trunk/Source/WebKit/ChangeLog (219540 => 219541)
--- trunk/Source/WebKit/ChangeLog 2017-07-16 03:45:04 UTC (rev 219540)
+++ trunk/Source/WebKit/ChangeLog 2017-07-16 04:01:30 UTC (rev 219541)
@@ -1,3 +1,19 @@
+2017-07-15 Wenson Hsieh <[email protected]>
+
+ [iOS WK2] Presenting an action sheet on an image map prevents selection UI from updating
+ https://bugs.webkit.org/show_bug.cgi?id=174539
+ <rdar://problem/33307395>
+
+ Reviewed by Darin Adler.
+
+ Small tweak to avoid presenting at the element rect or text rect if the interaction information failed to
+ capture valid bounds for the element. We instead fall back to presenting at the touch location. This addresses
+ problems when presenting the action sheet popover on image maps on iPad, where GetPositionInformation fails to
+ capture correct data about for the <area>.
+
+ * UIProcess/ios/WKActionSheetAssistant.mm:
+ (presentationStyleForView):
+
2017-07-14 Jonathan Bedard <[email protected]>
Add iOS 11 SPI
Modified: trunk/Source/WebKit/UIProcess/ios/WKActionSheetAssistant.mm (219540 => 219541)
--- trunk/Source/WebKit/UIProcess/ios/WKActionSheetAssistant.mm 2017-07-16 03:45:04 UTC (rev 219540)
+++ trunk/Source/WebKit/UIProcess/ios/WKActionSheetAssistant.mm 2017-07-16 04:01:30 UTC (rev 219541)
@@ -396,6 +396,9 @@
static WKActionSheetPresentationStyle presentationStyleForView(UIView *view, const InteractionInformationAtPosition& positionInfo, _WKActivatedElementInfo *elementInfo)
{
auto apparentElementRect = [view convertRect:positionInfo.bounds toView:view.window];
+ if (CGRectIsEmpty(apparentElementRect))
+ return WKActionSheetPresentAtTouchLocation;
+
auto windowRect = view.window.bounds;
apparentElementRect = CGRectIntersection(apparentElementRect, windowRect);
Modified: trunk/Tools/ChangeLog (219540 => 219541)
--- trunk/Tools/ChangeLog 2017-07-16 03:45:04 UTC (rev 219540)
+++ trunk/Tools/ChangeLog 2017-07-16 04:01:30 UTC (rev 219541)
@@ -1,3 +1,28 @@
+2017-07-15 Wenson Hsieh <[email protected]>
+
+ [iOS WK2] Presenting an action sheet on an image map prevents selection UI from updating
+ https://bugs.webkit.org/show_bug.cgi?id=174539
+ <rdar://problem/33307395>
+
+ Reviewed by Darin Adler.
+
+ Adds a new unit test suite to cover action sheet popover presentation.
+
+ * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+ * TestWebKitAPI/Tests/WebKit2Cocoa/image-map.html: Added.
+ * TestWebKitAPI/Tests/ios/ActionSheetTests.mm: Added.
+ (-[ActionSheetObserver waitForActionSheetAfterBlock:]):
+
+ Runs the given block and waits until the UI process has indicated that it will present an action sheet.
+
+ (-[ActionSheetObserver _webView:actionsForElement:defaultActions:]):
+ (TestWebKitAPI::IPadUserInterfaceSwizzler::IPadUserInterfaceSwizzler):
+
+ Helper class to alter the behavior of [[UIDevice currentDevice] userInterfaceIdiom] for testing.
+
+ (TestWebKitAPI::IPadUserInterfaceSwizzler::padUserInterfaceIdiom):
+ (TestWebKitAPI::TEST):
+
2017-07-15 Sam Weinig <[email protected]>
[Scripts] Make svn-create-patch work better when called in sub directories
Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (219540 => 219541)
--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2017-07-16 03:45:04 UTC (rev 219540)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2017-07-16 04:01:30 UTC (rev 219541)
@@ -648,6 +648,8 @@
F42DA5161D8CEFE400336F40 /* large-input-field-focus-onload.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F42DA5151D8CEFDB00336F40 /* large-input-field-focus-onload.html */; };
F4451C761EB8FD890020C5DA /* two-paragraph-contenteditable.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4451C751EB8FD7C0020C5DA /* two-paragraph-contenteditable.html */; };
F4538EF71E8473E600B5C953 /* large-red-square.png in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4538EF01E846B4100B5C953 /* large-red-square.png */; };
+ F45B63FB1F197F4A009D38B9 /* image-map.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F45B63FA1F197F33009D38B9 /* image-map.html */; };
+ F45B63FE1F19D410009D38B9 /* ActionSheetTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = F45B63FC1F19D410009D38B9 /* ActionSheetTests.mm */; };
F46849BE1EEF58E400B937FE /* UIPasteboardTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = F46849BD1EEF58E400B937FE /* UIPasteboardTests.mm */; };
F46849C01EEF5EF300B937FE /* rich-and-plain-text.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F46849BF1EEF5EDC00B937FE /* rich-and-plain-text.html */; };
F469FB241F01804B00401539 /* contenteditable-and-target.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F469FB231F01803500401539 /* contenteditable-and-target.html */; };
@@ -739,6 +741,7 @@
dstPath = TestWebKitAPI.resources;
dstSubfolderSpec = 7;
files = (
+ F45B63FB1F197F4A009D38B9 /* image-map.html in Copy Resources */,
F4D5E4E81F0C5D38008C1A49 /* dragstart-clear-selection.html in Copy Resources */,
F4A32EC41F05F3850047C544 /* dragstart-change-selection-offscreen.html in Copy Resources */,
F4A32ECB1F0643370047C544 /* contenteditable-in-iframe.html in Copy Resources */,
@@ -1631,6 +1634,8 @@
F42DA5151D8CEFDB00336F40 /* large-input-field-focus-onload.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = "large-input-field-focus-onload.html"; path = "Tests/WebKit2Cocoa/large-input-field-focus-onload.html"; sourceTree = SOURCE_ROOT; };
F4451C751EB8FD7C0020C5DA /* two-paragraph-contenteditable.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "two-paragraph-contenteditable.html"; sourceTree = "<group>"; };
F4538EF01E846B4100B5C953 /* large-red-square.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "large-red-square.png"; sourceTree = "<group>"; };
+ F45B63FA1F197F33009D38B9 /* image-map.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "image-map.html"; sourceTree = "<group>"; };
+ F45B63FC1F19D410009D38B9 /* ActionSheetTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ActionSheetTests.mm; sourceTree = "<group>"; };
F46849BD1EEF58E400B937FE /* UIPasteboardTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = UIPasteboardTests.mm; sourceTree = "<group>"; };
F46849BF1EEF5EDC00B937FE /* rich-and-plain-text.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "rich-and-plain-text.html"; sourceTree = "<group>"; };
F469FB231F01803500401539 /* contenteditable-and-target.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "contenteditable-and-target.html"; sourceTree = "<group>"; };
@@ -1994,6 +1999,7 @@
7560917719259C59009EF06E /* MemoryCacheAddImageToCacheIOS.mm */,
F4D7BCD61EA574DD00C421D3 /* PositionInformationTests.mm */,
F46849BD1EEF58E400B937FE /* UIPasteboardTests.mm */,
+ F45B63FC1F19D410009D38B9 /* ActionSheetTests.mm */,
);
path = ios;
sourceTree = "<group>";
@@ -2050,6 +2056,7 @@
F41AB99B1EF4692C0083FA08 /* file-uploading.html */,
F41AB9991EF4692C0083FA08 /* image-and-contenteditable.html */,
F41AB9931EF4692C0083FA08 /* image-and-textarea.html */,
+ F45B63FA1F197F33009D38B9 /* image-map.html */,
F41AB9961EF4692C0083FA08 /* link-and-input.html */,
F41AB99D1EF4692C0083FA08 /* link-and-target-div.html */,
F41AB9941EF4692C0083FA08 /* prevent-operation.html */,
@@ -3041,6 +3048,7 @@
07492B3B1DF8B14C00633DE1 /* EnumerateMediaDevices.cpp in Sources */,
448D7E471EA6C55500ECC756 /* EnvironmentUtilitiesTest.cpp in Sources */,
7CCE7EEF1A411AE600447C4C /* EphemeralSessionPushStateNoHistoryCallback.cpp in Sources */,
+ F45B63FE1F19D410009D38B9 /* ActionSheetTests.mm in Sources */,
7CCE7EF01A411AE600447C4C /* EvaluateJavaScript.cpp in Sources */,
315118101DB1AE4000176304 /* ExtendedColor.cpp in Sources */,
7CCE7EF11A411AE600447C4C /* FailedLoad.cpp in Sources */,
Added: trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/image-map.html (0 => 219541)
--- trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/image-map.html (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/image-map.html 2017-07-16 04:01:30 UTC (rev 219541)
@@ -0,0 +1,31 @@
+<head>
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <style>
+ body {
+ width: 100%;
+ height: 100%;
+ margin: 0;
+ }
+
+ img {
+ width: 320px;
+ height: 320px;
+ }
+
+ h1 {
+ font-size: 50px;
+ }
+ </style>
+</head>
+
+<body>
+ <img src="" usemap=""
+ <map name="imgmap"><area href="" coords="0,0,400,400" shape="rect"></map>
+ <h1 id="h1">Hello world</h1>
+ <script>
+ function selectTextNode(text)
+ {
+ getSelection().setBaseAndExtent(text, 0, text, text.data.length);
+ }
+ </script>
+</body>
Added: trunk/Tools/TestWebKitAPI/Tests/ios/ActionSheetTests.mm (0 => 219541)
--- trunk/Tools/TestWebKitAPI/Tests/ios/ActionSheetTests.mm (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/ios/ActionSheetTests.mm 2017-07-16 04:01:30 UTC (rev 219541)
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#include "config.h"
+
+#if PLATFORM(IOS)
+
+#import "InstanceMethodSwizzler.h"
+#import "PlatformUtilities.h"
+#import "TestWKWebView.h"
+#import <WebKit/WKUIDelegatePrivate.h>
+#import <WebKit/WKWebViewPrivate.h>
+#import <wtf/RetainPtr.h>
+#import <wtf/SoftLinking.h>
+
+@interface ActionSheetObserver : NSObject<WKUIDelegatePrivate>
+@property (nonatomic) BOOL presentedActionSheet;
+@end
+
+@implementation ActionSheetObserver
+
+- (BOOL)waitForActionSheetAfterBlock:(dispatch_block_t)block
+{
+ _presentedActionSheet = NO;
+ block();
+ while ([[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantPast]]) {
+ if (_presentedActionSheet)
+ break;
+ }
+ return _presentedActionSheet;
+}
+
+- (NSArray *)_webView:(ActionSheetObserver *)webView actionsForElement:(_WKActivatedElementInfo *)element defaultActions:(NSArray<_WKElementAction *> *)defaultActions
+{
+ _presentedActionSheet = YES;
+ return defaultActions;
+}
+
+@end
+
+namespace TestWebKitAPI {
+
+class IPadUserInterfaceSwizzler {
+public:
+ IPadUserInterfaceSwizzler()
+ : m_swizzler([UIDevice class], @selector(userInterfaceIdiom), reinterpret_cast<IMP>(padUserInterfaceIdiom))
+ {
+ }
+private:
+ static UIUserInterfaceIdiom padUserInterfaceIdiom()
+ {
+ return UIUserInterfaceIdiomPad;
+ }
+ InstanceMethodSwizzler m_swizzler;
+};
+
+TEST(ActionSheetTests, ImageMapDoesNotDestroySelection)
+{
+ IPadUserInterfaceSwizzler iPadUserInterface;
+
+ auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)]);
+ auto observer = adoptNS([[ActionSheetObserver alloc] init]);
+ [webView setUIDelegate:observer.get()];
+ [webView synchronouslyLoadTestPageNamed:@"image-map"];
+ [webView stringByEvaluatingJavaScript:@"selectTextNode(h1.childNodes[0])"];
+
+ EXPECT_WK_STREQ("Hello world", [webView stringByEvaluatingJavaScript:@"getSelection().toString()"]);
+ [observer waitForActionSheetAfterBlock:^() {
+ [webView _simulateLongPressActionAtLocation:CGPointMake(200, 200)];
+ }];
+ EXPECT_WK_STREQ("Hello world", [webView stringByEvaluatingJavaScript:@"getSelection().toString()"]);
+}
+
+} // namespace TestWebKitAPI
+
+#endif // PLATFORM(IOS)