1/*
2 * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#ifndef PDFPlugin_h
27#define PDFPlugin_h
28
29#if ENABLE(PDFKIT_PLUGIN)
30
31#include "Plugin.h"
32#include "WebEvent.h"
33#include <WebCore/AffineTransform.h>
34#include <WebCore/FindOptions.h>
35#include <WebCore/ScrollableArea.h>
36#include <wtf/RetainPtr.h>
37
38typedef const struct OpaqueJSContext* JSContextRef;
39typedef struct OpaqueJSValue* JSObjectRef;
40typedef const struct OpaqueJSValue* JSValueRef;
41
42OBJC_CLASS NSArray;
43OBJC_CLASS NSAttributedString;
44OBJC_CLASS NSData;
45OBJC_CLASS NSString;
46OBJC_CLASS PDFAnnotation;
47OBJC_CLASS PDFLayerController;
48OBJC_CLASS PDFSelection;
49OBJC_CLASS WKPDFPluginAccessibilityObject;
50OBJC_CLASS WKPDFLayerControllerDelegate;
51
52namespace IPC {
53class DataReference;
54}
55
56namespace WebCore {
57class Element;
58struct PluginInfo;
59}
60
61namespace WebKit {
62
63class PDFPluginAnnotation;
64class PDFPluginPasswordField;
65class PluginView;
66class WebFrame;
67
68class PDFPlugin final : public Plugin, private WebCore::ScrollableArea {
69public:
70    static PassRefPtr<PDFPlugin> create(WebFrame*);
71    ~PDFPlugin();
72
73    static WebCore::PluginInfo pluginInfo();
74
75    WebCore::IntSize size() const { return m_size; }
76
77    void didMutatePDFDocument() { m_pdfDocumentWasMutated = true; }
78
79    void paintControlForLayerInContext(CALayer *, CGContextRef);
80    void setActiveAnnotation(PDFAnnotation *);
81
82    using ScrollableArea::notifyScrollPositionChanged;
83    void notifyContentScaleFactorChanged(CGFloat scaleFactor);
84    void notifyDisplayModeChanged(int);
85
86    void notifySelectionChanged(PDFSelection *);
87
88    void clickedLink(NSURL *);
89    void saveToPDF();
90    void openWithNativeApplication();
91    void writeItemsToPasteboard(NSString *pasteboardName, NSArray *items, NSArray *types);
92    void showDefinitionForAttributedString(NSAttributedString *, CGPoint);
93    void performWebSearch(NSString *);
94    void performSpotlightSearch(NSString *);
95
96    void focusNextAnnotation();
97    void focusPreviousAnnotation();
98
99    void attemptToUnlockPDF(const String& password);
100
101    WebCore::FloatRect convertFromPDFViewToScreen(const WebCore::FloatRect&) const;
102    WebCore::IntRect boundsOnScreen() const;
103
104    bool showContextMenuAtPoint(const WebCore::IntPoint&);
105
106private:
107    explicit PDFPlugin(WebFrame*);
108
109    // Plugin functions.
110    virtual bool initialize(const Parameters&);
111    virtual void destroy() override;
112    virtual void paint(WebCore::GraphicsContext*, const WebCore::IntRect& dirtyRectInWindowCoordinates) override { }
113    virtual void updateControlTints(WebCore::GraphicsContext*) override;
114    virtual bool supportsSnapshotting() const override { return true; }
115    virtual PassRefPtr<ShareableBitmap> snapshot() override;
116    virtual PlatformLayer* pluginLayer() override;
117    virtual bool isTransparent() override { return false; }
118    virtual bool wantsWheelEvents() override { return true; }
119    virtual void geometryDidChange(const WebCore::IntSize& pluginSize, const WebCore::IntRect& clipRect, const WebCore::AffineTransform& pluginToRootViewTransform) override;
120    virtual void contentsScaleFactorChanged(float) override;
121    virtual void visibilityDidChange(bool) override { }
122    virtual void frameDidFinishLoading(uint64_t requestID) override;
123    virtual void frameDidFail(uint64_t requestID, bool wasCancelled) override;
124    virtual void didEvaluateJavaScript(uint64_t requestID, const String& result) override;
125    virtual void streamDidReceiveResponse(uint64_t streamID, const WebCore::URL& responseURL, uint32_t streamLength, uint32_t lastModifiedTime, const String& mimeType, const String& headers, const String& suggestedFileName) override;
126    virtual void streamDidReceiveData(uint64_t streamID, const char* bytes, int length) override;
127    virtual void streamDidFinishLoading(uint64_t streamID) override;
128    virtual void streamDidFail(uint64_t streamID, bool wasCancelled) override;
129    virtual void manualStreamDidReceiveResponse(const WebCore::URL& responseURL, uint32_t streamLength, uint32_t lastModifiedTime, const WTF::String& mimeType, const WTF::String& headers, const String& suggestedFileName) override;
130    virtual void manualStreamDidReceiveData(const char* bytes, int length) override;
131    virtual void manualStreamDidFinishLoading() override;
132    virtual void manualStreamDidFail(bool wasCancelled) override;
133    virtual bool handleMouseEvent(const WebMouseEvent&) override;
134    virtual bool handleWheelEvent(const WebWheelEvent&) override;
135    virtual bool handleMouseEnterEvent(const WebMouseEvent&) override;
136    virtual bool handleMouseLeaveEvent(const WebMouseEvent&) override;
137    virtual bool handleContextMenuEvent(const WebMouseEvent&) override;
138    virtual bool handleKeyboardEvent(const WebKeyboardEvent&) override;
139    virtual bool handleEditingCommand(const String& commandName, const String& argument) override;
140    virtual bool isEditingCommandEnabled(const String&) override;
141    virtual bool handlesPageScaleFactor() override;
142    virtual void setFocus(bool) override { }
143    virtual NPObject* pluginScriptableNPObject() override { return 0; }
144    virtual void windowFocusChanged(bool) override { }
145    virtual void windowAndViewFramesChanged(const WebCore::IntRect& windowFrameInScreenCoordinates, const WebCore::IntRect& viewFrameInWindowCoordinates) override { }
146    virtual void windowVisibilityChanged(bool) override { }
147    virtual uint64_t pluginComplexTextInputIdentifier() const override { return 0; }
148    virtual void sendComplexTextInput(const String& textInput) override { }
149    virtual void setLayerHostingMode(LayerHostingMode) override { }
150    virtual WebCore::Scrollbar* horizontalScrollbar() override { return m_horizontalScrollbar.get(); }
151    virtual WebCore::Scrollbar* verticalScrollbar() override { return m_verticalScrollbar.get(); }
152    virtual void storageBlockingStateChanged(bool) override { }
153    virtual void privateBrowsingStateChanged(bool) override { }
154    virtual bool getFormValue(String& formValue) override { return false; }
155    virtual bool handleScroll(WebCore::ScrollDirection, WebCore::ScrollGranularity) override;
156    virtual PassRefPtr<WebCore::SharedBuffer> liveResourceData() const override;
157
158    virtual bool isBeingAsynchronouslyInitialized() const override { return false; }
159
160    virtual RetainPtr<PDFDocument> pdfDocumentForPrinting() const override { return m_pdfDocument; }
161    virtual NSObject *accessibilityObject() const override;
162
163    virtual unsigned countFindMatches(const String& target, WebCore::FindOptions, unsigned maxMatchCount) override;
164    virtual bool findString(const String& target, WebCore::FindOptions, unsigned maxMatchCount) override;
165
166    PDFSelection *nextMatchForString(const String& target, BOOL searchForward, BOOL caseSensitive, BOOL wrapSearch, PDFSelection *initialSelection, BOOL startInSelection);
167
168    virtual bool performDictionaryLookupAtLocation(const WebCore::FloatPoint&) override;
169    virtual String getSelectionString() const override;
170
171    virtual bool shouldAllowScripting() override { return false; }
172    virtual bool shouldAllowNavigationFromDrags() override { return true; }
173    virtual bool shouldAlwaysAutoStart() const override { return true; }
174
175    // ScrollableArea functions.
176    virtual WebCore::IntRect scrollCornerRect() const override;
177    virtual WebCore::ScrollableArea* enclosingScrollableArea() const override;
178    virtual WebCore::IntRect scrollableAreaBoundingBox() const override;
179    virtual void setScrollOffset(const WebCore::IntPoint&) override;
180    virtual void invalidateScrollbarRect(WebCore::Scrollbar*, const WebCore::IntRect&) override;
181    virtual void invalidateScrollCornerRect(const WebCore::IntRect&) override;
182    virtual WebCore::IntPoint lastKnownMousePosition() const override { return m_lastMousePositionInPluginCoordinates; }
183    virtual int scrollSize(WebCore::ScrollbarOrientation) const override;
184    virtual bool isActive() const override;
185    virtual bool isScrollCornerVisible() const override { return false; }
186    virtual int scrollPosition(WebCore::Scrollbar*) const override;
187    virtual WebCore::IntPoint scrollPosition() const override;
188    virtual WebCore::IntPoint minimumScrollPosition() const override;
189    virtual WebCore::IntPoint maximumScrollPosition() const override;
190    virtual WebCore::IntSize visibleSize() const override { return m_size; }
191    virtual WebCore::IntSize contentsSize() const override { return m_pdfDocumentSize; }
192    virtual WebCore::Scrollbar* horizontalScrollbar() const override { return m_horizontalScrollbar.get(); }
193    virtual WebCore::Scrollbar* verticalScrollbar() const override { return m_verticalScrollbar.get(); }
194    virtual bool shouldSuspendScrollAnimations() const override { return false; } // If we return true, ScrollAnimatorMac will keep cycling a timer forever, waiting for a good time to animate.
195    virtual void scrollbarStyleChanged(int newStyle, bool forceUpdate) override;
196    virtual WebCore::IntRect convertFromScrollbarToContainingView(const WebCore::Scrollbar*, const WebCore::IntRect& scrollbarRect) const override;
197    virtual WebCore::IntRect convertFromContainingViewToScrollbar(const WebCore::Scrollbar*, const WebCore::IntRect& parentRect) const override;
198    virtual WebCore::IntPoint convertFromScrollbarToContainingView(const WebCore::Scrollbar*, const WebCore::IntPoint& scrollbarPoint) const override;
199    virtual WebCore::IntPoint convertFromContainingViewToScrollbar(const WebCore::Scrollbar*, const WebCore::IntPoint& parentPoint) const override;
200    virtual bool updatesScrollLayerPositionOnMainThread() const override { return true; }
201    virtual bool forceUpdateScrollbarsOnMainThreadForPerformanceTesting() const;
202
203    // PDFPlugin functions.
204    void updateScrollbars();
205    PassRefPtr<WebCore::Scrollbar> createScrollbar(WebCore::ScrollbarOrientation);
206    void destroyScrollbar(WebCore::ScrollbarOrientation);
207    void pdfDocumentDidLoad();
208    void addArchiveResource();
209    void computePageBoxes();
210    void calculateSizes();
211    void runScriptsInPDFDocument();
212
213    NSEvent *nsEventForWebMouseEvent(const WebMouseEvent&);
214    WebCore::IntPoint convertFromPluginToPDFView(const WebCore::IntPoint&) const;
215    WebCore::IntPoint convertFromRootViewToPlugin(const WebCore::IntPoint&) const;
216    WebCore::IntPoint convertFromPDFViewToRootView(const WebCore::IntPoint&) const;
217
218    bool supportsForms();
219    bool isFullFramePlugin();
220
221    void updatePageAndDeviceScaleFactors();
222
223    void createPasswordEntryForm();
224
225    RetainPtr<PDFDocument> pdfDocument() const { return m_pdfDocument; }
226    void setPDFDocument(RetainPtr<PDFDocument> document) { m_pdfDocument = document; }
227
228    WebCore::IntSize pdfDocumentSize() const { return m_pdfDocumentSize; }
229    void setPDFDocumentSize(WebCore::IntSize size) { m_pdfDocumentSize = size; }
230
231    NSData *liveData() const;
232    NSData *rawData() const { return (NSData *)m_data.get(); }
233
234    WebFrame* webFrame() const { return m_frame; }
235
236    enum UpdateCursorMode {
237        UpdateIfNeeded,
238        ForceUpdate
239    };
240
241    enum HitTestResult {
242        None,
243        Text
244    };
245
246    void updateCursor(const WebMouseEvent&, UpdateCursorMode = UpdateIfNeeded);
247
248    JSObjectRef makeJSPDFDoc(JSContextRef);
249    static JSValueRef jsPDFDocPrint(JSContextRef, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
250
251    void convertPostScriptDataIfNeeded();
252
253    // Regular plug-ins don't need access to view, but we add scrollbars to embedding FrameView for proper event handling.
254    PluginView* pluginView();
255    const PluginView* pluginView() const;
256
257    WebFrame* m_frame;
258
259    bool m_isPostScript;
260    bool m_pdfDocumentWasMutated;
261
262    WebCore::IntSize m_scrollOffset;
263
264    RetainPtr<CALayer> m_containerLayer;
265    RetainPtr<CALayer> m_contentLayer;
266    RetainPtr<CALayer> m_horizontalScrollbarLayer;
267    RetainPtr<CALayer> m_verticalScrollbarLayer;
268    RetainPtr<CALayer> m_scrollCornerLayer;
269    RetainPtr<PDFLayerController> m_pdfLayerController;
270    RetainPtr<WKPDFPluginAccessibilityObject> m_accessibilityObject;
271
272    RefPtr<PDFPluginAnnotation> m_activeAnnotation;
273    RefPtr<PDFPluginPasswordField> m_passwordField;
274    RefPtr<WebCore::Element> m_annotationContainer;
275
276    WebCore::AffineTransform m_rootViewToPluginTransform;
277    WebMouseEvent m_lastMouseEvent;
278    WebCore::IntPoint m_lastMousePositionInPluginCoordinates;
279
280    String m_temporaryPDFUUID;
281
282    String m_lastFoundString;
283
284    HitTestResult m_lastHitTestResult;
285
286    RetainPtr<WKPDFLayerControllerDelegate> m_pdfLayerControllerDelegate;
287
288    WebCore::IntSize m_size;
289
290    WebCore::URL m_sourceURL;
291
292    String m_suggestedFilename;
293    RetainPtr<CFMutableDataRef> m_data;
294
295    RetainPtr<PDFDocument> m_pdfDocument;
296    Vector<WebCore::IntRect> m_pageBoxes;
297    WebCore::IntSize m_pdfDocumentSize; // All pages, including gaps.
298
299    RefPtr<WebCore::Scrollbar> m_horizontalScrollbar;
300    RefPtr<WebCore::Scrollbar> m_verticalScrollbar;
301};
302
303} // namespace WebKit
304
305#endif // ENABLE(PDFKIT_PLUGIN)
306
307#endif // PDFPlugin_h
308