Title: [291304] trunk
Revision
291304
Author
[email protected]
Date
2022-03-15 10:39:30 -0700 (Tue, 15 Mar 2022)

Log Message

[iOS] Indefinite hang when printing using a UIPrintPageRenderer
https://bugs.webkit.org/show_bug.cgi?id=237835
rdar://90002387

Reviewed by Devin Rousso.

Source/WebKit:

r290186 adopted UIKit API to support printing web content on a
background thread, to avoid blocking the main thread while waiting
on PDF data from the web process. However, the changes made the
assumption that, with the new API, all printing would be performed on
a background thread. While this is the case when using
UIPrintInteractionController, clients can also print using
UIPrintPageRenderer on the main thread. The background thread logic
waits on a semaphore, until PDF data is received on the main thread.
However, if the logic runs on the main thread, it will wait on the
semaphore indefinitely.

To fix, restore the original sync IPC codepath when performing printing
on the main thread. Additionally, make the BinarySemaphore a
unique_ptr, so that it can be signalled and reset in failure scenarios,
regardless of whether a thread was waiting on the semaphore. This
change also allows us to avoid creating the BinarySemaphore unless it
is actually needed.

All uses of HAVE(UIKIT_BACKGROUND_THREAD_PRINTING) are removed, as the
API adoption only involves a method override, which is harmless in
builds that lack support for the new API.

* UIProcess/WebPageProxy.h:
* UIProcess/_WKWebViewPrintFormatter.mm:
* UIProcess/_WKWebViewPrintFormatterInternal.h:
* UIProcess/ios/WKContentView.mm:
(-[WKContentView _processDidExit]):
(-[WKContentView _wk_pageCountForPrintFormatter:]):
(-[WKContentView _waitForDrawToPDFCallbackIfNeeded]):
(-[WKContentView _wk_printedDocument]):
* UIProcess/ios/WKPDFView.mm:
* UIProcess/ios/WebPageProxyIOS.mm:
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:
* WebProcess/WebPage/ios/WebPageIOS.mm:

Source/WTF:

Remove unused HAVE macro.

* wtf/PlatformHave.h:

Tools:

Add API test coverage for printing web content to a PDF, using a
UIPrintPageRenderer (which uses the main thread) and a
UIPrintInteractionController (which uses a background thread).

* TestWebKitAPI/Tests/WebKitCocoa/WKWebViewPrintFormatter.mm:
(TEST):

Modified Paths

Diff

Modified: trunk/Source/WTF/ChangeLog (291303 => 291304)


--- trunk/Source/WTF/ChangeLog	2022-03-15 17:36:18 UTC (rev 291303)
+++ trunk/Source/WTF/ChangeLog	2022-03-15 17:39:30 UTC (rev 291304)
@@ -1,3 +1,15 @@
+2022-03-15  Aditya Keerthi  <[email protected]>
+
+        [iOS] Indefinite hang when printing using a UIPrintPageRenderer
+        https://bugs.webkit.org/show_bug.cgi?id=237835
+        rdar://90002387
+
+        Reviewed by Devin Rousso.
+
+        Remove unused HAVE macro.
+
+        * wtf/PlatformHave.h:
+
 2022-03-15  Jer Noble  <[email protected]>
 
         [Cocoa] Adopt AVAssetPrefersSandboxedParsingOptionKey

Modified: trunk/Source/WTF/wtf/PlatformHave.h (291303 => 291304)


--- trunk/Source/WTF/wtf/PlatformHave.h	2022-03-15 17:36:18 UTC (rev 291303)
+++ trunk/Source/WTF/wtf/PlatformHave.h	2022-03-15 17:39:30 UTC (rev 291304)
@@ -1223,7 +1223,3 @@
 #if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 130000) || (PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 160000) || (PLATFORM(WATCHOS) && __WATCH_OS_VERSION_MIN_REQUIRED >= 90000)
 #define HAVE_SAFE_BROWSING_RESULT_DETAILS 1
 #endif
-
-#if (PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 160000)
-#define HAVE_UIKIT_BACKGROUND_THREAD_PRINTING 1
-#endif

Modified: trunk/Source/WebKit/ChangeLog (291303 => 291304)


