Title: [291445] trunk/Source/WebKit
Revision
291445
Author
[email protected]
Date
2022-03-17 14:57:54 -0700 (Thu, 17 Mar 2022)

Log Message

[iOS] Support PDF search when using a find interaction
https://bugs.webkit.org/show_bug.cgi?id=237408
rdar://89437334

Reviewed by Wenson Hsieh.

Ensure that PDFs can be searched when using a _UIFindInteraction by
making WKPDFView conform to _UITextSearching.

The implementation is a thin wrapper around existing find SPI on
PDFHostViewController. Found ranges in PDFs are uniquely identified
by an index, as more detailed range information is not exposed. Unlike
web content, there is currently no requirement to support restorable
found ranges for PDFs, making indexes safe to use.

* UIProcess/API/ios/WKWebViewIOS.h:
* UIProcess/API/ios/WKWebViewIOS.mm:

Use WKPDFView or WKContentView as the searchable object, depending on
the loaded content.

(-[WKWebView _didCommitLoadForMainFrame]):
(-[WKWebView _searchableObject]):
(-[WKWebView _setFindInteractionEnabled:]):
* UIProcess/ios/WKPDFView.mm:
(+[WKPDFFoundTextRange foundTextRangeWithIndex:]):
(-[WKPDFFoundTextRange start]):
(-[WKPDFFoundTextRange end]):
(-[WKPDFFoundTextRange isEmpty]):
(+[WKPDFFoundTextPosition textPositionWithIndex:]):
(-[WKPDFView dealloc]):
(-[WKPDFView pdfHostViewController:findStringUpdate:done:]):
(-[WKPDFView selectedTextRange]):
(-[WKPDFView compareFoundRange:toRange:inDocument:]):
(-[WKPDFView performTextSearchWithQueryString:usingOptions:resultAggregator:]):
(-[WKPDFView decorateFoundTextRange:inDocument:usingStyle:]):
(-[WKPDFView clearAllDecoratedFoundText]):

Modified Paths

Diff

Modified: trunk/Source/WebKit/ChangeLog (291444 => 291445)


--- trunk/Source/WebKit/ChangeLog	2022-03-17 21:41:29 UTC (rev 291444)
+++ trunk/Source/WebKit/ChangeLog	2022-03-17 21:57:54 UTC (rev 291445)
@@ -1,3 +1,43 @@
+2022-03-17  Aditya Keerthi  <[email protected]>
+
+        [iOS] Support PDF search when using a find interaction
+        https://bugs.webkit.org/show_bug.cgi?id=237408
+        rdar://89437334
+
+        Reviewed by Wenson Hsieh.
+
+        Ensure that PDFs can be searched when using a _UIFindInteraction by
+        making WKPDFView conform to _UITextSearching.
+
+        The implementation is a thin wrapper around existing find SPI on
+        PDFHostViewController. Found ranges in PDFs are uniquely identified
+        by an index, as more detailed range information is not exposed. Unlike
+        web content, there is currently no requirement to support restorable
+        found ranges for PDFs, making indexes safe to use.
+
+        * UIProcess/API/ios/WKWebViewIOS.h:
+        * UIProcess/API/ios/WKWebViewIOS.mm:
+
+        Use WKPDFView or WKContentView as the searchable object, depending on
+        the loaded content.
+
+        (-[WKWebView _didCommitLoadForMainFrame]):
+        (-[WKWebView _searchableObject]):
+        (-[WKWebView _setFindInteractionEnabled:]):
+        * UIProcess/ios/WKPDFView.mm:
+        (+[WKPDFFoundTextRange foundTextRangeWithIndex:]):
+        (-[WKPDFFoundTextRange start]):
+        (-[WKPDFFoundTextRange end]):
+        (-[WKPDFFoundTextRange isEmpty]):
+        (+[WKPDFFoundTextPosition textPositionWithIndex:]):
+        (-[WKPDFView dealloc]):
+        (-[WKPDFView pdfHostViewController:findStringUpdate:done:]):
+        (-[WKPDFView selectedTextRange]):
+        (-[WKPDFView compareFoundRange:toRange:inDocument:]):
+        (-[WKPDFView performTextSearchWithQueryString:usingOptions:resultAggregator:]):
+        (-[WKPDFView decorateFoundTextRange:inDocument:usingStyle:]):
+        (-[WKPDFView clearAllDecoratedFoundText]):
+
 2022-03-17  Brent Fulgham  <[email protected]>
 
         Disable push features in CaptivePortal mode 

Modified: trunk/Source/WebKit/UIProcess/API/ios/WKWebViewIOS.h (291444 => 291445)


