Link clicks in PDFs shouldn't send referrer headers.
[WebKit-https.git] / Source / WebKit / WebProcess / Plugins / PDF / PDFPlugin.mm
1 /*
2  * Copyright (C) 2009-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 #import "config.h"
27 #import "PDFPlugin.h"
28
29 #if ENABLE(PDFKIT_PLUGIN)
30
31 #import "ArgumentCoders.h"
32 #import "DataReference.h"
33 #import "PDFAnnotationTextWidgetDetails.h"
34 #import "PDFContextMenu.h"
35 #import "PDFLayerControllerSPI.h"
36 #import "PDFPluginAnnotation.h"
37 #import "PDFPluginPasswordField.h"
38 #import "PluginView.h"
39 #import "WKAccessibilityWebPageObjectMac.h"
40 #import "WKPageFindMatchesClient.h"
41 #import "WebCoreArgumentCoders.h"
42 #import "WebEvent.h"
43 #import "WebEventConversion.h"
44 #import "WebFindOptions.h"
45 #import "WebPage.h"
46 #import "WebPageProxyMessages.h"
47 #import "WebPasteboardProxyMessages.h"
48 #import "WebProcess.h"
49 #import <JavaScriptCore/JSContextRef.h>
50 #import <JavaScriptCore/JSObjectRef.h>
51 #import <Quartz/Quartz.h>
52 #import <QuartzCore/QuartzCore.h>
53 #import <WebCore/AXObjectCache.h>
54 #import <WebCore/ArchiveResource.h>
55 #import <WebCore/Chrome.h>
56 #import <WebCore/Cursor.h>
57 #import <WebCore/DictionaryLookup.h>
58 #import <WebCore/DocumentLoader.h>
59 #import <WebCore/EventNames.h>
60 #import <WebCore/FocusController.h>
61 #import <WebCore/FormState.h>
62 #import <WebCore/Frame.h>
63 #import <WebCore/FrameLoader.h>
64 #import <WebCore/FrameView.h>
65 #import <WebCore/GraphicsContext.h>
66 #import <WebCore/HTMLElement.h>
67 #import <WebCore/HTMLFormElement.h>
68 #import <WebCore/HTMLPlugInElement.h>
69 #import <WebCore/LegacyNSPasteboardTypes.h>
70 #import <WebCore/LocalDefaultSystemAppearance.h>
71 #import <WebCore/LocalizedStrings.h>
72 #import <WebCore/MouseEvent.h>
73 #import <WebCore/PDFDocumentImage.h>
74 #import <WebCore/Page.h>
75 #import <WebCore/Pasteboard.h>
76 #import <WebCore/PlatformScreen.h>
77 #import <WebCore/PluginData.h>
78 #import <WebCore/PluginDocument.h>
79 #import <WebCore/RenderBoxModelObject.h>
80 #import <WebCore/ScrollAnimator.h>
81 #import <WebCore/ScrollbarTheme.h>
82 #import <WebCore/Settings.h>
83 #import <WebCore/WebAccessibilityObjectWrapperMac.h>
84 #import <WebCore/WheelEventTestTrigger.h>
85 #import <pal/spi/cg/CoreGraphicsSPI.h>
86 #import <pal/spi/mac/NSMenuSPI.h>
87 #import <wtf/UUID.h>
88
89 // Set overflow: hidden on the annotation container so <input> elements scrolled out of view don't show
90 // scrollbars on the body. We can't add annotations directly to the body, because overflow: hidden on the body
91 // will break rubber-banding.
92 static const char* annotationStyle =
93 "#annotationContainer {"
94 "    overflow: hidden; "
95 "    position: absolute; "
96 "    pointer-events: none; "
97 "    top: 0; "
98 "    left: 0; "
99 "    right: 0; "
100 "    bottom: 0; "
101 "    display: -webkit-box; "
102 "    -webkit-box-align: center; "
103 "    -webkit-box-pack: center; "
104 "} "
105 ".annotation { "
106 "    position: absolute; "
107 "    pointer-events: auto; "
108 "} "
109 "textarea.annotation { "
110 "    resize: none; "
111 "} "
112 "input.annotation[type='password'] { "
113 "    position: static; "
114 "    width: 200px; "
115 "    margin-top: 100px; "
116 "} ";
117
118 // In non-continuous modes, a single scroll event with a magnitude of >= 20px
119 // will jump to the next or previous page, to match PDFKit behavior.
120 static const int defaultScrollMagnitudeThresholdForPageFlip = 20;
121
122 @interface WKPDFPluginAccessibilityObject : NSObject {
123     PDFLayerController *_pdfLayerController;
124     __unsafe_unretained NSObject *_parent;
125     WebKit::PDFPlugin* _pdfPlugin;
126 }
127
128 @property (assign) PDFLayerController *pdfLayerController;
129 @property (assign) NSObject *parent;
130 @property (assign) WebKit::PDFPlugin* pdfPlugin;
131
132 - (id)initWithPDFPlugin:(WebKit::PDFPlugin *)plugin;
133
134 @end
135
136 @implementation WKPDFPluginAccessibilityObject
137
138 @synthesize parent=_parent;
139 @synthesize pdfPlugin=_pdfPlugin;
140
141 - (id)initWithPDFPlugin:(WebKit::PDFPlugin *)plugin
142 {
143     if (!(self = [super init]))
144         return nil;
145
146     _pdfPlugin = plugin;
147
148     return self;
149 }
150
151 - (PDFLayerController *)pdfLayerController
152 {
153     return _pdfLayerController;
154 }
155
156 - (void)setPdfLayerController:(PDFLayerController *)pdfLayerController
157 {
158     _pdfLayerController = pdfLayerController;
159 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300
160     [_pdfLayerController setAccessibilityParent:self];
161 #endif
162 }
163
164 IGNORE_WARNINGS_BEGIN("deprecated-implementations")
165 - (BOOL)accessibilityIsIgnored
166 IGNORE_WARNINGS_END
167 {
168     return NO;
169 }
170
171 // This is called by PDFAccessibilityNodes from inside PDFKit to get final bounds.
172 - (NSRect)convertRectToScreenSpace:(NSRect)rect
173 {
174     return _pdfPlugin->convertFromPDFViewToScreen(rect);
175 }
176
177 IGNORE_WARNINGS_BEGIN("deprecated-implementations")
178 - (id)accessibilityAttributeValue:(NSString *)attribute
179 IGNORE_WARNINGS_END
180 {
181     if ([attribute isEqualToString:NSAccessibilityParentAttribute])
182         return _parent;
183     if ([attribute isEqualToString:NSAccessibilityTopLevelUIElementAttribute])
184         return [_parent accessibilityAttributeValue:NSAccessibilityTopLevelUIElementAttribute];
185     if ([attribute isEqualToString:NSAccessibilityWindowAttribute])
186         return [_parent accessibilityAttributeValue:NSAccessibilityWindowAttribute];
187     if ([attribute isEqualToString:NSAccessibilitySizeAttribute])
188         return [NSValue valueWithSize:_pdfPlugin->boundsOnScreen().size()];
189     if ([attribute isEqualToString:NSAccessibilityEnabledAttribute])
190         return [_parent accessibilityAttributeValue:NSAccessibilityEnabledAttribute];
191     if ([attribute isEqualToString:NSAccessibilityPositionAttribute])
192         return [NSValue valueWithPoint:_pdfPlugin->boundsOnScreen().location()];
193
194 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300
195     if ([attribute isEqualToString:NSAccessibilityChildrenAttribute])
196         return @[ _pdfLayerController ];
197     if ([attribute isEqualToString:NSAccessibilityRoleAttribute])
198         return NSAccessibilityGroupRole;
199 #else
200     if ([attribute isEqualToString:NSAccessibilityValueAttribute])
201         return [_pdfLayerController accessibilityValueAttribute];
202     if ([attribute isEqualToString:NSAccessibilitySelectedTextAttribute])
203         return [_pdfLayerController accessibilitySelectedTextAttribute];
204     if ([attribute isEqualToString:NSAccessibilitySelectedTextRangeAttribute])
205         return [_pdfLayerController accessibilitySelectedTextRangeAttribute];
206     if ([attribute isEqualToString:NSAccessibilityNumberOfCharactersAttribute])
207         return [_pdfLayerController accessibilityNumberOfCharactersAttribute];
208     if ([attribute isEqualToString:NSAccessibilityVisibleCharacterRangeAttribute])
209         return [_pdfLayerController accessibilityVisibleCharacterRangeAttribute];
210     if ([attribute isEqualToString:NSAccessibilityRoleAttribute])
211         return [_pdfLayerController accessibilityRoleAttribute];
212     if ([attribute isEqualToString:NSAccessibilityRoleDescriptionAttribute])
213         return [_pdfLayerController accessibilityRoleDescriptionAttribute];
214     if ([attribute isEqualToString:NSAccessibilityFocusedAttribute])
215         return [_parent accessibilityAttributeValue:NSAccessibilityFocusedAttribute];
216 #endif
217
218     return 0;
219 }
220
221 IGNORE_WARNINGS_BEGIN("deprecated-implementations")
222 - (id)accessibilityAttributeValue:(NSString *)attribute forParameter:(id)parameter
223 IGNORE_WARNINGS_END
224 {
225     if ([attribute isEqualToString:NSAccessibilityBoundsForRangeParameterizedAttribute]) {
226         NSRect boundsInPDFViewCoordinates = [[_pdfLayerController accessibilityBoundsForRangeAttributeForParameter:parameter] rectValue];
227         NSRect boundsInScreenCoordinates = _pdfPlugin->convertFromPDFViewToScreen(boundsInPDFViewCoordinates);
228         return [NSValue valueWithRect:boundsInScreenCoordinates];
229     }
230
231     if ([attribute isEqualToString:NSAccessibilityLineForIndexParameterizedAttribute])
232         return [_pdfLayerController accessibilityLineForIndexAttributeForParameter:parameter];
233     if ([attribute isEqualToString:NSAccessibilityRangeForLineParameterizedAttribute])
234         return [_pdfLayerController accessibilityRangeForLineAttributeForParameter:parameter];
235     if ([attribute isEqualToString:NSAccessibilityStringForRangeParameterizedAttribute])
236         return [_pdfLayerController accessibilityStringForRangeAttributeForParameter:parameter];
237
238     return 0;
239 }
240
241 - (CPReadingModel *)readingModel
242 {
243     return [_pdfLayerController readingModel];
244 }
245
246 IGNORE_WARNINGS_BEGIN("deprecated-implementations")
247 - (NSArray *)accessibilityAttributeNames
248 IGNORE_WARNINGS_END
249 {
250     static NSArray *attributeNames = 0;
251
252     if (!attributeNames) {
253         attributeNames = @[
254             NSAccessibilityParentAttribute,
255             NSAccessibilityWindowAttribute,
256             NSAccessibilityTopLevelUIElementAttribute,
257             NSAccessibilityRoleDescriptionAttribute,
258             NSAccessibilitySizeAttribute,
259             NSAccessibilityEnabledAttribute,
260             NSAccessibilityPositionAttribute,
261             NSAccessibilityFocusedAttribute,
262             // PDFLayerController has its own accessibilityChildren.
263 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300
264             NSAccessibilityChildrenAttribute
265 #else
266             NSAccessibilityRoleAttribute,
267             NSAccessibilityValueAttribute,
268             NSAccessibilitySelectedTextAttribute,
269             NSAccessibilitySelectedTextRangeAttribute,
270             NSAccessibilityNumberOfCharactersAttribute,
271             NSAccessibilityVisibleCharacterRangeAttribute
272 #endif
273             ];
274         [attributeNames retain];
275     }
276
277     return attributeNames;
278 }
279
280 IGNORE_WARNINGS_BEGIN("deprecated-implementations")
281 - (NSArray *)accessibilityActionNames
282 IGNORE_WARNINGS_END
283 {
284 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300
285     return nil;
286 #else
287     static NSArray *actionNames = 0;
288     
289     if (!actionNames)
290         actionNames = [[NSArray arrayWithObject:NSAccessibilityShowMenuAction] retain];
291     
292     return actionNames;
293 #endif
294 }
295
296 IGNORE_WARNINGS_BEGIN("deprecated-implementations")
297 - (void)accessibilityPerformAction:(NSString *)action
298 IGNORE_WARNINGS_END
299 {
300     if ([action isEqualToString:NSAccessibilityShowMenuAction])
301         _pdfPlugin->showContextMenuAtPoint(WebCore::IntRect(WebCore::IntPoint(), _pdfPlugin->size()).center());
302 }
303
304 IGNORE_WARNINGS_BEGIN("deprecated-implementations")
305 - (BOOL)accessibilityIsAttributeSettable:(NSString *)attribute
306 IGNORE_WARNINGS_END
307 {
308     return [_pdfLayerController accessibilityIsAttributeSettable:attribute];
309 }
310
311 IGNORE_WARNINGS_BEGIN("deprecated-implementations")
312 - (void)accessibilitySetValue:(id)value forAttribute:(NSString *)attribute
313 IGNORE_WARNINGS_END
314 {
315     return [_pdfLayerController accessibilitySetValue:value forAttribute:attribute];
316 }
317
318 IGNORE_WARNINGS_BEGIN("deprecated-implementations")
319 - (NSArray *)accessibilityParameterizedAttributeNames
320 IGNORE_WARNINGS_END
321 {
322 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300
323     return nil;
324 #else
325     return [_pdfLayerController accessibilityParameterizedAttributeNames];
326 #endif
327 }
328
329 - (id)accessibilityFocusedUIElement
330 {
331 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300
332     if (WebKit::PDFPluginAnnotation* activeAnnotation = _pdfPlugin->activeAnnotation()) {
333         if (WebCore::AXObjectCache* existingCache = _pdfPlugin->axObjectCache()) {
334             if (WebCore::AccessibilityObject* object = existingCache->getOrCreate(activeAnnotation->element()))
335                 ALLOW_DEPRECATED_DECLARATIONS_BEGIN
336                 return [object->wrapper() accessibilityAttributeValue:@"_AXAssociatedPluginParent"];
337                 ALLOW_DEPRECATED_DECLARATIONS_END
338         }
339     }
340     return nil;
341 #else
342     return self;
343 #endif
344 }
345
346 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300
347 - (id)accessibilityAssociatedControlForAnnotation:(PDFAnnotation *)annotation
348 {
349     // Only active annotations seem to have their associated controls available.
350     WebKit::PDFPluginAnnotation* activeAnnotation = _pdfPlugin->activeAnnotation();
351     if (!activeAnnotation || ![activeAnnotation->annotation() isEqual:annotation])
352         return nil;
353     
354     WebCore::AXObjectCache* cache = _pdfPlugin->axObjectCache();
355     if (!cache)
356         return nil;
357     
358     WebCore::AccessibilityObject* object = cache->getOrCreate(activeAnnotation->element());
359     if (!object)
360         return nil;
361
362     return object->wrapper();
363 }
364 #endif
365
366 - (id)accessibilityHitTest:(NSPoint)point
367 {
368 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300
369     point = _pdfPlugin->convertFromRootViewToPDFView(WebCore::IntPoint(point));
370     return [_pdfLayerController accessibilityHitTest:point];
371 #else
372     return self;
373 #endif
374 }
375
376 @end
377
378
379 @interface WKPDFPluginScrollbarLayer : CALayer {
380     WebKit::PDFPlugin* _pdfPlugin;
381 }
382
383 @property (assign) WebKit::PDFPlugin* pdfPlugin;
384
385 @end
386
387 @implementation WKPDFPluginScrollbarLayer
388
389 @synthesize pdfPlugin=_pdfPlugin;
390
391 - (id)initWithPDFPlugin:(WebKit::PDFPlugin *)plugin
392 {
393     if (!(self = [super init]))
394         return nil;
395     
396     _pdfPlugin = plugin;
397     
398     return self;
399 }
400
401 - (id<CAAction>)actionForKey:(NSString *)key
402 {
403     return nil;
404 }
405
406 - (void)drawInContext:(CGContextRef)ctx
407 {
408     _pdfPlugin->paintControlForLayerInContext(self, ctx);
409 }
410
411 @end
412
413 @interface WKPDFLayerControllerDelegate : NSObject<PDFLayerControllerDelegate> {
414     WebKit::PDFPlugin* _pdfPlugin;
415 }
416
417 @property (assign) WebKit::PDFPlugin* pdfPlugin;
418
419 @end
420
421 @implementation WKPDFLayerControllerDelegate
422
423 @synthesize pdfPlugin=_pdfPlugin;
424
425 - (id)initWithPDFPlugin:(WebKit::PDFPlugin *)plugin
426 {
427     if (!(self = [super init]))
428         return nil;
429     
430     _pdfPlugin = plugin;
431     
432     return self;
433 }
434
435 - (void)updateScrollPosition:(CGPoint)newPosition
436 {
437     _pdfPlugin->notifyScrollPositionChanged(WebCore::IntPoint(newPosition));
438 }
439
440 - (void)writeItemsToPasteboard:(NSArray *)items withTypes:(NSArray *)types
441 {
442     ALLOW_DEPRECATED_DECLARATIONS_BEGIN
443     _pdfPlugin->writeItemsToPasteboard(NSGeneralPboard, items, types);
444     ALLOW_DEPRECATED_DECLARATIONS_END
445 }
446
447 - (void)showDefinitionForAttributedString:(NSAttributedString *)string atPoint:(CGPoint)point
448 {
449     _pdfPlugin->showDefinitionForAttributedString(string, point);
450 }
451
452 - (void)performWebSearch:(NSString *)string
453 {
454     _pdfPlugin->performWebSearch(string);
455 }
456
457 - (void)performSpotlightSearch:(NSString *)string
458 {
459     _pdfPlugin->performSpotlightSearch(string);
460 }
461
462 - (void)openWithNativeApplication
463 {
464     _pdfPlugin->openWithNativeApplication();
465 }
466
467 - (void)saveToPDF
468 {
469     _pdfPlugin->saveToPDF();
470 }
471
472 - (void)pdfLayerController:(PDFLayerController *)pdfLayerController clickedLinkWithURL:(NSURL *)url
473 {
474     _pdfPlugin->clickedLink(url);
475 }
476
477 - (void)pdfLayerController:(PDFLayerController *)pdfLayerController didChangeActiveAnnotation:(PDFAnnotation *)annotation
478 {
479     _pdfPlugin->setActiveAnnotation(annotation);
480 }
481
482 - (void)pdfLayerController:(PDFLayerController *)pdfLayerController didChangeContentScaleFactor:(CGFloat)scaleFactor
483 {
484     _pdfPlugin->notifyContentScaleFactorChanged(scaleFactor);
485 }
486
487 - (void)pdfLayerController:(PDFLayerController *)pdfLayerController didChangeDisplayMode:(int)mode
488 {
489     _pdfPlugin->notifyDisplayModeChanged(mode);
490 }
491
492 - (void)pdfLayerController:(PDFLayerController *)pdfLayerController didChangeSelection:(PDFSelection *)selection
493 {
494     _pdfPlugin->notifySelectionChanged(selection);
495 }
496
497 - (void)setMouseCursor:(PDFLayerControllerCursorType)cursorType
498 {
499     _pdfPlugin->notifyCursorChanged(cursorType);
500 }
501
502 - (void)didChangeAnnotationState
503 {
504     _pdfPlugin->didMutatePDFDocument();
505 }
506
507 @end
508
509 @interface PDFViewLayout
510 - (NSPoint)convertPoint:(NSPoint)point toPage:(PDFPage *)page forScaleFactor:(CGFloat)scaleFactor;
511 - (NSRect)convertRect:(NSRect)rect fromPage:(PDFPage *) page forScaleFactor:(CGFloat) scaleFactor;
512 - (PDFPage *)pageNearestPoint:(NSPoint)point currentPage:(PDFPage *)currentPage;
513 @end
514
515 namespace WebKit {
516 using namespace WebCore;
517 using namespace HTMLNames;
518
519 static const char* postScriptMIMEType = "application/postscript";
520 const uint64_t pdfDocumentRequestID = 1; // PluginController supports loading multiple streams, but we only need one for PDF.
521
522 static void appendValuesInPDFNameSubtreeToVector(CGPDFDictionaryRef subtree, Vector<CGPDFObjectRef>& values)
523 {
524     CGPDFArrayRef names;
525     if (CGPDFDictionaryGetArray(subtree, "Names", &names)) {
526         size_t nameCount = CGPDFArrayGetCount(names) / 2;
527         for (size_t i = 0; i < nameCount; ++i) {
528             CGPDFObjectRef object;
529             CGPDFArrayGetObject(names, 2 * i + 1, &object);
530             values.append(object);
531         }
532         return;
533     }
534
535     CGPDFArrayRef kids;
536     if (!CGPDFDictionaryGetArray(subtree, "Kids", &kids))
537         return;
538
539     size_t kidCount = CGPDFArrayGetCount(kids);
540     for (size_t i = 0; i < kidCount; ++i) {
541         CGPDFDictionaryRef kid;
542         if (!CGPDFArrayGetDictionary(kids, i, &kid))
543             continue;
544         appendValuesInPDFNameSubtreeToVector(kid, values);
545     }
546 }
547
548 static void getAllValuesInPDFNameTree(CGPDFDictionaryRef tree, Vector<CGPDFObjectRef>& allValues)
549 {
550     appendValuesInPDFNameSubtreeToVector(tree, allValues);
551 }
552
553 static void getAllScriptsInPDFDocument(CGPDFDocumentRef pdfDocument, Vector<RetainPtr<CFStringRef>>& scripts)
554 {
555     if (!pdfDocument)
556         return;
557
558     CGPDFDictionaryRef pdfCatalog = CGPDFDocumentGetCatalog(pdfDocument);
559     if (!pdfCatalog)
560         return;
561
562     // Get the dictionary of all document-level name trees.
563     CGPDFDictionaryRef namesDictionary;
564     if (!CGPDFDictionaryGetDictionary(pdfCatalog, "Names", &namesDictionary))
565         return;
566
567     // Get the document-level "JavaScript" name tree.
568     CGPDFDictionaryRef javaScriptNameTree;
569     if (!CGPDFDictionaryGetDictionary(namesDictionary, "JavaScript", &javaScriptNameTree))
570         return;
571
572     // The names are arbitrary. We are only interested in the values.
573     Vector<CGPDFObjectRef> objects;
574     getAllValuesInPDFNameTree(javaScriptNameTree, objects);
575     size_t objectCount = objects.size();
576
577     for (size_t i = 0; i < objectCount; ++i) {
578         CGPDFDictionaryRef javaScriptAction;
579         if (!CGPDFObjectGetValue(reinterpret_cast<CGPDFObjectRef>(objects[i]), kCGPDFObjectTypeDictionary, &javaScriptAction))
580             continue;
581
582         // A JavaScript action must have an action type of "JavaScript".
583         const char* actionType;
584         if (!CGPDFDictionaryGetName(javaScriptAction, "S", &actionType) || strcmp(actionType, "JavaScript"))
585             continue;
586
587         const UInt8* bytes = 0;
588         CFIndex length;
589         CGPDFStreamRef stream;
590         CGPDFStringRef string;
591         RetainPtr<CFDataRef> data;
592         if (CGPDFDictionaryGetStream(javaScriptAction, "JS", &stream)) {
593             CGPDFDataFormat format;
594             data = adoptCF(CGPDFStreamCopyData(stream, &format));
595             if (!data)
596                 continue;
597             bytes = CFDataGetBytePtr(data.get());
598             length = CFDataGetLength(data.get());
599         } else if (CGPDFDictionaryGetString(javaScriptAction, "JS", &string)) {
600             bytes = CGPDFStringGetBytePtr(string);
601             length = CGPDFStringGetLength(string);
602         }
603         if (!bytes)
604             continue;
605
606         CFStringEncoding encoding = (length > 1 && bytes[0] == 0xFE && bytes[1] == 0xFF) ? kCFStringEncodingUnicode : kCFStringEncodingUTF8;
607         RetainPtr<CFStringRef> script = adoptCF(CFStringCreateWithBytes(kCFAllocatorDefault, bytes, length, encoding, true));
608         if (!script)
609             continue;
610         
611         scripts.append(script);
612     }
613 }
614
615 Ref<PDFPlugin> PDFPlugin::create(WebFrame& frame)
616 {
617     return adoptRef(*new PDFPlugin(frame));
618 }
619
620 inline PDFPlugin::PDFPlugin(WebFrame& frame)
621     : Plugin(PDFPluginType)
622     , m_frame(&frame)
623     , m_containerLayer(adoptNS([[CALayer alloc] init]))
624     , m_contentLayer(adoptNS([[CALayer alloc] init]))
625     , m_scrollCornerLayer(adoptNS([[WKPDFPluginScrollbarLayer alloc] initWithPDFPlugin:this]))
626     , m_pdfLayerController(adoptNS([[pdfLayerControllerClass() alloc] init]))
627     , m_pdfLayerControllerDelegate(adoptNS([[WKPDFLayerControllerDelegate alloc] initWithPDFPlugin:this]))
628 {
629     m_pdfLayerController.get().delegate = m_pdfLayerControllerDelegate.get();
630     m_pdfLayerController.get().parentLayer = m_contentLayer.get();
631
632     if (supportsForms()) {
633         Document* document = webFrame()->coreFrame()->document();
634         m_annotationContainer = document->createElement(divTag, false);
635         m_annotationContainer->setAttributeWithoutSynchronization(idAttr, AtomicString("annotationContainer", AtomicString::ConstructFromLiteral));
636
637         auto annotationStyleElement = document->createElement(styleTag, false);
638         annotationStyleElement->setTextContent(annotationStyle);
639
640         m_annotationContainer->appendChild(annotationStyleElement);
641         document->bodyOrFrameset()->appendChild(*m_annotationContainer);
642     }
643
644     m_accessibilityObject = adoptNS([[WKPDFPluginAccessibilityObject alloc] initWithPDFPlugin:this]);
645     [m_accessibilityObject setPdfLayerController:m_pdfLayerController.get()];
646     [m_accessibilityObject setParent:webFrame()->page()->accessibilityRemoteObject()];
647
648     [m_containerLayer addSublayer:m_contentLayer.get()];
649     [m_containerLayer addSublayer:m_scrollCornerLayer.get()];
650 #if ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING)
651     if ([m_pdfLayerController respondsToSelector:@selector(setDeviceColorSpace:)]) {
652         auto view = webFrame()->coreFrame()->view();
653         [m_pdfLayerController setDeviceColorSpace:screenColorSpace(view)];
654     }
655 #endif
656 }
657
658 PDFPlugin::~PDFPlugin()
659 {
660 }
661
662 PluginInfo PDFPlugin::pluginInfo()
663 {
664     PluginInfo info;
665     info.name = builtInPDFPluginName();
666     info.isApplicationPlugin = true;
667     info.clientLoadPolicy = PluginLoadClientPolicyUndefined;
668     info.bundleIdentifier = "com.apple.webkit.builtinpdfplugin"_s;
669
670     MimeClassInfo pdfMimeClassInfo;
671     pdfMimeClassInfo.type = "application/pdf";
672     pdfMimeClassInfo.desc = pdfDocumentTypeDescription();
673     pdfMimeClassInfo.extensions.append("pdf");
674     info.mimes.append(pdfMimeClassInfo);
675
676     MimeClassInfo textPDFMimeClassInfo;
677     textPDFMimeClassInfo.type = "text/pdf";
678     textPDFMimeClassInfo.desc = pdfDocumentTypeDescription();
679     textPDFMimeClassInfo.extensions.append("pdf");
680     info.mimes.append(textPDFMimeClassInfo);
681
682     MimeClassInfo postScriptMimeClassInfo;
683     postScriptMimeClassInfo.type = postScriptMIMEType;
684     postScriptMimeClassInfo.desc = postScriptDocumentTypeDescription();
685     postScriptMimeClassInfo.extensions.append("ps");
686     info.mimes.append(postScriptMimeClassInfo);
687     
688     return info;
689 }
690
691 void PDFPlugin::updateScrollbars()
692 {
693     bool hadScrollbars = m_horizontalScrollbar || m_verticalScrollbar;
694
695     if (m_horizontalScrollbar) {
696         if (m_size.width() >= m_pdfDocumentSize.width())
697             destroyScrollbar(HorizontalScrollbar);
698     } else if (m_size.width() < m_pdfDocumentSize.width())
699         m_horizontalScrollbar = createScrollbar(HorizontalScrollbar);
700
701     if (m_verticalScrollbar) {
702         if (m_size.height() >= m_pdfDocumentSize.height())
703             destroyScrollbar(VerticalScrollbar);
704     } else if (m_size.height() < m_pdfDocumentSize.height())
705         m_verticalScrollbar = createScrollbar(VerticalScrollbar);
706
707     IntSize scrollbarSpace = scrollbarIntrusion();
708
709     if (m_horizontalScrollbar) {
710         m_horizontalScrollbar->setSteps(Scrollbar::pixelsPerLineStep(), m_firstPageHeight);
711         m_horizontalScrollbar->setProportion(m_size.width() - scrollbarSpace.width(), m_pdfDocumentSize.width());
712         IntRect scrollbarRect(pluginView()->x(), pluginView()->y() + m_size.height() - m_horizontalScrollbar->height(), m_size.width(), m_horizontalScrollbar->height());
713         if (m_verticalScrollbar)
714             scrollbarRect.contract(m_verticalScrollbar->width(), 0);
715         m_horizontalScrollbar->setFrameRect(scrollbarRect);
716     }
717
718     if (m_verticalScrollbar) {
719         m_verticalScrollbar->setSteps(Scrollbar::pixelsPerLineStep(), m_firstPageHeight);
720         m_verticalScrollbar->setProportion(m_size.height() - scrollbarSpace.height(), m_pdfDocumentSize.height());
721         IntRect scrollbarRect(IntRect(pluginView()->x() + m_size.width() - m_verticalScrollbar->width(), pluginView()->y(), m_verticalScrollbar->width(), m_size.height()));
722         if (m_horizontalScrollbar)
723             scrollbarRect.contract(0, m_horizontalScrollbar->height());
724         m_verticalScrollbar->setFrameRect(scrollbarRect);
725     }
726
727     FrameView* frameView = m_frame->coreFrame()->view();
728     if (!frameView)
729         return;
730
731     bool hasScrollbars = m_horizontalScrollbar || m_verticalScrollbar;
732     if (hadScrollbars != hasScrollbars) {
733         if (hasScrollbars)
734             frameView->addScrollableArea(this);
735         else
736             frameView->removeScrollableArea(this);
737
738         frameView->setNeedsLayoutAfterViewConfigurationChange();
739     }
740     
741     if (m_verticalScrollbarLayer) {
742         m_verticalScrollbarLayer.get().frame = verticalScrollbar()->frameRect();
743         [m_verticalScrollbarLayer setNeedsDisplay];
744     }
745     
746     if (m_horizontalScrollbarLayer) {
747         m_horizontalScrollbarLayer.get().frame = horizontalScrollbar()->frameRect();
748         [m_horizontalScrollbarLayer setNeedsDisplay];
749     }
750     
751     if (m_scrollCornerLayer) {
752         m_scrollCornerLayer.get().frame = scrollCornerRect();
753         [m_scrollCornerLayer setNeedsDisplay];
754     }
755 }
756
757 PluginView* PDFPlugin::pluginView()
758 {
759     return static_cast<PluginView*>(controller());
760 }
761
762 const PluginView* PDFPlugin::pluginView() const
763 {
764     return static_cast<const PluginView*>(controller());
765 }
766
767 Ref<Scrollbar> PDFPlugin::createScrollbar(ScrollbarOrientation orientation)
768 {
769     auto widget = Scrollbar::createNativeScrollbar(*this, orientation, RegularScrollbar);
770     if (orientation == HorizontalScrollbar) {
771         m_horizontalScrollbarLayer = adoptNS([[WKPDFPluginScrollbarLayer alloc] initWithPDFPlugin:this]);
772         [m_containerLayer addSublayer:m_horizontalScrollbarLayer.get()];
773     } else {
774         m_verticalScrollbarLayer = adoptNS([[WKPDFPluginScrollbarLayer alloc] initWithPDFPlugin:this]);
775         [m_containerLayer addSublayer:m_verticalScrollbarLayer.get()];
776     }
777     didAddScrollbar(widget.ptr(), orientation);
778     if (Frame* frame = webFrame()->coreFrame()) {
779         if (Page* page = frame->page()) {
780             if (page->expectsWheelEventTriggers())
781                 scrollAnimator().setWheelEventTestTrigger(page->testTrigger());
782         }
783     }
784     pluginView()->frame()->view()->addChild(widget);
785     return widget;
786 }
787
788 void PDFPlugin::destroyScrollbar(ScrollbarOrientation orientation)
789 {
790     RefPtr<Scrollbar>& scrollbar = orientation == HorizontalScrollbar ? m_horizontalScrollbar : m_verticalScrollbar;
791     if (!scrollbar)
792         return;
793
794     willRemoveScrollbar(scrollbar.get(), orientation);
795     scrollbar->removeFromParent();
796     scrollbar = nullptr;
797
798     if (orientation == HorizontalScrollbar) {
799         [m_horizontalScrollbarLayer removeFromSuperlayer];
800         m_horizontalScrollbarLayer = 0;
801     } else {
802         [m_verticalScrollbarLayer removeFromSuperlayer];
803         m_verticalScrollbarLayer = 0;
804     }
805 }
806
807 IntRect PDFPlugin::convertFromScrollbarToContainingView(const Scrollbar& scrollbar, const IntRect& scrollbarRect) const
808 {
809     IntRect rect = scrollbarRect;
810     rect.move(scrollbar.location() - pluginView()->location());
811
812     return pluginView()->frame()->view()->convertFromRendererToContainingView(pluginView()->pluginElement()->renderer(), rect);
813 }
814
815 IntRect PDFPlugin::convertFromContainingViewToScrollbar(const Scrollbar& scrollbar, const IntRect& parentRect) const
816 {
817     IntRect rect = pluginView()->frame()->view()->convertFromContainingViewToRenderer(pluginView()->pluginElement()->renderer(), parentRect);
818     rect.move(pluginView()->location() - scrollbar.location());
819
820     return rect;
821 }
822
823 IntPoint PDFPlugin::convertFromScrollbarToContainingView(const Scrollbar& scrollbar, const IntPoint& scrollbarPoint) const
824 {
825     IntPoint point = scrollbarPoint;
826     point.move(scrollbar.location() - pluginView()->location());
827
828     return pluginView()->frame()->view()->convertFromRendererToContainingView(pluginView()->pluginElement()->renderer(), point);
829 }
830
831 IntPoint PDFPlugin::convertFromContainingViewToScrollbar(const Scrollbar& scrollbar, const IntPoint& parentPoint) const
832 {
833     IntPoint point = pluginView()->frame()->view()->convertFromContainingViewToRenderer(pluginView()->pluginElement()->renderer(), parentPoint);
834     point.move(pluginView()->location() - scrollbar.location());
835     
836     return point;
837 }
838
839 bool PDFPlugin::handleScroll(ScrollDirection direction, ScrollGranularity granularity)
840 {
841     return scroll(direction, granularity);
842 }
843
844 IntRect PDFPlugin::scrollCornerRect() const
845 {
846     if (!m_horizontalScrollbar || !m_verticalScrollbar)
847         return IntRect();
848     if (m_horizontalScrollbar->isOverlayScrollbar()) {
849         ASSERT(m_verticalScrollbar->isOverlayScrollbar());
850         return IntRect();
851     }
852     return IntRect(pluginView()->width() - m_verticalScrollbar->width(), pluginView()->height() - m_horizontalScrollbar->height(), m_verticalScrollbar->width(), m_horizontalScrollbar->height());
853 }
854
855 ScrollableArea* PDFPlugin::enclosingScrollableArea() const
856 {
857     // FIXME: Walk up the frame tree and look for a scrollable parent frame or RenderLayer.
858     return nullptr;
859 }
860
861 IntRect PDFPlugin::scrollableAreaBoundingBox(bool*) const
862 {
863     return pluginView()->frameRect();
864 }
865
866 int PDFPlugin::scrollSize(ScrollbarOrientation orientation) const
867 {
868     Scrollbar* scrollbar = ((orientation == HorizontalScrollbar) ? m_horizontalScrollbar : m_verticalScrollbar).get();
869     return scrollbar ? (scrollbar->totalSize() - scrollbar->visibleSize()) : 0;
870 }
871
872 bool PDFPlugin::isActive() const
873 {
874     if (Frame* coreFrame = m_frame->coreFrame()) {
875         if (Page* page = coreFrame->page())
876             return page->focusController().isActive();
877     }
878
879     return false;
880 }
881
882 bool PDFPlugin::forceUpdateScrollbarsOnMainThreadForPerformanceTesting() const
883 {
884     if (Frame* coreFrame = m_frame->coreFrame()) {
885         if (Page* page = coreFrame->page())
886             return page->settings().forceUpdateScrollbarsOnMainThreadForPerformanceTesting();
887     }
888
889     return false;
890 }
891
892 int PDFPlugin::scrollOffset(ScrollbarOrientation orientation) const
893 {
894     if (orientation == HorizontalScrollbar)
895         return m_scrollOffset.width();
896
897     if (orientation == VerticalScrollbar)
898         return m_scrollOffset.height();
899
900     ASSERT_NOT_REACHED();
901     return 0;
902 }
903
904 ScrollPosition PDFPlugin::scrollPosition() const
905 {
906     return IntPoint(m_scrollOffset.width(), m_scrollOffset.height());
907 }
908
909 ScrollPosition PDFPlugin::minimumScrollPosition() const
910 {
911     return IntPoint();
912 }
913
914 ScrollPosition PDFPlugin::maximumScrollPosition() const
915 {
916     IntSize scrollbarSpace = scrollbarIntrusion();
917
918     IntPoint maximumOffset(m_pdfDocumentSize.width() - m_size.width() + scrollbarSpace.width(), m_pdfDocumentSize.height() - m_size.height() + scrollbarSpace.height());
919     maximumOffset.clampNegativeToZero();
920     return maximumOffset;
921 }
922
923 void PDFPlugin::scrollbarStyleChanged(ScrollbarStyle style, bool forceUpdate)
924 {
925     if (!forceUpdate)
926         return;
927
928     // If the PDF was scrolled all the way to bottom right and scrollbars change to overlay style, we don't want to display white rectangles where scrollbars were.
929     IntPoint newScrollOffset = IntPoint(m_scrollOffset).shrunkTo(maximumScrollPosition());
930     setScrollOffset(newScrollOffset);
931     
932     ScrollableArea::scrollbarStyleChanged(style, forceUpdate);
933     // As size of the content area changes, scrollbars may need to appear or to disappear.
934     updateScrollbars();
935 }
936
937 void PDFPlugin::addArchiveResource()
938 {
939     // FIXME: It's a hack to force add a resource to DocumentLoader. PDF documents should just be fetched as CachedResources.
940
941     // Add just enough data for context menu handling and web archives to work.
942     NSDictionary* headers = @{ @"Content-Disposition": (NSString *)m_suggestedFilename, @"Content-Type" : @"application/pdf" };
943     RetainPtr<NSURLResponse> response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:m_sourceURL statusCode:200 HTTPVersion:(NSString*)kCFHTTPVersion1_1 headerFields:headers]);
944     ResourceResponse synthesizedResponse(response.get());
945
946     auto resource = ArchiveResource::create(SharedBuffer::create(m_data.get()), m_sourceURL, "application/pdf", String(), String(), synthesizedResponse);
947     pluginView()->frame()->document()->loader()->addArchiveResource(resource.releaseNonNull());
948 }
949
950 static void jsPDFDocInitialize(JSContextRef ctx, JSObjectRef object)
951 {
952     PDFPlugin* pdfView = static_cast<PDFPlugin*>(JSObjectGetPrivate(object));
953     pdfView->ref();
954 }
955
956 static void jsPDFDocFinalize(JSObjectRef object)
957 {
958     PDFPlugin* pdfView = static_cast<PDFPlugin*>(JSObjectGetPrivate(object));
959     pdfView->deref();
960 }
961
962 JSValueRef PDFPlugin::jsPDFDocPrint(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
963 {
964     PDFPlugin* pdfView = static_cast<PDFPlugin*>(JSObjectGetPrivate(thisObject));
965
966     WebFrame* frame = pdfView->m_frame;
967     if (!frame)
968         return JSValueMakeUndefined(ctx);
969
970     Frame* coreFrame = frame->coreFrame();
971     if (!coreFrame)
972         return JSValueMakeUndefined(ctx);
973
974     Page* page = coreFrame->page();
975     if (!page)
976         return JSValueMakeUndefined(ctx);
977
978     page->chrome().print(*coreFrame);
979
980     return JSValueMakeUndefined(ctx);
981 }
982
983 JSObjectRef PDFPlugin::makeJSPDFDoc(JSContextRef ctx)
984 {
985     static JSStaticFunction jsPDFDocStaticFunctions[] = {
986         { "print", jsPDFDocPrint, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
987         { 0, 0, 0 },
988     };
989
990     static JSClassDefinition jsPDFDocClassDefinition = {
991         0,
992         kJSClassAttributeNone,
993         "Doc",
994         0,
995         0,
996         jsPDFDocStaticFunctions,
997         jsPDFDocInitialize, jsPDFDocFinalize, 0, 0, 0, 0, 0, 0, 0, 0, 0
998     };
999
1000     static JSClassRef jsPDFDocClass = JSClassCreate(&jsPDFDocClassDefinition);
1001
1002     return JSObjectMake(ctx, jsPDFDocClass, this);
1003 }
1004
1005 void PDFPlugin::convertPostScriptDataIfNeeded()
1006 {
1007     if (!m_isPostScript)
1008         return;
1009
1010     m_suggestedFilename = String(m_suggestedFilename + ".pdf");
1011     m_data = PDFDocumentImage::convertPostScriptDataToPDF(WTFMove(m_data));
1012 }
1013
1014 void PDFPlugin::pdfDocumentDidLoad()
1015 {
1016     addArchiveResource();
1017     
1018     RetainPtr<PDFDocument> document = adoptNS([[pdfDocumentClass() alloc] initWithData:rawData()]);
1019
1020     setPDFDocument(document);
1021
1022     updatePageAndDeviceScaleFactors();
1023
1024     [m_pdfLayerController setFrameSize:size()];
1025     m_pdfLayerController.get().document = document.get();
1026
1027     if (handlesPageScaleFactor())
1028         pluginView()->setPageScaleFactor([m_pdfLayerController contentScaleFactor], IntPoint());
1029
1030     notifyScrollPositionChanged(IntPoint([m_pdfLayerController scrollPosition]));
1031
1032     calculateSizes();
1033     updateScrollbars();
1034
1035     runScriptsInPDFDocument();
1036
1037     if ([document isLocked])
1038         createPasswordEntryForm();
1039
1040 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300
1041     if ([m_pdfLayerController respondsToSelector:@selector(setURLFragment:)]) {
1042         String pdfURLFragment = webFrame()->url().fragmentIdentifier();
1043         [m_pdfLayerController setURLFragment:pdfURLFragment];
1044     }
1045 #endif
1046 }
1047     
1048 void PDFPlugin::streamDidReceiveResponse(uint64_t streamID, const URL&, uint32_t, uint32_t, const String& mimeType, const String&, const String& suggestedFilename)
1049 {
1050     ASSERT_UNUSED(streamID, streamID == pdfDocumentRequestID);
1051
1052     m_suggestedFilename = suggestedFilename;
1053
1054     if (equalIgnoringASCIICase(mimeType, postScriptMIMEType))
1055         m_isPostScript = true;
1056 }
1057
1058 void PDFPlugin::streamDidReceiveData(uint64_t streamID, const char* bytes, int length)
1059 {
1060     ASSERT_UNUSED(streamID, streamID == pdfDocumentRequestID);
1061
1062     if (!m_data)
1063         m_data = adoptCF(CFDataCreateMutable(0, 0));
1064
1065     CFDataAppendBytes(m_data.get(), reinterpret_cast<const UInt8*>(bytes), length);
1066 }
1067
1068 void PDFPlugin::streamDidFinishLoading(uint64_t streamID)
1069 {
1070     ASSERT_UNUSED(streamID, streamID == pdfDocumentRequestID);
1071
1072     convertPostScriptDataIfNeeded();
1073     pdfDocumentDidLoad();
1074 }
1075
1076 void PDFPlugin::streamDidFail(uint64_t streamID, bool wasCancelled)
1077 {
1078     ASSERT_UNUSED(streamID, streamID == pdfDocumentRequestID);
1079
1080     m_data.clear();
1081 }
1082
1083 void PDFPlugin::manualStreamDidReceiveResponse(const URL& responseURL, uint32_t streamLength,  uint32_t lastModifiedTime, const String& mimeType, const String& headers, const String& suggestedFilename)
1084 {
1085     m_suggestedFilename = suggestedFilename;
1086
1087     if (equalIgnoringASCIICase(mimeType, postScriptMIMEType))
1088         m_isPostScript = true;
1089 }
1090
1091 void PDFPlugin::manualStreamDidReceiveData(const char* bytes, int length)
1092 {
1093     if (!m_data)
1094         m_data = adoptCF(CFDataCreateMutable(0, 0));
1095
1096     CFDataAppendBytes(m_data.get(), reinterpret_cast<const UInt8*>(bytes), length);
1097 }
1098
1099 void PDFPlugin::manualStreamDidFinishLoading()
1100 {
1101     convertPostScriptDataIfNeeded();
1102     pdfDocumentDidLoad();
1103 }
1104
1105 void PDFPlugin::manualStreamDidFail(bool)
1106 {
1107     m_data.clear();
1108 }
1109
1110 void PDFPlugin::runScriptsInPDFDocument()
1111 {
1112     Vector<RetainPtr<CFStringRef>> scripts;
1113     getAllScriptsInPDFDocument([m_pdfDocument documentRef], scripts);
1114
1115     if (scripts.isEmpty())
1116         return;
1117
1118     JSGlobalContextRef ctx = JSGlobalContextCreate(0);
1119     JSObjectRef jsPDFDoc = makeJSPDFDoc(ctx);
1120     for (auto& script : scripts)
1121         JSEvaluateScript(ctx, OpaqueJSString::tryCreate(script.get()).get(), jsPDFDoc, nullptr, 0, nullptr);
1122     JSGlobalContextRelease(ctx);
1123 }
1124
1125 void PDFPlugin::createPasswordEntryForm()
1126 {
1127     if (!supportsForms())
1128         return;
1129
1130     m_passwordField = PDFPluginPasswordField::create(m_pdfLayerController.get(), this);
1131     m_passwordField->attach(m_annotationContainer.get());
1132 }
1133
1134 void PDFPlugin::attemptToUnlockPDF(const String& password)
1135 {
1136     [m_pdfLayerController attemptToUnlockWithPassword:password];
1137
1138     if (![pdfDocument() isLocked]) {
1139         m_passwordField = nullptr;
1140
1141         calculateSizes();
1142         updateScrollbars();
1143     }
1144 }
1145
1146 void PDFPlugin::updatePageAndDeviceScaleFactors()
1147 {
1148     double newScaleFactor = controller()->contentsScaleFactor();
1149     if (!handlesPageScaleFactor())
1150         newScaleFactor *= webFrame()->page()->pageScaleFactor();
1151
1152     if (newScaleFactor != [m_pdfLayerController deviceScaleFactor])
1153         [m_pdfLayerController setDeviceScaleFactor:newScaleFactor];
1154 }
1155
1156 void PDFPlugin::contentsScaleFactorChanged(float)
1157 {
1158     updatePageAndDeviceScaleFactors();
1159 }
1160
1161 void PDFPlugin::calculateSizes()
1162 {
1163     if ([pdfDocument() isLocked]) {
1164         m_firstPageHeight = 0;
1165         setPDFDocumentSize(IntSize(0, 0));
1166         return;
1167     }
1168
1169     m_firstPageHeight = [m_pdfDocument pageCount] ? static_cast<unsigned>(CGCeiling([[m_pdfDocument pageAtIndex:0] boundsForBox:kPDFDisplayBoxCropBox].size.height)) : 0;
1170     setPDFDocumentSize(IntSize([m_pdfLayerController contentSizeRespectingZoom]));
1171 }
1172
1173 bool PDFPlugin::initialize(const Parameters& parameters)
1174 {
1175     m_sourceURL = parameters.url;
1176     if (!parameters.shouldUseManualLoader && !parameters.url.isEmpty())
1177         controller()->loadURL(pdfDocumentRequestID, "GET", parameters.url.string(), String(), HTTPHeaderMap(), Vector<uint8_t>(), false);
1178
1179     controller()->didInitializePlugin();
1180     return true;
1181 }
1182
1183 void PDFPlugin::willDetachRenderer()
1184 {
1185     if (webFrame()) {
1186         if (FrameView* frameView = webFrame()->coreFrame()->view())
1187             frameView->removeScrollableArea(this);
1188     }
1189 }
1190
1191 void PDFPlugin::destroy()
1192 {
1193     m_pdfLayerController.get().delegate = 0;
1194
1195     if (webFrame()) {
1196         if (FrameView* frameView = webFrame()->coreFrame()->view())
1197             frameView->removeScrollableArea(this);
1198     }
1199
1200     m_activeAnnotation = nullptr;
1201     m_annotationContainer = nullptr;
1202
1203     destroyScrollbar(HorizontalScrollbar);
1204     destroyScrollbar(VerticalScrollbar);
1205     
1206     [m_scrollCornerLayer removeFromSuperlayer];
1207     [m_contentLayer removeFromSuperlayer];
1208 }
1209
1210 void PDFPlugin::updateControlTints(GraphicsContext& graphicsContext)
1211 {
1212     ASSERT(graphicsContext.invalidatingControlTints());
1213
1214     if (m_horizontalScrollbar)
1215         m_horizontalScrollbar->invalidate();
1216     if (m_verticalScrollbar)
1217         m_verticalScrollbar->invalidate();
1218     invalidateScrollCorner(scrollCornerRect());
1219 }
1220
1221 void PDFPlugin::paintControlForLayerInContext(CALayer *layer, CGContextRef context)
1222 {
1223 #if PLATFORM(MAC)
1224     auto* page = webFrame()->coreFrame()->page();
1225     LocalDefaultSystemAppearance localAppearance(page->useDarkAppearance());
1226 #endif
1227
1228     GraphicsContext graphicsContext(context);
1229     GraphicsContextStateSaver stateSaver(graphicsContext);
1230
1231     graphicsContext.setIsCALayerContext(true);
1232
1233     if (layer == m_scrollCornerLayer) {
1234         IntRect scrollCornerRect = this->scrollCornerRect();
1235         graphicsContext.translate(-scrollCornerRect.x(), -scrollCornerRect.y());
1236         ScrollbarTheme::theme().paintScrollCorner(graphicsContext, scrollCornerRect);
1237         return;
1238     }
1239
1240     Scrollbar* scrollbar = nullptr;
1241
1242     if (layer == m_verticalScrollbarLayer)
1243         scrollbar = verticalScrollbar();
1244     else if (layer == m_horizontalScrollbarLayer)
1245         scrollbar = horizontalScrollbar();
1246
1247     if (!scrollbar)
1248         return;
1249
1250     graphicsContext.translate(-scrollbar->x(), -scrollbar->y());
1251     scrollbar->paint(graphicsContext, scrollbar->frameRect());
1252 }
1253
1254 RefPtr<ShareableBitmap> PDFPlugin::snapshot()
1255 {
1256     if (size().isEmpty())
1257         return nullptr;
1258
1259     float contentsScaleFactor = controller()->contentsScaleFactor();
1260     IntSize backingStoreSize = size();
1261     backingStoreSize.scale(contentsScaleFactor);
1262
1263     auto bitmap = ShareableBitmap::createShareable(backingStoreSize, { });
1264     auto context = bitmap->createGraphicsContext();
1265
1266     context->scale(FloatSize(contentsScaleFactor, -contentsScaleFactor));
1267     context->translate(-m_scrollOffset.width(), -m_pdfDocumentSize.height() + m_scrollOffset.height());
1268
1269     [m_pdfLayerController snapshotInContext:context->platformContext()];
1270
1271     return bitmap;
1272 }
1273
1274 PlatformLayer* PDFPlugin::pluginLayer()
1275 {
1276     return m_containerLayer.get();
1277 }
1278
1279 IntPoint PDFPlugin::convertFromPluginToPDFView(const IntPoint& point) const
1280 {
1281     return IntPoint(point.x(), size().height() - point.y());
1282 }
1283
1284 IntPoint PDFPlugin::convertFromRootViewToPlugin(const IntPoint& point) const
1285 {
1286     return m_rootViewToPluginTransform.mapPoint(point);
1287 }
1288
1289 IntPoint PDFPlugin::convertFromPDFViewToRootView(const IntPoint& point) const
1290 {
1291     IntPoint pointInPluginCoordinates(point.x(), size().height() - point.y());
1292     return m_rootViewToPluginTransform.inverse().valueOr(AffineTransform()).mapPoint(pointInPluginCoordinates);
1293 }
1294     
1295 IntPoint PDFPlugin::convertFromRootViewToPDFView(const IntPoint& point) const
1296 {
1297     IntPoint pointInPluginCoordinates = m_rootViewToPluginTransform.mapPoint(point);
1298     return IntPoint(pointInPluginCoordinates.x(), size().height() - pointInPluginCoordinates.y());
1299 }
1300
1301 FloatRect PDFPlugin::convertFromPDFViewToScreen(const FloatRect& rect) const
1302 {
1303     FrameView* frameView = webFrame()->coreFrame()->view();
1304
1305     if (!frameView)
1306         return FloatRect();
1307
1308     FloatRect updatedRect = rect;
1309     updatedRect.setLocation(convertFromPDFViewToRootView(IntPoint(updatedRect.location())));
1310     return webFrame()->coreFrame()->page()->chrome().rootViewToScreen(enclosingIntRect(updatedRect));
1311 }
1312
1313 IntRect PDFPlugin::boundsOnScreen() const
1314 {
1315     FrameView* frameView = webFrame()->coreFrame()->view();
1316
1317     if (!frameView)
1318         return IntRect();
1319
1320     FloatRect bounds = FloatRect(FloatPoint(), size());
1321     FloatRect rectInRootViewCoordinates = m_rootViewToPluginTransform.inverse().valueOr(AffineTransform()).mapRect(bounds);
1322     return frameView->contentsToScreen(enclosingIntRect(rectInRootViewCoordinates));
1323 }
1324
1325 void PDFPlugin::geometryDidChange(const IntSize& pluginSize, const IntRect&, const AffineTransform& pluginToRootViewTransform)
1326 {
1327     if (size() == pluginSize && pluginView()->pageScaleFactor() == [m_pdfLayerController contentScaleFactor])
1328         return;
1329
1330     m_size = pluginSize;
1331     m_rootViewToPluginTransform = pluginToRootViewTransform.inverse().valueOr(AffineTransform());
1332     [m_pdfLayerController setFrameSize:pluginSize];
1333
1334     [CATransaction begin];
1335     [CATransaction setDisableActions:YES];
1336     CATransform3D transform = CATransform3DMakeScale(1, -1, 1);
1337     transform = CATransform3DTranslate(transform, 0, -pluginSize.height(), 0);
1338     
1339     if (handlesPageScaleFactor()) {
1340         CGFloat magnification = pluginView()->pageScaleFactor() - [m_pdfLayerController contentScaleFactor];
1341
1342         // FIXME: Instead of m_lastMousePositionInPluginCoordinates, we should use the zoom origin from PluginView::setPageScaleFactor.
1343         if (magnification)
1344             [m_pdfLayerController magnifyWithMagnification:magnification atPoint:convertFromPluginToPDFView(m_lastMousePositionInPluginCoordinates) immediately:NO];
1345     } else {
1346         // If we don't handle page scale ourselves, we need to respect our parent page's
1347         // scale, which may have changed.
1348         updatePageAndDeviceScaleFactors();
1349     } 
1350
1351     calculateSizes();
1352     updateScrollbars();
1353
1354     if (m_activeAnnotation)
1355         m_activeAnnotation->updateGeometry();
1356
1357     [m_contentLayer setSublayerTransform:transform];
1358     [CATransaction commit];
1359 }
1360
1361 void PDFPlugin::frameDidFinishLoading(uint64_t)
1362 {
1363     ASSERT_NOT_REACHED();
1364 }
1365
1366 void PDFPlugin::frameDidFail(uint64_t, bool)
1367 {
1368     ASSERT_NOT_REACHED();
1369 }
1370
1371 void PDFPlugin::didEvaluateJavaScript(uint64_t, const WTF::String&)
1372 {
1373     ASSERT_NOT_REACHED();
1374 }
1375
1376     
1377 static NSUInteger modifierFlagsFromWebEvent(const WebEvent& event)
1378 {
1379     return (event.shiftKey() ? NSEventModifierFlagShift : 0)
1380         | (event.controlKey() ? NSEventModifierFlagControl : 0)
1381         | (event.altKey() ? NSEventModifierFlagOption : 0)
1382         | (event.metaKey() ? NSEventModifierFlagCommand : 0);
1383 }
1384     
1385 static bool getEventTypeFromWebEvent(const WebEvent& event, NSEventType& eventType)
1386 {
1387     switch (event.type()) {
1388     case WebEvent::KeyDown:
1389         eventType = NSEventTypeKeyDown;
1390         return true;
1391     case WebEvent::KeyUp:
1392         eventType = NSEventTypeKeyUp;
1393         return true;
1394     case WebEvent::MouseDown:
1395         switch (static_cast<const WebMouseEvent&>(event).button()) {
1396         case WebMouseEvent::LeftButton:
1397             eventType = NSEventTypeLeftMouseDown;
1398             return true;
1399         case WebMouseEvent::RightButton:
1400             eventType = NSEventTypeRightMouseDown;
1401             return true;
1402         default:
1403             return false;
1404         }
1405     case WebEvent::MouseUp:
1406         switch (static_cast<const WebMouseEvent&>(event).button()) {
1407         case WebMouseEvent::LeftButton:
1408             eventType = NSEventTypeLeftMouseUp;
1409             return true;
1410         case WebMouseEvent::RightButton:
1411             eventType = NSEventTypeRightMouseUp;
1412             return true;
1413         default:
1414             return false;
1415         }
1416     case WebEvent::MouseMove:
1417         switch (static_cast<const WebMouseEvent&>(event).button()) {
1418         case WebMouseEvent::LeftButton:
1419             eventType = NSEventTypeLeftMouseDragged;
1420             return true;
1421         case WebMouseEvent::RightButton:
1422             eventType = NSEventTypeRightMouseDragged;
1423             return true;
1424         case WebMouseEvent::NoButton:
1425             eventType = NSEventTypeMouseMoved;
1426             return true;
1427         default:
1428             return false;
1429         }
1430     default:
1431         return false;
1432     }
1433 }
1434     
1435 NSEvent *PDFPlugin::nsEventForWebMouseEvent(const WebMouseEvent& event)
1436 {
1437     m_lastMousePositionInPluginCoordinates = convertFromRootViewToPlugin(event.position());
1438
1439     IntPoint positionInPDFViewCoordinates(convertFromPluginToPDFView(m_lastMousePositionInPluginCoordinates));
1440
1441     NSEventType eventType;
1442
1443     if (!getEventTypeFromWebEvent(event, eventType))
1444         return 0;
1445
1446     NSUInteger modifierFlags = modifierFlagsFromWebEvent(event);
1447
1448     return [NSEvent mouseEventWithType:eventType location:positionInPDFViewCoordinates modifierFlags:modifierFlags timestamp:0 windowNumber:0 context:nil eventNumber:0 clickCount:event.clickCount() pressure:0];
1449 }
1450
1451 #if __MAC_OS_X_VERSION_MIN_REQUIRED < 101300
1452 void PDFPlugin::updateCursor(const WebMouseEvent& event, UpdateCursorMode mode)
1453 {
1454     HitTestResult hitTestResult = None;
1455
1456     PDFSelection *selectionUnderMouse = [m_pdfLayerController getSelectionForWordAtPoint:convertFromPluginToPDFView(event.position())];
1457     if (selectionUnderMouse && [[selectionUnderMouse string] length])
1458         hitTestResult = Text;
1459
1460     if (hitTestResult == m_lastHitTestResult && mode == UpdateIfNeeded)
1461         return;
1462
1463     webFrame()->page()->send(Messages::WebPageProxy::SetCursor(hitTestResult == Text ? WebCore::iBeamCursor() : WebCore::pointerCursor()));
1464     m_lastHitTestResult = hitTestResult;
1465 }
1466 #endif
1467
1468 bool PDFPlugin::handleMouseEvent(const WebMouseEvent& event)
1469 {
1470     PlatformMouseEvent platformEvent = platform(event);
1471     IntPoint mousePosition = convertFromRootViewToPlugin(event.position());
1472
1473     m_lastMouseEvent = event;
1474
1475     RefPtr<Scrollbar> targetScrollbar;
1476     RefPtr<Scrollbar> targetScrollbarForLastMousePosition;
1477
1478     if (m_verticalScrollbarLayer) {
1479         IntRect verticalScrollbarFrame(m_verticalScrollbarLayer.get().frame);
1480         if (verticalScrollbarFrame.contains(mousePosition))
1481             targetScrollbar = verticalScrollbar();
1482         if (verticalScrollbarFrame.contains(m_lastMousePositionInPluginCoordinates))
1483             targetScrollbarForLastMousePosition = verticalScrollbar();
1484     }
1485
1486     if (m_horizontalScrollbarLayer) {
1487         IntRect horizontalScrollbarFrame(m_horizontalScrollbarLayer.get().frame);
1488         if (horizontalScrollbarFrame.contains(mousePosition))
1489             targetScrollbar = horizontalScrollbar();
1490         if (horizontalScrollbarFrame.contains(m_lastMousePositionInPluginCoordinates))
1491             targetScrollbarForLastMousePosition = horizontalScrollbar();
1492     }
1493
1494     if (m_scrollCornerLayer && IntRect(m_scrollCornerLayer.get().frame).contains(mousePosition))
1495         return false;
1496
1497     if ([pdfDocument() isLocked])
1498         return false;
1499
1500     // Right-clicks and Control-clicks always call handleContextMenuEvent as well.
1501     if (event.button() == WebMouseEvent::RightButton || (event.button() == WebMouseEvent::LeftButton && event.controlKey()))
1502         return true;
1503
1504     NSEvent *nsEvent = nsEventForWebMouseEvent(event);
1505
1506     switch (event.type()) {
1507     case WebEvent::MouseMove:
1508         mouseMovedInContentArea();
1509 #if __MAC_OS_X_VERSION_MIN_REQUIRED < 101300
1510         updateCursor(event);
1511 #endif
1512
1513         if (targetScrollbar) {
1514             if (!targetScrollbarForLastMousePosition) {
1515                 targetScrollbar->mouseEntered();
1516                 return true;
1517             }
1518             return targetScrollbar->mouseMoved(platformEvent);
1519         }
1520
1521         if (!targetScrollbar && targetScrollbarForLastMousePosition)
1522             targetScrollbarForLastMousePosition->mouseExited();
1523
1524         switch (event.button()) {
1525         case WebMouseEvent::LeftButton:
1526             [m_pdfLayerController mouseDragged:nsEvent];
1527             return true;
1528         case WebMouseEvent::RightButton:
1529         case WebMouseEvent::MiddleButton:
1530             return false;
1531         case WebMouseEvent::NoButton:
1532             [m_pdfLayerController mouseMoved:nsEvent];
1533             return true;
1534         }
1535         break;
1536     case WebEvent::MouseDown:
1537         switch (event.button()) {
1538         case WebMouseEvent::LeftButton:
1539             if (targetScrollbar)
1540                 return targetScrollbar->mouseDown(platformEvent);
1541
1542             [m_pdfLayerController mouseDown:nsEvent];
1543             return true;
1544         case WebMouseEvent::RightButton:
1545             [m_pdfLayerController rightMouseDown:nsEvent];
1546             return true;
1547         case WebMouseEvent::MiddleButton:
1548         case WebMouseEvent::NoButton:
1549             return false;
1550         }
1551         break;
1552     case WebEvent::MouseUp:
1553         switch (event.button()) {
1554         case WebMouseEvent::LeftButton:
1555             if (targetScrollbar)
1556                 return targetScrollbar->mouseUp(platformEvent);
1557
1558             [m_pdfLayerController mouseUp:nsEvent];
1559             return true;
1560         case WebMouseEvent::RightButton:
1561         case WebMouseEvent::MiddleButton:
1562         case WebMouseEvent::NoButton:
1563             return false;
1564         }
1565         break;
1566     default:
1567         break;
1568     }
1569
1570     return false;
1571 }
1572
1573 bool PDFPlugin::handleMouseEnterEvent(const WebMouseEvent& event)
1574 {
1575     mouseEnteredContentArea();
1576 #if __MAC_OS_X_VERSION_MIN_REQUIRED < 101300
1577     updateCursor(event, ForceUpdate);
1578 #endif
1579     return false;
1580 }
1581
1582 bool PDFPlugin::handleMouseLeaveEvent(const WebMouseEvent&)
1583 {
1584     mouseExitedContentArea();
1585     return false;
1586 }
1587     
1588 bool PDFPlugin::showContextMenuAtPoint(const IntPoint& point)
1589 {
1590     FrameView* frameView = webFrame()->coreFrame()->view();
1591     IntPoint contentsPoint = frameView->contentsToRootView(point);
1592     WebMouseEvent event(WebEvent::MouseDown, WebMouseEvent::RightButton, 0, contentsPoint, contentsPoint, 0, 0, 0, 1, OptionSet<WebEvent::Modifier> { }, WallTime::now(), WebCore::ForceAtClick);
1593     return handleContextMenuEvent(event);
1594 }
1595
1596 bool PDFPlugin::handleContextMenuEvent(const WebMouseEvent& event)
1597 {
1598     if (!webFrame()->page())
1599         return false;
1600
1601     WebPage* webPage = webFrame()->page();
1602     FrameView* frameView = webFrame()->coreFrame()->view();
1603     IntPoint point = frameView->contentsToScreen(IntRect(frameView->windowToContents(event.position()), IntSize())).location();
1604
1605 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300
1606     NSUserInterfaceLayoutDirection uiLayoutDirection = webPage->userInterfaceLayoutDirection() == UserInterfaceLayoutDirection::LTR ? NSUserInterfaceLayoutDirectionLeftToRight : NSUserInterfaceLayoutDirectionRightToLeft;
1607     NSMenu *nsMenu = [m_pdfLayerController menuForEvent:nsEventForWebMouseEvent(event) withUserInterfaceLayoutDirection:uiLayoutDirection];
1608 #else
1609     NSMenu *nsMenu = [m_pdfLayerController menuForEvent:nsEventForWebMouseEvent(event)];
1610 #endif
1611
1612     if (!nsMenu)
1613         return false;
1614     
1615     Vector<PDFContextMenuItem> items;
1616     auto itemCount = [nsMenu numberOfItems];
1617     for (int i = 0; i < itemCount; i++) {
1618         auto item = [nsMenu itemAtIndex:i];
1619         if ([item submenu])
1620             continue;
1621         PDFContextMenuItem menuItem { String([item title]), !![item isEnabled], !![item isSeparatorItem], static_cast<int>([item state]), [item action], i };
1622         items.append(WTFMove(menuItem));
1623     }
1624     PDFContextMenu contextMenu { point, WTFMove(items) };
1625
1626     Optional<int> selectedIndex = -1;
1627     webPage->sendSync(Messages::WebPageProxy::ShowPDFContextMenu(contextMenu), Messages::WebPageProxy::ShowPDFContextMenu::Reply(selectedIndex));
1628
1629     if (selectedIndex && *selectedIndex >= 0 && *selectedIndex < itemCount)
1630         [nsMenu performActionForItemAtIndex:*selectedIndex];
1631
1632     return true;
1633 }
1634
1635 bool PDFPlugin::handleKeyboardEvent(const WebKeyboardEvent& event)
1636 {
1637     NSEventType eventType;
1638
1639     if (!getEventTypeFromWebEvent(event, eventType))
1640         return false;
1641
1642     NSUInteger modifierFlags = modifierFlagsFromWebEvent(event);
1643     
1644     NSEvent *fakeEvent = [NSEvent keyEventWithType:eventType location:NSZeroPoint modifierFlags:modifierFlags timestamp:0 windowNumber:0 context:0 characters:event.text() charactersIgnoringModifiers:event.unmodifiedText() isARepeat:event.isAutoRepeat() keyCode:event.nativeVirtualKeyCode()];
1645     
1646     switch (event.type()) {
1647     case WebEvent::KeyDown:
1648         return [m_pdfLayerController keyDown:fakeEvent];
1649     default:
1650         return false;
1651     }
1652     
1653     return false;
1654 }
1655     
1656 bool PDFPlugin::handleEditingCommand(const String& commandName, const String& argument)
1657 {
1658     if (commandName == "copy")
1659         [m_pdfLayerController copySelection];
1660     else if (commandName == "selectAll")
1661         [m_pdfLayerController selectAll];
1662     else if (commandName == "takeFindStringFromSelection") {
1663         NSString *string = [m_pdfLayerController currentSelection].string;
1664         ALLOW_DEPRECATED_DECLARATIONS_BEGIN
1665         if (string.length)
1666             writeItemsToPasteboard(NSFindPboard, @[ [string dataUsingEncoding:NSUTF8StringEncoding] ], @[ NSPasteboardTypeString ]);
1667         ALLOW_DEPRECATED_DECLARATIONS_END
1668     }
1669
1670     return true;
1671 }
1672
1673 bool PDFPlugin::isEditingCommandEnabled(const String& commandName)
1674 {
1675     if (commandName == "copy" || commandName == "takeFindStringFromSelection")
1676         return [m_pdfLayerController currentSelection];
1677
1678     if (commandName == "selectAll")
1679         return true;
1680
1681     return false;
1682 }
1683
1684 void PDFPlugin::setScrollOffset(const ScrollOffset& offset)
1685 {
1686     m_scrollOffset = IntSize(offset.x(), offset.y());
1687
1688     [CATransaction begin];
1689     [m_pdfLayerController setScrollPosition:offset];
1690
1691     if (m_activeAnnotation)
1692         m_activeAnnotation->updateGeometry();
1693
1694     [CATransaction commit];
1695 }
1696
1697 void PDFPlugin::invalidateScrollbarRect(Scrollbar& scrollbar, const IntRect& rect)
1698 {
1699     if (&scrollbar == horizontalScrollbar())
1700         [m_horizontalScrollbarLayer setNeedsDisplay];
1701     else if (&scrollbar == verticalScrollbar())
1702         [m_verticalScrollbarLayer setNeedsDisplay];
1703 }
1704
1705 void PDFPlugin::invalidateScrollCornerRect(const IntRect& rect)
1706 {
1707     [m_scrollCornerLayer setNeedsDisplay];
1708 }
1709
1710 bool PDFPlugin::isFullFramePlugin() const
1711 {
1712     // <object> or <embed> plugins will appear to be in their parent frame, so we have to
1713     // check whether our frame's widget is exactly our PluginView.
1714     Document* document = webFrame()->coreFrame()->document();
1715     return document->isPluginDocument() && static_cast<PluginDocument*>(document)->pluginWidget() == pluginView();
1716 }
1717
1718 bool PDFPlugin::handlesPageScaleFactor() const
1719 {
1720     return webFrame()->isMainFrame() && isFullFramePlugin();
1721 }
1722
1723 void PDFPlugin::clickedLink(NSURL *url)
1724 {
1725     URL coreURL = url;
1726     if (WTF::protocolIsJavaScript(coreURL))
1727         return;
1728
1729     Frame* frame = webFrame()->coreFrame();
1730
1731     RefPtr<Event> coreEvent;
1732     if (m_lastMouseEvent.type() != WebEvent::NoType)
1733         coreEvent = MouseEvent::create(eventNames().clickEvent, &frame->windowProxy(), platform(m_lastMouseEvent), 0, 0);
1734
1735     frame->loader().urlSelected(coreURL, emptyString(), coreEvent.get(), LockHistory::No, LockBackForwardList::No, NeverSendReferrer, ShouldOpenExternalURLsPolicy::ShouldAllow);
1736 }
1737
1738 void PDFPlugin::setActiveAnnotation(PDFAnnotation *annotation)
1739 {
1740     if (!supportsForms())
1741         return;
1742
1743     if (m_activeAnnotation)
1744         m_activeAnnotation->commit();
1745
1746     if (annotation) {
1747         ALLOW_DEPRECATED_DECLARATIONS_BEGIN
1748         if ([annotation isKindOfClass:pdfAnnotationTextWidgetClass()] && static_cast<PDFAnnotationTextWidget *>(annotation).isReadOnly) {
1749             m_activeAnnotation = nullptr;
1750             return;
1751         }
1752         ALLOW_DEPRECATED_DECLARATIONS_END
1753
1754         m_activeAnnotation = PDFPluginAnnotation::create(annotation, m_pdfLayerController.get(), this);
1755         m_activeAnnotation->attach(m_annotationContainer.get());
1756     } else
1757         m_activeAnnotation = nullptr;
1758 }
1759
1760 bool PDFPlugin::supportsForms()
1761 {
1762     // FIXME: We support forms for full-main-frame and <iframe> PDFs, but not <embed> or <object>, because those cases do not have their own Document into which to inject form elements.
1763     return isFullFramePlugin();
1764 }
1765
1766 void PDFPlugin::notifyContentScaleFactorChanged(CGFloat scaleFactor)
1767 {
1768     if (handlesPageScaleFactor())
1769         pluginView()->setPageScaleFactor(scaleFactor, IntPoint());
1770
1771     calculateSizes();
1772     updateScrollbars();
1773 }
1774
1775 void PDFPlugin::notifyDisplayModeChanged(int)
1776 {
1777     calculateSizes();
1778     updateScrollbars();
1779 }
1780
1781 RefPtr<SharedBuffer> PDFPlugin::liveResourceData() const
1782 {
1783     NSData *pdfData = liveData();
1784
1785     if (!pdfData)
1786         return nullptr;
1787
1788     return SharedBuffer::create(pdfData);
1789 }
1790
1791 bool PDFPlugin::pluginHandlesContentOffsetForAccessibilityHitTest() const
1792 {
1793     // The PDF plugin handles the scroll view offset natively as part of the layer conversions.
1794 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300
1795     return true;
1796 #else
1797     return false;
1798 #endif
1799 }
1800
1801     
1802 void PDFPlugin::saveToPDF()
1803 {
1804     // FIXME: We should probably notify the user that they can't save before the document is finished loading.
1805     // PDFViewController does an NSBeep(), but that seems insufficient.
1806     if (!pdfDocument())
1807         return;
1808
1809     NSData *data = liveData();
1810     webFrame()->page()->savePDFToFileInDownloadsFolder(m_suggestedFilename, webFrame()->url(), static_cast<const unsigned char *>([data bytes]), [data length]);
1811 }
1812
1813 void PDFPlugin::openWithNativeApplication()
1814 {
1815     if (!m_temporaryPDFUUID) {
1816         // FIXME: We should probably notify the user that they can't save before the document is finished loading.
1817         // PDFViewController does an NSBeep(), but that seems insufficient.
1818         if (!pdfDocument())
1819             return;
1820
1821         NSData *data = liveData();
1822
1823         m_temporaryPDFUUID = createCanonicalUUIDString();
1824         ASSERT(m_temporaryPDFUUID);
1825
1826         webFrame()->page()->savePDFToTemporaryFolderAndOpenWithNativeApplication(m_suggestedFilename, webFrame()->url(), static_cast<const unsigned char *>([data bytes]), [data length], m_temporaryPDFUUID);
1827         return;
1828     }
1829
1830     webFrame()->page()->send(Messages::WebPageProxy::OpenPDFFromTemporaryFolderWithNativeApplication(m_temporaryPDFUUID));
1831 }
1832
1833 void PDFPlugin::writeItemsToPasteboard(NSString *pasteboardName, NSArray *items, NSArray *types)
1834 {
1835     Vector<String> pasteboardTypes;
1836
1837     for (NSString *type in types)
1838         pasteboardTypes.append(type);
1839
1840     uint64_t newChangeCount;
1841     auto& webProcess = WebProcess::singleton();
1842     webProcess.parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::SetPasteboardTypes(pasteboardName, pasteboardTypes),
1843         Messages::WebPasteboardProxy::SetPasteboardTypes::Reply(newChangeCount), 0);
1844
1845     for (NSUInteger i = 0, count = items.count; i < count; ++i) {
1846         NSString *type = [types objectAtIndex:i];
1847         NSData *data = [items objectAtIndex:i];
1848
1849         // We don't expect the data for any items to be empty, but aren't completely sure.
1850         // Avoid crashing in the SharedMemory constructor in release builds if we're wrong.
1851         ASSERT(data.length);
1852         if (!data.length)
1853             continue;
1854
1855         if ([type isEqualToString:legacyStringPasteboardType()] || [type isEqualToString:NSPasteboardTypeString]) {
1856             RetainPtr<NSString> plainTextString = adoptNS([[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
1857             webProcess.parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::SetPasteboardStringForType(pasteboardName, type, plainTextString.get()), Messages::WebPasteboardProxy::SetPasteboardStringForType::Reply(newChangeCount), 0);
1858         } else {
1859             auto buffer = SharedBuffer::create(data);
1860             SharedMemory::Handle handle;
1861             RefPtr<SharedMemory> sharedMemory = SharedMemory::allocate(buffer->size());
1862             memcpy(sharedMemory->data(), buffer->data(), buffer->size());
1863             sharedMemory->createHandle(handle, SharedMemory::Protection::ReadOnly);
1864             webProcess.parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::SetPasteboardBufferForType(pasteboardName, type, handle, buffer->size()), Messages::WebPasteboardProxy::SetPasteboardBufferForType::Reply(newChangeCount), 0);
1865         }
1866     }
1867 }
1868
1869 void PDFPlugin::showDefinitionForAttributedString(NSAttributedString *string, CGPoint point)
1870 {
1871     DictionaryPopupInfo dictionaryPopupInfo;
1872     dictionaryPopupInfo.origin = convertFromPDFViewToRootView(IntPoint(point));
1873     dictionaryPopupInfo.attributedString = string;
1874     
1875     
1876     NSRect rangeRect;
1877     rangeRect.origin = NSMakePoint(point.x, point.y);
1878     CGFloat scaleFactor = PDFPlugin::scaleFactor();
1879
1880     rangeRect.size.height = string.size.height * scaleFactor;
1881     rangeRect.size.width = string.size.width * scaleFactor;
1882
1883     rangeRect.origin.y -= rangeRect.size.height;
1884
1885     TextIndicatorData dataForSelection;
1886     dataForSelection.selectionRectInRootViewCoordinates = rangeRect;
1887     dataForSelection.textBoundingRectInRootViewCoordinates = rangeRect;
1888     dataForSelection.contentImageScaleFactor = scaleFactor;
1889     dataForSelection.presentationTransition = TextIndicatorPresentationTransition::FadeIn;
1890     dictionaryPopupInfo.textIndicator = dataForSelection;
1891     
1892     webFrame()->page()->send(Messages::WebPageProxy::DidPerformDictionaryLookup(dictionaryPopupInfo));
1893 }
1894
1895 unsigned PDFPlugin::countFindMatches(const String& target, WebCore::FindOptions options, unsigned /*maxMatchCount*/)
1896 {
1897     // FIXME: Why is it OK to ignore the passed-in maximum match count?
1898
1899     if (!target.length())
1900         return 0;
1901
1902     NSStringCompareOptions nsOptions = options.contains(WebCore::CaseInsensitive) ? NSCaseInsensitiveSearch : 0;
1903     return [[pdfDocument() findString:target withOptions:nsOptions] count];
1904 }
1905
1906 PDFSelection *PDFPlugin::nextMatchForString(const String& target, BOOL searchForward, BOOL caseSensitive, BOOL wrapSearch, PDFSelection *initialSelection, BOOL startInSelection)
1907 {
1908     if (!target.length())
1909         return nil;
1910
1911     NSStringCompareOptions options = 0;
1912     if (!searchForward)
1913         options |= NSBackwardsSearch;
1914     if (!caseSensitive)
1915         options |= NSCaseInsensitiveSearch;
1916
1917     PDFDocument *document = pdfDocument().get();
1918
1919     RetainPtr<PDFSelection> selectionForInitialSearch = adoptNS([initialSelection copy]);
1920     if (startInSelection) {
1921         // Initially we want to include the selected text in the search. So we must modify the starting search
1922         // selection to fit PDFDocument's search requirements: selection must have a length >= 1, begin before
1923         // the current selection (if searching forwards) or after (if searching backwards).
1924         int initialSelectionLength = [[initialSelection string] length];
1925         if (searchForward) {
1926             [selectionForInitialSearch extendSelectionAtStart:1];
1927             [selectionForInitialSearch extendSelectionAtEnd:-initialSelectionLength];
1928         } else {
1929             [selectionForInitialSearch extendSelectionAtEnd:1];
1930             [selectionForInitialSearch extendSelectionAtStart:-initialSelectionLength];
1931         }
1932     }
1933
1934     PDFSelection *foundSelection = [document findString:target fromSelection:selectionForInitialSearch.get() withOptions:options];
1935
1936     // If we first searched in the selection, and we found the selection, search again from just past the selection.
1937     if (startInSelection && [foundSelection isEqual:initialSelection])
1938         foundSelection = [document findString:target fromSelection:initialSelection withOptions:options];
1939
1940     if (!foundSelection && wrapSearch) {
1941         auto emptySelection = adoptNS([[pdfSelectionClass() alloc] initWithDocument:document]);
1942         foundSelection = [document findString:target fromSelection:emptySelection.get() withOptions:options];
1943     }
1944
1945     return foundSelection;
1946 }
1947
1948 bool PDFPlugin::findString(const String& target, WebCore::FindOptions options, unsigned maxMatchCount)
1949 {
1950     bool searchForward = !options.contains(WebCore::Backwards);
1951     bool caseSensitive = !options.contains(WebCore::CaseInsensitive);
1952     bool wrapSearch = options.contains(WebCore::WrapAround);
1953
1954     // If the max was zero, any result means we exceeded the max, so we can skip computing the actual count.
1955     // FIXME: How can always returning true without searching if passed a max of 0 be right?
1956     // Even if it is right, why not put that special case inside countFindMatches instead of here?
1957     bool foundMatch = !maxMatchCount || countFindMatches(target, options, maxMatchCount);
1958
1959     if (target.isEmpty()) {
1960         auto searchSelection = [m_pdfLayerController searchSelection];
1961         [m_pdfLayerController findString:target caseSensitive:caseSensitive highlightMatches:YES];
1962         [m_pdfLayerController setSearchSelection:searchSelection];
1963         m_lastFoundString = emptyString();
1964         return false;
1965     }
1966
1967     if (m_lastFoundString == target) {
1968         auto selection = nextMatchForString(target, searchForward, caseSensitive, wrapSearch, [m_pdfLayerController searchSelection], NO);
1969         if (!selection)
1970             return false;
1971         [m_pdfLayerController setSearchSelection:selection];
1972         [m_pdfLayerController gotoSelection:selection];
1973     } else {
1974         [m_pdfLayerController findString:target caseSensitive:caseSensitive highlightMatches:YES];
1975         m_lastFoundString = target;
1976     }
1977
1978     return foundMatch;
1979 }
1980
1981 bool PDFPlugin::performDictionaryLookupAtLocation(const WebCore::FloatPoint& point)
1982 {
1983     IntPoint localPoint = convertFromRootViewToPlugin(roundedIntPoint(point));
1984     PDFSelection* lookupSelection = [m_pdfLayerController getSelectionForWordAtPoint:convertFromPluginToPDFView(localPoint)];
1985     if ([[lookupSelection string] length])
1986         [m_pdfLayerController searchInDictionaryWithSelection:lookupSelection];
1987     return true;
1988 }
1989
1990 void PDFPlugin::focusNextAnnotation()
1991 {
1992     [m_pdfLayerController activateNextAnnotation:false];
1993 }
1994
1995 void PDFPlugin::focusPreviousAnnotation()
1996 {
1997     [m_pdfLayerController activateNextAnnotation:true];
1998 }
1999
2000 void PDFPlugin::notifySelectionChanged(PDFSelection *)
2001 {
2002     webFrame()->page()->didChangeSelection();
2003 }
2004
2005 static const WebCore::Cursor& coreCursor(PDFLayerControllerCursorType type)
2006 {
2007     switch (type) {
2008     case kPDFLayerControllerCursorTypeHand:
2009         return WebCore::handCursor();
2010     case kPDFLayerControllerCursorTypeIBeam:
2011         return WebCore::iBeamCursor();
2012     case kPDFLayerControllerCursorTypePointer:
2013     default:
2014         return WebCore::pointerCursor();
2015     }
2016 }
2017
2018 void PDFPlugin::notifyCursorChanged(uint64_t type)
2019 {
2020     webFrame()->page()->send(Messages::WebPageProxy::SetCursor(coreCursor(static_cast<PDFLayerControllerCursorType>(type))));
2021 }
2022
2023 String PDFPlugin::getSelectionString() const
2024 {
2025     return [[m_pdfLayerController currentSelection] string];
2026 }
2027
2028 String PDFPlugin::getSelectionForWordAtPoint(const WebCore::FloatPoint& point) const
2029 {
2030     IntPoint pointInView = convertFromPluginToPDFView(convertFromRootViewToPlugin(roundedIntPoint(point)));
2031     PDFSelection *selectionForWord = [m_pdfLayerController getSelectionForWordAtPoint:pointInView];
2032     [m_pdfLayerController setCurrentSelection:selectionForWord];
2033     return [selectionForWord string];
2034 }
2035
2036 bool PDFPlugin::existingSelectionContainsPoint(const WebCore::FloatPoint& locationInViewCoordinates) const
2037 {
2038     PDFSelection *currentSelection = [m_pdfLayerController currentSelection];
2039     if (!currentSelection)
2040         return false;
2041     
2042     IntPoint pointInPDFView = convertFromPluginToPDFView(convertFromRootViewToPlugin(roundedIntPoint(locationInViewCoordinates)));
2043     PDFSelection *selectionForWord = [m_pdfLayerController getSelectionForWordAtPoint:pointInPDFView];
2044
2045     NSUInteger currentPageIndex = [m_pdfLayerController currentPageIndex];
2046     
2047     NSArray *selectionRects = [m_pdfLayerController rectsForSelectionInLayoutSpace:currentSelection];
2048     if (!selectionRects || !selectionRects.count)
2049         return false;
2050     
2051     if (currentPageIndex >= selectionRects.count)
2052         currentPageIndex = selectionRects.count - 1;
2053
2054     NSArray *wordSelectionRects = [m_pdfLayerController rectsForSelectionInLayoutSpace:selectionForWord];
2055     if (!wordSelectionRects || !wordSelectionRects.count)
2056         return false;
2057
2058     NSValue *selectionBounds = [selectionRects objectAtIndex:currentPageIndex];
2059     NSValue *wordSelectionBounds = [wordSelectionRects objectAtIndex:0];
2060
2061     NSRect selectionBoundsRect = selectionBounds.rectValue;
2062     NSRect wordSelectionBoundsRect = wordSelectionBounds.rectValue;
2063     return NSIntersectsRect(wordSelectionBoundsRect, selectionBoundsRect);
2064 }
2065
2066 static NSPoint pointInLayoutSpaceForPointInWindowSpace(PDFLayerController* pdfLayerController, NSPoint pointInView)
2067 {
2068     CGPoint point = NSPointToCGPoint(pointInView);
2069     CGPoint scrollOffset = [pdfLayerController scrollPosition];
2070     CGFloat scaleFactor = [pdfLayerController contentScaleFactor];
2071
2072     scrollOffset.y = [pdfLayerController contentSizeRespectingZoom].height - NSRectToCGRect([pdfLayerController frame]).size.height - scrollOffset.y;
2073
2074     CGPoint newPoint = CGPointMake(scrollOffset.x + point.x, scrollOffset.y + point.y);
2075     newPoint.x /= scaleFactor;
2076     newPoint.y /= scaleFactor;
2077     return NSPointFromCGPoint(newPoint);
2078 }
2079
2080 std::tuple<String, PDFSelection *, NSDictionary *> PDFPlugin::lookupTextAtLocation(const WebCore::FloatPoint& locationInViewCoordinates, WebHitTestResultData& data) const
2081 {
2082     auto selection = [m_pdfLayerController currentSelection];
2083     if (existingSelectionContainsPoint(locationInViewCoordinates))
2084         return { selection.string, selection, nil };
2085
2086     IntPoint pointInPDFView = convertFromPluginToPDFView(convertFromRootViewToPlugin(roundedIntPoint(locationInViewCoordinates)));
2087     selection = [m_pdfLayerController getSelectionForWordAtPoint:pointInPDFView];
2088     if (!selection)
2089         return { emptyString(), nil, nil };
2090
2091     NSPoint pointInLayoutSpace = pointInLayoutSpaceForPointInWindowSpace(m_pdfLayerController.get(), pointInPDFView);
2092     PDFPage *currentPage = [[m_pdfLayerController layout] pageNearestPoint:pointInLayoutSpace currentPage:[m_pdfLayerController currentPage]];
2093     NSPoint pointInPageSpace = [[m_pdfLayerController layout] convertPoint:pointInLayoutSpace toPage:currentPage forScaleFactor:1.0];
2094
2095     for (PDFAnnotation *annotation in currentPage.annotations) {
2096         if (![annotation isKindOfClass:pdfAnnotationLinkClass()])
2097             continue;
2098
2099         NSRect bounds = annotation.bounds;
2100         if (!NSPointInRect(pointInPageSpace, bounds))
2101             continue;
2102
2103         ALLOW_DEPRECATED_DECLARATIONS_BEGIN
2104         PDFAnnotationLink *linkAnnotation = (PDFAnnotationLink *)annotation;
2105         ALLOW_DEPRECATED_DECLARATIONS_END
2106         NSURL *url = linkAnnotation.URL;
2107         if (!url)
2108             continue;
2109
2110         data.absoluteLinkURL = url.absoluteString;
2111         data.linkLabel = selection.string;
2112         return { selection.string, selection, nil };
2113     }
2114
2115     NSString *lookupText;
2116     NSDictionary *options;
2117     std::tie(lookupText, options) = DictionaryLookup::stringForPDFSelection(selection);
2118     if (!lookupText.length)
2119         return { emptyString(), selection, nil };
2120
2121     [m_pdfLayerController setCurrentSelection:selection];
2122     return { lookupText, selection, options };
2123 }
2124
2125 static NSRect rectInViewSpaceForRectInLayoutSpace(PDFLayerController* pdfLayerController, NSRect layoutSpaceRect)
2126 {
2127     CGRect newRect = NSRectToCGRect(layoutSpaceRect);
2128     CGFloat scaleFactor = pdfLayerController.contentScaleFactor;
2129     CGPoint scrollOffset = pdfLayerController.scrollPosition;
2130
2131     scrollOffset.y = pdfLayerController.contentSizeRespectingZoom.height - NSRectToCGRect(pdfLayerController.frame).size.height - scrollOffset.y;
2132
2133     newRect.origin.x *= scaleFactor;
2134     newRect.origin.y *= scaleFactor;
2135     newRect.size.width *= scaleFactor;
2136     newRect.size.height *= scaleFactor;
2137
2138     newRect.origin.x -= scrollOffset.x;
2139     newRect.origin.y -= scrollOffset.y;
2140
2141     return NSRectFromCGRect(newRect);
2142 }
2143     
2144 WebCore::AXObjectCache* PDFPlugin::axObjectCache() const
2145 {
2146     return webFrame()->coreFrame()->document()->axObjectCache();
2147 }
2148
2149 WebCore::FloatRect PDFPlugin::rectForSelectionInRootView(PDFSelection *selection) const
2150 {
2151     PDFPage *currentPage = nil;
2152     NSArray *pages = selection.pages;
2153     if (pages.count)
2154         currentPage = (PDFPage *)[pages objectAtIndex:0];
2155
2156     if (!currentPage)
2157         currentPage = [m_pdfLayerController currentPage];
2158
2159     NSRect rectInPageSpace = [selection boundsForPage:currentPage];
2160     NSRect rectInLayoutSpace = [[m_pdfLayerController layout] convertRect:rectInPageSpace fromPage:currentPage forScaleFactor:1.0];
2161     NSRect rectInView = rectInViewSpaceForRectInLayoutSpace(m_pdfLayerController.get(), rectInLayoutSpace);
2162
2163     rectInView.origin = convertFromPDFViewToRootView(IntPoint(rectInView.origin));
2164
2165     return rectInView;
2166 }
2167
2168 CGFloat PDFPlugin::scaleFactor() const
2169 {
2170     return [m_pdfLayerController contentScaleFactor];
2171 }
2172
2173 void PDFPlugin::performWebSearch(NSString *string)
2174 {
2175     webFrame()->page()->send(Messages::WebPageProxy::SearchTheWeb(string));
2176 }
2177
2178 void PDFPlugin::performSpotlightSearch(NSString *string)
2179 {
2180     webFrame()->page()->send(Messages::WebPageProxy::SearchWithSpotlight(string));
2181 }
2182
2183 bool PDFPlugin::handleWheelEvent(const WebWheelEvent& event)
2184 {
2185     PDFDisplayMode displayMode = [m_pdfLayerController displayMode];
2186
2187     if (displayMode == kPDFDisplaySinglePageContinuous || displayMode == kPDFDisplayTwoUpContinuous)
2188         return ScrollableArea::handleWheelEvent(platform(event));
2189
2190     NSUInteger currentPageIndex = [m_pdfLayerController currentPageIndex];
2191     bool inFirstPage = !currentPageIndex;
2192     bool inLastPage = [m_pdfLayerController lastPageIndex] == currentPageIndex;
2193
2194     bool atScrollTop = !scrollPosition().y();
2195     bool atScrollBottom = scrollPosition().y() == maximumScrollPosition().y();
2196
2197     bool inMomentumScroll = event.momentumPhase() != WebWheelEvent::PhaseNone;
2198
2199     int scrollMagnitudeThresholdForPageFlip = defaultScrollMagnitudeThresholdForPageFlip;
2200
2201     // Imprecise input devices should have a lower threshold so that "clicky" scroll wheels can flip pages.
2202     if (!event.hasPreciseScrollingDeltas())
2203         scrollMagnitudeThresholdForPageFlip = 0;
2204
2205     if (atScrollBottom && !inLastPage && event.delta().height() < 0) {
2206         if (event.delta().height() <= -scrollMagnitudeThresholdForPageFlip && !inMomentumScroll)
2207             [m_pdfLayerController gotoNextPage];
2208         return true;
2209     }
2210
2211     if (atScrollTop && !inFirstPage && event.delta().height() > 0) {
2212         if (event.delta().height() >= scrollMagnitudeThresholdForPageFlip && !inMomentumScroll) {
2213             [CATransaction begin];
2214             [m_pdfLayerController gotoPreviousPage];
2215             scrollToOffsetWithoutAnimation(maximumScrollPosition());
2216             [CATransaction commit];
2217         }
2218         return true;
2219     }
2220
2221     return ScrollableArea::handleWheelEvent(platform(event));
2222 }
2223
2224 NSData *PDFPlugin::liveData() const
2225 {
2226     if (m_activeAnnotation)
2227         m_activeAnnotation->commit();
2228
2229     // Save data straight from the resource instead of PDFKit if the document is
2230     // untouched by the user, so that PDFs which PDFKit can't display will still be downloadable.
2231     if (m_pdfDocumentWasMutated)
2232         return [m_pdfDocument dataRepresentation];
2233
2234     return rawData();
2235 }
2236
2237 id PDFPlugin::accessibilityAssociatedPluginParentForElement(WebCore::Element* element) const
2238 {
2239 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300
2240     if (!m_activeAnnotation)
2241         return nil;
2242
2243     if (m_activeAnnotation->element() != element)
2244         return nil;
2245
2246     return [m_activeAnnotation->annotation() accessibilityNode];
2247 #else
2248     return nil;
2249 #endif
2250 }
2251
2252 NSObject *PDFPlugin::accessibilityObject() const
2253 {
2254     return m_accessibilityObject.get();
2255 }
2256
2257 } // namespace WebKit
2258
2259 #endif // ENABLE(PDFKIT_PLUGIN)