--- trunk/Source/WebKit/ChangeLog	2022-03-15 17:36:18 UTC (rev 291303)
+++ trunk/Source/WebKit/ChangeLog	2022-03-15 17:39:30 UTC (rev 291304)
@@ -1,3 +1,47 @@
+2022-03-15  Aditya Keerthi  <[email protected]>
+
+        [iOS] Indefinite hang when printing using a UIPrintPageRenderer
+        https://bugs.webkit.org/show_bug.cgi?id=237835
+        rdar://90002387
+
+        Reviewed by Devin Rousso.
+
+        r290186 adopted UIKit API to support printing web content on a
+        background thread, to avoid blocking the main thread while waiting
+        on PDF data from the web process. However, the changes made the
+        assumption that, with the new API, all printing would be performed on
+        a background thread. While this is the case when using
+        UIPrintInteractionController, clients can also print using
+        UIPrintPageRenderer on the main thread. The background thread logic
+        waits on a semaphore, until PDF data is received on the main thread.
+        However, if the logic runs on the main thread, it will wait on the
+        semaphore indefinitely.
+
+        To fix, restore the original sync IPC codepath when performing printing
+        on the main thread. Additionally, make the BinarySemaphore a
+        unique_ptr, so that it can be signalled and reset in failure scenarios,
+        regardless of whether a thread was waiting on the semaphore. This
+        change also allows us to avoid creating the BinarySemaphore unless it
+        is actually needed.
+
+        All uses of HAVE(UIKIT_BACKGROUND_THREAD_PRINTING) are removed, as the
+        API adoption only involves a method override, which is harmless in
+        builds that lack support for the new API.
+
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/_WKWebViewPrintFormatter.mm:
+        * UIProcess/_WKWebViewPrintFormatterInternal.h:
+        * UIProcess/ios/WKContentView.mm:
+        (-[WKContentView _processDidExit]):
+        (-[WKContentView _wk_pageCountForPrintFormatter:]):
+        (-[WKContentView _waitForDrawToPDFCallbackIfNeeded]):
+        (-[WKContentView _wk_printedDocument]):
+        * UIProcess/ios/WKPDFView.mm:
+        * UIProcess/ios/WebPageProxyIOS.mm:
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in:
+        * WebProcess/WebPage/ios/WebPageIOS.mm:
+
 2022-03-15  Per Arne Vollan  <[email protected]>
 
         [macOS][WP] Add required syscall

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (291303 => 291304)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.h	2022-03-15 17:36:18 UTC (rev 291303)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h	2022-03-15 17:39:30 UTC (rev 291304)
@@ -1419,9 +1419,7 @@
     uint64_t drawPagesToPDF(WebFrameProxy*, const PrintInfo&, uint32_t first, uint32_t count, CompletionHandler<void(API::Data*)>&&);
     void drawToPDF(WebCore::FrameIdentifier, const std::optional<WebCore::FloatRect>&, CompletionHandler<void(const IPC::SharedBufferCopy&)>&&);
 #if PLATFORM(IOS_FAMILY)
-#if !HAVE(UIKIT_BACKGROUND_THREAD_PRINTING)
     size_t computePagesForPrintingiOS(WebCore::FrameIdentifier, const PrintInfo&);
-#endif
     uint64_t drawToPDFiOS(WebCore::FrameIdentifier, const PrintInfo&, size_t pageCount, CompletionHandler<void(const IPC::SharedBufferCopy&)>&&);
 #endif
 #elif PLATFORM(GTK)

Modified: trunk/Source/WebKit/UIProcess/_WKWebViewPrintFormatter.mm (291303 => 291304)


--- trunk/Source/WebKit/UIProcess/_WKWebViewPrintFormatter.mm	2022-03-15 17:36:18 UTC (rev 291303)
+++ trunk/Source/WebKit/UIProcess/_WKWebViewPrintFormatter.mm	2022-03-15 17:39:30 UTC (rev 291304)
@@ -44,15 +44,11 @@
     BOOL _suppressPageCountRecalc;
 }
 
-#if HAVE(UIKIT_BACKGROUND_THREAD_PRINTING)
-
 - (BOOL)requiresMainThread
 {
     return self._webView._printProvider._wk_printFormatterRequiresMainThread;
 }
 
