Source/WebCore: WebCore change for <rdar://problem/10463059> Cannot print USPS shippi...
authormitz@apple.com <mitz@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 31 Dec 2011 20:58:39 +0000 (20:58 +0000)
committermitz@apple.com <mitz@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 31 Dec 2011 20:58:39 +0000 (20:58 +0000)
http://webkit.org/b/72801

Reviewed by Anders Carlsson and Alexey Proskuryakov.

* WebCore.exp.in: Exported Chrome::print().

Source/WebKit2: <rdar://problem/10463059> Cannot print USPS shipping labels
http://webkit.org/b/72801

Reviewed by Anders Carlsson and Alexey Proskuryakov.

* WebProcess/Plugins/PDF/BuiltInPDFView.cpp:
(appendValuesInPDFNameSubtreeToVector): Copied from WebKit/mac/WebView/WebPDFDocumentExtras.mm.
(getAllValuesInPDFNameTree): Ditto.
(getAllScriptsInPDFDocument): Copied allScriptsInPDFDocument() from WebPDFDocumentExtras.mm
and changed it to append to a Vector<RetainPtr<CFStringRef> >.
(WebKit::BuiltInPDFView::create): Changed to take a WebFrame* rather than a Page*.
(WebKit::BuiltInPDFView::BuiltInPDFView): Ditto. Updated initializer accordingly.
(WebKit::BuiltInPDFView::pdfDocumentDidLoad): Copied and adapted code from
-[WebPDFRepresentation finishedLoadingWithDataSource:] to run scripts from the PDF with a
Doc object as the this object.
(WebKit::BuiltInPDFView::initialize): Adapted for the change from having a Page* to having
a WebFrame*.
(WebKit::BuiltInPDFView::destroy): Ditto.
(WebKit::BuiltInPDFView::isActive): Ditto.
(WebKit::jsPDFDocInitialize): Added. Refs the BuiltInPDFView which is the private object for
this Doc.
(WebKit::jsPDFDocFinalize): Added. Derefs the BuiltInPDFView for this Doc.
(WebKit::BuiltInPDFView::jsPDFDocPrint): Added. Calls WebCore::Chrome::print().
(WebKit::BuiltInPDFView::makeJSPDFDoc): Copied from WebKit/mac/WebView/WebJSPDFDoc.mm and
modified to use this BuiltInPDFView as the private object of the Doc being made.
* WebProcess/Plugins/PDF/BuiltInPDFView.h:
(WebKit::BuiltInPDFView::disconnectFromPage): Adapted for the change from having a Page* to
having a WebFrame*.
* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::createPlugin): Pass the WebFrame to WebPage::createPlugin().
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::createPlugin): Added a WebFrame* parameter, which is used when creating
a BuiltInPDFView.
* WebProcess/WebPage/WebPage.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@103860 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/WebCore.exp.in
Source/WebKit2/ChangeLog
Source/WebKit2/WebProcess/Plugins/PDF/BuiltInPDFView.cpp
Source/WebKit2/WebProcess/Plugins/PDF/BuiltInPDFView.h
Source/WebKit2/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp
Source/WebKit2/WebProcess/WebPage/WebPage.cpp
Source/WebKit2/WebProcess/WebPage/WebPage.h

index 424265289b234becacf11aa05c0843f6488b653c..e30795a12c8f023a34af3e9800418355bb3eda29 100644 (file)
@@ -1,3 +1,12 @@
+2011-12-31  Dan Bernstein  <mitz@apple.com>
+
+        WebCore change for <rdar://problem/10463059> Cannot print USPS shipping labels
+        http://webkit.org/b/72801
+
+        Reviewed by Anders Carlsson and Alexey Proskuryakov.
+
+        * WebCore.exp.in: Exported Chrome::print().
+
 2011-12-31  Dan Bernstein  <mitz@apple.com>
 
         WebCore changes for <rdar://problem/8750356> REGRESSION (WebKit2): Printing a subframe containing a PDF prints the on-screen view instead of the entire PDF document