--- trunk/Source/WebKit/UIProcess/API/ios/WKWebViewIOS.h	2022-03-17 21:41:29 UTC (rev 291444)
+++ trunk/Source/WebKit/UIProcess/API/ios/WKWebViewIOS.h	2022-03-17 21:57:54 UTC (rev 291445)
@@ -130,6 +130,8 @@
 - (void)find:(id)sender;
 - (void)findNext:(id)sender;
 - (void)findPrevious:(id)sender;
+
+- (id<_UITextSearching>)_searchableObject;
 #endif
 
 - (void)_nextAccessoryTab:(id)sender;

Modified: trunk/Source/WebKit/UIProcess/API/ios/WKWebViewIOS.mm (291444 => 291445)


--- trunk/Source/WebKit/UIProcess/API/ios/WKWebViewIOS.mm	2022-03-17 21:41:29 UTC (rev 291444)
+++ trunk/Source/WebKit/UIProcess/API/ios/WKWebViewIOS.mm	2022-03-17 21:57:54 UTC (rev 291445)
@@ -778,6 +778,13 @@
 
     if (![self _scrollViewIsRubberBandingForRefreshControl])
         [_scrollView _stopScrollingAndZoomingAnimations];
+
+#if HAVE(UIFINDINTERACTION)
+    if (_findInteractionEnabled) {
+        [_findInteraction dismissFindNavigator];
+        [_findInteraction setSearchableObject:[self _searchableObject]];
+    }
+#endif
 }
 
 static CGPoint contentOffsetBoundedInValidRange(UIScrollView *scrollView, CGPoint contentOffset)
@@ -2711,6 +2718,18 @@
     [super buildMenuWithBuilder:builder];
 }
 
+#if HAVE(UIFINDINTERACTION)
+
+- (id<_UITextSearching>)_searchableObject
+{
+    if ([_customContentView conformsToProtocol:@protocol(_UITextSearching)])
+        return (id<_UITextSearching>)_customContentView.get();
+
+    return _contentView.get();
+}
+
+#endif
+
 @end
 
 @implementation WKWebView (WKPrivateIOS)
@@ -3551,7 +3570,7 @@
         if (enabled) {
             if (!_findInteraction) {
                 _findInteraction = adoptNS([[_UIFindInteraction alloc] init]);
-                [_findInteraction setSearchableObject:_contentView.get()];
+                [_findInteraction setSearchableObject:[self _searchableObject]];
             }
 
             [self addInteraction:_findInteraction.get()];

Modified: trunk/Source/WebKit/UIProcess/ios/WKPDFView.mm (291444 => 291445)


--- trunk/Source/WebKit/UIProcess/ios/WKPDFView.mm	2022-03-17 21:41:29 UTC (rev 291444)
+++ trunk/Source/WebKit/UIProcess/ios/WKPDFView.mm	2022-03-17 21:57:54 UTC (rev 291445)
@@ -49,9 +49,71 @@
 #import <wtf/cocoa/Entitlements.h>
 #import <wtf/cocoa/NSURLExtras.h>
 
-@interface WKPDFView () <PDFHostViewControllerDelegate, WKActionSheetAssistantDelegate>
+#if HAVE(UIFINDINTERACTION)
+
+@interface WKPDFFoundTextRange : UITextRange
+
+@property (nonatomic) NSUInteger index;
+
++ (WKPDFFoundTextRange *)foundTextRangeWithIndex:(NSUInteger)index;
+
 @end
 
+@interface WKPDFFoundTextPosition : UITextPosition
+
+@property (nonatomic) NSUInteger index;
+
++ (WKPDFFoundTextPosition *)textPositionWithIndex:(NSUInteger)index;
+
+@end
+
+@implementation WKPDFFoundTextRange
+
++ (WKPDFFoundTextRange *)foundTextRangeWithIndex:(NSUInteger)index
+{
+    auto range = adoptNS([[WKPDFFoundTextRange alloc] init]);
+    [range setIndex:index];
+    return range.autorelease();
+}
+
+- (WKPDFFoundTextPosition *)start
+{
+    WKPDFFoundTextPosition *position = [WKPDFFoundTextPosition textPositionWithIndex:self.index];
+    return position;
+}
+
+- (UITextPosition *)end
+{
+    return self.start;
+}
+
+- (BOOL)isEmpty
+{
+    return NO;
+}
+
+@end
+
+@implementation WKPDFFoundTextPosition
+
++ (WKPDFFoundTextPosition *)textPositionWithIndex:(NSUInteger)index
+{
+    auto position = adoptNS([[WKPDFFoundTextPosition alloc] init]);
+    [position setIndex:index];
+    return position.autorelease();
+}
+
+@end
+
+#endif // HAVE(UIFINDINTERACTION)
+
+@interface WKPDFView () <PDFHostViewControllerDelegate, WKActionSheetAssistantDelegate
+#if HAVE(UIFINDINTERACTION)
+    , _UITextSearching
+#endif
+>
+@end
+
 @implementation WKPDFView {
     RetainPtr<WKActionSheetAssistant> _actionSheetAssistant;
     RetainPtr<NSData> _data;
@@ -72,6 +134,10 @@
     WeakObjCPtr<WKWebView> _webView;
     RetainPtr<WKKeyboardScrollViewAnimator> _keyboardScrollingAnimator;
     RetainPtr<WKShareSheet> _shareSheet;
+#if HAVE(UIFINDINTERACTION)
+    RetainPtr<id<_UITextSearchAggregator>> _searchAggregator;
+    RetainPtr<NSString> _searchString;
+#endif
 }
 
 - (void)dealloc
@@ -86,6 +152,10 @@
     [_pageNumberIndicator removeFromSuperview];
     [_keyboardScrollingAnimator invalidate];
     std::memset(_passwordForPrinting.mutableData(), 0, _passwordForPrinting.length());
+#if HAVE(UIFINDINTERACTION)
+    _searchAggregator = nil;
+    _searchString = nil;
+#endif
     [super dealloc];
 }
 
