Move URL from WebCore to WTF
[WebKit-https.git] / Source / WebKit / WebProcess / Plugins / PDF / PDFPlugin.h
1 /*
2  * Copyright (C) 2011-2017 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 #pragma once
27
28 #if ENABLE(PDFKIT_PLUGIN)
29
30 #include "PDFKitImports.h"
31 #include "Plugin.h"
32 #include "WebEvent.h"
33 #include "WebHitTestResultData.h"
34 #include <WebCore/AXObjectCache.h>
35 #include <WebCore/AffineTransform.h>
36 #include <WebCore/FindOptions.h>
37 #include <WebCore/ScrollableArea.h>
38 #include <wtf/RetainPtr.h>
39
40 typedef const struct OpaqueJSContext* JSContextRef;
41 typedef struct OpaqueJSValue* JSObjectRef;
42 typedef const struct OpaqueJSValue* JSValueRef;
43
44 OBJC_CLASS NSArray;
45 OBJC_CLASS NSAttributedString;
46 OBJC_CLASS NSData;
47 OBJC_CLASS NSString;
48 OBJC_CLASS PDFAnnotation;
49 OBJC_CLASS PDFLayerController;
50 OBJC_CLASS PDFSelection;
51 OBJC_CLASS WKPDFPluginAccessibilityObject;
52 OBJC_CLASS WKPDFLayerControllerDelegate;
53
54 namespace IPC {
55 class DataReference;
56 }
57
58 namespace WebCore {
59 class AXObjectCache;
60 class Element;
61 struct PluginInfo;
62 }
63
64 namespace WebKit {
65
66 class PDFPluginAnnotation;
67 class PDFPluginPasswordField;
68 class PluginView;
69 class WebFrame;
70
71 class PDFPlugin final : public Plugin, private WebCore::ScrollableArea {
72 public:
73     static Ref<PDFPlugin> create(WebFrame&);
74     ~PDFPlugin();
75
76     static WebCore::PluginInfo pluginInfo();
77
78     WebCore::IntSize size() const { return m_size; }
79
80     void didMutatePDFDocument() { m_pdfDocumentWasMutated = true; }
81
82     void paintControlForLayerInContext(CALayer *, CGContextRef);
83     void setActiveAnnotation(PDFAnnotation *);
84
85     using ScrollableArea::notifyScrollPositionChanged;
86     void notifyContentScaleFactorChanged(CGFloat scaleFactor);
87     void notifyDisplayModeChanged(int);
88
89     void notifySelectionChanged(PDFSelection *);
90     void notifyCursorChanged(uint64_t /* PDFLayerControllerCursorType */);
91
92     void clickedLink(NSURL *);
93     void saveToPDF();
94     void openWithNativeApplication();
95     void writeItemsToPasteboard(NSString *pasteboardName, NSArray *items, NSArray *types);
96     void showDefinitionForAttributedString(NSAttributedString *, CGPoint);
97     void performWebSearch(NSString *);
98     void performSpotlightSearch(NSString *);
99
100     void focusNextAnnotation();
101     void focusPreviousAnnotation();
102
103     void attemptToUnlockPDF(const String& password);
104
105     WebCore::FloatRect convertFromPDFViewToScreen(const WebCore::FloatRect&) const;
106     WebCore::IntPoint convertFromRootViewToPDFView(const WebCore::IntPoint&) const;
107     WebCore::IntRect boundsOnScreen() const;
108
109     bool showContextMenuAtPoint(const WebCore::IntPoint&);
110
111     std::tuple<String, PDFSelection *, NSDictionary *> lookupTextAtLocation(const WebCore::FloatPoint&, WebHitTestResultData&) const;
112     WebCore::FloatRect rectForSelectionInRootView(PDFSelection *) const;
113
114     CGFloat scaleFactor() const;
115
116     PDFPluginAnnotation* activeAnnotation() const { return m_activeAnnotation.get(); }
117     WebCore::AXObjectCache* axObjectCache() const;
118
119 private:
120     explicit PDFPlugin(WebFrame&);
121
122     // Plugin functions.
123     bool initialize(const Parameters&) final;
124     void destroy() final;
125     void paint(WebCore::GraphicsContext&, const WebCore::IntRect& dirtyRectInWindowCoordinates) final { }
126     void updateControlTints(WebCore::GraphicsContext&) final;
127     bool supportsSnapshotting() const final { return true; }
128     RefPtr<ShareableBitmap> snapshot() final;
129     PlatformLayer* pluginLayer() final;
130     bool isTransparent() final { return false; }
131     bool wantsWheelEvents() final { return true; }
132     void geometryDidChange(const WebCore::IntSize& pluginSize, const WebCore::IntRect& clipRect, const WebCore::AffineTransform& pluginToRootViewTransform) final;
133     void contentsScaleFactorChanged(float) final;
134     void visibilityDidChange(bool) final { }
135     void frameDidFinishLoading(uint64_t requestID) final;
136     void frameDidFail(uint64_t requestID, bool wasCancelled) final;
137     void didEvaluateJavaScript(uint64_t requestID, const String& result) final;
138     void streamWillSendRequest(uint64_t streamID, const URL& requestURL, const URL& responseURL, int responseStatus) final { }
139     void streamDidReceiveResponse(uint64_t streamID, const URL& responseURL, uint32_t streamLength, uint32_t lastModifiedTime, const String& mimeType, const String& headers, const String& suggestedFileName) final;
140     void streamDidReceiveData(uint64_t streamID, const char* bytes, int length) final;
141     void streamDidFinishLoading(uint64_t streamID) final;
142     void streamDidFail(uint64_t streamID, bool wasCancelled) final;
143     void manualStreamDidReceiveResponse(const URL& responseURL, uint32_t streamLength, uint32_t lastModifiedTime, const WTF::String& mimeType, const WTF::String& headers, const String& suggestedFileName) final;
144     void manualStreamDidReceiveData(const char* bytes, int length) final;
145     void manualStreamDidFinishLoading() final;
146     void manualStreamDidFail(bool wasCancelled) final;
147     bool handleMouseEvent(const WebMouseEvent&) final;
148     bool handleWheelEvent(const WebWheelEvent&) final;
149     bool handleMouseEnterEvent(const WebMouseEvent&) final;
150     bool handleMouseLeaveEvent(const WebMouseEvent&) final;
151     bool handleContextMenuEvent(const WebMouseEvent&) final;
152     bool handleKeyboardEvent(const WebKeyboardEvent&) final;
153     bool handleEditingCommand(const String& commandName, const String& argument) final;
154     bool isEditingCommandEnabled(const String&) final;
155     bool handlesPageScaleFactor() const final;
156     bool requiresUnifiedScaleFactor() const final { return true; }
157     void setFocus(bool) final { }
158     NPObject* pluginScriptableNPObject() final { return nullptr; }
159     void windowFocusChanged(bool) final { }
160     void windowAndViewFramesChanged(const WebCore::IntRect& windowFrameInScreenCoordinates, const WebCore::IntRect& viewFrameInWindowCoordinates) final { }
161     void windowVisibilityChanged(bool) final { }
162     uint64_t pluginComplexTextInputIdentifier() const final { return 0; }
163     void sendComplexTextInput(const String& textInput) final { }
164     void setLayerHostingMode(LayerHostingMode) final { }
165     WebCore::Scrollbar* horizontalScrollbar() final { return m_horizontalScrollbar.get(); }
166     WebCore::Scrollbar* verticalScrollbar() final { return m_verticalScrollbar.get(); }
167     void storageBlockingStateChanged(bool) final { }
168     void privateBrowsingStateChanged(bool) final { }
169     bool getFormValue(String& formValue) final { return false; }
170     bool handleScroll(WebCore::ScrollDirection, WebCore::ScrollGranularity) final;
171     RefPtr<WebCore::SharedBuffer> liveResourceData() const final;
172     void willDetachRenderer() final;
173     bool pluginHandlesContentOffsetForAccessibilityHitTest() const final;
174     
175     bool isBeingAsynchronouslyInitialized() const final { return false; }
176
177     RetainPtr<PDFDocument> pdfDocumentForPrinting() const final { return m_pdfDocument; }
178     NSObject *accessibilityObject() const final;
179     id accessibilityAssociatedPluginParentForElement(WebCore::Element*) const final;
180
181     unsigned countFindMatches(const String& target, WebCore::FindOptions, unsigned maxMatchCount) final;
182     bool findString(const String& target, WebCore::FindOptions, unsigned maxMatchCount) final;
183
184     PDFSelection *nextMatchForString(const String& target, BOOL searchForward, BOOL caseSensitive, BOOL wrapSearch, PDFSelection *initialSelection, BOOL startInSelection);
185
186     bool performDictionaryLookupAtLocation(const WebCore::FloatPoint&) final;
187     String getSelectionString() const final;
188     String getSelectionForWordAtPoint(const WebCore::FloatPoint&) const final;
189     bool existingSelectionContainsPoint(const WebCore::FloatPoint&) const final;
190
191     bool shouldAllowScripting() final { return false; }
192     bool shouldAllowNavigationFromDrags() final { return true; }
193     bool shouldAlwaysAutoStart() const final { return true; }
194
195     // ScrollableArea functions.
196     WebCore::IntRect scrollCornerRect() const final;
197     WebCore::ScrollableArea* enclosingScrollableArea() const final;
198     bool isScrollableOrRubberbandable() final { return true; }
199     bool hasScrollableOrRubberbandableAncestor() final { return true; }
200     WebCore::IntRect scrollableAreaBoundingBox(bool* = nullptr) const final;
201     void setScrollOffset(const WebCore::ScrollOffset&) final;
202     void invalidateScrollbarRect(WebCore::Scrollbar&, const WebCore::IntRect&) final;
203     void invalidateScrollCornerRect(const WebCore::IntRect&) final;
204     WebCore::IntPoint lastKnownMousePosition() const final { return m_lastMousePositionInPluginCoordinates; }
205     int scrollSize(WebCore::ScrollbarOrientation) const final;
206     bool isActive() const final;
207     bool isScrollCornerVisible() const final { return false; }
208     int scrollOffset(WebCore::ScrollbarOrientation) const final;
209     WebCore::ScrollPosition scrollPosition() const final;
210     WebCore::ScrollPosition minimumScrollPosition() const final;
211     WebCore::ScrollPosition maximumScrollPosition() const final;
212     WebCore::IntSize visibleSize() const final { return m_size; }
213     WebCore::IntSize contentsSize() const final { return m_pdfDocumentSize; }
214     WebCore::Scrollbar* horizontalScrollbar() const final { return m_horizontalScrollbar.get(); }
215     WebCore::Scrollbar* verticalScrollbar() const final { return m_verticalScrollbar.get(); }
216     bool shouldSuspendScrollAnimations() const final { return false; } // If we return true, ScrollAnimatorMac will keep cycling a timer forever, waiting for a good time to animate.
217     void scrollbarStyleChanged(WebCore::ScrollbarStyle, bool forceUpdate) final;
218     WebCore::IntRect convertFromScrollbarToContainingView(const WebCore::Scrollbar&, const WebCore::IntRect& scrollbarRect) const final;
219     WebCore::IntRect convertFromContainingViewToScrollbar(const WebCore::Scrollbar&, const WebCore::IntRect& parentRect) const final;
220     WebCore::IntPoint convertFromScrollbarToContainingView(const WebCore::Scrollbar&, const WebCore::IntPoint& scrollbarPoint) const final;
221     WebCore::IntPoint convertFromContainingViewToScrollbar(const WebCore::Scrollbar&, const WebCore::IntPoint& parentPoint) const final;
222     bool forceUpdateScrollbarsOnMainThreadForPerformanceTesting() const final;
223     bool shouldPlaceBlockDirectionScrollbarOnLeft() const final { return false; }
224
225     // PDFPlugin functions.
226     void updateScrollbars();
227     Ref<WebCore::Scrollbar> createScrollbar(WebCore::ScrollbarOrientation);
228     void destroyScrollbar(WebCore::ScrollbarOrientation);
229     void pdfDocumentDidLoad();
230     void addArchiveResource();
231     void calculateSizes();
232     void runScriptsInPDFDocument();
233
234     NSEvent *nsEventForWebMouseEvent(const WebMouseEvent&);
235     WebCore::IntPoint convertFromPluginToPDFView(const WebCore::IntPoint&) const;
236     WebCore::IntPoint convertFromRootViewToPlugin(const WebCore::IntPoint&) const;
237     WebCore::IntPoint convertFromPDFViewToRootView(const WebCore::IntPoint&) const;
238     
239     bool supportsForms();
240     bool isFullFramePlugin() const;
241
242     void updatePageAndDeviceScaleFactors();
243
244     void createPasswordEntryForm();
245
246     RetainPtr<PDFDocument> pdfDocument() const { return m_pdfDocument; }
247     void setPDFDocument(RetainPtr<PDFDocument> document) { m_pdfDocument = document; }
248
249     WebCore::IntSize pdfDocumentSize() const { return m_pdfDocumentSize; }
250     void setPDFDocumentSize(WebCore::IntSize size) { m_pdfDocumentSize = size; }
251
252 #ifdef __OBJC__
253     NSData *liveData() const;
254     NSData *rawData() const { return (__bridge NSData *)m_data.get(); }
255 #endif
256
257     WebFrame* webFrame() const { return m_frame; }
258
259 #if __MAC_OS_X_VERSION_MIN_REQUIRED < 101300
260     enum UpdateCursorMode { UpdateIfNeeded, ForceUpdate };
261     void updateCursor(const WebMouseEvent&, UpdateCursorMode = UpdateIfNeeded);
262 #endif
263
264     JSObjectRef makeJSPDFDoc(JSContextRef);
265     static JSValueRef jsPDFDocPrint(JSContextRef, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
266
267     void convertPostScriptDataIfNeeded();
268
269     // Regular plug-ins don't need access to view, but we add scrollbars to embedding FrameView for proper event handling.
270     PluginView* pluginView();
271     const PluginView* pluginView() const;
272
273     WebFrame* m_frame;
274
275     bool m_isPostScript { false };
276     bool m_pdfDocumentWasMutated { false };
277
278     WebCore::IntSize m_scrollOffset;
279
280     RetainPtr<CALayer> m_containerLayer;
281     RetainPtr<CALayer> m_contentLayer;
282     RetainPtr<CALayer> m_horizontalScrollbarLayer;
283     RetainPtr<CALayer> m_verticalScrollbarLayer;
284     RetainPtr<CALayer> m_scrollCornerLayer;
285     RetainPtr<PDFLayerController> m_pdfLayerController;
286     RetainPtr<WKPDFPluginAccessibilityObject> m_accessibilityObject;
287     
288     RefPtr<PDFPluginAnnotation> m_activeAnnotation;
289     RefPtr<PDFPluginPasswordField> m_passwordField;
290     RefPtr<WebCore::Element> m_annotationContainer;
291
292     WebCore::AffineTransform m_rootViewToPluginTransform;
293     WebMouseEvent m_lastMouseEvent;
294     WebCore::IntPoint m_lastMousePositionInPluginCoordinates;
295
296     String m_temporaryPDFUUID;
297
298     String m_lastFoundString;
299
300 #if __MAC_OS_X_VERSION_MIN_REQUIRED < 101300
301     enum HitTestResult { None, Text };
302     HitTestResult m_lastHitTestResult { None };
303 #endif
304
305     RetainPtr<WKPDFLayerControllerDelegate> m_pdfLayerControllerDelegate;
306
307     WebCore::IntSize m_size;
308
309     URL m_sourceURL;
310
311     String m_suggestedFilename;
312     RetainPtr<CFMutableDataRef> m_data;
313
314     RetainPtr<PDFDocument> m_pdfDocument;
315     unsigned m_firstPageHeight { 0 };
316     WebCore::IntSize m_pdfDocumentSize; // All pages, including gaps.
317
318     RefPtr<WebCore::Scrollbar> m_horizontalScrollbar;
319     RefPtr<WebCore::Scrollbar> m_verticalScrollbar;
320 };
321
322 } // namespace WebKit
323
324 SPECIALIZE_TYPE_TRAITS_PLUGIN(PDFPlugin, PDFPluginType)
325
326 #endif // ENABLE(PDFKIT_PLUGIN)