-#endif // HAVE(UIKIT_BACKGROUND_THREAD_PRINTING)
-
 - (_WKFrameHandle *)frameToPrint
 {
     return _frameToPrint.get();

Modified: trunk/Source/WebKit/UIProcess/_WKWebViewPrintFormatterInternal.h (291303 => 291304)


--- trunk/Source/WebKit/UIProcess/_WKWebViewPrintFormatterInternal.h	2022-03-15 17:36:18 UTC (rev 291303)
+++ trunk/Source/WebKit/UIProcess/_WKWebViewPrintFormatterInternal.h	2022-03-15 17:39:30 UTC (rev 291304)
@@ -37,10 +37,8 @@
 @end
 
 @protocol _WKWebViewPrintProvider <NSObject>
-#if HAVE(UIKIT_BACKGROUND_THREAD_PRINTING)
+- (NSUInteger)_wk_pageCountForPrintFormatter:(_WKWebViewPrintFormatter *)printFormatter;
 @property (nonatomic, readonly) BOOL _wk_printFormatterRequiresMainThread;
-#endif
-- (NSUInteger)_wk_pageCountForPrintFormatter:(_WKWebViewPrintFormatter *)printFormatter;
 @property (nonatomic, readonly) CGPDFDocumentRef _wk_printedDocument;
 @end
 

Modified: trunk/Source/WebKit/UIProcess/ios/WKContentView.mm (291303 => 291304)


--- trunk/Source/WebKit/UIProcess/ios/WKContentView.mm	2022-03-15 17:36:18 UTC (rev 291303)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentView.mm	2022-03-15 17:39:30 UTC (rev 291304)
@@ -148,9 +148,7 @@
     RetainPtr<NSUndoManager> _undoManager;
     RetainPtr<WKQuirkyNSUndoManager> _quirkyUndoManager;
 
-#if HAVE(UIKIT_BACKGROUND_THREAD_PRINTING)
-    BinarySemaphore _pdfPrintCompletionSemaphore;
-#endif
+    std::unique_ptr<BinarySemaphore> _pdfPrintCompletionSemaphore;
     uint64_t _pdfPrintCallbackID;
     RetainPtr<CGPDFDocumentRef> _printedDocument;
     Vector<RetainPtr<NSURL>> _temporaryURLsToDeleteWhenDeallocated;
@@ -691,10 +689,9 @@
     [self _removeVisibilityPropagationViewForWebProcess];
 #endif
 
-#if HAVE(UIKIT_BACKGROUND_THREAD_PRINTING)
-    if (_pdfPrintCallbackID)
-        _pdfPrintCompletionSemaphore.signal();
-#endif
+    if (auto pdfPrintCompletionSemaphore = std::exchange(_pdfPrintCompletionSemaphore, nullptr))
+        pdfPrintCompletionSemaphore->signal();
+
     _pdfPrintCallbackID = 0;
 }
 
@@ -869,20 +866,14 @@
 
 @implementation WKContentView (_WKWebViewPrintFormatter)
 
-#if HAVE(UIKIT_BACKGROUND_THREAD_PRINTING)
-
 - (BOOL)_wk_printFormatterRequiresMainThread
 {
     return NO;
 }
 
