Changeset 249739 in webkit


Ignore:
Timestamp:
Sep 10, 2019 4:12:49 PM (5 years ago)
Author:
beidson@apple.com
Message:

Add SPI to save a PDF from the contents of a WKWebView.
<rdar://problem/48955900> and https://bugs.webkit.org/show_bug.cgi?id=195765

Reviewed by Tim Horton.

Source/WebCore:

Covered by API tests.

  • page/FrameView.cpp:

(WebCore::FrameView::paintContents): Don't paint the debug color outside of the FrameRect.

  • platform/graphics/cg/GraphicsContextCG.cpp:

(WebCore::GraphicsContext::setURLForRect):

  • rendering/PaintPhase.h: Add "AnnotateLinks" option to always gather and annotation links.
  • rendering/RenderElement.cpp:

(WebCore::RenderElement::hasOutlineAnnotation const): Also return true when the PaintOptions include "AnnotateLinks"

Source/WebKit:

This is refactoring a combination of "snapshotFirstPage" PDF printing code and the
"takeSnapshot" API code to capture the on-screen visible page to a PDF at full fidelity.

  • UIProcess/API/Cocoa/WKWebView.mm:

(-[WKWebView _takePDFSnapshotWithConfiguration:completionHandler:]):

  • UIProcess/API/Cocoa/WKWebViewPrivate.h:
  • UIProcess/WebPageProxy.cpp:

(WebKit::WebPageProxy::drawToPDF):
(WebKit::WebPageProxy::drawToPDFCallback):

  • UIProcess/WebPageProxy.h:
  • UIProcess/WebPageProxy.messages.in:
  • UIProcess/ios/WKContentView.mm:

(-[WKContentView _wk_pageCountForPrintFormatter:]):

  • UIProcess/ios/WebPageProxyIOS.mm:

(WebKit::WebPageProxy::drawToPDFCallback): Move to cross platform WebPageProxy.

  • WebProcess/WebPage/Cocoa/WebPageCocoa.mm:

(WebKit::WebPage::pdfSnapshotAtSize):

  • WebProcess/WebPage/WebPage.cpp:

(WebKit::WebPage::pdfSnapshotAtSize): Instead of assuming 1 page capped at 200 inches,

paginate every 200 inches.

(WebKit::WebPage::drawToPDF):
(WebKit::paintSnapshotAtSize): Deleted.
(WebKit::WebPage::pdfSnapshotAtSize): Deleted.

  • WebProcess/WebPage/WebPage.h:
  • WebProcess/WebPage/WebPage.messages.in:

Tools:

-Add an "Export to PDF..." menu option to MiniBrowser.
-Add API tests for the API itself.

  • MiniBrowser/MiniBrowser.entitlements:
  • MiniBrowser/mac/BrowserWindowController.h:
  • MiniBrowser/mac/BrowserWindowController.m:

(-[BrowserWindowController forceRepaint:]):
(-[BrowserWindowController saveAsPDF:]):

  • MiniBrowser/mac/MainMenu.xib:
  • MiniBrowser/mac/WK1BrowserWindowController.m:

(-[WK1BrowserWindowController validateMenuItem:]):

  • MiniBrowser/mac/WK2BrowserWindowController.m:

(-[WK2BrowserWindowController validateMenuItem:]):
(-[WK2BrowserWindowController saveAsPDF:]):

  • TestWebKitAPI/Configurations/Base.xcconfig:
  • TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
  • TestWebKitAPI/Tests/WebKitCocoa/PDFSnapshot.mm: Added.

(TestWebKitAPI::TEST):

  • TestWebKitAPI/cocoa/TestPDFDocument.h: Added.
  • TestWebKitAPI/cocoa/TestPDFDocument.mm: Added.

(TestWebKitAPI::toCGRect):
(TestWebKitAPI::toPlatformPoint):
(TestWebKitAPI::TestPDFAnnotation::TestPDFAnnotation):
(TestWebKitAPI::TestPDFAnnotation::isLink const):
(TestWebKitAPI::TestPDFAnnotation::bounds const):
(TestWebKitAPI::TestPDFAnnotation::linkURL const):
(TestWebKitAPI::TestPDFPage::create):
(TestWebKitAPI::TestPDFPage::TestPDFPage):
(TestWebKitAPI::TestPDFPage::annotations):
(TestWebKitAPI::TestPDFPage::characterCount const):
(TestWebKitAPI::TestPDFPage::text const):
(TestWebKitAPI::TestPDFPage::rectForCharacterAtIndex const):
(TestWebKitAPI::TestPDFPage::characterIndexAtPoint const):
(TestWebKitAPI::TestPDFPage::bounds const):
(TestWebKitAPI::TestPDFPage::colorAtPoint const):
(TestWebKitAPI::TestPDFDocument::createFromData):
(TestWebKitAPI::TestPDFDocument::TestPDFDocument):
(TestWebKitAPI::TestPDFDocument::pageCount const):
(TestWebKitAPI::TestPDFDocument::page):

