Diff
Modified: trunk/Source/WebKit/ChangeLog (290449 => 290450)
--- trunk/Source/WebKit/ChangeLog 2022-02-24 20:08:49 UTC (rev 290449)
+++ trunk/Source/WebKit/ChangeLog 2022-02-24 20:13:49 UTC (rev 290450)
@@ -1,3 +1,70 @@
+2022-02-24 Wenson Hsieh <wenson_hs...@apple.com>
+
+ Refactor logic for showing "Markup Image" and Quick Note items in the callout bar
+ https://bugs.webkit.org/show_bug.cgi?id=237127
+ rdar://89396617
+
+ Reviewed by Megan Gardner.
+
+ Use `-buildMenuWithBuilder:` to supply additional Quick Note and image analysis items, instead of adding them
+ directly to the shared menu controller. See below for more details.
+
+ Tests: ImageAnalysisTests.MenuControllerItems
+ WebKit.AppHighlightsInImageOverlays
+
+ * UIProcess/API/ios/WKWebViewIOS.mm:
+ (-[WKWebView didMoveToWindow]):
+
+ See below.
+
+ (-[WKWebView buildMenuWithBuilder:]):
+
+ Override this method and call into the content view via `-buildMenuForWebViewWithBuilder:` to populate the given
+ builder with either Quick Note or "Markup Image" items, if necessary. Note that overriding this method on
+ WKWebView is sufficient, since UIKit walks up the responder hierarchy starting from the first responder
+ (WKContentView) when populating menu items.
+
+ * UIProcess/ios/WKContentViewInteraction.h:
+ * UIProcess/ios/WKContentViewInteraction.mm:
+ (-[WKContentView targetForAction:withSender:]):
+
+ Move some logic for conditionally enabling the Quick Note items into `-imageAnalysisMarkupMenu`.
+
+ (-[WKContentView imageAnalysisMarkupMenu]):
+ (-[WKContentView _selectionChanged]):
+
+ Remove logic that updates the shared UIMenuController's menu items every time the selection changes. This is
+ no longer needed, since UIKit will always call into `-buildMenuWithBuilder:` when presenting the callout bar,
+ which allows us to lazily run logic to determine whether or not we should show the Quick Note and image analysis
+ items when the callout bar is shown, instead of keeping the menu controller's `-menuItems` array up to date upon
+ each selection change.
+
+ (-[WKContentView buildMenuForWebViewWithBuilder:]):
+
+ Consult `-appHighlightMenu` and `-imageAnalysisMarkupMenu` to populate the menu with inline UIMenus. Note that
+ these menus' items are always inlined into the callout bar as top-level items, since we explicitly specify
+ `UIMenuOptionsDisplayInline` when creating the menu.
+
+ (-[WKContentView menuWithInlineAction:identifier:handler:]):
+ (-[WKContentView appHighlightMenu]):
+
+ Refactor this, and `-imageAnalysisMarkupMenu` above to return a UIMenu with a single UIAction presented inline.
+
+ (-[WKContentView updateImageAnalysisMarkupMenuItems:]): Deleted.
+
+ Replaced with `-imageAnalysisMarkupMenu`.
+
+ (-[WKContentView canPerformImageAnalysisMarkup]): Deleted.
+ (-[WKContentView performImageAnalysisMarkup:]): Deleted.
+ (-[WKContentView setUpAdditionalMenuControllerActions]): Deleted.
+ (findMenuItemWithAction): Deleted.
+ (-[WKContentView updateAppHighlightMenuItems:]): Deleted.
+
+ Replaced with `-appHighlightMenu`.
+
+ (-[WKContentView createHighlightForCurrentQuickNoteWithRange:]): Deleted.
+ (-[WKContentView createHighlightForNewQuickNoteWithRange:]): Deleted.
+
2022-02-24 Chris Dumez <cdu...@apple.com>
Regression(r273929) FrameState no longer gets a move constructor
Modified: trunk/Source/WebKit/UIProcess/API/ios/WKWebViewIOS.mm (290449 => 290450)
--- trunk/Source/WebKit/UIProcess/API/ios/WKWebViewIOS.mm 2022-02-24 20:08:49 UTC (rev 290449)
+++ trunk/Source/WebKit/UIProcess/API/ios/WKWebViewIOS.mm 2022-02-24 20:13:49 UTC (rev 290450)
@@ -1538,8 +1538,6 @@
[self _dispatchSetDeviceOrientation:[self _deviceOrientation]];
_page->activityStateDidChange(WebCore::ActivityState::allFlags());
_page->webViewDidMoveToWindow();
-
- [_contentView setUpAdditionalMenuControllerActions];
}
- (void)_setOpaqueInternal:(BOOL)opaque
@@ -2702,6 +2700,14 @@
_page->setUserInterfaceLayoutDirection(toUserInterfaceLayoutDirection(contentAttribute));
}
+- (void)buildMenuWithBuilder:(id <UIMenuBuilder>)builder
+{
+ if (self.usesStandardContentView)
+ [_contentView buildMenuForWebViewWithBuilder:builder];
+
+ [super buildMenuWithBuilder:builder];
+}
+
@end
@implementation WKWebView (WKPrivateIOS)
Modified: trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h (290449 => 290450)
--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h 2022-02-24 20:08:49 UTC (rev 290449)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h 2022-02-24 20:13:49 UTC (rev 290450)
@@ -262,6 +262,7 @@
}
@class WKFocusedElementInfo;
+@protocol UIMenuBuilder;
@protocol WKFormControl;
@interface WKFormInputSession : NSObject <_WKFormInputSession>
@@ -593,6 +594,8 @@
- (void)scrollViewWillStartPanOrPinchGesture;
+- (void)buildMenuForWebViewWithBuilder:(id <UIMenuBuilder>)builder;
+
- (BOOL)canBecomeFirstResponderForWebView;
- (BOOL)becomeFirstResponderForWebView;
- (BOOL)resignFirstResponderForWebView;
@@ -782,8 +785,6 @@
- (WebCore::DataOwnerType)_dataOwnerForPasteboard:(WebKit::PasteboardAccessIntent)intent;
#endif
-- (void)setUpAdditionalMenuControllerActions;
-
#if ENABLE(IMAGE_ANALYSIS)
- (void)_endImageAnalysisGestureDeferral:(WebKit::ShouldPreventGestures)shouldPreventGestures;
- (void)requestTextRecognition:(NSURL *)imageURL imageData:(const WebKit::ShareableBitmap::Handle&)imageData identifier:(NSString *)identifier completionHandler:(CompletionHandler<void(WebCore::TextRecognitionResult&&)>&&)completion;
Modified: trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm (290449 => 290450)
--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm 2022-02-24 20:08:49 UTC (rev 290449)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm 2022-02-24 20:13:49 UTC (rev 290450)
@@ -4106,16 +4106,6 @@
- (id)targetForAction:(SEL)action withSender:(id)sender
{
-#if ENABLE(APP_HIGHLIGHTS)
- if (action == @selector(createHighlightForCurrentQuickNoteWithRange:))
- return self.shouldAllowAppHighlightCreation && _page->appHighlightsVisibility() ? self : nil;
- if (action == @selector(createHighlightForNewQuickNoteWithRange:))
- return self.shouldAllowAppHighlightCreation && !_page->appHighlightsVisibility() ? self : nil;
-#endif
-#if ENABLE(IMAGE_ANALYSIS_ENHANCEMENTS)
- if (action == @selector(performImageAnalysisMarkup:))
- return self.canPerformImageAnalysisMarkup ? self : nil;
-#endif
return [_webView targetForAction:action withSender:sender];
}
@@ -4693,39 +4683,22 @@
#if ENABLE(IMAGE_ANALYSIS_ENHANCEMENTS)
-- (void)updateImageAnalysisMarkupMenuItems:(NSMutableArray<UIMenuItem *> *)updatedItems
+- (UIMenu *)imageAnalysisMarkupMenu
{
- auto currentItem = findMenuItemWithAction(updatedItems, @selector(performImageAnalysisMarkup:));
- auto& editorState = _page->editorState();
- if (!_page->preferences().imageAnalysisMarkupEnabled() || !self.window || editorState.isMissingPostLayoutData || !editorState.postLayoutData().selectedEditableImage) {
- if (currentItem)
- [updatedItems removeObject:currentItem];
- } else if (!currentItem) {
- auto item = adoptNS([[UIMenuItem alloc] initWithTitle:WebCore::contextMenuItemTitleMarkupImage() action:@selector(performImageAnalysisMarkup:)]);
- [updatedItems insertObject:item.get() atIndex:0];
- }
-}
-
-- (BOOL)canPerformImageAnalysisMarkup
-{
if (!_page || !_page->preferences().imageAnalysisMarkupEnabled())
- return NO;
+ return nil;
- if (!_imageAnalysisMarkupData)
- return NO;
+ if (_page->editorState().isMissingPostLayoutData || !_page->editorState().postLayoutData().selectedEditableImage)
+ return nil;
- auto [elementContext, image, preferredMIMEType] = *_imageAnalysisMarkupData;
- return !_page->editorState().isMissingPostLayoutData && elementContext == _page->editorState().postLayoutData().selectedEditableImage;
-}
+ return [self menuWithInlineAction:WebCore::contextMenuItemTitleMarkupImage() identifier:@"WKActionMarkupImage" handler:[](WKContentView *view) {
+ if (!view->_imageAnalysisMarkupData)
+ return;
-- (void)performImageAnalysisMarkup:(id)sender
-{
- if (!self.canPerformImageAnalysisMarkup)
- return;
-
- auto [elementContext, image, preferredMIMEType] = *_imageAnalysisMarkupData;
- if (auto [data, type] = WebKit::transcodeWithPreferredMIMEType(image.get(), preferredMIMEType.createCFString().get(), (__bridge CFStringRef)UTTypeTIFF.identifier); data)
- _page->replaceWithPasteboardData(elementContext, { String { type.get() } }, { static_cast<const uint8_t*>([data bytes]), [data length] });
+ auto [elementContext, image, preferredMIMEType] = *view->_imageAnalysisMarkupData;
+ if (auto [data, type] = WebKit::transcodeWithPreferredMIMEType(image.get(), preferredMIMEType.createCFString().get(), (__bridge CFStringRef)UTTypeTIFF.identifier); data)
+ view->_page->replaceWithPasteboardData(elementContext, { String { type.get() } }, { static_cast<const uint8_t*>([data bytes]), [data length] });
+ }];
}
- (void)doAfterComputingImageAnalysisResultsForMarkup:(CompletionHandler<void()>&&)completion
@@ -7472,7 +7445,6 @@
{
_autocorrectionContextNeedsUpdate = YES;
- [self setUpAdditionalMenuControllerActions];
[self _updateSelectionAssistantSuppressionState];
_cachedSelectedTextRange = nil;
@@ -9774,63 +9746,42 @@
}
#endif
-- (void)setUpAdditionalMenuControllerActions
+- (void)buildMenuForWebViewWithBuilder:(id <UIMenuBuilder>)builder
{
- auto updatedItems = adoptNS(UIMenuController.sharedMenuController.menuItems.mutableCopy ?: [NSMutableArray<UIMenuItem *> new]);
#if ENABLE(IMAGE_ANALYSIS_ENHANCEMENTS)
- [self updateImageAnalysisMarkupMenuItems:updatedItems.get()];
+ if (auto menu = self.imageAnalysisMarkupMenu)
+ [builder insertSiblingMenu:menu afterMenuForIdentifier:UIMenuStandardEdit];
#endif
+
#if ENABLE(APP_HIGHLIGHTS)
- [self updateAppHighlightMenuItems:updatedItems.get()];
+ if (auto menu = self.appHighlightMenu)
+ [builder insertChildMenu:menu atEndOfMenuForIdentifier:UIMenuRoot];
#endif
- UIMenuController.sharedMenuController.menuItems = updatedItems.get();
}
-#if ENABLE(IMAGE_ANALYSIS_ENHANCEMENTS) || ENABLE(APP_HIGHLIGHTS)
-
-static UIMenuItem *findMenuItemWithAction(NSArray<UIMenuItem *> *items, SEL action)
+- (UIMenu *)menuWithInlineAction:(NSString *)title identifier:(NSString *)identifier handler:(Function<void(WKContentView *)>&&)handler
{
- for (UIMenuItem *item in items) {
- if (item.action == action)
- return item;
- }
- return nil;
+ auto action = "" actionWithTitle:title image:nil identifier:identifier handler:makeBlockPtr([handler = WTFMove(handler), weakSelf = WeakObjCPtr<WKContentView>(self)](UIAction *) mutable {
+ if (auto strongSelf = weakSelf.get())
+ handler(strongSelf.get());
+ }).get()];
+ return [UIMenu menuWithTitle:@"" image:nil identifier:nil options:UIMenuOptionsDisplayInline children:@[ action ]];
}
-#endif // ENABLE(IMAGE_ANALYSIS_ENHANCEMENTS) || ENABLE(APP_HIGHLIGHTS)
-
#if ENABLE(APP_HIGHLIGHTS)
-- (void)updateAppHighlightMenuItems:(NSMutableArray<UIMenuItem *> *)updatedItems
+- (UIMenu *)appHighlightMenu
{
- auto currentQuickNoteItem = findMenuItemWithAction(updatedItems, @selector(createHighlightForCurrentQuickNoteWithRange:));
- auto newQuickNoteItem = findMenuItemWithAction(updatedItems, @selector(createHighlightForNewQuickNoteWithRange:));
+ if (!_page->preferences().appHighlightsEnabled() || !_page->editorState().selectionIsRange || !self.shouldAllowAppHighlightCreation)
+ return nil;
- if (!_page->preferences().appHighlightsEnabled() || !self.window || !_page->editorState().selectionIsRange) {
- if (currentQuickNoteItem)
- [updatedItems removeObject:currentQuickNoteItem];
- if (newQuickNoteItem)
- [updatedItems removeObject:newQuickNoteItem];
- return;
- }
-
- if (!currentQuickNoteItem)
- [updatedItems addObject:adoptNS([[UIMenuItem alloc] initWithTitle:WebCore::contextMenuItemTagAddHighlightToCurrentQuickNote() action:@selector(createHighlightForCurrentQuickNoteWithRange:)]).get()];
-
- if (!newQuickNoteItem)
- [updatedItems addObject:adoptNS([[UIMenuItem alloc] initWithTitle:WebCore::contextMenuItemTagAddHighlightToNewQuickNote() action:@selector(createHighlightForNewQuickNoteWithRange:)]).get()];
+ bool isVisible = _page->appHighlightsVisibility();
+ auto title = isVisible ? WebCore::contextMenuItemTagAddHighlightToCurrentQuickNote() : WebCore::contextMenuItemTagAddHighlightToNewQuickNote();
+ return [self menuWithInlineAction:title identifier:@"WKActionCreateQuickNote" handler:[isVisible](WKContentView *view) mutable {
+ view->_page->createAppHighlightInSelectedRange(isVisible ? WebCore::CreateNewGroupForHighlight::No : WebCore::CreateNewGroupForHighlight::Yes, WebCore::HighlightRequestOriginatedInApp::No);
+ }];
}
-- (void)createHighlightForCurrentQuickNoteWithRange:(id)sender
-{
- _page->createAppHighlightInSelectedRange(WebCore::CreateNewGroupForHighlight::No, WebCore::HighlightRequestOriginatedInApp::No);
-}
-
-- (void)createHighlightForNewQuickNoteWithRange:(id)sender
-{
- _page->createAppHighlightInSelectedRange(WebCore::CreateNewGroupForHighlight::Yes, WebCore::HighlightRequestOriginatedInApp::No);
-}
-
#endif // ENABLE(APP_HIGHLIGHTS)
- (void)setContinuousSpellCheckingEnabled:(BOOL)enabled
Modified: trunk/Tools/ChangeLog (290449 => 290450)
--- trunk/Tools/ChangeLog 2022-02-24 20:08:49 UTC (rev 290449)
+++ trunk/Tools/ChangeLog 2022-02-24 20:13:49 UTC (rev 290450)
@@ -1,3 +1,49 @@
+2022-02-24 Wenson Hsieh <wenson_hs...@apple.com>
+
+ Refactor logic for showing "Markup Image" and Quick Note items in the callout bar
+ https://bugs.webkit.org/show_bug.cgi?id=237127
+ rdar://89396617
+
+ Reviewed by Megan Gardner.
+
+ Adjust a couple of existing API tests. See comments below.
+
+ * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+ * TestWebKitAPI/Tests/WebKitCocoa/ImageAnalysisTests.mm:
+
+ Refactor ImageAnalysisTests.MenuControllerItems to exercise `-buildMenuWithBuilder:` instead of swizzling
+ UIMenuController methods and checking `-menuItems`.
+
+ (TestWebKitAPI::swizzledSetMenuItems): Deleted.
+ (): Deleted.
+ * TestWebKitAPI/Tests/WebKitCocoa/WKContentViewEditingActions.mm:
+
+ Refactor WebKit.AppHighlightsInImageOverlays to exercise `-buildMenuWithBuilder:` instead of passing in actions
+ to `-targetForAction:withSender:`.
+
+ * TestWebKitAPI/ios/TestUIMenuBuilder.h: Added.
+ * TestWebKitAPI/ios/TestUIMenuBuilder.mm: Added.
+
+ Add a helper class that conforms to UIMenuBuilder. This is used in the two API tests above as an argument to
+ `-buildMenuWithBuilder:` in order to collect additional menu items that WKWebView adds to the callout bar.
+
+ (-[TestUIMenuBuilder init]):
+ (-[TestUIMenuBuilder system]):
+ (-[TestUIMenuBuilder menuForIdentifier:]):
+ (-[TestUIMenuBuilder findMatching:]):
+ (-[TestUIMenuBuilder containsActionWithTitle:]):
+ (-[TestUIMenuBuilder reset]):
+ (-[TestUIMenuBuilder actionForIdentifier:]):
+ (-[TestUIMenuBuilder commandForAction:propertyList:]):
+ (-[TestUIMenuBuilder replaceMenuForIdentifier:withMenu:]):
+ (-[TestUIMenuBuilder replaceChildrenOfMenuForIdentifier:fromChildrenBlock:]):
+ (-[TestUIMenuBuilder insertChildMenu:atStartOfMenuForIdentifier:]):
+ (-[TestUIMenuBuilder insertChildMenu:atEndOfMenuForIdentifier:]):
+ (-[TestUIMenuBuilder removeMenuForIdentifier:]):
+ (-[TestUIMenuBuilder insertSiblingMenu:beforeMenuForIdentifier:]):
+ (-[TestUIMenuBuilder insertSiblingMenu:afterMenuForIdentifier:]):
+ (-[TestUIMenuBuilder registerMenu:]):
+
2022-02-24 Jonathan Bedard <jbed...@apple.com>
[Python3] Convert shebangs in generate_xcfilelists_lib
Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (290449 => 290450)
--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2022-02-24 20:08:49 UTC (rev 290449)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2022-02-24 20:13:49 UTC (rev 290450)
@@ -1112,6 +1112,7 @@
F4D060082734A1AB008FA67A /* simple-editor.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4D060072734A08C008FA67A /* simple-editor.html */; };
F4D4F3B61E4E2BCB00BB2767 /* DragAndDropSimulatorIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = F4D4F3B41E4E2BCB00BB2767 /* DragAndDropSimulatorIOS.mm */; };
F4D4F3B91E4E36E400BB2767 /* DragAndDropTestsIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = F4D4F3B71E4E36E400BB2767 /* DragAndDropTestsIOS.mm */; };
+ F4D5C55827C6FF4800ED1C23 /* TestUIMenuBuilder.mm in Sources */ = {isa = PBXBuildFile; fileRef = F4D5C55727C6EBDC00ED1C23 /* TestUIMenuBuilder.mm */; };
F4D5D69525AF8BE400205280 /* DisableAutomaticSpellingCorrection.mm in Sources */ = {isa = PBXBuildFile; fileRef = F4D5D69425AF8BE400205280 /* DisableAutomaticSpellingCorrection.mm */; };
F4D5E4E81F0C5D38008C1A49 /* dragstart-clear-selection.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4D5E4E71F0C5D27008C1A49 /* dragstart-clear-selection.html */; };
F4D65DA81F5E4704009D8C27 /* selected-text-image-link-and-editable.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4D65DA71F5E46C0009D8C27 /* selected-text-image-link-and-editable.html */; };
@@ -3129,6 +3130,8 @@
F4D2986D20FEE7370092D636 /* RunScriptAfterDocumentLoad.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = RunScriptAfterDocumentLoad.mm; sourceTree = "<group>"; };
F4D4F3B41E4E2BCB00BB2767 /* DragAndDropSimulatorIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DragAndDropSimulatorIOS.mm; sourceTree = "<group>"; };
F4D4F3B71E4E36E400BB2767 /* DragAndDropTestsIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DragAndDropTestsIOS.mm; sourceTree = "<group>"; };
+ F4D5C55627C6EBDC00ED1C23 /* TestUIMenuBuilder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TestUIMenuBuilder.h; sourceTree = "<group>"; };
+ F4D5C55727C6EBDC00ED1C23 /* TestUIMenuBuilder.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = TestUIMenuBuilder.mm; sourceTree = "<group>"; };
F4D5D69425AF8BE400205280 /* DisableAutomaticSpellingCorrection.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = DisableAutomaticSpellingCorrection.mm; sourceTree = "<group>"; };
F4D5E4E71F0C5D27008C1A49 /* dragstart-clear-selection.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "dragstart-clear-selection.html"; sourceTree = "<group>"; };
F4D65DA71F5E46C0009D8C27 /* selected-text-image-link-and-editable.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "selected-text-image-link-and-editable.html"; sourceTree = "<group>"; };
@@ -3734,6 +3737,8 @@
F4D4F3B41E4E2BCB00BB2767 /* DragAndDropSimulatorIOS.mm */,
2E7765CC16C4D80A00BA2BB1 /* mainIOS.mm */,
F48D6C0F224B377000E3E2FB /* PreferredContentMode.mm */,
+ F4D5C55627C6EBDC00ED1C23 /* TestUIMenuBuilder.h */,
+ F4D5C55727C6EBDC00ED1C23 /* TestUIMenuBuilder.mm */,
F4517B652054C49500C26721 /* TestWKWebViewController.h */,
F4517B662054C49500C26721 /* TestWKWebViewController.mm */,
2D2171C3262F8B8200C209DC /* UIKitMacHelperSPI.h */,
@@ -5799,6 +5804,7 @@
F45D3891215A7B4B002A2979 /* TestInspectorBar.mm in Sources */,
516281252325C18000BB7E42 /* TestPDFDocument.mm in Sources */,
7B774906267CCE72009873B4 /* TestRunnerTests.cpp in Sources */,
+ F4D5C55827C6FF4800ED1C23 /* TestUIMenuBuilder.mm in Sources */,
F4517B672054C49500C26721 /* TestWKWebViewController.mm in Sources */,
F45033F5206BEC95009351CE /* TextAutosizingBoost.mm in Sources */,
93E6193B1F931B3A00AF245E /* TextCodec.cpp in Sources */,
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ImageAnalysisTests.mm (290449 => 290450)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ImageAnalysisTests.mm 2022-02-24 20:08:49 UTC (rev 290449)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ImageAnalysisTests.mm 2022-02-24 20:13:49 UTC (rev 290450)
@@ -31,6 +31,7 @@
#import "InstanceMethodSwizzler.h"
#import "PlatformUtilities.h"
#import "TestInputDelegate.h"
+#import "TestUIMenuBuilder.h"
#import "TestWKWebView.h"
#import "WKWebViewConfigurationExtras.h"
#import <WebCore/LocalizedStrings.h>
@@ -263,27 +264,8 @@
#if ENABLE(IMAGE_ANALYSIS_ENHANCEMENTS) && PLATFORM(IOS_FAMILY)
-static NeverDestroyed<RetainPtr<NSArray<UIMenuItem *>>> gSwizzledMenuItems;
-static void swizzledSetMenuItems(id, SEL, NSArray<UIMenuItem *> *items)
-{
- gSwizzledMenuItems.get() = items;
-}
-
-static NSArray<UIMenuItem *> *swizzledMenuItems(id, SEL)
-{
- return gSwizzledMenuItems.get().get();
-}
-
TEST(ImageAnalysisTests, MenuControllerItems)
{
- auto sharedMenuController = UIMenuController.sharedMenuController;
- InstanceMethodSwizzler menuItemsSwizzler { sharedMenuController.class, @selector(menuItems), reinterpret_cast<IMP>(swizzledMenuItems) };
- InstanceMethodSwizzler setMenuItemsSwizzler { sharedMenuController.class, @selector(setMenuItems:), reinterpret_cast<IMP>(swizzledSetMenuItems) };
-
- NSString *testActionName = @"Test action";
- auto customAction = adoptNS([[UIMenuItem alloc] initWithTitle:testActionName action:@selector(becomeFirstResponder)]);
- [sharedMenuController setMenuItems:@[customAction.get()]];
-
auto webView = createWebViewWithTextRecognitionEnhancements();
auto inputDelegate = adoptNS([TestInputDelegate new]);
[inputDelegate setFocusStartsInputSessionPolicyHandler:[](WKWebView *, id <_WKFocusedElementInfo>) {
@@ -296,27 +278,23 @@
[webView objectByEvaluatingJavaScript:@"let image = document.images[0]; getSelection().setBaseAndExtent(image, 0, image, 1);"];
[webView waitForNextPresentationUpdate];
- auto hasMenuItemWithTitle = [&] (NSString *title) {
- for (UIMenuItem *item in sharedMenuController.menuItems) {
- if ([item.title isEqualToString:title])
- return YES;
- }
- return NO;
- };
+ auto menuBuilder = adoptNS([[TestUIMenuBuilder alloc] init]);
+ [webView buildMenuWithBuilder:menuBuilder.get()];
+ EXPECT_TRUE([menuBuilder containsActionWithTitle:WebCore::contextMenuItemTitleMarkupImage()]);
- EXPECT_TRUE(hasMenuItemWithTitle(testActionName));
- EXPECT_WK_STREQ(sharedMenuController.menuItems.firstObject.title, WebCore::contextMenuItemTitleMarkupImage());
-
[webView selectAll:nil];
[webView waitForNextPresentationUpdate];
- EXPECT_TRUE(hasMenuItemWithTitle(testActionName));
- EXPECT_FALSE(hasMenuItemWithTitle(WebCore::contextMenuItemTitleMarkupImage()));
+ [menuBuilder reset];
+ [webView buildMenuWithBuilder:menuBuilder.get()];
+ EXPECT_FALSE([menuBuilder containsActionWithTitle:WebCore::contextMenuItemTitleMarkupImage()]);
[webView objectByEvaluatingJavaScript:@"getSelection().setBaseAndExtent(document.body, 0, document.images[0], 1);"];
[webView waitForNextPresentationUpdate];
- EXPECT_TRUE(hasMenuItemWithTitle(testActionName));
- EXPECT_WK_STREQ(sharedMenuController.menuItems.firstObject.title, WebCore::contextMenuItemTitleMarkupImage());
+
+ [menuBuilder reset];
+ [webView buildMenuWithBuilder:menuBuilder.get()];
+ EXPECT_TRUE([menuBuilder containsActionWithTitle:WebCore::contextMenuItemTitleMarkupImage()]);
}
#endif // ENABLE(IMAGE_ANALYSIS_ENHANCEMENTS) && PLATFORM(IOS_FAMILY)
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKContentViewEditingActions.mm (290449 => 290450)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKContentViewEditingActions.mm 2022-02-24 20:08:49 UTC (rev 290449)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKContentViewEditingActions.mm 2022-02-24 20:13:49 UTC (rev 290450)
@@ -32,9 +32,11 @@
#import "Test.h"
#import "TestInputDelegate.h"
#import "TestNavigationDelegate.h"
+#import "TestUIMenuBuilder.h"
#import "TestWKWebView.h"
#import "UIKitSPI.h"
#import "WKWebViewConfigurationExtras.h"
+#import <WebCore/LocalizedStrings.h>
#import <WebKit/WKWebViewConfigurationPrivate.h>
#import <WebKit/WebKit.h>
#import <wtf/RetainPtr.h>
@@ -89,18 +91,19 @@
[webView stringByEvaluatingJavaScript:@"selectImageOverlay()"];
[webView waitForNextPresentationUpdate];
- auto createHighlightForCurrentQuickNoteWithRangeSelector = NSSelectorFromString(@"createHighlightForCurrentQuickNoteWithRange:");
- auto createHighlightForNewQuickNoteWithRangeSelector = NSSelectorFromString(@"createHighlightForNewQuickNoteWithRange:");
+ auto menuBuilder = adoptNS([[TestUIMenuBuilder alloc] init]);
+ [webView buildMenuWithBuilder:menuBuilder.get()];
+ EXPECT_FALSE([menuBuilder containsActionWithTitle:WebCore::contextMenuItemTagAddHighlightToNewQuickNote()]);
+ EXPECT_FALSE([menuBuilder containsActionWithTitle:WebCore::contextMenuItemTagAddHighlightToCurrentQuickNote()]);
- auto contentView = [webView textInputContentView];
- EXPECT_NULL([contentView targetForAction:createHighlightForCurrentQuickNoteWithRangeSelector withSender:nil]);
- EXPECT_NULL([contentView targetForAction:createHighlightForNewQuickNoteWithRangeSelector withSender:nil]);
-
[webView synchronouslyLoadTestPageNamed:@"simple"];
[webView selectAll:nil];
[webView waitForNextPresentationUpdate];
- EXPECT_NULL([contentView targetForAction:createHighlightForCurrentQuickNoteWithRangeSelector withSender:nil]);
- EXPECT_EQ([contentView targetForAction:createHighlightForNewQuickNoteWithRangeSelector withSender:nil], contentView);
+
+ [menuBuilder reset];
+ [webView buildMenuWithBuilder:menuBuilder.get()];
+ EXPECT_TRUE([menuBuilder containsActionWithTitle:WebCore::contextMenuItemTagAddHighlightToNewQuickNote()]);
+ EXPECT_FALSE([menuBuilder containsActionWithTitle:WebCore::contextMenuItemTagAddHighlightToCurrentQuickNote()]);
}
#endif // ENABLE(APP_HIGHLIGHTS)
Added: trunk/Tools/TestWebKitAPI/ios/TestUIMenuBuilder.h (0 => 290450)
--- trunk/Tools/TestWebKitAPI/ios/TestUIMenuBuilder.h (rev 0)
+++ trunk/Tools/TestWebKitAPI/ios/TestUIMenuBuilder.h 2022-02-24 20:13:49 UTC (rev 290450)
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#if PLATFORM(IOS_FAMILY)
+
+#import <UIKit/UIKit.h>
+
+@interface TestUIMenuBuilder : NSObject<UIMenuBuilder>
+
+- (BOOL)containsActionWithTitle:(NSString *)title;
+- (void)reset;
+
+@end
+
+#endif // PLATFORM(IOS_FAMILY)
Added: trunk/Tools/TestWebKitAPI/ios/TestUIMenuBuilder.mm (0 => 290450)
--- trunk/Tools/TestWebKitAPI/ios/TestUIMenuBuilder.mm (rev 0)
+++ trunk/Tools/TestWebKitAPI/ios/TestUIMenuBuilder.mm 2022-02-24 20:13:49 UTC (rev 290450)
@@ -0,0 +1,140 @@
+/*
+ * 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 "TestUIMenuBuilder.h"
+
+#import <wtf/RetainPtr.h>
+
+#if PLATFORM(IOS_FAMILY)
+
+@implementation TestUIMenuBuilder {
+ RetainPtr<NSMutableDictionary<UIMenuIdentifier, UIMenu *>> _menusByIdentifier;
+}
+
+- (instancetype)init
+{
+ if (!(self = [super init]))
+ return nil;
+
+ // FIXME: A flat dictionary containing all UIMenus is sufficient to test all of the
+ // non-default items currently supplied by WebKit. We'll want to augment this in the
+ // future if we need to test menu nesting or item ordering.
+ _menusByIdentifier = adoptNS([NSMutableDictionary<UIMenuIdentifier, UIMenu *> new]);
+ return self;
+}
+
+- (UIMenuSystem *)system
+{
+ return UIMenuSystem.mainSystem;
+}
+
+- (UIMenu *)menuForIdentifier:(UIMenuIdentifier)identifier
+{
+ return [_menusByIdentifier objectForKey:identifier];
+}
+
+- (UIMenuElement *)findMatching:(BOOL(^)(UIMenuElement *))isMatch
+{
+ for (UIMenu *menu in [_menusByIdentifier allValues]) {
+ for (UIMenuElement *child in menu.children) {
+ if (isMatch(child))
+ return child;
+ }
+ }
+ return nil;
+}
+
+- (BOOL)containsActionWithTitle:(NSString *)title
+{
+ return [self findMatching:^BOOL(UIMenuElement *element) {
+ return [dynamic_objc_cast<UIAction>(element).title isEqual:title];
+ }];
+}
+
+- (void)reset
+{
+ [_menusByIdentifier removeAllObjects];
+}
+
+- (UIAction *)actionForIdentifier:(UIActionIdentifier)identifier
+{
+ return (UIAction *)[self findMatching:^BOOL(UIMenuElement *element) {
+ return [dynamic_objc_cast<UIAction>(element).identifier isEqual:identifier];
+ }];
+}
+
+- (UICommand *)commandForAction:(SEL)action propertyList:(id)propertyList
+{
+ return (UICommand *)[self findMatching:^BOOL(UIMenuElement *element) {
+ auto command = dynamic_objc_cast<UICommand>(element);
+ return command.action == action && (command.propertyList == propertyList || [command.propertyList isEqual:propertyList]);
+ }];
+}
+
+- (void)replaceMenuForIdentifier:(UIMenuIdentifier)replacedIdentifier withMenu:(UIMenu *)replacementMenu
+{
+ [_menusByIdentifier setObject:replacementMenu forKey:replacedIdentifier];
+}
+
+- (void)replaceChildrenOfMenuForIdentifier:(UIMenuIdentifier)parentIdentifier fromChildrenBlock:(NSArray<UIMenuElement *> *(NS_NOESCAPE^)(NSArray<UIMenuElement *> *))childrenBlock
+{
+ if (auto menu = [self menuForIdentifier:parentIdentifier])
+ [_menusByIdentifier setObject:[menu menuByReplacingChildren:childrenBlock(menu.children)] forKey:parentIdentifier];
+}
+
+- (void)insertChildMenu:(UIMenu *)childMenu atStartOfMenuForIdentifier:(UIMenuIdentifier)parentIdentifier
+{
+ [self registerMenu:childMenu];
+}
+
+- (void)insertChildMenu:(UIMenu *)childMenu atEndOfMenuForIdentifier:(UIMenuIdentifier)parentIdentifier
+{
+ [self registerMenu:childMenu];
+}
+
+- (void)removeMenuForIdentifier:(UIMenuIdentifier)removedIdentifier
+{
+ [_menusByIdentifier removeObjectForKey:removedIdentifier];
+}
+
+- (void)insertSiblingMenu:(UIMenu *)siblingMenu beforeMenuForIdentifier:(UIMenuIdentifier)siblingIdentifier
+{
+ [self registerMenu:siblingMenu];
+}
+
+- (void)insertSiblingMenu:(UIMenu *)siblingMenu afterMenuForIdentifier:(UIMenuIdentifier)siblingIdentifier
+{
+ [self registerMenu:siblingMenu];
+}
+
+- (void)registerMenu:(UIMenu *)menu
+{
+ [_menusByIdentifier setObject:menu forKey:menu.identifier];
+}
+
+@end
+
+#endif // PLATFORM(IOS_FAMILY)