index 1e40126a22919d082ad3dbe507ab67ca86805bd0..2f335bf34ebdbc743039dc41411918309cadef71 100644 (file)
@@ -813,6 +813,7 @@ __ZN7WebCore5Range8setStartEN3WTF10PassRefPtrINS_4NodeEEEiRi
 __ZN7WebCore5Range9textRectsERN3WTF6VectorINS_7IntRectELm0EEEbPNS0_20RangeInFixedPositionE
 __ZN7WebCore5RangeD1Ev
 __ZN7WebCore6Chrome16setStatusbarTextEPNS_5FrameERKN3WTF6StringE
+__ZN7WebCore6Chrome5printEPNS_5FrameE
 __ZN7WebCore6Cursor8fromTypeENS0_4TypeE
 __ZN7WebCore6CursorC1EPNS_5ImageERKNS_8IntPointE
 __ZN7WebCore6CursorD1Ev
index 94d204844a5d104f35f77b2765214559a0753b62..d7a788c5aeb3e7d59e7c09d1a561c0951c5d41b0 100644 (file)
@@ -1,3 +1,40 @@
+2011-12-31  Dan Bernstein  <mitz@apple.com>
+
+        <rdar://problem/10463059> Cannot print USPS shipping labels
+        http://webkit.org/b/72801
+
+        Reviewed by Anders Carlsson and Alexey Proskuryakov.
+
+        * WebProcess/Plugins/PDF/BuiltInPDFView.cpp:
+        (appendValuesInPDFNameSubtreeToVector): Copied from WebKit/mac/WebView/WebPDFDocumentExtras.mm.
+        (getAllValuesInPDFNameTree): Ditto.
+        (getAllScriptsInPDFDocument): Copied allScriptsInPDFDocument() from WebPDFDocumentExtras.mm
+        and changed it to append to a Vector<RetainPtr<CFStringRef> >.
+        (WebKit::BuiltInPDFView::create): Changed to take a WebFrame* rather than a Page*.
+        (WebKit::BuiltInPDFView::BuiltInPDFView): Ditto. Updated initializer accordingly.
+        (WebKit::BuiltInPDFView::pdfDocumentDidLoad): Copied and adapted code from
+        -[WebPDFRepresentation finishedLoadingWithDataSource:] to run scripts from the PDF with a
+        Doc object as the this object.
+        (WebKit::BuiltInPDFView::initialize): Adapted for the change from having a Page* to having
+        a WebFrame*.
+        (WebKit::BuiltInPDFView::destroy): Ditto.
+        (WebKit::BuiltInPDFView::isActive): Ditto.
+        (WebKit::jsPDFDocInitialize): Added. Refs the BuiltInPDFView which is the private object for
+        this Doc.
+        (WebKit::jsPDFDocFinalize): Added. Derefs the BuiltInPDFView for this Doc.
+        (WebKit::BuiltInPDFView::jsPDFDocPrint): Added. Calls WebCore::Chrome::print().
+        (WebKit::BuiltInPDFView::makeJSPDFDoc): Copied from WebKit/mac/WebView/WebJSPDFDoc.mm and
+        modified to use this BuiltInPDFView as the private object of the Doc being made.
+        * WebProcess/Plugins/PDF/BuiltInPDFView.h:
+        (WebKit::BuiltInPDFView::disconnectFromPage): Adapted for the change from having a Page* to
+        having a WebFrame*.
+        * WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
+        (WebKit::WebFrameLoaderClient::createPlugin): Pass the WebFrame to WebPage::createPlugin().
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::createPlugin): Added a WebFrame* parameter, which is used when creating
+        a BuiltInPDFView.
+        * WebProcess/WebPage/WebPage.h:
+
 2011-12-31  Dan Bernstein  <mitz@apple.com>
 
         <rdar://problem/8553040> REGRESSION (WebKit2): Safari status text doesn't change when you change the modifier keys without moving the mouse