Location:
trunk
Files:
3 added
26 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r249737 r249739  
     12019-09-10  Brady Eidson  <beidson@apple.com>
     2
     3        Add SPI to save a PDF from the contents of a WKWebView.
     4        <rdar://problem/48955900> and https://bugs.webkit.org/show_bug.cgi?id=195765
     5
     6        Reviewed by Tim Horton.
     7
     8        Covered by API tests.
     9
     10        * page/FrameView.cpp:
     11        (WebCore::FrameView::paintContents): Don't paint the debug color outside of the FrameRect.
     12
     13        * platform/graphics/cg/GraphicsContextCG.cpp:
     14        (WebCore::GraphicsContext::setURLForRect):
     15
     16        * rendering/PaintPhase.h: Add "AnnotateLinks" option to always gather and annotation links.
     17
     18        * rendering/RenderElement.cpp:
     19        (WebCore::RenderElement::hasOutlineAnnotation const): Also return true when the PaintOptions include "AnnotateLinks"
     20
    1212019-09-10  Jiewen Tan  <jiewen_tan@apple.com>
    222
  • trunk/Source/WebCore/page/FrameView.cpp

    r249605 r249739  
    41144114    else
    41154115        fillWithWarningColor = true;
    4116    
    4117     if (fillWithWarningColor)
    4118         context.fillRect(dirtyRect, Color(255, 64, 255));
     4116
     4117    if (fillWithWarningColor) {
     4118        IntRect debugRect = frameRect();
     4119        debugRect.intersect(dirtyRect);
     4120        context.fillRect(debugRect, Color(255, 64, 255));
     4121    }
    41194122#endif
    41204123
  • trunk/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp

    r249217 r249739  
    16361636void GraphicsContext::setURLForRect(const URL& link, const FloatRect& destRect)
    16371637{
     1638    // FIXME: <rdar://problem/54900133> PDF exporting on iOS should include URL rects
    16381639#if !PLATFORM(IOS_FAMILY)
    16391640    if (paintingDisabled())
  • trunk/Source/WebCore/rendering/PaintPhase.h

    r242794 r249739  
    6868    Snapshotting                = 1 << 10,
    6969    TileFirstPaint              = 1 << 11,
     70    AnnotateLinks               = 1 << 12, // Collect all renderers with links to annotate their URLs (e.g. PDFs)
    7071};
    7172
  • trunk/Source/WebCore/rendering/RenderElement.cpp

    r249364 r249739  
    20342034bool RenderElement::hasOutlineAnnotation() const
    20352035{
    2036     return element() && element()->isLink() && document().printing();
     2036    return element() && element()->isLink() && (document().printing() || (view().frameView().paintBehavior() & PaintBehavior::AnnotateLinks));
    20372037}
    20382038
  • trunk/Source/WebKit/ChangeLog

    r249723 r249739  
     12019-09-10  Brady Eidson  <beidson@apple.com>
     2
     3        Add SPI to save a PDF from the contents of a WKWebView.
     4        <rdar://problem/48955900> and https://bugs.webkit.org/show_bug.cgi?id=195765
     5
     6        Reviewed by Tim Horton.
     7
     8        This is refactoring a combination of "snapshotFirstPage" PDF printing code and the
     9        "takeSnapshot" API code to capture the on-screen visible page to a PDF at full fidelity.
     10
     11        * UIProcess/API/Cocoa/WKWebView.mm:
     12        (-[WKWebView _takePDFSnapshotWithConfiguration:completionHandler:]):
     13        * UIProcess/API/Cocoa/WKWebViewPrivate.h:
     14
     15        * UIProcess/WebPageProxy.cpp:
     16        (WebKit::WebPageProxy::drawToPDF):
     17        (WebKit::WebPageProxy::drawToPDFCallback):
     18        * UIProcess/WebPageProxy.h:
     19        * UIProcess/WebPageProxy.messages.in:
     20
     21        * UIProcess/ios/WKContentView.mm:
     22        (-[WKContentView _wk_pageCountForPrintFormatter:]):
     23
     24        * UIProcess/ios/WebPageProxyIOS.mm:
     25        (WebKit::WebPageProxy::drawToPDFCallback): Move to cross platform WebPageProxy.
     26
     27        * WebProcess/WebPage/Cocoa/WebPageCocoa.mm:
     28        (WebKit::WebPage::pdfSnapshotAtSize):
     29
     30        * WebProcess/WebPage/WebPage.cpp:
     31        (WebKit::WebPage::pdfSnapshotAtSize): Instead of assuming 1 page capped at 200 inches,
     32          paginate every 200 inches.
     33        (WebKit::WebPage::drawToPDF):
     34        (WebKit::paintSnapshotAtSize): Deleted.
     35        (WebKit::WebPage::pdfSnapshotAtSize): Deleted.
     36        * WebProcess/WebPage/WebPage.h:
     37        * WebProcess/WebPage/WebPage.messages.in:
     38
    1392019-09-10  Chris Dumez  <cdumez@apple.com>
    240
  • trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm

    r249492 r249739  
    50385038}
    50395039
     5040- (void)_takePDFSnapshotWithConfiguration:(WKSnapshotConfiguration *)snapshotConfiguration completionHandler:(void (^)(NSData *, NSError *))completionHandler
     5041{
     5042    WebCore::FrameIdentifier frameID;
     5043    if (auto mainFrame = _page->mainFrame())
     5044        frameID = mainFrame->frameID();
     5045    else {
     5046        completionHandler(nil, createNSError(WKErrorUnknown).get());
     5047        return;
     5048    }
     5049
     5050    Optional<WebCore::FloatRect> floatRect;
     5051    if (snapshotConfiguration && !CGRectIsNull(snapshotConfiguration.rect))
     5052        floatRect = WebCore::FloatRect(snapshotConfiguration.rect);
     5053
     5054    auto handler = makeBlockPtr(completionHandler);
     5055    _page->drawToPDF(frameID, floatRect, [retainedSelf = retainPtr(self), handler = WTFMove(handler)](const IPC::DataReference& pdfData, WebKit::CallbackBase::Error error) {
     5056        if (error != WebKit::CallbackBase::Error::None) {
     5057            handler(nil, createNSError(WKErrorUnknown).get());
     5058            return;
     5059        }
     5060
     5061        auto data = adoptCF(CFDataCreate(kCFAllocatorDefault, pdfData.data(), pdfData.size()));
     5062        handler((NSData *)data.get(), nil);
     5063    });
     5064}
     5065
    50405066#if PLATFORM(MAC)
    50415067- (void)_setShouldSuppressFirstResponderChanges:(BOOL)shouldSuppress
  • trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h

    r249112 r249739  
    433433- (void)_focusTextInputContext:(_WKTextInputContext *)textInputElement completionHandler:(void(^)(BOOL))completionHandler WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
    434434
     435- (void)_takePDFSnapshotWithConfiguration:(WKSnapshotConfiguration *)snapshotConfiguration completionHandler:(void (^)(NSData *pdfSnapshotData, NSError *error))completionHandler WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
    435436@end
    436437
  • trunk/Source/WebKit/UIProcess/WebPageProxy.cpp

    r249649 r249739  
    77847784#endif
    77857785
     7786#if PLATFORM(COCOA)
     7787void WebPageProxy::drawToPDF(FrameIdentifier frameID, const Optional<FloatRect>& rect, DrawToPDFCallback::CallbackFunction&& callback)
     7788{
     7789    if (!hasRunningProcess()) {
     7790        callback(IPC::DataReference(), CallbackBase::Error::OwnerWasInvalidated);
     7791        return;
     7792    }
     7793
     7794    auto callbackID = m_callbacks.put(WTFMove(callback), m_process->throttler().backgroundActivityToken());
     7795    m_process->send(Messages::WebPage::DrawToPDF(frameID, rect, callbackID), m_webPageID);
     7796}
     7797
     7798void WebPageProxy::drawToPDFCallback(const IPC::DataReference& pdfData, CallbackID callbackID)
     7799{
     7800    auto callback = m_callbacks.take<DrawToPDFCallback>(callbackID);
     7801    RELEASE_ASSERT(callback);
     7802    callback->performCallbackWithReturnValue(pdfData);
     7803}
     7804#endif // PLATFORM(COCOA)
     7805
    77867806void WebPageProxy::updateBackingStoreDiscardableState()
    77877807{
  • trunk/Source/WebKit/UIProcess/WebPageProxy.h

    r249335 r249739  
    361361    RefPtr<API::Object> userData;
    362362};
    363 
     363#endif
     364
     365#if PLATFORM(COCOA)
    364366using DrawToPDFCallback = GenericCallback<const IPC::DataReference&>;
    365 #endif
    366 
    367 #if PLATFORM(COCOA)
    368367typedef GenericCallback<const WTF::MachSendRight&> MachSendRightCallback;
    369368typedef GenericCallback<bool, bool, String, double, double, uint64_t> NowPlayingInfoCallback;
     
    11731172    void drawRectToImage(WebFrameProxy*, const PrintInfo&, const WebCore::IntRect&, const WebCore::IntSize&, Ref<ImageCallback>&&);
    11741173    void drawPagesToPDF(WebFrameProxy*, const PrintInfo&, uint32_t first, uint32_t count, Ref<DataCallback>&&);
     1174    void drawToPDF(WebCore::FrameIdentifier, const Optional<WebCore::FloatRect>&, DrawToPDFCallback::CallbackFunction&&);
     1175    void drawToPDFCallback(const IPC::DataReference& pdfData, WebKit::CallbackID);
    11751176#if PLATFORM(IOS_FAMILY)
    11761177    uint32_t computePagesForPrintingAndDrawToPDF(WebCore::FrameIdentifier, const PrintInfo&, DrawToPDFCallback::CallbackFunction&&);
    1177     void drawToPDFCallback(const IPC::DataReference& pdfData, WebKit::CallbackID);
    11781178#endif
    11791179#elif PLATFORM(GTK)
  • trunk/Source/WebKit/UIProcess/WebPageProxy.messages.in

    r249329 r249739  
    197197    DisableDoubleTapGesturesDuringTapIfNecessary(uint64_t requestID)
    198198    HandleSmartMagnificationInformationForPotentialTap(uint64_t requestID, WebCore::FloatRect renderRect, bool fitEntireRect, double viewportMinimumScale, double viewportMaximumScale)
    199     DrawToPDFCallback(IPC::DataReference pdfData, WebKit::CallbackID callbackID)
    200199    SelectionRectsCallback(Vector<WebCore::SelectionRect> selectionRects, WebKit::CallbackID callbackID);
    201200#endif
     
    207206#endif
    208207#if PLATFORM(COCOA)
     208    DrawToPDFCallback(IPC::DataReference pdfData, WebKit::CallbackID callbackID)
    209209    MachSendRightCallback(MachSendRight sendRight, WebKit::CallbackID callbackID)
    210210    NowPlayingInfoCallback(bool active, bool registeredAsNowPlayingApplication, String title, double duration, double elapsedTime, uint64_t uniqueIdentifier, WebKit::CallbackID callbackID)
  • trunk/Source/WebKit/UIProcess/ios/WKContentView.mm

    r249624 r249739  
    721721    printInfo.pageSetupScaleFactor = 1;
    722722    printInfo.snapshotFirstPage = printFormatter.snapshotFirstPage;
     723
     724    // FIXME: Paginate when exporting PDFs taller than 200"
    723725    if (printInfo.snapshotFirstPage) {
    724726        static const CGFloat maximumPDFHeight = 200 * 72; // maximum PDF height for a single page is 200 inches
  • trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm

    r249275 r249739  
    10871087}
    10881088
    1089 void WebPageProxy::drawToPDFCallback(const IPC::DataReference& pdfData, CallbackID callbackID)
    1090 {
    1091     auto callback = m_callbacks.take<DrawToPDFCallback>(callbackID);
    1092     RELEASE_ASSERT(callback);
    1093     callback->performCallbackWithReturnValue(pdfData);
    1094 }
    1095 
    10961089void WebPageProxy::contentSizeCategoryDidChange(const String& contentSizeCategory)
    10971090{
  • trunk/Source/WebKit/WebProcess/WebPage/Cocoa/WebPageCocoa.mm

    r249155 r249739  
    233233    [m_mockAccessibilityElement setHasMainFramePlugin:document ? document->isPluginDocument() : false];
    234234}
    235    
     235
     236RetainPtr<CFDataRef> WebPage::pdfSnapshotAtSize(IntRect rect, IntSize bitmapSize, SnapshotOptions options)
     237{
     238    Frame* coreFrame = m_mainFrame->coreFrame();
     239    if (!coreFrame)
     240        return nullptr;
     241
     242    FrameView* frameView = coreFrame->view();
     243    if (!frameView)
     244        return nullptr;
     245
     246    auto data = adoptCF(CFDataCreateMutable(kCFAllocatorDefault, 0));
     247
     248    auto dataConsumer = adoptCF(CGDataConsumerCreateWithCFData(data.get()));
     249    auto mediaBox = CGRectMake(0, 0, bitmapSize.width(), bitmapSize.height());
     250    auto pdfContext = adoptCF(CGPDFContextCreate(dataConsumer.get(), &mediaBox, nullptr));
     251
     252    int64_t remainingHeight = bitmapSize.height();
     253    int64_t nextRectY = rect.y();
     254    while (remainingHeight > 0) {
     255        // PDFs have a per-page height limit of 200 inches at 72dpi.
     256        // We'll export one PDF page at a time, up to that maximum height.
     257        static const int64_t maxPageHeight = 72 * 200;
     258        bitmapSize.setHeight(std::min(remainingHeight, maxPageHeight));
     259        rect.setHeight(bitmapSize.height());
     260        rect.setY(nextRectY);
     261
     262        CGRect mediaBox = CGRectMake(0, 0, bitmapSize.width(), bitmapSize.height());
     263        auto mediaBoxData = adoptCF(CFDataCreate(NULL, (const UInt8 *)&mediaBox, sizeof(CGRect)));
     264        auto dictionary = (CFDictionaryRef)@{
     265            (NSString *)kCGPDFContextMediaBox : (NSData *)mediaBoxData.get()
     266        };
     267
     268        CGPDFContextBeginPage(pdfContext.get(), dictionary);
     269
     270        GraphicsContext graphicsContext { pdfContext.get() };
     271        graphicsContext.scale({ 1, -1 });
     272        graphicsContext.translate(0, -bitmapSize.height());
     273
     274        paintSnapshotAtSize(rect, bitmapSize, options, *coreFrame, *frameView, graphicsContext);
     275
     276        CGPDFContextEndPage(pdfContext.get());
     277
     278        nextRectY += bitmapSize.height();
     279        remainingHeight -= maxPageHeight;
     280    }
     281
     282    CGPDFContextClose(pdfContext.get());
     283
     284    return data;
     285}
     286
    236287} // namespace WebKit
    237288
  • trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp

    r249649 r249739  
    23132313}
    23142314
    2315 static void paintSnapshotAtSize(const IntRect& rect, const IntSize& bitmapSize, SnapshotOptions options, Frame& frame, FrameView& frameView, GraphicsContext& graphicsContext)
     2315void WebPage::paintSnapshotAtSize(const IntRect& rect, const IntSize& bitmapSize, SnapshotOptions options, Frame& frame, FrameView& frameView, GraphicsContext& graphicsContext)
    23162316{
    23172317    IntRect snapshotRect = rect;
     
    23862386    return snapshot;
    23872387}
    2388 
    2389 #if USE(CF)
    2390 RetainPtr<CFDataRef> WebPage::pdfSnapshotAtSize(const IntRect& rect, const IntSize& bitmapSize, SnapshotOptions options)
    2391 {
    2392     Frame* coreFrame = m_mainFrame->coreFrame();
    2393     if (!coreFrame)
    2394         return nullptr;
    2395 
    2396     FrameView* frameView = coreFrame->view();
    2397     if (!frameView)
    2398         return nullptr;
    2399 
    2400     auto data = adoptCF(CFDataCreateMutable(kCFAllocatorDefault, 0));
    2401 
    2402 #if USE(CG)
    2403     auto dataConsumer = adoptCF(CGDataConsumerCreateWithCFData(data.get()));
    2404     auto mediaBox = CGRectMake(0, 0, bitmapSize.width(), bitmapSize.height());
    2405     auto pdfContext = adoptCF(CGPDFContextCreate(dataConsumer.get(), &mediaBox, nullptr));
    2406 
    2407     CGPDFContextBeginPage(pdfContext.get(), nullptr);
    2408 
    2409     GraphicsContext graphicsContext { pdfContext.get() };
    2410     graphicsContext.scale({ 1, -1 });
    2411     graphicsContext.translate(0, -bitmapSize.height());
    2412     paintSnapshotAtSize(rect, bitmapSize, options, *coreFrame, *frameView, graphicsContext);
    2413 
    2414     CGPDFContextEndPage(pdfContext.get());
    2415     CGPDFContextClose(pdfContext.get());
    2416 #endif
    2417 
    2418     return data;
    2419 }
    2420 #endif
    24212388
    24222389RefPtr<WebImage> WebPage::snapshotNode(WebCore::Node& node, SnapshotOptions options, unsigned maximumPixelCount)
     
    47564723
    47574724#if PLATFORM(COCOA)
     4725void WebPage::drawToPDF(FrameIdentifier frameID, const Optional<FloatRect>& rect, CallbackID callbackID)
     4726{
     4727    auto& frameView = *m_page->mainFrame().view();
     4728    IntSize snapshotSize;
     4729    if (rect)
     4730        snapshotSize = IntSize(rect->size());
     4731    else
     4732        snapshotSize = { frameView.contentsSize() };
     4733
     4734    IntRect snapshotRect;
     4735    if (rect)
     4736        snapshotRect = { {(int)rect->x(), (int)rect->y()}, snapshotSize };
     4737    else
     4738        snapshotRect = { {0, 0}, snapshotSize };
     4739
     4740    auto originalLayoutViewportOverrideRect = frameView.layoutViewportOverrideRect();
     4741    frameView.setLayoutViewportOverrideRect(LayoutRect(snapshotRect));
     4742    auto originalPaintBehavior = frameView.paintBehavior();
     4743    frameView.setPaintBehavior(originalPaintBehavior | PaintBehavior::AnnotateLinks);
     4744
     4745    auto pdfData = pdfSnapshotAtSize(snapshotRect, snapshotSize, 0);
     4746
     4747    frameView.setLayoutViewportOverrideRect(originalLayoutViewportOverrideRect);
     4748    frameView.setPaintBehavior(originalPaintBehavior);
     4749
     4750    send(Messages::WebPageProxy::DrawToPDFCallback(IPC::DataReference(CFDataGetBytePtr(pdfData.get()), CFDataGetLength(pdfData.get())), callbackID));
     4751}
     4752
    47584753void WebPage::drawRectToImage(FrameIdentifier frameID, const PrintInfo& printInfo, const IntRect& rect, const WebCore::IntSize& imageSize, CallbackID callbackID)
    47594754{
  • trunk/Source/WebKit/WebProcess/WebPage/WebPage.h

    r249669 r249739  
    882882#endif
    883883
     884    void drawToPDF(WebCore::FrameIdentifier, const Optional<WebCore::FloatRect>&, CallbackID);
     885
    884886#if PLATFORM(GTK)
    885887    void drawPagesForPrinting(WebCore::FrameIdentifier, const PrintInfo&, CallbackID);
     
    16071609    RefPtr<WebImage> snapshotAtSize(const WebCore::IntRect&, const WebCore::IntSize& bitmapSize, SnapshotOptions);
    16081610    RefPtr<WebImage> snapshotNode(WebCore::Node&, SnapshotOptions, unsigned maximumPixelCount = std::numeric_limits<unsigned>::max());
    1609 #if USE(CF)
    1610     RetainPtr<CFDataRef> pdfSnapshotAtSize(const WebCore::IntRect&, const WebCore::IntSize& bitmapSize, SnapshotOptions);
     1611#if PLATFORM(COCOA)
     1612    RetainPtr<CFDataRef> pdfSnapshotAtSize(WebCore::IntRect, WebCore::IntSize bitmapSize, SnapshotOptions);
    16111613#endif
    16121614
     
    16221624
    16231625    void updateMockAccessibilityElementAfterCommittingLoad();
     1626
     1627    void paintSnapshotAtSize(const WebCore::IntRect&, const WebCore::IntSize&, SnapshotOptions, WebCore::Frame&, WebCore::FrameView&, WebCore::GraphicsContext&);
    16241628
    16251629    WebCore::PageIdentifier m_identifier;
  • trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in

    r249649 r249739  
    390390    ComputePagesForPrintingAndDrawToPDF(WebCore::FrameIdentifier frameID, struct WebKit::PrintInfo printInfo, WebKit::CallbackID callbackID) -> (uint32_t pageCount) Synchronous
    391391#endif
     392    DrawToPDF(WebCore::FrameIdentifier frameID, Optional<WebCore::FloatRect> rect, WebKit::CallbackID callbackID)
    392393#endif
    393394#if PLATFORM(GTK)
  • trunk/Tools/ChangeLog

    r249738 r249739  
     12019-09-10  Brady Eidson  <beidson@apple.com>
     2
     3        Add SPI to save a PDF from the contents of a WKWebView.
     4        <rdar://problem/48955900> and https://bugs.webkit.org/show_bug.cgi?id=195765
     5
     6        Reviewed by Tim Horton.
     7
     8        -Add an "Export to PDF..." menu option to MiniBrowser.
     9        -Add API tests for the API itself.
     10
     11        * MiniBrowser/MiniBrowser.entitlements:
     12
     13        * MiniBrowser/mac/BrowserWindowController.h:
     14        * MiniBrowser/mac/BrowserWindowController.m:
     15        (-[BrowserWindowController forceRepaint:]):
     16        (-[BrowserWindowController saveAsPDF:]):
     17
     18        * MiniBrowser/mac/MainMenu.xib:
     19
     20        * MiniBrowser/mac/WK1BrowserWindowController.m:
     21        (-[WK1BrowserWindowController validateMenuItem:]):
     22        * MiniBrowser/mac/WK2BrowserWindowController.m:
     23        (-[WK2BrowserWindowController validateMenuItem:]):
     24        (-[WK2BrowserWindowController saveAsPDF:]):
     25
     26        * TestWebKitAPI/Configurations/Base.xcconfig:
     27        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
     28        * TestWebKitAPI/Tests/WebKitCocoa/PDFSnapshot.mm: Added.
     29        (TestWebKitAPI::TEST):
     30        * TestWebKitAPI/cocoa/TestPDFDocument.h: Added.
     31        * TestWebKitAPI/cocoa/TestPDFDocument.mm: Added.
     32        (TestWebKitAPI::toCGRect):
     33        (TestWebKitAPI::toPlatformPoint):
     34        (TestWebKitAPI::TestPDFAnnotation::TestPDFAnnotation):
     35        (TestWebKitAPI::TestPDFAnnotation::isLink const):
     36        (TestWebKitAPI::TestPDFAnnotation::bounds const):
     37        (TestWebKitAPI::TestPDFAnnotation::linkURL const):
     38        (TestWebKitAPI::TestPDFPage::create):
     39        (TestWebKitAPI::TestPDFPage::TestPDFPage):
     40        (TestWebKitAPI::TestPDFPage::annotations):
     41        (TestWebKitAPI::TestPDFPage::characterCount const):
     42        (TestWebKitAPI::TestPDFPage::text const):
     43        (TestWebKitAPI::TestPDFPage::rectForCharacterAtIndex const):
     44        (TestWebKitAPI::TestPDFPage::characterIndexAtPoint const):
     45        (TestWebKitAPI::TestPDFPage::bounds const):
     46        (TestWebKitAPI::TestPDFPage::colorAtPoint const):
     47        (TestWebKitAPI::TestPDFDocument::createFromData):
     48        (TestWebKitAPI::TestPDFDocument::TestPDFDocument):
     49        (TestWebKitAPI::TestPDFDocument::pageCount const):
     50        (TestWebKitAPI::TestPDFDocument::page):
     51
    1522019-09-10  Keith Rollin  <krollin@apple.com>
    253
  • trunk/Tools/MiniBrowser/MiniBrowser.entitlements

    r241238 r249739  
    33<plist version="1.0">
    44<dict>
     5        <key>com.apple.security.app-sandbox</key>
     6        <true/>
    57        <key>com.apple.security.device.usb</key>
    68        <true/>
    7         <key>com.apple.security.files.user-selected.read-only</key>
     9        <key>com.apple.security.files.user-selected.read-write</key>
    810        <true/>
     11        <key>com.apple.security.network.client</key>
     12        <true/>
     13        <key>com.apple.security.temporary-exception.files.absolute-path.read-only</key>
     14        <string>/</string>
    915        <key>com.apple.security.temporary-exception.mach-lookup.global-name</key>
    1016        <array>
     
    1218                <string>com.apple.WebKit.NetworkingDaemon</string>
    1319        </array>
    14         <key>com.apple.security.app-sandbox</key>
    15         <true/>
    16         <key>com.apple.security.network.client</key>
    17         <true/>
    18         <key>com.apple.security.temporary-exception.files.absolute-path.read-only</key>
    19         <string>/</string>
    2020</dict>
    2121</plist>
  • trunk/Tools/MiniBrowser/mac/BrowserWindowController.h

    r224268 r249739  
    4747- (IBAction)openLocation:(id)sender;
    4848
     49- (IBAction)saveAsPDF:(id)sender;
     50
    4951- (IBAction)fetch:(id)sender;
    5052- (IBAction)share:(id)sender;
  • trunk/Tools/MiniBrowser/mac/BrowserWindowController.m

    r239856 r249739  
    9494}
    9595
     96- (IBAction)saveAsPDF:(id)sender
     97{
     98    [self doesNotRecognizeSelector:_cmd];
     99}
     100
    96101- (IBAction)goBack:(id)sender
    97102{
  • trunk/Tools/MiniBrowser/mac/MainMenu.xib

    r235955 r249739  
    11<?xml version="1.0" encoding="UTF-8"?>
    2 <document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="13771" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
     2<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
    33    <dependencies>
    4         <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="13771"/>
     4        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14490.70"/>
    55    </dependencies>
    66    <objects>
     
    132132                                <connections>
    133133                                    <action selector="saveDocumentAs:" target="-1" id="363"/>
     134                                </connections>
     135                            </menuItem>
     136                            <menuItem title="Save As PDF…" keyEquivalent="S" id="gmS-3Q-oLs">
     137                                <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
     138                                <connections>
     139                                    <action selector="saveAsPDF:" target="-1" id="25T-Id-334"/>
    134140                                </connections>
    135141                            </menuItem>
  • trunk/Tools/MiniBrowser/mac/WK1BrowserWindowController.m

    r249327 r249739  
    135135    SEL action = [menuItem action];
    136136
     137    if (action == @selector(saveAsPDF:))
     138        return NO;
     139
    137140    if (action == @selector(zoomIn:))
    138141        return [self canZoomIn];
  • trunk/Tools/MiniBrowser/mac/WK2BrowserWindowController.m

    r249327 r249739  
    207207{
    208208    SEL action = menuItem.action;
     209
     210    if (action == @selector(saveAsPDF:))
     211        return YES;
    209212
    210213    if (action == @selector(zoomIn:))
     
    815818}
    816819
     820- (IBAction)saveAsPDF:(id)sender
     821{
     822    NSSavePanel *panel = [NSSavePanel savePanel];
     823    panel.allowedFileTypes = @[ @"pdf" ];
     824    [panel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result) {
     825        if (result == NSModalResponseOK) {
     826            [_webView _takePDFSnapshotWithConfiguration:nil completionHandler:^(NSData *pdfSnapshotData, NSError *error) {
     827                [pdfSnapshotData writeToURL:[panel URL] options:0 error:nil];
     828            }];
     829        }
     830    }];
     831}
     832
    817833@end
  • trunk/Tools/TestWebKitAPI/Configurations/Base.xcconfig

    r249312 r249739  
    114114WK_COCOA_TOUCH_appletvos = cocoatouch;
    115115WK_COCOA_TOUCH_appletvsimulator = cocoatouch;
     116
     117SYSTEM_FRAMEWORK_SEARCH_PATHS = $(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks $(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks $(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/Quartz.framework/Frameworks $(inherited);
  • trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj

    r249701 r249739  
    258258                515BE16F1D428BB100DD7C68 /* StoreBlobToBeDeleted.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 515BE16E1D4288FF00DD7C68 /* StoreBlobToBeDeleted.html */; };
    259259                515BE1711D428E4B00DD7C68 /* StoreBlobThenDelete.mm in Sources */ = {isa = PBXBuildFile; fileRef = 515BE1701D428BD100DD7C68 /* StoreBlobThenDelete.mm */; };
     260                516281252325C18000BB7E42 /* TestPDFDocument.mm in Sources */ = {isa = PBXBuildFile; fileRef = 516281242325C17B00BB7E42 /* TestPDFDocument.mm */; };
     261                516281272325C19800BB7E42 /* PDFSnapshot.mm in Sources */ = {isa = PBXBuildFile; fileRef = 516281262325C19100BB7E42 /* PDFSnapshot.mm */; };
     262                516281292325C45400BB7E42 /* PDFKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 516281282325C45400BB7E42 /* PDFKit.framework */; };
    260263                5165FE04201EE620009F7EC3 /* MessagePortProviders.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5165FE03201EE617009F7EC3 /* MessagePortProviders.mm */; };
    261264                51714EB41CF8C78C004723C4 /* WebProcessKillIDBCleanup-1.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 51714EB21CF8C761004723C4 /* WebProcessKillIDBCleanup-1.html */; };
     
    17471750                515BE16E1D4288FF00DD7C68 /* StoreBlobToBeDeleted.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = StoreBlobToBeDeleted.html; sourceTree = "<group>"; };
    17481751                515BE1701D428BD100DD7C68 /* StoreBlobThenDelete.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = StoreBlobThenDelete.mm; sourceTree = "<group>"; };
     1752                516281232325C17A00BB7E42 /* TestPDFDocument.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TestPDFDocument.h; path = cocoa/TestPDFDocument.h; sourceTree = "<group>"; };
     1753                516281242325C17B00BB7E42 /* TestPDFDocument.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = TestPDFDocument.mm; path = cocoa/TestPDFDocument.mm; sourceTree = "<group>"; };
     1754                516281262325C19100BB7E42 /* PDFSnapshot.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PDFSnapshot.mm; sourceTree = "<group>"; };
     1755                516281282325C45400BB7E42 /* PDFKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PDFKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/Frameworks/PDFKit.framework; sourceTree = DEVELOPER_DIR; };
    17491756                5165FE03201EE617009F7EC3 /* MessagePortProviders.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MessagePortProviders.mm; sourceTree = "<group>"; };
    17501757                51714EB21CF8C761004723C4 /* WebProcessKillIDBCleanup-1.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "WebProcessKillIDBCleanup-1.html"; sourceTree = "<group>"; };
     
    25722579                                7C83E03F1D0A61A000FEBCF3 /* libicucore.dylib in Frameworks */,
    25732580                                578CBD67204FB2C80083B9F2 /* LocalAuthentication.framework in Frameworks */,
     2581                                516281292325C45400BB7E42 /* PDFKit.framework in Frameworks */,
    25742582                                7A010BCD1D877C0D00EDE72A /* QuartzCore.framework in Frameworks */,
    25752583                                574F55D2204D47F0002948C6 /* Security.framework in Frameworks */,
     
    26692677                                2D1C04A51D76298B000A6816 /* TestNavigationDelegate.h */,
    26702678                                2D1C04A61D76298B000A6816 /* TestNavigationDelegate.mm */,
     2679                                516281232325C17A00BB7E42 /* TestPDFDocument.h */,
     2680                                516281242325C17B00BB7E42 /* TestPDFDocument.mm */,
    26712681                                A14FC58D1B8AE36500D107EB /* TestProtocol.h */,
    26722682                                A14FC58E1B8AE36500D107EB /* TestProtocol.mm */,
     
    28302840                                9B2346411F943A2400DB1D23 /* PasteWebArchive.mm */,
    28312841                                51D8C18F2267B26700797E40 /* PDFLinkReferrer.mm */,
     2842                                516281262325C19100BB7E42 /* PDFSnapshot.mm */,
    28322843                                3FCC4FE41EC4E8520076E37C /* PictureInPictureDelegate.mm */,
    28332844                                83BAEE8C1EF4625500DDE894 /* PluginLoadClientPolicies.mm */,
     
    31003111                                7C83E0291D0A5CDF00FEBCF3 /* libWTF.a */,
    31013112                                578CBD66204FB2C70083B9F2 /* LocalAuthentication.framework */,
     3113                                516281282325C45400BB7E42 /* PDFKit.framework */,
    31023114                                7A010BCC1D877C0D00EDE72A /* QuartzCore.framework */,
    31033115                                574F55D0204D471C002948C6 /* Security.framework */,
     
    46334645                                9B2346421F943E2700DB1D23 /* PasteWebArchive.mm in Sources */,
    46344646                                51D8C1902267B26D00797E40 /* PDFLinkReferrer.mm in Sources */,
     4647                                516281272325C19800BB7E42 /* PDFSnapshot.mm in Sources */,
    46354648                                7C83E0531D0A643A00FEBCF3 /* PendingAPIRequestURL.cpp in Sources */,
    46364649                                3FCC4FE51EC4E8520076E37C /* PictureInPictureDelegate.mm in Sources */,
     
    47314744                                F45E15762112CE6200307E82 /* TestInputDelegate.mm in Sources */,
    47324745                                F45D3891215A7B4B002A2979 /* TestInspectorBar.mm in Sources */,
     4746                                516281252325C18000BB7E42 /* TestPDFDocument.mm in Sources */,
    47334747                                5774AA6821FBBF7800AF2A1B /* TestSOAuthorization.mm in Sources */,
    47344748                                F4CD74C920FDB49600DE3794 /* TestURLSchemeHandler.mm in Sources */,
Note: See TracChangeset for help on using the changeset viewer.