Changeset 293730 in webkit
- Timestamp:
- May 3, 2022, 10:37:47 AM (4 years ago)
- Location:
- trunk/Source/WebKit
- Files:
-
- 3 edited
-
ChangeLog (modified) (1 diff)
-
UIProcess/ios/WKContentViewInteraction.h (modified) (1 diff)
-
UIProcess/ios/WKContentViewInteraction.mm (modified) (12 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebKit/ChangeLog
r293729 r293730 1 2022-05-03 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 [iOS] The "Copy Cropped Image" context menu action should be gated on cropped image results 4 https://bugs.webkit.org/show_bug.cgi?id=240013 5 rdar://88941787 6 7 Reviewed by Tim Horton. 8 9 Only show this item in the context menu when long pressing in the case where `requestImageAnalysisMarkup` 10 computes a non-null result for the given image bitmap. This gating logic runs alongside existing gating logic 11 for both the visual search item ("Look Up") and "Show Text" actions. See below for more details. 12 13 * UIProcess/ios/WKContentViewInteraction.h: 14 * UIProcess/ios/WKContentViewInteraction.mm: 15 (-[WKContentView _setUpImageAnalysis]): 16 (-[WKContentView _tearDownImageAnalysis]): 17 18 Introduce a `_croppedImageResult` ivar to cache the CGImage result after running image analysis over the image 19 corresponding to the element for which we're showing the context menu. This is reset in the same lifecycle as 20 the extant `_hasVisualSearchResults` and `_hasSelectableTextInImage` flags which are used for the same purpose. 21 22 (-[WKContentView imageAnalysisGestureDidBegin:]): 23 (-[WKContentView _completeImageAnalysisRequestForContextMenu:requestIdentifier:hasTextResults:]): 24 25 This is the codepath that currently prevents us from showing the context menu until we know whether or not there 26 are relevant visual search results, such that we can conditionally show the "Look Up" context menu item. Adjust 27 this so that it calls `-_invokeAllActionsToPerformAfterPendingImageAnalysis:` only after we've also determined 28 whether or not there is a non-null cropped image result, so that we can also conditionally show the "Copy 29 Cropped Image" item. 30 31 To achieve this, we move the call to `-_invokeAllActionsToPerformAfterPendingImageAnalysis:` into a 32 `WTF::CallbackAggregator`, and ref/deref the aggregator when invoking both of the async image analysis 33 operations. When the callback aggregator is destroyed (i.e., after both async image analysis operations are 34 complete), we proceed with showing the context menu. 35 36 (-[WKContentView imageAnalysisGestureDidTimeOut:]): 37 38 Implement similar logic as above, but for the scenario where we show the context menu after the user continues 39 to long press after selecting text inside of an image. 40 41 (-[WKContentView actionSheetAssistantShouldIncludeCopyCroppedImageAction:]): 42 43 Only show the item if `_croppedImageResult` is non-null. 44 45 (-[WKContentView actionSheetAssistant:copyCroppedImage:sourceMIMEType:]): 46 47 Instead of running image analysis and writing the resulting image to the clipboard, simply transcode the cached 48 image in `_croppedImageResult`. 49 1 50 2022-05-03 Philippe Normand <pnormand@igalia.com> and Yury Semikhatsky <yurys@chromium.org> 2 51 -
trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h
r293231 r293730 546 546 WebCore::FloatRect _imageAnalysisInteractionBounds; 547 547 std::optional<WebKit::ImageAnalysisMarkupData> _imageAnalysisMarkupData; 548 RetainPtr<CGImageRef> _croppedImageResult; 548 549 #endif 549 550 } -
trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm
r293663 r293730 149 149 #import <wtf/BlockObjCExceptions.h> 150 150 #import <wtf/BlockPtr.h> 151 #import <wtf/CallbackAggregator.h> 151 152 #import <wtf/Scope.h> 152 153 #import <wtf/SetForScope.h> … … 10715 10716 #if ENABLE(IMAGE_ANALYSIS_ENHANCEMENTS) 10716 10717 _imageAnalysisMarkupData = std::nullopt; 10718 _croppedImageResult = nil; 10717 10719 #endif 10718 10720 } … … 10744 10746 [self uninstallImageAnalysisInteraction]; 10745 10747 _imageAnalysisMarkupData = std::nullopt; 10748 _croppedImageResult = nil; 10746 10749 #endif 10747 10750 } … … 10838 10841 _hasVisualSearchResults = NO; 10839 10842 #endif // USE(QUICK_LOOK) 10843 10844 #if ENABLE(IMAGE_ANALYSIS_ENHANCEMENTS) 10845 _croppedImageResult = nil; 10846 #endif 10840 10847 10841 10848 #if USE(UICONTEXTMENU) && ENABLE(IMAGE_ANALYSIS_FOR_MACHINE_READABLE_CODES) … … 10888 10895 10889 10896 auto requestForTextSelection = [strongSelf createImageAnalyzerRequest:VKAnalysisTypeText image:cgImage.get()]; 10890 auto requestForContextMenu = [strongSelf createImageAnalyzerRequest:VKAnalysisTypeVisualSearch | VKAnalysisTypeMachineReadableCode | VKAnalysisTypeAppClip image:cgImage.get()];10891 10892 10897 if (information.elementContainsImageOverlay) { 10893 [strongSelf _completeImageAnalysisRequestForContextMenu: requestForContextMenu.get() requestIdentifier:requestIdentifier hasTextResults:YES];10898 [strongSelf _completeImageAnalysisRequestForContextMenu:cgImage.get() requestIdentifier:requestIdentifier hasTextResults:YES]; 10894 10899 return; 10895 10900 } 10896 10901 10897 10902 auto textAnalysisStartTime = MonotonicTime::now(); 10898 [[strongSelf imageAnalyzer] processRequest:requestForTextSelection.get() progressHandler:nil completionHandler:[requestIdentifier = WTFMove(requestIdentifier), weakSelf, elementContext, requestLocation, requestForContextMenu, gestureDeferralToken, textAnalysisStartTime] (CocoaImageAnalysis *result, NSError *error) mutable {10903 [[strongSelf imageAnalyzer] processRequest:requestForTextSelection.get() progressHandler:nil completionHandler:[requestIdentifier = WTFMove(requestIdentifier), weakSelf, elementContext, requestLocation, cgImage, gestureDeferralToken, textAnalysisStartTime] (CocoaImageAnalysis *result, NSError *error) mutable { 10899 10904 auto strongSelf = weakSelf.get(); 10900 10905 if (![strongSelf validateImageAnalysisRequestIdentifier:requestIdentifier]) … … 10904 10909 RELEASE_LOG(Images, "Image analysis completed in %.0f ms (request %" PRIu64 "; found text? %d)", (MonotonicTime::now() - textAnalysisStartTime).milliseconds(), requestIdentifier.toUInt64(), hasTextResults); 10905 10910 10906 strongSelf->_page->updateWithTextRecognitionResult(WebKit::makeTextRecognitionResult(result), elementContext, requestLocation, [requestIdentifier = WTFMove(requestIdentifier), weakSelf, hasTextResults, requestForContextMenu, gestureDeferralToken] (WebKit::TextRecognitionUpdateResult updateResult) mutable {10911 strongSelf->_page->updateWithTextRecognitionResult(WebKit::makeTextRecognitionResult(result), elementContext, requestLocation, [requestIdentifier = WTFMove(requestIdentifier), weakSelf, hasTextResults, cgImage, gestureDeferralToken] (WebKit::TextRecognitionUpdateResult updateResult) mutable { 10907 10912 auto strongSelf = weakSelf.get(); 10908 10913 if (![strongSelf validateImageAnalysisRequestIdentifier:requestIdentifier]) … … 10922 10927 } 10923 10928 10924 [strongSelf _completeImageAnalysisRequestForContextMenu: requestForContextMenu.get() requestIdentifier:requestIdentifier hasTextResults:hasTextResults];10929 [strongSelf _completeImageAnalysisRequestForContextMenu:cgImage.get() requestIdentifier:requestIdentifier hasTextResults:hasTextResults]; 10925 10930 }); 10926 10931 }]; … … 10928 10933 } 10929 10934 10930 - (void)_completeImageAnalysisRequestForContextMenu:(CocoaImageAnalyzerRequest *)requestForContextMenu requestIdentifier:(WebKit::ImageAnalysisRequestIdentifier)requestIdentifier hasTextResults:(BOOL)hasTextResults 10931 { 10935 - (void)_completeImageAnalysisRequestForContextMenu:(CGImageRef)image requestIdentifier:(WebKit::ImageAnalysisRequestIdentifier)requestIdentifier hasTextResults:(BOOL)hasTextResults 10936 { 10937 #if USE(QUICK_LOOK) 10938 _hasSelectableTextInImage = hasTextResults; 10939 #endif 10940 10941 auto weakSelf = WeakObjCPtr<WKContentView>(self); 10942 auto aggregator = CallbackAggregator::create([weakSelf, requestIdentifier]() mutable { 10943 if (auto strongSelf = weakSelf.get(); [strongSelf validateImageAnalysisRequestIdentifier:requestIdentifier]) 10944 [strongSelf _invokeAllActionsToPerformAfterPendingImageAnalysis:WebKit::ProceedWithTextSelectionInImage::No]; 10945 }); 10946 10947 auto request = [self createImageAnalyzerRequest:VKAnalysisTypeVisualSearch | VKAnalysisTypeMachineReadableCode | VKAnalysisTypeAppClip image:image]; 10932 10948 auto visualSearchAnalysisStartTime = MonotonicTime::now(); 10933 [self.imageAnalyzer processRequest:request ForContextMenu progressHandler:nil completionHandler:[requestIdentifier = WTFMove(requestIdentifier), weakSelf = WeakObjCPtr<WKContentView>(self), hasTextResults, visualSearchAnalysisStartTime] (CocoaImageAnalysis *result, NSError *error) mutable {10949 [self.imageAnalyzer processRequest:request.get() progressHandler:nil completionHandler:[requestIdentifier = WTFMove(requestIdentifier), weakSelf, visualSearchAnalysisStartTime, aggregator = aggregator.copyRef()] (CocoaImageAnalysis *result, NSError *error) mutable { 10934 10950 auto strongSelf = weakSelf.get(); 10935 10951 if (![strongSelf validateImageAnalysisRequestIdentifier:requestIdentifier]) … … 10942 10958 UNUSED_PARAM(visualSearchAnalysisStartTime); 10943 10959 #endif 10944 if (!result || error) { 10945 [strongSelf _invokeAllActionsToPerformAfterPendingImageAnalysis:WebKit::ProceedWithTextSelectionInImage::No]; 10960 if (!result || error) 10946 10961 return; 10947 }10948 10962 10949 10963 #if USE(QUICK_LOOK) 10950 strongSelf->_hasSelectableTextInImage = hasTextResults;10951 10964 strongSelf->_hasVisualSearchResults = hasVisualSearchResults; 10952 #else10953 UNUSED_PARAM(hasTextResults);10954 10965 #endif 10955 10966 #if USE(UICONTEXTMENU) && ENABLE(IMAGE_ANALYSIS_FOR_MACHINE_READABLE_CODES) 10956 10967 [strongSelf _updateContextMenuForMachineReadableCodeForImageAnalysis:result]; 10957 #endif // USE(UICONTEXTMENU) && ENABLE(IMAGE_ANALYSIS_FOR_MACHINE_READABLE_CODES) 10958 [strongSelf _invokeAllActionsToPerformAfterPendingImageAnalysis:WebKit::ProceedWithTextSelectionInImage::No]; 10968 #endif 10959 10969 }]; 10970 10971 #if ENABLE(IMAGE_ANALYSIS_ENHANCEMENTS) 10972 if (_page->preferences().imageAnalysisMarkupEnabled()) { 10973 WebKit::requestImageAnalysisMarkup(image, [weakSelf = WeakObjCPtr<WKContentView>(self), aggregator = aggregator.copyRef()](CGImageRef result, CGRect) mutable { 10974 if (auto strongSelf = weakSelf.get()) 10975 strongSelf->_croppedImageResult = result; 10976 }); 10977 } 10978 #endif 10960 10979 } 10961 10980 … … 10998 11017 // making redundant image analysis requests for the same image data. 10999 11018 11019 auto aggregator = CallbackAggregator::create([weakSelf, location]() mutable { 11020 auto strongSelf = weakSelf.get(); 11021 if (!strongSelf) 11022 return; 11023 11024 strongSelf->_contextMenuWasTriggeredByImageAnalysisTimeout = YES; 11025 [strongSelf presentContextMenu:strongSelf->_contextMenuInteraction.get() atLocation:location]; 11026 }); 11027 11000 11028 auto visualSearchAnalysisStartTime = MonotonicTime::now(); 11001 11029 auto requestForContextMenu = [strongSelf createImageAnalyzerRequest:VKAnalysisTypeVisualSearch | VKAnalysisTypeMachineReadableCode | VKAnalysisTypeAppClip image:cgImage.get()]; 11002 [[strongSelf imageAnalyzer] processRequest:requestForContextMenu.get() progressHandler:nil completionHandler:[weakSelf, location, visualSearchAnalysisStartTime] (CocoaImageAnalysis *result, NSError *error) {11030 [[strongSelf imageAnalyzer] processRequest:requestForContextMenu.get() progressHandler:nil completionHandler:[weakSelf, visualSearchAnalysisStartTime, aggregator = aggregator.copyRef()] (CocoaImageAnalysis *result, NSError *error) { 11003 11031 auto strongSelf = weakSelf.get(); 11004 11032 if (!strongSelf) … … 11014 11042 #endif 11015 11043 11016 #if USE(UICONTEXTMENU) 11017 #if ENABLE(IMAGE_ANALYSIS_FOR_MACHINE_READABLE_CODES) 11044 #if USE(UICONTEXTMENU) && ENABLE(IMAGE_ANALYSIS_FOR_MACHINE_READABLE_CODES) 11018 11045 [strongSelf _updateContextMenuForMachineReadableCodeForImageAnalysis:result]; 11019 #endif // ENABLE(IMAGE_ANALYSIS_FOR_MACHINE_READABLE_CODES) 11020 strongSelf->_contextMenuWasTriggeredByImageAnalysisTimeout = YES; 11021 [strongSelf presentContextMenu:strongSelf->_contextMenuInteraction.get() atLocation:location]; 11022 #else 11023 UNUSED_PARAM(location); 11024 #endif // USE(UICONTEXTMENU) 11046 #endif 11025 11047 }]; 11048 11049 #if ENABLE(IMAGE_ANALYSIS_ENHANCEMENTS) 11050 if (strongSelf->_page->preferences().imageAnalysisMarkupEnabled()) { 11051 WebKit::requestImageAnalysisMarkup(cgImage.get(), [weakSelf, aggregator = aggregator.copyRef()](CGImageRef result, CGRect) mutable { 11052 if (auto strongSelf = weakSelf.get()) 11053 strongSelf->_croppedImageResult = result; 11054 }); 11055 } 11056 #endif 11026 11057 } forRequest:request]; 11027 11058 } … … 11038 11069 - (BOOL)actionSheetAssistantShouldIncludeCopyCroppedImageAction:(WKActionSheetAssistant *)assistant 11039 11070 { 11040 return _page->preferences().imageAnalysisMarkupEnabled();11071 return !!_croppedImageResult; 11041 11072 } 11042 11073 11043 11074 - (void)actionSheetAssistant:(WKActionSheetAssistant *)assistant copyCroppedImage:(UIImage *)image sourceMIMEType:(NSString *)sourceMIMEType 11044 11075 { 11045 auto changeCount = UIPasteboard.generalPasteboard.changeCount; 11046 WebKit::requestImageAnalysisMarkup(image.CGImage, [changeCount, weakSelf = WeakObjCPtr<WKContentView>(self), originalImage = RetainPtr { image }, sourceMIMEType = RetainPtr { sourceMIMEType }](CGImageRef result, CGRect) mutable { 11047 if (!result) 11048 return; 11049 11050 auto strongSelf = weakSelf.get(); 11051 if (!strongSelf) 11052 return; 11053 11054 auto [data, type] = WebKit::imageDataForCroppedImageResult(result, (__bridge CFStringRef)sourceMIMEType.get()); 11055 if (!data) 11056 return; 11057 11058 [UIPasteboard _performAsDataOwner:[strongSelf _dataOwnerForCopy] block:[data = WTFMove(data), type = WTFMove(type), changeCount] { 11059 auto pasteboard = UIPasteboard.generalPasteboard; 11060 if (changeCount == pasteboard.changeCount) 11061 [pasteboard setData:data.get() forPasteboardType:(__bridge NSString *)type.get()]; 11062 }]; 11063 }); 11076 if (!_croppedImageResult) 11077 return; 11078 11079 auto [data, type] = WebKit::imageDataForCroppedImageResult(_croppedImageResult.get(), (__bridge CFStringRef)sourceMIMEType); 11080 if (!data) 11081 return; 11082 11083 [UIPasteboard _performAsDataOwner:self._dataOwnerForCopy block:[data = WTFMove(data), type = WTFMove(type)] { 11084 [UIPasteboard.generalPasteboard setData:data.get() forPasteboardType:(__bridge NSString *)type.get()]; 11085 }]; 11064 11086 } 11065 11087
Note:
See TracChangeset
for help on using the changeset viewer.