index 438ec8d2c366903df0ff8db76f487b65fa7d5e76..13f97d96f36f97f766d590fec29b1bcdf4bc05d7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2009, 2011 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #include "ShareableBitmap.h"
 #include "WebEvent.h"
 #include "WebEventConversion.h"
+#include <JavaScriptCore/JSContextRef.h>
+#include <JavaScriptCore/JSObjectRef.h>
+#include <JavaScriptCore/JSStringRef.h>
+#include <JavaScriptCore/JSStringRefCF.h>
 #include <WebCore/ArchiveResource.h>
+#include <WebCore/Chrome.h>
 #include <WebCore/DocumentLoader.h>
 #include <WebCore/FocusController.h>
 #include <WebCore/Frame.h>
 using namespace WebCore;
 using namespace std;
 
+static void appendValuesInPDFNameSubtreeToVector(CGPDFDictionaryRef subtree, Vector<CGPDFObjectRef>& values)
+{
+    CGPDFArrayRef names;
+    if (CGPDFDictionaryGetArray(subtree, "Names", &names)) {
+        size_t nameCount = CGPDFArrayGetCount(names) / 2;
+        for (size_t i = 0; i < nameCount; ++i) {
+            CGPDFObjectRef object;
+            CGPDFArrayGetObject(names, 2 * i + 1, &object);
+            values.append(object);
+        }
+        return;
+    }
+
+    CGPDFArrayRef kids;
+    if (!CGPDFDictionaryGetArray(subtree, "Kids", &kids))
+        return;
+
+    size_t kidCount = CGPDFArrayGetCount(kids);
+    for (size_t i = 0; i < kidCount; ++i) {
+        CGPDFDictionaryRef kid;
+        if (!CGPDFArrayGetDictionary(kids, i, &kid))
+            continue;
+        appendValuesInPDFNameSubtreeToVector(kid, values);
+    }
+}
+
+static void getAllValuesInPDFNameTree(CGPDFDictionaryRef tree, Vector<CGPDFObjectRef>& allValues)
+{
+    appendValuesInPDFNameSubtreeToVector(tree, allValues);
+}
+
+static void getAllScriptsInPDFDocument(CGPDFDocumentRef pdfDocument, Vector<RetainPtr<CFStringRef> >& scripts)
+{
+    if (!pdfDocument)
+        return;
+
+    CGPDFDictionaryRef pdfCatalog = CGPDFDocumentGetCatalog(pdfDocument);
+    if (!pdfCatalog)
+        return;
+
+    // Get the dictionary of all document-level name trees.
+    CGPDFDictionaryRef namesDictionary;
+    if (!CGPDFDictionaryGetDictionary(pdfCatalog, "Names", &namesDictionary))
+        return;
+
+    // Get the document-level "JavaScript" name tree.
+    CGPDFDictionaryRef javaScriptNameTree;
+    if (!CGPDFDictionaryGetDictionary(namesDictionary, "JavaScript", &javaScriptNameTree))
+        return;
+
+    // The names are arbitrary. We are only interested in the values.
+    Vector<CGPDFObjectRef> objects;
+    getAllValuesInPDFNameTree(javaScriptNameTree, objects);
+    size_t objectCount = objects.size();
+
+    for (size_t i = 0; i < objectCount; ++i) {
+        CGPDFDictionaryRef javaScriptAction;
+        if (!CGPDFObjectGetValue(reinterpret_cast<CGPDFObjectRef>(objects[i]), kCGPDFObjectTypeDictionary, &javaScriptAction))
+            continue;
+
+        // A JavaScript action must have an action type of "JavaScript".
+        const char* actionType;
+        if (!CGPDFDictionaryGetName(javaScriptAction, "S", &actionType) || strcmp(actionType, "JavaScript"))
+            continue;
+
+        const UInt8* bytes = 0;
+        CFIndex length;
+        CGPDFStreamRef stream;
+        CGPDFStringRef string;
+        RetainPtr<CFDataRef> data;
+        if (CGPDFDictionaryGetStream(javaScriptAction, "JS", &stream)) {
+            CGPDFDataFormat format;
+            data.adoptCF(CGPDFStreamCopyData(stream, &format));
+            if (!data)
+                continue;
+            bytes = CFDataGetBytePtr(data.get());
+            length = CFDataGetLength(data.get());
+        } else if (CGPDFDictionaryGetString(javaScriptAction, "JS", &string)) {
+            bytes = CGPDFStringGetBytePtr(string);
+            length = CGPDFStringGetLength(string);
+        }
+        if (!bytes)
+            continue;
+
+        CFStringEncoding encoding = (length > 1 && bytes[0] == 0xFE && bytes[1] == 0xFF) ? kCFStringEncodingUnicode : kCFStringEncodingUTF8;
+        RetainPtr<CFStringRef> script(AdoptCF, CFStringCreateWithBytes(kCFAllocatorDefault, bytes, length, encoding, true));
+        if (!script)
+            continue;
+
+        scripts.append(script);
+    }
+}
+
 namespace WebKit {
 
 const uint64_t pdfDocumentRequestID = 1; // PluginController supports loading multiple streams, but we only need one for PDF.
@@ -56,13 +154,13 @@ const int shadowOffsetX = 0;
 const int shadowOffsetY = -2;
 const int shadowSize = 7;
 
-PassRefPtr<BuiltInPDFView> BuiltInPDFView::create(Page* page)
+PassRefPtr<BuiltInPDFView> BuiltInPDFView::create(WebFrame* frame)
 {
-    return adoptRef(new BuiltInPDFView(page));
+    return adoptRef(new BuiltInPDFView(frame));
 }
 
-BuiltInPDFView::BuiltInPDFView(Page* page)
-    : m_page(page)
+BuiltInPDFView::BuiltInPDFView(WebFrame* frame)
+    : m_frame(frame)
 {
 }
 
@@ -211,6 +309,24 @@ void BuiltInPDFView::pdfDocumentDidLoad()
     updateScrollbars();
 
     controller()->invalidate(IntRect(0, 0, m_pluginSize.width(), m_pluginSize.height()));
+
+    Vector<RetainPtr<CFStringRef> > scripts;
+    getAllScriptsInPDFDocument(m_pdfDocument.get(), scripts);
+
+    size_t scriptCount = scripts.size();
+    if (!scriptCount)
+        return;
+
+    JSGlobalContextRef ctx = JSGlobalContextCreate(0);
+    JSObjectRef jsPDFDoc = makeJSPDFDoc(ctx);
+
+    for (size_t i = 0; i < scriptCount; ++i) {
+        JSStringRef script = JSStringCreateWithCFString(scripts[i].get());
+        JSEvaluateScript(ctx, script, jsPDFDoc, 0, 0, 0);
+        JSStringRelease(script);
+    }
+
+    JSGlobalContextRelease(ctx);
 }
 
 void BuiltInPDFView::calculateSizes()