-#endif // HAVE(UIKIT_BACKGROUND_THREAD_PRINTING)
-
 - (NSUInteger)_wk_pageCountForPrintFormatter:(_WKWebViewPrintFormatter *)printFormatter
 {
-#if HAVE(UIKIT_BACKGROUND_THREAD_PRINTING)
-    ASSERT(!isMainRunLoop());
-#endif
+    bool isPrintingOnBackgroundThread = !isMainRunLoop();
 
     [self _waitForDrawToPDFCallbackIfNeeded];
 
@@ -920,22 +911,25 @@
     if (printInfo.snapshotFirstPage)
         pageCount = 1;
     else {
-#if HAVE(UIKIT_BACKGROUND_THREAD_PRINTING)
-        BinarySemaphore computePagesSemaphore;
-        callOnMainRunLoop([self, frameID, printInfo, &pageCount, &computePagesSemaphore]() mutable {
-            _page->computePagesForPrinting(frameID, printInfo, [&pageCount, &computePagesSemaphore](const Vector<WebCore::IntRect>& pageRects, double /* totalScaleFactorForPrinting */, const WebCore::FloatBoxExtent& /* computedPageMargin */) mutable {
-                ASSERT(pageRects.size() >= 1);
-                pageCount = pageRects.size();
+        if (isPrintingOnBackgroundThread) {
+            BinarySemaphore computePagesSemaphore;
+            callOnMainRunLoop([self, frameID, printInfo, &pageCount, &computePagesSemaphore]() mutable {
+                _page->computePagesForPrinting(frameID, printInfo, [&pageCount, &computePagesSemaphore](const Vector<WebCore::IntRect>& pageRects, double /* totalScaleFactorForPrinting */, const WebCore::FloatBoxExtent& /* computedPageMargin */) mutable {
+                    ASSERT(pageRects.size() >= 1);
+                    pageCount = pageRects.size();
 
-                computePagesSemaphore.signal();
+                    computePagesSemaphore.signal();
+                });
             });
-        });
-        computePagesSemaphore.wait();
-#else
-        pageCount = _page->computePagesForPrintingiOS(frameID, printInfo);
-#endif
+            computePagesSemaphore.wait();
+        } else
+            pageCount = _page->computePagesForPrintingiOS(frameID, printInfo);
     }
 
+    ASSERT(!_pdfPrintCompletionSemaphore);
+    if (isPrintingOnBackgroundThread)
+        _pdfPrintCompletionSemaphore = makeUnique<BinarySemaphore>();
+
     // Begin generating the PDF in expectation of a (eventual) request for the drawn data.
     _pdfPrintCallbackID = _page->drawToPDFiOS(frameID, printInfo, pageCount, [retainedSelf = retainPtr(self)](const IPC::SharedBufferCopy& pdfData) {
         if (pdfData.isEmpty())
@@ -946,9 +940,9 @@
             retainedSelf->_printedDocument = adoptCF(CGPDFDocumentCreateWithProvider(dataProvider.get()));
         }
 
-#if HAVE(UIKIT_BACKGROUND_THREAD_PRINTING)
-        retainedSelf->_pdfPrintCompletionSemaphore.signal();
-#endif
+        if (auto pdfPrintCompletionSemaphore = std::exchange(retainedSelf->_pdfPrintCompletionSemaphore, nullptr))
+            pdfPrintCompletionSemaphore->signal();
+
         retainedSelf->_pdfPrintCallbackID = 0;
     });
 
@@ -958,13 +952,10 @@
 - (BOOL)_waitForDrawToPDFCallbackIfNeeded
 {
     if (auto callbackID = std::exchange(_pdfPrintCallbackID, 0)) {
-#if HAVE(UIKIT_BACKGROUND_THREAD_PRINTING)
-        ASSERT(!isMainRunLoop());
-        _pdfPrintCompletionSemaphore.wait();
-#else
-        if (!_page->process().connection()->waitForAsyncCallbackAndDispatchImmediately<Messages::WebPage::DrawToPDFiOS>(callbackID, Seconds::infinity()))
+        if (_pdfPrintCompletionSemaphore)
+            _pdfPrintCompletionSemaphore->wait();
+        else if (!_page->process().connection()->waitForAsyncCallbackAndDispatchImmediately<Messages::WebPage::DrawToPDFiOS>(callbackID, Seconds::infinity()))
             return false;
-#endif
     }
     ASSERT(!_pdfPrintCallbackID);
     return true;
@@ -972,10 +963,6 @@
 
 - (CGPDFDocumentRef)_wk_printedDocument
 {
-#if HAVE(UIKIT_BACKGROUND_THREAD_PRINTING)
-    ASSERT(!isMainRunLoop());
-#endif
-
     if (![self _waitForDrawToPDFCallbackIfNeeded])
         return nullptr;
 

Modified: trunk/Source/WebKit/UIProcess/ios/WKPDFView.mm (291303 => 291304)


--- trunk/Source/WebKit/UIProcess/ios/WKPDFView.mm	2022-03-15 17:36:18 UTC (rev 291303)
+++ trunk/Source/WebKit/UIProcess/ios/WKPDFView.mm	2022-03-15 17:39:30 UTC (rev 291304)
@@ -629,15 +629,11 @@
     return _documentForPrinting.get();
 }
 
-#if HAVE(UIKIT_BACKGROUND_THREAD_PRINTING)
-
 - (BOOL)_wk_printFormatterRequiresMainThread
 {
     return YES;
 }
 
-#endif // HAVE(UIKIT_BACKGROUND_THREAD_PRINTING)
-
 - (NSUInteger)_wk_pageCountForPrintFormatter:(_WKWebViewPrintFormatter *)printFormatter
 {
     CGPDFDocumentRef documentForPrinting = [self _ensureDocumentForPrinting];

Modified: trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm (291303 => 291304)


--- trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm	2022-03-15 17:36:18 UTC (rev 291303)
+++ trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm	2022-03-15 17:39:30 UTC (rev 291304)
@@ -1028,8 +1028,6 @@
     pageClient().handleSmartMagnificationInformationForPotentialTap(requestID, renderRect, fitEntireRect, viewportMinimumScale, viewportMaximumScale, nodeIsRootLevel);
 }
 
-#if !HAVE(UIKIT_BACKGROUND_THREAD_PRINTING)
-
 size_t WebPageProxy::computePagesForPrintingiOS(FrameIdentifier frameID, const PrintInfo& printInfo)
 {
     ASSERT_WITH_MESSAGE(!printInfo.snapshotFirstPage, "If we are just snapshotting the first page, we don't need a synchronous message to determine the page count, which is 1.");
@@ -1042,8 +1040,6 @@
     return pageCount;
 }
 
-#endif // !HAVE(UIKIT_BACKGROUND_THREAD_PRINTING)
-
 uint64_t WebPageProxy::drawToPDFiOS(FrameIdentifier frameID, const PrintInfo& printInfo, size_t pageCount, CompletionHandler<void(const IPC::SharedBufferCopy&)>&& completionHandler)
 {
     if (!hasRunningProcess()) {

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.h (291303 => 291304)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.h	2022-03-15 17:36:18 UTC (rev 291303)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.h	2022-03-15 17:39:30 UTC (rev 291304)
@@ -1040,9 +1040,7 @@
 #endif
 
 #if PLATFORM(IOS_FAMILY)
-#if !HAVE(UIKIT_BACKGROUND_THREAD_PRINTING)
     void computePagesForPrintingiOS(WebCore::FrameIdentifier, const PrintInfo&, Messages::WebPage::ComputePagesForPrintingiOSDelayedReply&&);
-#endif
     void drawToPDFiOS(WebCore::FrameIdentifier, const PrintInfo&, size_t, Messages::WebPage::DrawToPDFiOSAsyncReply&&);
 #endif
 

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in (291303 => 291304)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in	2022-03-15 17:36:18 UTC (rev 291303)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in	2022-03-15 17:39:30 UTC (rev 291304)
@@ -433,9 +433,7 @@
     DrawRectToImage(WebCore::FrameIdentifier frameID, struct WebKit::PrintInfo printInfo, WebCore::IntRect rect, WebCore::IntSize imageSize) -> (WebKit::ShareableBitmap::Handle image)
     DrawPagesToPDF(WebCore::FrameIdentifier frameID, struct WebKit::PrintInfo printInfo, uint32_t first, uint32_t count) -> (IPC::SharedBufferCopy data)
 #if PLATFORM(IOS_FAMILY)
-#if !HAVE(UIKIT_BACKGROUND_THREAD_PRINTING)
     ComputePagesForPrintingiOS(WebCore::FrameIdentifier frameID, struct WebKit::PrintInfo printInfo) -> (size_t pageCount) Synchronous
-#endif
     DrawToPDFiOS(WebCore::FrameIdentifier frameID, struct WebKit::PrintInfo printInfo, size_t pageCount) -> (IPC::SharedBufferCopy data)
 #endif
     DrawToPDF(WebCore::FrameIdentifier frameID, std::optional<WebCore::FloatRect> rect) -> (IPC::SharedBufferCopy data)

Modified: trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm (291303 => 291304)


--- trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm	2022-03-15 17:36:18 UTC (rev 291303)
+++ trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm	2022-03-15 17:39:30 UTC (rev 291304)
@@ -4282,8 +4282,6 @@
 }
 #endif
 
-#if !HAVE(UIKIT_BACKGROUND_THREAD_PRINTING)
-
 void WebPage::computePagesForPrintingiOS(WebCore::FrameIdentifier frameID, const PrintInfo& printInfo, Messages::WebPage::ComputePagesForPrintingiOS::DelayedReply&& reply)
 {
     ASSERT_WITH_MESSAGE(!printInfo.snapshotFirstPage, "If we are just snapshotting the first page, we don't need a synchronous message to determine the page count, which is 1.");
@@ -4297,8 +4295,6 @@
     reply(pageRects.size());
 }
 
-#endif // !HAVE(UIKIT_BACKGROUND_THREAD_PRINTING)
-
 void WebPage::drawToPDFiOS(WebCore::FrameIdentifier frameID, const PrintInfo& printInfo, size_t pageCount, Messages::WebPage::DrawToPDFiOSAsyncReply&& reply)
 {
     if (printInfo.snapshotFirstPage) {

Modified: trunk/Tools/ChangeLog (291303 => 291304)


--- trunk/Tools/ChangeLog	2022-03-15 17:36:18 UTC (rev 291303)
+++ trunk/Tools/ChangeLog	2022-03-15 17:39:30 UTC (rev 291304)
@@ -1,3 +1,18 @@
+2022-03-15  Aditya Keerthi  <[email protected]>
+
+        [iOS] Indefinite hang when printing using a UIPrintPageRenderer
+        https://bugs.webkit.org/show_bug.cgi?id=237835
+        rdar://90002387
+
+        Reviewed by Devin Rousso.
+
+        Add API test coverage for printing web content to a PDF, using a
+        UIPrintPageRenderer (which uses the main thread) and a
+        UIPrintInteractionController (which uses a background thread).
+
+        * TestWebKitAPI/Tests/WebKitCocoa/WKWebViewPrintFormatter.mm:
+        (TEST):
+
 2022-03-15  Alex Christensen  <[email protected]>
 
         Stop using DYLD_INTERPOSE

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKWebViewPrintFormatter.mm (291303 => 291304)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKWebViewPrintFormatter.mm	2022-03-15 17:36:18 UTC (rev 291303)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKWebViewPrintFormatter.mm	2022-03-15 17:39:30 UTC (rev 291304)
@@ -45,6 +45,12 @@
 @property (nonatomic) CGRect printableRect;
 @end
 
+@interface UIPrintInteractionController ()
+- (BOOL)_setupPrintPanel:(void (^)(UIPrintInteractionController *printInteractionController, BOOL completed, NSError *error))completion;
+- (void)_generatePrintPreview:(void (^)(NSURL *previewPDF, BOOL shouldRenderOnChosenPaper))completionHandler;
+- (void)_cleanPrintState;
+@end
+
 TEST(WKWebView, PrintFormatterCanRecalcPageCountWhilePrinting)
 {
     RetainPtr<TestWKWebView> webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
@@ -96,4 +102,63 @@
     }];
 }
 
+TEST(WKWebView, PrintToPDFUsingPrintPageRenderer)
+{
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
+
+    [webView synchronouslyLoadTestPageNamed:@"simple"];
+    [webView waitForNextPresentationUpdate];
+
+    CGRect pageRect = CGRectMake(0, 0, 100, 100);
+    auto printPageRenderer = adoptNS([[UIPrintPageRenderer alloc] init]);
+    [printPageRenderer addPrintFormatter:[webView viewPrintFormatter] startingAtPageAtIndex:0];
+    [printPageRenderer setPaperRect:pageRect];
+    [printPageRenderer setPrintableRect:pageRect];
+
+    NSMutableData *pdfData = [NSMutableData data];
+    UIGraphicsBeginPDFContextToData(pdfData, pageRect, nil);
+
+    NSInteger numberOfPages = [printPageRenderer numberOfPages];
+    for (NSInteger i = 0; i < numberOfPages; i++) {
+        UIGraphicsBeginPDFPage();
+        CGRect bounds = UIGraphicsGetPDFContextBounds();
+        [printPageRenderer drawPageAtIndex:i inRect:bounds];
+    }
+
+    UIGraphicsEndPDFContext();
+
+    EXPECT_NE([pdfData length], 0UL);
+}
+
+TEST(WKWebView, PrintToPDFUsingPrintInteractionController)
+{
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
+
+    [webView synchronouslyLoadTestPageNamed:@"simple"];
+    [webView waitForNextPresentationUpdate];
+
+    auto printPageRenderer = adoptNS([[UIPrintPageRenderer alloc] init]);
+    [printPageRenderer addPrintFormatter:[webView viewPrintFormatter] startingAtPageAtIndex:0];
+
+    auto printInteractionController = adoptNS([[UIPrintInteractionController alloc] init]);
+    [printInteractionController setPrintPageRenderer:printPageRenderer.get()];
+
+    __block NSUInteger pdfDataLength = 0;
+    __block bool done = false;
+
+    [printInteractionController _setupPrintPanel:nil];
+    [printInteractionController _generatePrintPreview:^(NSURL *pdfURL, BOOL shouldRenderOnChosenPaper) {
+        dispatch_async(dispatch_get_main_queue(), ^{
+            auto pdfData = adoptNS([[NSData alloc] initWithContentsOfURL:pdfURL]);
+            pdfDataLength = [pdfData length];
+
+            [printInteractionController _cleanPrintState];
+            done = true;
+        });
+    }];
+
+    TestWebKitAPI::Util::run(&done);
+    EXPECT_NE(pdfDataLength, 0UL);
+}
+
 #endif
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to