+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
/*
- * 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.
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)
{
}
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()
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;
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);
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)
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
#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();
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) { }
// 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;
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;
};