@@ -232,7 +348,7 @@ void BuiltInPDFView::calculateSizes()
 
 bool BuiltInPDFView::initialize(const Parameters& parameters)
 {
-    m_page->addScrollableArea(this);
+    m_frame->coreFrame()->page()->addScrollableArea(this);
 
     // Load the src URL if needed.
     m_sourceURL = parameters.url;
@@ -244,8 +360,10 @@ bool BuiltInPDFView::initialize(const Parameters& parameters)
 
 void BuiltInPDFView::destroy()
 {
-    if (m_page)
-        m_page->removeScrollableArea(this);
+    if (m_frame) {
+        if (Page* page = m_frame->coreFrame()->page())
+            page->removeScrollableArea(this);
+    }
 
     destroyScrollbar(HorizontalScrollbar);
     destroyScrollbar(VerticalScrollbar);
@@ -601,7 +719,12 @@ int BuiltInPDFView::scrollSize(ScrollbarOrientation orientation) const
 
 bool BuiltInPDFView::isActive() const
 {
-    return m_page->focusController()->isActive();
+    if (Frame* coreFrame = m_frame->coreFrame()) {
+        if (Page* page = coreFrame->page())
+            return page->focusController()->isActive();
+    }
+
+    return false;
 }
 
 void BuiltInPDFView::invalidateScrollbarRect(Scrollbar* scrollbar, const LayoutRect& rect)
@@ -695,4 +818,59 @@ IntPoint BuiltInPDFView::convertFromContainingViewToScrollbar(const Scrollbar* s
     return point;
 }
 
+static void jsPDFDocInitialize(JSContextRef ctx, JSObjectRef object)
+{
+    BuiltInPDFView* pdfView = static_cast<BuiltInPDFView*>(JSObjectGetPrivate(object));
+    pdfView->ref();
+}
+
+static void jsPDFDocFinalize(JSObjectRef object)
+{
+    BuiltInPDFView* pdfView = static_cast<BuiltInPDFView*>(JSObjectGetPrivate(object));
+    pdfView->deref();
+}
+
+JSValueRef BuiltInPDFView::jsPDFDocPrint(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+    BuiltInPDFView* pdfView = static_cast<BuiltInPDFView*>(JSObjectGetPrivate(thisObject));
+
+    WebFrame* frame = pdfView->m_frame;
+    if (!frame)
+        return JSValueMakeUndefined(ctx);
+
+    Frame* coreFrame = frame->coreFrame();
+    if (!coreFrame)
+        return JSValueMakeUndefined(ctx);
+
+    Page* page = coreFrame->page();
+    if (!page)
+        return JSValueMakeUndefined(ctx);
+
+    page->chrome()->print(coreFrame);
+
+    return JSValueMakeUndefined(ctx);
+}
+
+JSObjectRef BuiltInPDFView::makeJSPDFDoc(JSContextRef ctx)
+{
+    static JSStaticFunction jsPDFDocStaticFunctions[] = {
+        { "print", jsPDFDocPrint, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+        { 0, 0, 0 },
+    };
+
+    static JSClassDefinition jsPDFDocClassDefinition = {
+        0,
+        kJSClassAttributeNone,
+        "Doc",
+        0,
+        0,
+        jsPDFDocStaticFunctions,
+        jsPDFDocInitialize, jsPDFDocFinalize, 0, 0, 0, 0, 0, 0, 0, 0, 0
+    };
+
+    static JSClassRef jsPDFDocClass = JSClassCreate(&jsPDFDocClassDefinition);
+
+    return JSObjectMake(ctx, jsPDFDocClass, this);
+}
+
 } // namespace WebKit
index 9d83bf35596956b0597623e622117a0275bc7099..6ee4bf3c5948babc619557e696cdd43e5c5c28ee 100644 (file)
 #include <WebCore/ScrollableArea.h>
 #include <wtf/RetainPtr.h>
 
+typedef const struct OpaqueJSContext* JSContextRef;
+typedef struct OpaqueJSValue* JSObjectRef;
+typedef const struct OpaqueJSValue* JSValueRef;
+
 namespace WebCore {
-    class Page;
     struct PluginInfo;
 }
 
 namespace WebKit {
 
 class PluginView;
+class WebFrame;
 
 class BuiltInPDFView : public Plugin, private WebCore::ScrollableArea {
 public:
-    static PassRefPtr<BuiltInPDFView> create(WebCore::Page*);
+    static PassRefPtr<BuiltInPDFView> create(WebFrame*);
     ~BuiltInPDFView();
 
     static WebCore::PluginInfo pluginInfo();
 
 private:
-    explicit BuiltInPDFView(WebCore::Page*);
+    explicit BuiltInPDFView(WebFrame*);
 
     // Regular plug-ins don't need access to view, but we add scrollbars to embedding FrameView for proper event handling.
     PluginView* pluginView();
@@ -134,7 +138,7 @@ private:
     virtual WebCore::Scrollbar* horizontalScrollbar() const  { return m_horizontalScrollbar.get(); }
     virtual WebCore::Scrollbar* verticalScrollbar() const { return m_verticalScrollbar.get(); }
     virtual bool isOnActivePage() const;
-    virtual void disconnectFromPage() { m_page = 0; }
+    virtual void disconnectFromPage() { m_frame = 0; }
     virtual bool shouldSuspendScrollAnimations() const { return false; } // If we return true, ScrollAnimatorMac will keep cycling a timer forever, waiting for a good time to animate.
     virtual void scrollbarStyleChanged(int newStyle, bool forceUpdate);
     virtual void zoomAnimatorTransformChanged(float, float, float, ZoomAnimationState) { }
@@ -142,6 +146,9 @@ private:
     // FIXME: Implement the other conversion functions; this one is enough to get scrollbar hit testing working.
     virtual WebCore::IntPoint convertFromContainingViewToScrollbar(const WebCore::Scrollbar*, const WebCore::IntPoint& parentPoint) const;
 
+    JSObjectRef makeJSPDFDoc(JSContextRef);
+    static JSValueRef jsPDFDocPrint(JSContextRef, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+
     WebCore::IntSize m_pluginSize;
 
     WebCore::KURL m_sourceURL;
@@ -156,7 +163,7 @@ private:
     RefPtr<WebCore::Scrollbar> m_horizontalScrollbar;
     RefPtr<WebCore::Scrollbar> m_verticalScrollbar;
 
-    WebCore::Page* m_page; // Needed to register and unregister ScrollableArea.
+    WebFrame* m_frame;
 
     WebCore::IntSize m_scrollOffset;
 };
index 4dd5699a4d4d9f268bdbd3ed5a647f4410dbe5d9..c774468bf147f4aabab230decd57ca156242e685 100644 (file)
@@ -1274,7 +1274,7 @@ PassRefPtr<Widget> WebFrameLoaderClient::createPlugin(const IntSize&, HTMLPlugIn
     }
 #endif
 
-    RefPtr<Plugin> plugin = webPage->createPlugin(parameters);
+    RefPtr<Plugin> plugin = webPage->createPlugin(m_frame, parameters);
     if (!plugin)
         return 0;
     
index 50051a2a1a431f851ce3558e38ae2de2e0b2f921..8ab06178e5a04e4290667c62e49cd496a6a8b026 100644 (file)
@@ -345,7 +345,7 @@ void WebPage::initializeInjectedBundleFullScreenClient(WKBundlePageFullScreenCli
 }
 #endif
 
-PassRefPtr<Plugin> WebPage::createPlugin(const Plugin::Parameters& parameters)
+PassRefPtr<Plugin> WebPage::createPlugin(WebFrame* frame, const Plugin::Parameters& parameters)
 {
     String pluginPath;
 
@@ -359,7 +359,9 @@ PassRefPtr<Plugin> WebPage::createPlugin(const Plugin::Parameters& parameters)
 #if PLATFORM(MAC)
         if (parameters.mimeType == "application/pdf"
             || (parameters.mimeType.isEmpty() && parameters.url.path().lower().endsWith(".pdf")))
-            return BuiltInPDFView::create(m_page.get());
+            return BuiltInPDFView::create(frame);
+#else
+        UNUSED_PARAM(frame);
 #endif
         return 0;
     }
index f1862fb6faf2f84d78fbd04c49da1f9c07eeca18..3573dd6199de545f30cd7c0ac1a5994f457357e4 100644 (file)
@@ -237,7 +237,7 @@ public:
     WebCore::Frame* mainFrame() const; // May return 0.
     WebCore::FrameView* mainFrameView() const; // May return 0.
 
-    PassRefPtr<Plugin> createPlugin(const Plugin::Parameters&);
+    PassRefPtr<Plugin> createPlugin(WebFrame*, const Plugin::Parameters&);
 
     EditorState editorState() const;