Modified: branches/safari-534.54-branch/Source/WebKit2/WebProcess/Plugins/PDF/BuiltInPDFView.cpp (105117 => 105118)
--- branches/safari-534.54-branch/Source/WebKit2/WebProcess/Plugins/PDF/BuiltInPDFView.cpp 2012-01-17 01:33:06 UTC (rev 105117)
+++ branches/safari-534.54-branch/Source/WebKit2/WebProcess/Plugins/PDF/BuiltInPDFView.cpp 2012-01-17 01:49:01 UTC (rev 105118)
@@ -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
@@ -30,7 +30,12 @@
#include "ShareableBitmap.h"
#include "WebEvent.h"
#include "WebEventConversion.h"
+#include <_javascript_Core/JSContextRef.h>
+#include <_javascript_Core/JSObjectRef.h>
+#include <_javascript_Core/JSStringRef.h>
+#include <_javascript_Core/JSStringRefCF.h>
#include <WebCore/ArchiveResource.h>
+#include <WebCore/Chrome.h>
#include <WebCore/DocumentLoader.h>
#include <WebCore/FocusController.h>
#include <WebCore/Frame.h>
@@ -47,6 +52,99 @@
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 _javascript_NameTree;
+ if (!CGPDFDictionaryGetDictionary(namesDictionary, "_javascript_", &_javascript_NameTree))
+ return;
+
+ // The names are arbitrary. We are only interested in the values.
+ Vector<CGPDFObjectRef> objects;
+ getAllValuesInPDFNameTree(_javascript_NameTree, objects);
+ size_t objectCount = objects.size();
+
+ for (size_t i = 0; i < objectCount; ++i) {
+ CGPDFDictionaryRef _javascript_Action;
+ if (!CGPDFObjectGetValue(reinterpret_cast<CGPDFObjectRef>(objects[i]), kCGPDFObjectTypeDictionary, &_javascript_Action))
+ continue;
+
+ // A _javascript_ action must have an action type of "_javascript_".
+ const char* actionType;
+ if (!CGPDFDictionaryGetName(_javascript_Action, "S", &actionType) || strcmp(actionType, "_javascript_"))
+ continue;
+
+ const UInt8* bytes = 0;
+ CFIndex length;
+ CGPDFStreamRef stream;
+ CGPDFStringRef string;
+ RetainPtr<CFDataRef> data;
+ if (CGPDFDictionaryGetStream(_javascript_Action, "JS", &stream)) {
+ CGPDFDataFormat format;
+ data.adoptCF(CGPDFStreamCopyData(stream, &format));
+ if (!data)
+ continue;
+ bytes = CFDataGetBytePtr(data.get());
+ length = CFDataGetLength(data.get());
+ } else if (CGPDFDictionaryGetString(_javascript_Action, "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,14 +154,14 @@
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)
+BuiltInPDFView::BuiltInPDFView(WebFrame* frame)
: m_pluginController(0)
- , m_page(page)
+ , m_frame(frame)
{
}
@@ -218,6 +316,24 @@
updateScrollbars();
m_pluginController->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()
@@ -241,7 +357,7 @@
{
m_pluginController = pluginController;
- m_page->addScrollableArea(this);
+ m_frame->coreFrame()->page()->addScrollableArea(this);
// Load the src URL if needed.
m_sourceURL = parameters.url;
@@ -253,8 +369,10 @@
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);
@@ -623,7 +741,12 @@
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 IntRect& rect)
@@ -717,4 +840,59 @@
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
Modified: branches/safari-534.54-branch/Source/WebKit2/WebProcess/Plugins/PDF/BuiltInPDFView.h (105117 => 105118)
--- branches/safari-534.54-branch/Source/WebKit2/WebProcess/Plugins/PDF/BuiltInPDFView.h 2012-01-17 01:33:06 UTC (rev 105117)
+++ branches/safari-534.54-branch/Source/WebKit2/WebProcess/Plugins/PDF/BuiltInPDFView.h 2012-01-17 01:49:01 UTC (rev 105118)
@@ -30,24 +30,28 @@
#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();
@@ -139,13 +143,16 @@
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);
// 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);
+
PluginController* m_pluginController;
WebCore::IntSize m_pluginSize;
@@ -162,7 +169,7 @@
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;
};