wpt/css/css-images/gradient/color-stops-parsing.html fails
[WebKit-https.git] / Source / WebKit / UIProcess / ios / WKPDFView.mm
1 /*
2  * Copyright (C) 2018 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "config.h"
27 #import "WKPDFView.h"
28
29 #if ENABLE(WKPDFVIEW)
30
31 #import "APIUIClient.h"
32 #import "FindClient.h"
33 #import "PDFKitSPI.h"
34 #import "UIKitSPI.h"
35 #import "WKActionSheetAssistant.h"
36 #import "WKKeyboardScrollingAnimator.h"
37 #import "WKUIDelegatePrivate.h"
38 #import "WKWebEvent.h"
39 #import "WKWebViewInternal.h"
40 #import "WebPageProxy.h"
41 #import "_WKWebViewPrintFormatterInternal.h"
42 #import <MobileCoreServices/MobileCoreServices.h>
43 #import <WebCore/DataDetection.h>
44 #import <wtf/BlockPtr.h>
45 #import <wtf/MainThread.h>
46 #import <wtf/RetainPtr.h>
47 #import <wtf/WeakObjCPtr.h>
48 #import <wtf/cocoa/Entitlements.h>
49 #import <wtf/cocoa/NSURLExtras.h>
50
51 @interface WKPDFView () <PDFHostViewControllerDelegate, WKActionSheetAssistantDelegate>
52 @end
53
54 @implementation WKPDFView {
55     RetainPtr<WKActionSheetAssistant> _actionSheetAssistant;
56     RetainPtr<NSData> _data;
57     RetainPtr<CGPDFDocumentRef> _documentForPrinting;
58     BlockPtr<void()> _findCompletion;
59     RetainPtr<NSString> _findString;
60     NSUInteger _findStringCount;
61     NSUInteger _findStringMaxCount;
62     RetainPtr<UIView> _fixedOverlayView;
63     Optional<NSUInteger> _focusedSearchResultIndex;
64     NSInteger _focusedSearchResultPendingOffset;
65     RetainPtr<PDFHostViewController> _hostViewController;
66     CGSize _overlaidAccessoryViewsInset;
67     RetainPtr<UIView> _pageNumberIndicator;
68     CString _passwordForPrinting;
69     WebKit::InteractionInformationAtPosition _positionInformation;
70     RetainPtr<NSString> _suggestedFilename;
71     WeakObjCPtr<WKWebView> _webView;
72     RetainPtr<WKKeyboardScrollViewAnimator> _keyboardScrollingAnimator;
73 }
74
75 - (void)dealloc
76 {
77     [_actionSheetAssistant cleanupSheet];
78     [[_hostViewController view] removeFromSuperview];
79     [_pageNumberIndicator removeFromSuperview];
80     [_keyboardScrollingAnimator invalidate];
81     std::memset(_passwordForPrinting.mutableData(), 0, _passwordForPrinting.length());
82     [super dealloc];
83 }
84
85 - (BOOL)web_handleKeyEvent:(::UIEvent *)event
86 {
87     auto webEvent = adoptNS([[WKWebEvent alloc] initWithEvent:event]);
88
89     if ([_keyboardScrollingAnimator beginWithEvent:webEvent.get()])
90         return YES;
91     [_keyboardScrollingAnimator handleKeyEvent:webEvent.get()];
92     return NO;
93 }
94
95 - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
96 {
97     return [_hostViewController gestureRecognizerShouldBegin:gestureRecognizer];
98 }
99
100
101 #pragma mark WKApplicationStateTrackingView
102
103 - (UIView *)_contentView
104 {
105     return _hostViewController ? [_hostViewController view] : self;
106 }
107
108
109 #pragma mark WKWebViewContentProvider
110
111 - (instancetype)web_initWithFrame:(CGRect)frame webView:(WKWebView *)webView mimeType:(NSString *)mimeType
112 {
113     if (!(self = [super initWithFrame:frame webView:webView]))
114         return nil;
115
116 #if USE(PDFKIT_BACKGROUND_COLOR)
117     UIColor *backgroundColor = PDFHostViewController.backgroundColor;
118 #else
119     UIColor *backgroundColor = UIColor.grayColor;
120 #endif
121     self.backgroundColor = backgroundColor;
122     webView.scrollView.backgroundColor = backgroundColor;
123
124     _keyboardScrollingAnimator = adoptNS([[WKKeyboardScrollViewAnimator alloc] initWithScrollView:webView.scrollView]);
125
126     _webView = webView;
127     return self;
128 }
129
130 - (void)web_setContentProviderData:(NSData *)data suggestedFilename:(NSString *)filename
131 {
132     _data = adoptNS([data copy]);
133     _suggestedFilename = adoptNS([filename copy]);
134
135     [PDFHostViewController createHostView:[self, weakSelf = WeakObjCPtr<WKPDFView>(self)](PDFHostViewController *hostViewController) {
136         ASSERT(isMainThread());
137
138         WKPDFView *autoreleasedSelf = weakSelf.getAutoreleased();
139         if (!autoreleasedSelf)
140             return;
141
142         WKWebView *webView = _webView.getAutoreleased();
143         if (!webView)
144             return;
145
146         if (!hostViewController)
147             return;
148         _hostViewController = hostViewController;
149
150         UIView *hostView = hostViewController.view;
151         hostView.frame = webView.bounds;
152
153         UIScrollView *scrollView = webView.scrollView;
154         [self removeFromSuperview];
155         [scrollView addSubview:hostView];
156
157         _actionSheetAssistant = adoptNS([[WKActionSheetAssistant alloc] initWithView:hostView]);
158         [_actionSheetAssistant setDelegate:self];
159
160         _pageNumberIndicator = hostViewController.pageNumberIndicator;
161         [_fixedOverlayView addSubview:_pageNumberIndicator.get()];
162
163         hostViewController.delegate = self;
164         [hostViewController setDocumentData:_data.get() withScrollView:scrollView];
165     } forExtensionIdentifier:nil];
166 }
167
168 - (CGPoint)_offsetForPageNumberIndicator
169 {
170     WKWebView *webView = _webView.getAutoreleased();
171     if (!webView)
172         return CGPointZero;
173
174     UIEdgeInsets insets = UIEdgeInsetsAdd(webView._computedUnobscuredSafeAreaInset, webView._computedObscuredInset, UIRectEdgeAll);
175     return CGPointMake(insets.left, insets.top + _overlaidAccessoryViewsInset.height);
176 }
177
178 - (void)_movePageNumberIndicatorToPoint:(CGPoint)point animated:(BOOL)animated
179 {
180     void (^setFrame)() = ^{
181         static const CGFloat margin = 20;
182         const CGRect frame = { CGPointMake(point.x + margin, point.y + margin), [_pageNumberIndicator frame].size };
183         [_pageNumberIndicator setFrame:frame];
184     };
185
186     if (animated) {
187         static const NSTimeInterval duration = 0.3;
188         [UIView animateWithDuration:duration animations:setFrame];
189         return;
190     }
191
192     setFrame();
193 }
194
195 - (void)_updateLayoutAnimated:(BOOL)animated
196 {
197     [_hostViewController updatePDFViewLayout];
198     [self _movePageNumberIndicatorToPoint:self._offsetForPageNumberIndicator animated:animated];
199 }
200
201 - (void)web_setMinimumSize:(CGSize)size
202 {
203     self.frame = { self.frame.origin, size };
204     [self _updateLayoutAnimated:NO];
205 }
206
207 - (void)web_setOverlaidAccessoryViewsInset:(CGSize)inset
208 {
209     _overlaidAccessoryViewsInset = inset;
210     [self _updateLayoutAnimated:YES];
211 }
212
213 - (void)web_computedContentInsetDidChange
214 {
215     [self _updateLayoutAnimated:NO];
216 }
217
218 - (void)web_setFixedOverlayView:(UIView *)fixedOverlayView
219 {
220     _fixedOverlayView = fixedOverlayView;
221 }
222
223 - (void)_scrollToURLFragment:(NSString *)fragment
224 {
225     NSInteger pageIndex = 0;
226     if ([fragment hasPrefix:@"page"])
227         pageIndex = [[fragment substringFromIndex:4] integerValue] - 1;
228
229     if (pageIndex >= 0 && pageIndex < [_hostViewController pageCount] && pageIndex != [_hostViewController currentPageIndex])
230         [_hostViewController goToPageIndex:pageIndex];
231 }
232
233 - (void)web_didSameDocumentNavigation:(WKSameDocumentNavigationType)navigationType
234 {
235     if (navigationType == kWKSameDocumentNavigationSessionStatePop)
236         [self _scrollToURLFragment:[_webView URL].fragment];
237 }
238
239 static NSStringCompareOptions stringCompareOptions(_WKFindOptions findOptions)
240 {
241     NSStringCompareOptions compareOptions = 0;
242     if (findOptions & _WKFindOptionsBackwards)
243         compareOptions |= NSBackwardsSearch;
244     if (findOptions & _WKFindOptionsCaseInsensitive)
245         compareOptions |= NSCaseInsensitiveSearch;
246     return compareOptions;
247 }
248
249 - (void)_resetFind
250 {
251     if (_findCompletion)
252         [_hostViewController cancelFindString];
253
254     _findCompletion = nil;
255     _findString = nil;
256     _findStringCount = 0;
257     _findStringMaxCount = 0;
258     _focusedSearchResultIndex = WTF::nullopt;
259     _focusedSearchResultPendingOffset = 0;
260 }
261
262 - (void)_findString:(NSString *)string withOptions:(_WKFindOptions)options maxCount:(NSUInteger)maxCount completion:(void(^)())completion
263 {
264     [self _resetFind];
265
266     _findCompletion = completion;
267     _findString = adoptNS([string copy]);
268     _findStringMaxCount = maxCount;
269     [_hostViewController findString:_findString.get() withOptions:stringCompareOptions(options)];
270 }
271
272 - (void)web_countStringMatches:(NSString *)string options:(_WKFindOptions)options maxCount:(NSUInteger)maxCount
273 {
274     [self _findString:string withOptions:options maxCount:maxCount completion:^{
275         ASSERT([_findString isEqualToString:string]);
276         if (auto page = [_webView _page])
277             page->findClient().didCountStringMatches(page, _findString.get(), _findStringCount);
278     }];
279 }
280
281 - (BOOL)_computeFocusedSearchResultIndexWithOptions:(_WKFindOptions)options didWrapAround:(BOOL *)didWrapAround
282 {
283     BOOL isBackwards = options & _WKFindOptionsBackwards;
284     NSInteger singleOffset = isBackwards ? -1 : 1;
285
286     if (_findCompletion) {
287         ASSERT(!_focusedSearchResultIndex);
288         _focusedSearchResultPendingOffset += singleOffset;
289         return NO;
290     }
291
292     if (!_findStringCount)
293         return NO;
294
295     NSInteger newIndex;
296     if (_focusedSearchResultIndex) {
297         ASSERT(!_focusedSearchResultPendingOffset);
298         newIndex = *_focusedSearchResultIndex + singleOffset;
299     } else {
300         newIndex = isBackwards ? _findStringCount - 1 : 0;
301         newIndex += std::exchange(_focusedSearchResultPendingOffset, 0);
302     }
303
304     if (newIndex < 0 || static_cast<NSUInteger>(newIndex) >= _findStringCount) {
305         if (!(options & _WKFindOptionsWrapAround))
306             return NO;
307
308         NSUInteger wrappedIndex = std::abs(newIndex) % _findStringCount;
309         if (newIndex < 0)
310             wrappedIndex = _findStringCount - wrappedIndex;
311         newIndex = wrappedIndex;
312         *didWrapAround = YES;
313     }
314
315     _focusedSearchResultIndex = newIndex;
316     ASSERT(*_focusedSearchResultIndex < _findStringCount);
317     return YES;
318 }
319
320 - (void)_focusOnSearchResultWithOptions:(_WKFindOptions)options
321 {
322     auto page = [_webView _page];
323     if (!page)
324         return;
325
326     BOOL didWrapAround = NO;
327     if (![self _computeFocusedSearchResultIndexWithOptions:options didWrapAround:&didWrapAround]) {
328         if (!_findCompletion)
329             page->findClient().didFailToFindString(page, _findString.get());
330         return;
331     }
332
333     auto focusedIndex = *_focusedSearchResultIndex;
334     [_hostViewController focusOnSearchResultAtIndex:focusedIndex];
335     page->findClient().didFindString(page, _findString.get(), { }, _findStringCount, focusedIndex, didWrapAround);
336 }
337
338 - (void)web_findString:(NSString *)string options:(_WKFindOptions)options maxCount:(NSUInteger)maxCount
339 {
340     if ([_findString isEqualToString:string]) {
341         [self _focusOnSearchResultWithOptions:options];
342         return;
343     }
344
345     [self _findString:string withOptions:options maxCount:maxCount completion:^{
346         ASSERT([_findString isEqualToString:string]);
347         [self _focusOnSearchResultWithOptions:options];
348     }];
349 }
350
351 - (void)web_hideFindUI
352 {
353     [self _resetFind];
354 }
355
356 - (UIView *)web_contentView
357 {
358     return self._contentView;
359 }
360
361 + (BOOL)web_requiresCustomSnapshotting
362 {
363 #if HAVE(PDFHOSTVIEWCONTROLLER_SNAPSHOTTING)
364     static bool hasGlobalCaptureEntitlement = WTF::processHasEntitlement("com.apple.QuartzCore.global-capture");
365     return !hasGlobalCaptureEntitlement;
366 #else
367     return false;
368 #endif
369 }
370
371 - (void)web_scrollViewDidScroll:(UIScrollView *)scrollView
372 {
373     [_hostViewController updatePDFViewLayout];
374 }
375
376 - (void)web_scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view
377 {
378     [_hostViewController updatePDFViewLayout];
379 }
380
381 - (void)web_scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale
382 {
383     [_hostViewController updatePDFViewLayout];
384 }
385
386 - (void)web_scrollViewDidZoom:(UIScrollView *)scrollView
387 {
388     [_hostViewController updatePDFViewLayout];
389 }
390
391 - (void)web_beginAnimatedResizeWithUpdates:(void (^)(void))updateBlock
392 {
393     [_hostViewController beginPDFViewRotation];
394     updateBlock();
395     [_hostViewController endPDFViewRotation];
396 }
397
398 - (void)web_snapshotRectInContentViewCoordinates:(CGRect)rectInContentViewCoordinates snapshotWidth:(CGFloat)snapshotWidth completionHandler:(void (^)(CGImageRef))completionHandler
399 {
400 #if HAVE(PDFHOSTVIEWCONTROLLER_SNAPSHOTTING)
401     CGRect rectInHostViewCoordinates = [self._contentView convertRect:rectInContentViewCoordinates toView:[_hostViewController view]];
402     [_hostViewController snapshotViewRect:rectInHostViewCoordinates snapshotWidth:@(snapshotWidth) afterScreenUpdates:NO withResult:^(UIImage *image) {
403         completionHandler(image.CGImage);
404     }];
405 #endif
406 }
407
408 - (NSData *)web_dataRepresentation
409 {
410     return _data.get();
411 }
412
413 - (NSString *)web_suggestedFilename
414 {
415     return _suggestedFilename.get();
416 }
417
418 - (BOOL)web_isBackground
419 {
420     return self.isBackground;
421 }
422
423
424 #pragma mark PDFHostViewControllerDelegate
425
426 - (void)pdfHostViewController:(PDFHostViewController *)controller updatePageCount:(NSInteger)pageCount
427 {
428     [self _scrollToURLFragment:[_webView URL].fragment];
429 }
430
431 - (void)pdfHostViewController:(PDFHostViewController *)controller documentDidUnlockWithPassword:(NSString *)password
432 {
433     _passwordForPrinting = [password UTF8String];
434 }
435
436 - (void)pdfHostViewController:(PDFHostViewController *)controller findStringUpdate:(NSUInteger)numFound done:(BOOL)done
437 {
438     if (numFound > _findStringMaxCount && !done) {
439         [controller cancelFindStringWithHighlightsCleared:NO];
440         done = YES;
441     }
442     
443     if (!done)
444         return;
445     
446     if (auto findCompletion = std::exchange(_findCompletion, nil)) {
447         _findStringCount = numFound;
448         findCompletion();
449     }
450 }
451
452 - (NSURL *)_URLWithPageIndex:(NSInteger)pageIndex
453 {
454     return [NSURL URLWithString:[NSString stringWithFormat:@"#page%ld", (long)pageIndex + 1] relativeToURL:[_webView URL]];
455 }
456
457 - (void)_goToURL:(NSURL *)url atLocation:(CGPoint)location
458 {
459     auto page = [_webView _page];
460     if (!page)
461         return;
462
463     UIView *hostView = [_hostViewController view];
464     CGPoint locationInScreen = [hostView.window convertPoint:[hostView convertPoint:location toView:nil] toWindow:nil];
465     page->navigateToPDFLinkWithSimulatedClick(url.absoluteString, WebCore::roundedIntPoint(location), WebCore::roundedIntPoint(locationInScreen));
466 }
467
468 - (void)pdfHostViewController:(PDFHostViewController *)controller goToURL:(NSURL *)url
469 {
470     // FIXME: We'd use the real tap location if we knew it.
471     [self _goToURL:url atLocation:CGPointMake(0, 0)];
472 }
473
474 - (void)pdfHostViewController:(PDFHostViewController *)controller goToPageIndex:(NSInteger)pageIndex withViewFrustum:(CGRect)documentViewRect
475 {
476     [self _goToURL:[self _URLWithPageIndex:pageIndex] atLocation:documentViewRect.origin];
477 }
478
479 - (void)_showActionSheetForURL:(NSURL *)url atLocation:(CGPoint)location withAnnotationRect:(CGRect)annotationRect
480 {
481     WKWebView *webView = _webView.getAutoreleased();
482     if (!webView)
483         return;
484
485     WebKit::InteractionInformationAtPosition positionInformation;
486     positionInformation.bounds = WebCore::roundedIntRect(annotationRect);
487     positionInformation.request.point = WebCore::roundedIntPoint(location);
488     positionInformation.url = url;
489
490     _positionInformation = WTFMove(positionInformation);
491 #if ENABLE(DATA_DETECTION)
492     if (WebCore::DataDetection::canBePresentedByDataDetectors(_positionInformation.url))
493         [_actionSheetAssistant showDataDetectorsSheet];
494     else
495 #endif
496         [_actionSheetAssistant showLinkSheet];
497 }
498
499 - (void)pdfHostViewController:(PDFHostViewController *)controller didLongPressURL:(NSURL *)url atLocation:(CGPoint)location withAnnotationRect:(CGRect)annotationRect
500 {
501     [self _showActionSheetForURL:url atLocation:location withAnnotationRect:annotationRect];
502 }
503
504 - (void)pdfHostViewController:(PDFHostViewController *)controller didLongPressPageIndex:(NSInteger)pageIndex atLocation:(CGPoint)location withAnnotationRect:(CGRect)annotationRect
505 {
506     [self _showActionSheetForURL:[self _URLWithPageIndex:pageIndex] atLocation:location withAnnotationRect:annotationRect];
507 }
508
509 - (void)pdfHostViewControllerExtensionProcessDidCrash:(PDFHostViewController *)controller
510 {
511     // FIXME 40916725: PDFKit should dispatch this message to the main thread like it does for other delegate messages.
512     dispatch_async(dispatch_get_main_queue(), [webView = _webView] {
513         if (auto page = [webView _page])
514             page->dispatchProcessDidTerminate(WebKit::ProcessTerminationReason::Crash);
515     });
516 }
517
518
519 #pragma mark WKActionSheetAssistantDelegate
520
521 - (Optional<WebKit::InteractionInformationAtPosition>)positionInformationForActionSheetAssistant:(WKActionSheetAssistant *)assistant
522 {
523     return _positionInformation;
524 }
525
526 - (void)actionSheetAssistant:(WKActionSheetAssistant *)assistant performAction:(WebKit::SheetAction)action
527 {
528     if (action != WebKit::SheetAction::Copy)
529         return;
530
531     NSDictionary *representations = @{
532         (NSString *)kUTTypeUTF8PlainText : (NSString *)_positionInformation.url,
533         (NSString *)kUTTypeURL : (NSURL *)_positionInformation.url,
534     };
535
536     [UIPasteboard generalPasteboard].items = @[ representations ];
537 }
538
539 - (void)actionSheetAssistant:(WKActionSheetAssistant *)assistant openElementAtLocation:(CGPoint)location
540 {
541     [self _goToURL:_positionInformation.url atLocation:location];
542 }
543
544 - (void)actionSheetAssistant:(WKActionSheetAssistant *)assistant shareElementWithURL:(NSURL *)url rect:(CGRect)boundingRect
545 {
546     // FIXME: We should use WKShareSheet instead of UIWKSelectionAssistant for this.
547     auto selectionAssistant = adoptNS([[UIWKSelectionAssistant alloc] initWithView:[_hostViewController view]]);
548     [selectionAssistant showShareSheetFor:WTF::userVisibleString(url) fromRect:boundingRect];
549 }
550
551 #if HAVE(APP_LINKS)
552 - (BOOL)actionSheetAssistant:(WKActionSheetAssistant *)assistant shouldIncludeAppLinkActionsForElement:(_WKActivatedElementInfo *)element
553 {
554     auto page = [_webView _page];
555     if (!page)
556         return NO;
557
558     return page->uiClient().shouldIncludeAppLinkActionsForElement(element);
559 }
560 #endif
561
562 - (RetainPtr<NSArray>)actionSheetAssistant:(WKActionSheetAssistant *)assistant decideActionsForElement:(_WKActivatedElementInfo *)element defaultActions:(RetainPtr<NSArray>)defaultActions
563 {
564     auto page = [_webView _page];
565     if (!page)
566         return nil;
567
568     return page->uiClient().actionsForElement(element, WTFMove(defaultActions));
569 }
570
571 - (NSDictionary *)dataDetectionContextForActionSheetAssistant:(WKActionSheetAssistant *)assistant
572 {
573     auto webView = _webView.getAutoreleased();
574     if (!webView)
575         return nil;
576
577     id <WKUIDelegatePrivate> uiDelegate = static_cast<id <WKUIDelegatePrivate>>(webView.UIDelegate);
578     if (![uiDelegate respondsToSelector:@selector(_dataDetectionContextForWebView:)])
579         return nil;
580
581     return [uiDelegate _dataDetectionContextForWebView:webView];
582 }
583
584 @end
585
586
587 #pragma mark _WKWebViewPrintProvider
588
589 @interface WKPDFView (_WKWebViewPrintFormatter) <_WKWebViewPrintProvider>
590 @end
591
592 @implementation WKPDFView (_WKWebViewPrintFormatter)
593
594 - (CGPDFDocumentRef)_ensureDocumentForPrinting
595 {
596     if (_documentForPrinting)
597         return _documentForPrinting.get();
598
599     auto dataProvider = adoptCF(CGDataProviderCreateWithCFData((CFDataRef)_data.get()));
600     auto pdfDocument = adoptCF(CGPDFDocumentCreateWithProvider(dataProvider.get()));
601     if (!CGPDFDocumentIsUnlocked(pdfDocument.get()))
602         CGPDFDocumentUnlockWithPassword(pdfDocument.get(), _passwordForPrinting.data());
603
604     _documentForPrinting = WTFMove(pdfDocument);
605     return _documentForPrinting.get();
606 }
607
608 - (NSUInteger)_wk_pageCountForPrintFormatter:(_WKWebViewPrintFormatter *)printFormatter
609 {
610     CGPDFDocumentRef documentForPrinting = [self _ensureDocumentForPrinting];
611     if (!CGPDFDocumentAllowsPrinting(documentForPrinting))
612         return 0;
613
614     size_t pageCount = CGPDFDocumentGetNumberOfPages(documentForPrinting);
615     if (printFormatter.snapshotFirstPage)
616         return std::min<NSUInteger>(pageCount, 1);
617     return pageCount;
618 }
619
620 - (CGPDFDocumentRef)_wk_printedDocument
621 {
622     return [self _ensureDocumentForPrinting];
623 }
624
625 @end
626
627 #endif // ENABLE(WKPDFVIEW)