@@ -432,6 +502,24 @@
 
 - (void)pdfHostViewController:(PDFHostViewController *)controller findStringUpdate:(NSUInteger)numFound done:(BOOL)done
 {
+#if HAVE(UIFINDINTERACTION)
+    if (_searchAggregator) {
+        if (!done)
+            return;
+
+        for (NSUInteger index = 0; index < numFound; index++) {
+            WKPDFFoundTextRange *range = [WKPDFFoundTextRange foundTextRangeWithIndex:index];
+            [_searchAggregator foundRange:range forSearchString:_searchString.get() inDocument:nil];
+        }
+
+        [_searchAggregator finishedSearching];
+
+        _searchAggregator = nil;
+        _searchString = nil;
+        return;
+    }
+#endif
+
     if (numFound > _findStringMaxCount && !done) {
         [controller cancelFindStringWithHighlightsCleared:NO];
         done = YES;
@@ -600,6 +688,64 @@
     return [uiDelegate _dataDetectionContextForWebView:webView];
 }
 
+#pragma mark _UITextSearching
+
+#if HAVE(UIFINDINTERACTION)
+
+- (UITextRange *)selectedTextRange
+{
+    return nil;
+}
+
+- (NSComparisonResult)compareFoundRange:(UITextRange *)fromRange toRange:(UITextRange *)toRange inDocument:(_UITextSearchDocumentIdentifier)document
+{
+    auto from = dynamic_objc_cast<WKPDFFoundTextPosition>(fromRange.start);
+    if (!from)
+        return NSOrderedSame;
+
+    auto to = dynamic_objc_cast<WKPDFFoundTextPosition>(toRange.start);
+    if (!to)
+        return NSOrderedSame;
+
+    NSInteger offset = from.index - to.index;
+
+    if (offset < 0)
+        return NSOrderedAscending;
+
+    if (offset > 0)
+        return NSOrderedDescending;
+
+    return NSOrderedSame;
+}
+
+- (void)performTextSearchWithQueryString:(NSString *)string usingOptions:(_UITextSearchOptions *)options resultAggregator:(id<_UITextSearchAggregator>)aggregator
+{
+    [_hostViewController cancelFindString];
+    _searchAggregator = aggregator;
+    _searchString = string;
+    [_hostViewController findString:string withOptions:options.stringCompareOptions];
+}
+
+- (void)decorateFoundTextRange:(UITextRange *)range inDocument:(_UITextSearchDocumentIdentifier)document usingStyle:(_UIFoundTextStyle)style
+{
+    if (style != _UIFoundTextStyleHighlighted)
+        return;
+
+    auto foundTextRange = dynamic_objc_cast<WKPDFFoundTextRange>(range);
+    if (!foundTextRange)
+        return;
+
+    [_hostViewController focusOnSearchResultAtIndex:foundTextRange.index];
+}
+
+- (void)clearAllDecoratedFoundText
+{
+    [_hostViewController cancelFindString];
+    _searchAggregator = nil;
+}
+
+#endif // HAVE(UIFINDINTERACTION)
+
 @end
 
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to