Remove unused initializer for WebEvent on iOS.
[WebKit-https.git] / Source / WebKit / mac / WebView / WebHTMLView.mm
1 /*
2  * Copyright (C) 2005-2010, 2016 Apple Inc. All rights reserved.
3  *           (C) 2006, 2007 Graham Dennis (graham.dennis@gmail.com)
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1.  Redistributions of source code must retain the above copyright
10  *     notice, this list of conditions and the following disclaimer. 
11  * 2.  Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution. 
14  * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
15  *     its contributors may be used to endorse or promote products derived
16  *     from this software without specific prior written permission. 
17  *
18  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #import "WebHTMLView.h"
31
32 #import "DOMCSSStyleDeclarationInternal.h"
33 #import "DOMDocumentFragmentInternal.h"
34 #import "DOMDocumentInternal.h"
35 #import "DOMNodeInternal.h"
36 #import "DOMRangeInternal.h"
37 #import "WebArchive.h"
38 #import "WebClipView.h"
39 #import "WebContextMenuClient.h"
40 #import "WebDOMOperationsInternal.h"
41 #import "WebDataSourceInternal.h"
42 #import "WebDefaultUIDelegate.h"
43 #import "WebDelegateImplementationCaching.h"
44 #import "WebDocumentInternal.h"
45 #import "WebDynamicScrollBarsViewInternal.h"
46 #import "WebEditingDelegate.h"
47 #import "WebElementDictionary.h"
48 #import "WebFrameInternal.h"
49 #import "WebFramePrivate.h"
50 #import "WebFrameViewInternal.h"
51 #import "WebHTMLRepresentationPrivate.h"
52 #import "WebHTMLViewInternal.h"
53 #import "WebImmediateActionController.h"
54 #import "WebKitLogging.h"
55 #import "WebKitNSStringExtras.h"
56 #import "WebKitVersionChecks.h"
57 #import "WebLocalizableStringsInternal.h"
58 #import "WebNSFileManagerExtras.h"
59 #import "WebNSImageExtras.h"
60 #import "WebNSObjectExtras.h"
61 #import "WebNSPrintOperationExtras.h"
62 #import "WebNSURLExtras.h"
63 #import "WebNSViewExtras.h"
64 #import "WebNetscapePluginView.h"
65 #import "WebNodeHighlight.h"
66 #import "WebPluginController.h"
67 #import "WebPreferences.h"
68 #import "WebPreferencesPrivate.h"
69 #import "WebResourcePrivate.h"
70 #import "WebSharingServicePickerController.h"
71 #import "WebTextCompletionController.h"
72 #import "WebTypesInternal.h"
73 #import "WebUIDelegatePrivate.h"
74 #import "WebViewInternal.h"
75 #import <WebCore/BlockExceptions.h>
76 #import <WebCore/CSSStyleDeclaration.h>
77 #import <WebCore/CachedImage.h>
78 #import <WebCore/CachedResourceClient.h>
79 #import <WebCore/CachedResourceLoader.h>
80 #import <WebCore/Chrome.h>
81 #import <WebCore/ColorMac.h>
82 #import <WebCore/ContextMenu.h>
83 #import <WebCore/ContextMenuController.h>
84 #import <WebCore/DictionaryLookup.h>
85 #import <WebCore/Document.h>
86 #import <WebCore/DocumentFragment.h>
87 #import <WebCore/DocumentMarkerController.h>
88 #import <WebCore/DragController.h>
89 #import <WebCore/DragImage.h>
90 #import <WebCore/Editor.h>
91 #import <WebCore/EditorDeleteAction.h>
92 #import <WebCore/Element.h>
93 #import <WebCore/EventHandler.h>
94 #import <WebCore/ExceptionHandlers.h>
95 #import <WebCore/FloatRect.h>
96 #import <WebCore/FocusController.h>
97 #import <WebCore/Font.h>
98 #import <WebCore/FontCache.h>
99 #import <WebCore/Frame.h>
100 #import <WebCore/FrameLoader.h>
101 #import <WebCore/FrameSelection.h>
102 #import <WebCore/FrameView.h>
103 #import <WebCore/HTMLConverter.h>
104 #import <WebCore/HTMLNames.h>
105 #import <WebCore/HitTestResult.h>
106 #import <WebCore/Image.h>
107 #import <WebCore/KeyboardEvent.h>
108 #import <WebCore/LegacyWebArchive.h>
109 #import <WebCore/LocalizedStrings.h>
110 #import <WebCore/MIMETypeRegistry.h>
111 #import <WebCore/MainFrame.h>
112 #import <WebCore/NSSpellCheckerSPI.h>
113 #import <WebCore/NSURLFileTypeMappingsSPI.h>
114 #import <WebCore/NSViewSPI.h>
115 #import <WebCore/Page.h>
116 #import <WebCore/Range.h>
117 #import <WebCore/RenderView.h>
118 #import <WebCore/RenderWidget.h>
119 #import <WebCore/RuntimeApplicationChecks.h>
120 #import <WebCore/SharedBuffer.h>
121 #import <WebCore/StyleProperties.h>
122 #import <WebCore/Text.h>
123 #import <WebCore/TextAlternativeWithRange.h>
124 #import <WebCore/TextIndicator.h>
125 #import <WebCore/TextUndoInsertionMarkupMac.h>
126 #import <WebCore/WebCoreObjCExtras.h>
127 #import <WebCore/WebNSAttributedStringExtras.h>
128 #import <WebCore/markup.h>
129 #import <WebKitLegacy/DOM.h>
130 #import <WebKitLegacy/DOMExtensions.h>
131 #import <WebKitLegacy/DOMPrivate.h>
132 #import <WebKitSystemInterface.h>
133 #import <dlfcn.h>
134 #import <limits>
135 #import <runtime/InitializeThreading.h>
136 #import <wtf/MainThread.h>
137 #import <wtf/MathExtras.h>
138 #import <wtf/ObjcRuntimeExtras.h>
139 #import <wtf/RunLoop.h>
140
141 #if !PLATFORM(IOS)
142 #import <AppKit/NSAccessibility.h>
143 #import <ApplicationServices/ApplicationServices.h>
144 #import <WebCore/NSMenuSPI.h>
145 #import <WebCore/PlatformEventFactoryMac.h>
146 #import "WebNSEventExtras.h"
147 #import "WebNSPasteboardExtras.h"
148 #endif
149
150 #import <QuartzCore/QuartzCore.h>
151
152 #if PLATFORM(IOS)
153 #import "WebUIKitDelegate.h"
154 #import <WebCore/KeyEventCodesIOS.h>
155 #import <WebCore/PlatformEventFactoryIOS.h>
156 #import <WebCore/WAKClipView.h>
157 #import <WebCore/WAKScrollView.h>
158 #import <WebCore/WAKWindow.h>
159 #import <WebCore/WKGraphics.h>
160 #import <WebCore/WebEvent.h>
161 #endif
162
163 using namespace WebCore;
164 using namespace HTMLNames;
165 using namespace WTF;
166
167 #if PLATFORM(IOS)
168 @interface NSObject (Accessibility)
169 - (id)accessibilityHitTest:(NSPoint)point;
170 - (id)accessibilityFocusedUIElement;
171 @end
172 #endif
173
174 #if !PLATFORM(IOS)
175 @interface WebMenuTarget : NSObject {
176     WebCore::ContextMenuController* _menuController;
177 }
178 + (WebMenuTarget*)sharedMenuTarget;
179 - (WebCore::ContextMenuController*)menuController;
180 - (void)setMenuController:(WebCore::ContextMenuController*)menuController;
181 - (void)forwardContextMenuAction:(id)sender;
182 @end
183
184 static Optional<ContextMenuAction> toAction(NSInteger tag)
185 {
186     if (tag >= ContextMenuItemBaseCustomTag && tag <= ContextMenuItemLastCustomTag) {
187         // Just pass these through.
188         return static_cast<ContextMenuAction>(tag);
189     }
190
191     switch (tag) {
192     case WebMenuItemTagOpenLinkInNewWindow:
193         return ContextMenuItemTagOpenLinkInNewWindow;
194     case WebMenuItemTagDownloadLinkToDisk:
195         return ContextMenuItemTagDownloadLinkToDisk;
196     case WebMenuItemTagCopyLinkToClipboard:
197         return ContextMenuItemTagCopyLinkToClipboard;
198     case WebMenuItemTagOpenImageInNewWindow:
199         return ContextMenuItemTagOpenImageInNewWindow;
200     case WebMenuItemTagDownloadImageToDisk:
201         return ContextMenuItemTagDownloadImageToDisk;
202     case WebMenuItemTagCopyImageToClipboard:
203         return ContextMenuItemTagCopyImageToClipboard;
204     case WebMenuItemTagOpenFrameInNewWindow:
205         return ContextMenuItemTagOpenFrameInNewWindow;
206     case WebMenuItemTagCopy:
207         return ContextMenuItemTagCopy;
208     case WebMenuItemTagGoBack:
209         return ContextMenuItemTagGoBack;
210     case WebMenuItemTagGoForward:
211         return ContextMenuItemTagGoForward;
212     case WebMenuItemTagStop:
213         return ContextMenuItemTagStop;
214     case WebMenuItemTagReload:
215         return ContextMenuItemTagReload;
216     case WebMenuItemTagCut:
217         return ContextMenuItemTagCut;
218     case WebMenuItemTagPaste:
219         return ContextMenuItemTagPaste;
220     case WebMenuItemTagSpellingGuess:
221         return ContextMenuItemTagSpellingGuess;
222     case WebMenuItemTagNoGuessesFound:
223         return ContextMenuItemTagNoGuessesFound;
224     case WebMenuItemTagIgnoreSpelling:
225         return ContextMenuItemTagIgnoreSpelling;
226     case WebMenuItemTagLearnSpelling:
227         return ContextMenuItemTagLearnSpelling;
228     case WebMenuItemTagOther:
229         return ContextMenuItemTagOther;
230     case WebMenuItemTagSearchInSpotlight:
231         return ContextMenuItemTagSearchInSpotlight;
232     case WebMenuItemTagSearchWeb:
233         return ContextMenuItemTagSearchWeb;
234     case WebMenuItemTagLookUpInDictionary:
235         return ContextMenuItemTagLookUpInDictionary;
236     case WebMenuItemTagOpenWithDefaultApplication:
237         return ContextMenuItemTagOpenWithDefaultApplication;
238     case WebMenuItemPDFActualSize:
239         return ContextMenuItemPDFActualSize;
240     case WebMenuItemPDFZoomIn:
241         return ContextMenuItemPDFZoomIn;
242     case WebMenuItemPDFZoomOut:
243         return ContextMenuItemPDFZoomOut;
244     case WebMenuItemPDFAutoSize:
245         return ContextMenuItemPDFAutoSize;
246     case WebMenuItemPDFSinglePage:
247         return ContextMenuItemPDFSinglePage;
248     case WebMenuItemPDFFacingPages:
249         return ContextMenuItemPDFFacingPages;
250     case WebMenuItemPDFContinuous:
251         return ContextMenuItemPDFContinuous;
252     case WebMenuItemPDFNextPage:
253         return ContextMenuItemPDFNextPage;
254     case WebMenuItemPDFPreviousPage:
255         return ContextMenuItemPDFPreviousPage;
256     case WebMenuItemTagOpenLink:
257         return ContextMenuItemTagOpenLink;
258     case WebMenuItemTagIgnoreGrammar:
259         return ContextMenuItemTagIgnoreGrammar;
260     case WebMenuItemTagSpellingMenu:
261         return ContextMenuItemTagSpellingMenu;
262     case WebMenuItemTagShowSpellingPanel:
263         return ContextMenuItemTagShowSpellingPanel;
264     case WebMenuItemTagCheckSpelling:
265         return ContextMenuItemTagCheckSpelling;
266     case WebMenuItemTagCheckSpellingWhileTyping:
267         return ContextMenuItemTagCheckSpellingWhileTyping;
268     case WebMenuItemTagCheckGrammarWithSpelling:
269         return ContextMenuItemTagCheckGrammarWithSpelling;
270     case WebMenuItemTagFontMenu:
271         return ContextMenuItemTagFontMenu;
272     case WebMenuItemTagShowFonts:
273         return ContextMenuItemTagShowFonts;
274     case WebMenuItemTagBold:
275         return ContextMenuItemTagBold;
276     case WebMenuItemTagItalic:
277         return ContextMenuItemTagItalic;
278     case WebMenuItemTagUnderline:
279         return ContextMenuItemTagUnderline;
280     case WebMenuItemTagOutline:
281         return ContextMenuItemTagOutline;
282     case WebMenuItemTagStyles:
283         return ContextMenuItemTagStyles;
284     case WebMenuItemTagShowColors:
285         return ContextMenuItemTagShowColors;
286     case WebMenuItemTagSpeechMenu:
287         return ContextMenuItemTagSpeechMenu;
288     case WebMenuItemTagStartSpeaking:
289         return ContextMenuItemTagStartSpeaking;
290     case WebMenuItemTagStopSpeaking:
291         return ContextMenuItemTagStopSpeaking;
292     case WebMenuItemTagWritingDirectionMenu:
293         return ContextMenuItemTagWritingDirectionMenu;
294     case WebMenuItemTagDefaultDirection:
295         return ContextMenuItemTagDefaultDirection;
296     case WebMenuItemTagLeftToRight:
297         return ContextMenuItemTagLeftToRight;
298     case WebMenuItemTagRightToLeft:
299         return ContextMenuItemTagRightToLeft;
300     case WebMenuItemPDFSinglePageScrolling:
301         return ContextMenuItemTagPDFSinglePageScrolling;
302     case WebMenuItemPDFFacingPagesScrolling:
303         return ContextMenuItemTagPDFFacingPagesScrolling;
304     case WebMenuItemTagInspectElement:
305         return ContextMenuItemTagInspectElement;
306     case WebMenuItemTagTextDirectionMenu:
307         return ContextMenuItemTagTextDirectionMenu;
308     case WebMenuItemTagTextDirectionDefault:
309         return ContextMenuItemTagTextDirectionDefault;
310     case WebMenuItemTagTextDirectionLeftToRight:
311         return ContextMenuItemTagTextDirectionLeftToRight;
312     case WebMenuItemTagTextDirectionRightToLeft:
313         return ContextMenuItemTagTextDirectionRightToLeft;
314     case WebMenuItemTagCorrectSpellingAutomatically:
315         return ContextMenuItemTagCorrectSpellingAutomatically;
316     case WebMenuItemTagSubstitutionsMenu:
317         return ContextMenuItemTagSubstitutionsMenu;
318     case WebMenuItemTagShowSubstitutions:
319         return ContextMenuItemTagShowSubstitutions;
320     case WebMenuItemTagSmartCopyPaste:
321         return ContextMenuItemTagSmartCopyPaste;
322     case WebMenuItemTagSmartQuotes:
323         return ContextMenuItemTagSmartQuotes;
324     case WebMenuItemTagSmartDashes:
325         return ContextMenuItemTagSmartDashes;
326     case WebMenuItemTagSmartLinks:
327         return ContextMenuItemTagSmartLinks;
328     case WebMenuItemTagTextReplacement:
329         return ContextMenuItemTagTextReplacement;
330     case WebMenuItemTagTransformationsMenu:
331         return ContextMenuItemTagTransformationsMenu;
332     case WebMenuItemTagMakeUpperCase:
333         return ContextMenuItemTagMakeUpperCase;
334     case WebMenuItemTagMakeLowerCase:
335         return ContextMenuItemTagMakeLowerCase;
336     case WebMenuItemTagCapitalize:
337         return ContextMenuItemTagCapitalize;
338     case WebMenuItemTagChangeBack:
339         return ContextMenuItemTagChangeBack;
340     case WebMenuItemTagOpenMediaInNewWindow:
341         return ContextMenuItemTagOpenMediaInNewWindow;
342     case WebMenuItemTagCopyMediaLinkToClipboard:
343         return ContextMenuItemTagCopyMediaLinkToClipboard;
344     case WebMenuItemTagToggleMediaControls:
345         return ContextMenuItemTagToggleMediaControls;
346     case WebMenuItemTagToggleMediaLoop:
347         return ContextMenuItemTagToggleMediaLoop;
348     case WebMenuItemTagEnterVideoFullscreen:
349         return ContextMenuItemTagEnterVideoFullscreen;
350     case WebMenuItemTagToggleVideoEnhancedFullscreen:
351         return ContextMenuItemTagToggleVideoEnhancedFullscreen;
352     case WebMenuItemTagMediaPlayPause:
353         return ContextMenuItemTagMediaPlayPause;
354     case WebMenuItemTagMediaMute:
355         return ContextMenuItemTagMediaMute;
356     case WebMenuItemTagDictationAlternative:
357         return ContextMenuItemTagDictationAlternative;
358     }
359     return Nullopt;
360 }
361
362 static Optional<NSInteger> toTag(ContextMenuAction action)
363 {
364     switch (action) {
365     case ContextMenuItemTagNoAction:
366         return Nullopt;
367
368     case ContextMenuItemTagOpenLinkInNewWindow:
369         return WebMenuItemTagOpenLinkInNewWindow;
370     case ContextMenuItemTagDownloadLinkToDisk:
371         return WebMenuItemTagDownloadLinkToDisk;
372     case ContextMenuItemTagCopyLinkToClipboard:
373         return WebMenuItemTagCopyLinkToClipboard;
374     case ContextMenuItemTagOpenImageInNewWindow:
375         return WebMenuItemTagOpenImageInNewWindow;
376     case ContextMenuItemTagDownloadImageToDisk:
377         return WebMenuItemTagDownloadImageToDisk;
378     case ContextMenuItemTagCopyImageToClipboard:
379         return WebMenuItemTagCopyImageToClipboard;
380     case ContextMenuItemTagOpenFrameInNewWindow:
381         return WebMenuItemTagOpenFrameInNewWindow;
382     case ContextMenuItemTagCopy:
383         return WebMenuItemTagCopy;
384     case ContextMenuItemTagGoBack:
385         return WebMenuItemTagGoBack;
386     case ContextMenuItemTagGoForward:
387         return WebMenuItemTagGoForward;
388     case ContextMenuItemTagStop:
389         return WebMenuItemTagStop;
390     case ContextMenuItemTagReload:
391         return WebMenuItemTagReload;
392     case ContextMenuItemTagCut:
393         return WebMenuItemTagCut;
394     case ContextMenuItemTagPaste:
395         return WebMenuItemTagPaste;
396     case ContextMenuItemTagSpellingGuess:
397         return WebMenuItemTagSpellingGuess;
398     case ContextMenuItemTagNoGuessesFound:
399         return WebMenuItemTagNoGuessesFound;
400     case ContextMenuItemTagIgnoreSpelling:
401         return WebMenuItemTagIgnoreSpelling;
402     case ContextMenuItemTagLearnSpelling:
403         return WebMenuItemTagLearnSpelling;
404     case ContextMenuItemTagOther:
405         return WebMenuItemTagOther;
406     case ContextMenuItemTagSearchInSpotlight:
407         return WebMenuItemTagSearchInSpotlight;
408     case ContextMenuItemTagSearchWeb:
409         return WebMenuItemTagSearchWeb;
410     case ContextMenuItemTagLookUpInDictionary:
411         return WebMenuItemTagLookUpInDictionary;
412     case ContextMenuItemTagOpenWithDefaultApplication:
413         return WebMenuItemTagOpenWithDefaultApplication;
414     case ContextMenuItemPDFActualSize:
415         return WebMenuItemPDFActualSize;
416     case ContextMenuItemPDFZoomIn:
417         return WebMenuItemPDFZoomIn;
418     case ContextMenuItemPDFZoomOut:
419         return WebMenuItemPDFZoomOut;
420     case ContextMenuItemPDFAutoSize:
421         return WebMenuItemPDFAutoSize;
422     case ContextMenuItemPDFSinglePage:
423         return WebMenuItemPDFSinglePage;
424     case ContextMenuItemPDFFacingPages:
425         return WebMenuItemPDFFacingPages;
426     case ContextMenuItemPDFContinuous:
427         return WebMenuItemPDFContinuous;
428     case ContextMenuItemPDFNextPage:
429         return WebMenuItemPDFNextPage;
430     case ContextMenuItemPDFPreviousPage:
431         return WebMenuItemPDFPreviousPage;
432     case ContextMenuItemTagOpenLink:
433         return WebMenuItemTagOpenLink;
434     case ContextMenuItemTagIgnoreGrammar:
435         return WebMenuItemTagIgnoreGrammar;
436     case ContextMenuItemTagSpellingMenu:
437         return WebMenuItemTagSpellingMenu;
438     case ContextMenuItemTagShowSpellingPanel:
439         return WebMenuItemTagShowSpellingPanel;
440     case ContextMenuItemTagCheckSpelling:
441         return WebMenuItemTagCheckSpelling;
442     case ContextMenuItemTagCheckSpellingWhileTyping:
443         return WebMenuItemTagCheckSpellingWhileTyping;
444     case ContextMenuItemTagCheckGrammarWithSpelling:
445         return WebMenuItemTagCheckGrammarWithSpelling;
446     case ContextMenuItemTagFontMenu:
447         return WebMenuItemTagFontMenu;
448     case ContextMenuItemTagShowFonts:
449         return WebMenuItemTagShowFonts;
450     case ContextMenuItemTagBold:
451         return WebMenuItemTagBold;
452     case ContextMenuItemTagItalic:
453         return WebMenuItemTagItalic;
454     case ContextMenuItemTagUnderline:
455         return WebMenuItemTagUnderline;
456     case ContextMenuItemTagOutline:
457         return WebMenuItemTagOutline;
458     case ContextMenuItemTagStyles:
459         return WebMenuItemTagStyles;
460     case ContextMenuItemTagShowColors:
461         return WebMenuItemTagShowColors;
462     case ContextMenuItemTagSpeechMenu:
463         return WebMenuItemTagSpeechMenu;
464     case ContextMenuItemTagStartSpeaking:
465         return WebMenuItemTagStartSpeaking;
466     case ContextMenuItemTagStopSpeaking:
467         return WebMenuItemTagStopSpeaking;
468     case ContextMenuItemTagWritingDirectionMenu:
469         return WebMenuItemTagWritingDirectionMenu;
470     case ContextMenuItemTagDefaultDirection:
471         return WebMenuItemTagDefaultDirection;
472     case ContextMenuItemTagLeftToRight:
473         return WebMenuItemTagLeftToRight;
474     case ContextMenuItemTagRightToLeft:
475         return WebMenuItemTagRightToLeft;
476     case ContextMenuItemTagPDFSinglePageScrolling:
477         return WebMenuItemPDFSinglePageScrolling;
478     case ContextMenuItemTagPDFFacingPagesScrolling:
479         return WebMenuItemPDFFacingPagesScrolling;
480     case ContextMenuItemTagInspectElement:
481         return WebMenuItemTagInspectElement;
482     case ContextMenuItemTagTextDirectionMenu:
483         return WebMenuItemTagTextDirectionMenu;
484     case ContextMenuItemTagTextDirectionDefault:
485         return WebMenuItemTagTextDirectionDefault;
486     case ContextMenuItemTagTextDirectionLeftToRight:
487         return WebMenuItemTagTextDirectionLeftToRight;
488     case ContextMenuItemTagTextDirectionRightToLeft:
489         return WebMenuItemTagTextDirectionRightToLeft;
490     case ContextMenuItemTagCorrectSpellingAutomatically:
491         return WebMenuItemTagCorrectSpellingAutomatically;
492     case ContextMenuItemTagSubstitutionsMenu:
493         return WebMenuItemTagSubstitutionsMenu;
494     case ContextMenuItemTagShowSubstitutions:
495         return WebMenuItemTagShowSubstitutions;
496     case ContextMenuItemTagSmartCopyPaste:
497         return WebMenuItemTagSmartCopyPaste;
498     case ContextMenuItemTagSmartQuotes:
499         return WebMenuItemTagSmartQuotes;
500     case ContextMenuItemTagSmartDashes:
501         return WebMenuItemTagSmartDashes;
502     case ContextMenuItemTagSmartLinks:
503         return WebMenuItemTagSmartLinks;
504     case ContextMenuItemTagTextReplacement:
505         return WebMenuItemTagTextReplacement;
506     case ContextMenuItemTagTransformationsMenu:
507         return WebMenuItemTagTransformationsMenu;
508     case ContextMenuItemTagMakeUpperCase:
509         return WebMenuItemTagMakeUpperCase;
510     case ContextMenuItemTagMakeLowerCase:
511         return WebMenuItemTagMakeLowerCase;
512     case ContextMenuItemTagCapitalize:
513         return WebMenuItemTagCapitalize;
514     case ContextMenuItemTagChangeBack:
515         return WebMenuItemTagChangeBack;
516     case ContextMenuItemTagOpenMediaInNewWindow:
517         return WebMenuItemTagOpenMediaInNewWindow;
518     case ContextMenuItemTagDownloadMediaToDisk:
519         return WebMenuItemTagDownloadMediaToDisk;
520     case ContextMenuItemTagCopyMediaLinkToClipboard:
521         return WebMenuItemTagCopyMediaLinkToClipboard;
522     case ContextMenuItemTagToggleMediaControls:
523         return WebMenuItemTagToggleMediaControls;
524     case ContextMenuItemTagToggleMediaLoop:
525         return WebMenuItemTagToggleMediaLoop;
526     case ContextMenuItemTagEnterVideoFullscreen:
527         return WebMenuItemTagEnterVideoFullscreen;
528     case ContextMenuItemTagMediaPlayPause:
529         return WebMenuItemTagMediaPlayPause;
530     case ContextMenuItemTagMediaMute:
531         return WebMenuItemTagMediaMute;
532     case ContextMenuItemTagDictationAlternative:
533         return WebMenuItemTagDictationAlternative;
534     case ContextMenuItemTagToggleVideoFullscreen:
535         return WebMenuItemTagToggleVideoFullscreen;
536     case ContextMenuItemTagShareMenu:
537         return WebMenuItemTagShareMenu;
538     case ContextMenuItemTagToggleVideoEnhancedFullscreen:
539         return WebMenuItemTagToggleVideoEnhancedFullscreen;
540
541     case ContextMenuItemBaseCustomTag ... ContextMenuItemLastCustomTag:
542         // We just pass these through.
543         return static_cast<NSInteger>(action);
544
545     case ContextMenuItemBaseApplicationTag:
546         ASSERT_NOT_REACHED();
547     }
548
549     return Nullopt;
550 }
551
552 static WebMenuTarget* target;
553
554 @implementation WebMenuTarget
555
556 + (WebMenuTarget*)sharedMenuTarget
557 {
558     if (!target)
559         target = [[WebMenuTarget alloc] init];
560     return target;
561 }
562
563 - (WebCore::ContextMenuController*)menuController
564 {
565     return _menuController;
566 }
567
568 - (void)setMenuController:(WebCore::ContextMenuController*)menuController
569 {
570     _menuController = menuController;
571 }
572
573 - (void)forwardContextMenuAction:(id)sender
574 {
575     if (auto action = toAction([sender tag]))
576         _menuController->contextMenuItemSelected(*action, [sender title]);
577 }
578
579 @end
580
581 @interface NSWindow (BorderViewAccess)
582 - (NSView*)_web_borderView;
583 @end
584
585 @implementation NSWindow (BorderViewAccess)
586 - (NSView*)_web_borderView
587 {
588     return _borderView;
589 }
590 @end
591
592 @interface WebResponderChainSink : NSResponder {
593     NSResponder* _lastResponderInChain;
594     BOOL _receivedUnhandledCommand;
595 }
596 - (id)initWithResponderChain:(NSResponder *)chain;
597 - (void)detach;
598 - (BOOL)receivedUnhandledCommand;
599 @end
600
601 @interface WebLayerHostingFlippedView : NSView
602 @end
603
604 @implementation WebLayerHostingFlippedView
605 - (BOOL)isFlipped
606 {
607     return YES;
608 }
609 @end
610
611 @interface WebRootLayer : CALayer
612 @end
613
614 @implementation WebRootLayer
615 - (void)renderInContext:(CGContextRef)ctx
616 {
617     // AppKit calls -[CALayer renderInContext:] to render layer-backed views
618     // into bitmap contexts, but renderInContext: doesn't capture mask layers
619     // (<rdar://problem/9539526>), so we can't rely on it. Since our layer
620     // contents will have already been rendered by drawRect:, we can safely make
621     // this a NOOP.
622 }
623 @end
624
625 // if YES, do the standard NSView hit test (which can't give the right result when HTML overlaps a view)
626 static BOOL forceNSViewHitTest;
627
628 // if YES, do the "top WebHTMLView" hit test (which we'd like to do all the time but can't because of Java requirements [see bug 4349721])
629 static BOOL forceWebHTMLViewHitTest;
630
631 @interface NSApplication ()
632 - (BOOL)isSpeaking;
633 - (void)stopSpeaking:(id)sender;
634 @end
635
636 #endif // !PLATFORM(IOS)
637
638 static WebHTMLView *lastHitView;
639
640 #if !PLATFORM(IOS)
641 static bool needsCursorRectsSupportAtPoint(NSWindow* window, NSPoint point)
642 {
643     forceNSViewHitTest = YES;
644     NSView* view = [[window _web_borderView] hitTest:point];
645     forceNSViewHitTest = NO;
646
647     // WebHTMLView doesn't use cursor rects.
648     if ([view isKindOfClass:[WebHTMLView class]])
649         return false;
650
651 #if ENABLE(NETSCAPE_PLUGIN_API)
652     // Neither do NPAPI plug-ins.
653     if ([view isKindOfClass:[WebBaseNetscapePluginView class]])
654         return false;
655 #endif
656
657     // Non-Web content, WebPDFView, and WebKit plug-ins use normal cursor handling.
658     return true;
659 }
660
661
662 static IMP oldSetCursorForMouseLocationIMP;
663
664 // Overriding an internal method is a hack; <rdar://problem/7662987> tracks finding a better solution.
665 static void setCursor(NSWindow *self, SEL cmd, NSPoint point)
666 {
667     if (needsCursorRectsSupportAtPoint(self, point))
668         wtfCallIMP<id>(oldSetCursorForMouseLocationIMP, self, cmd, point);
669 }
670
671 #endif
672
673 extern "C" {
674
675 // Need to declare these attribute names because AppKit exports them but does not make them available in API or SPI headers.
676
677 extern NSString *NSMarkedClauseSegmentAttributeName;
678 extern NSString *NSTextInputReplacementRangeAttributeName;
679
680 }
681
682 @interface NSView (WebNSViewDetails)
683 - (void)_recursiveDisplayRectIfNeededIgnoringOpacity:(NSRect)rect isVisibleRect:(BOOL)isVisibleRect rectIsVisibleRectForView:(NSView *)visibleView topView:(BOOL)topView;
684 - (void)_recursiveDisplayAllDirtyWithLockFocus:(BOOL)needsLockFocus visRect:(NSRect)visRect;
685 #if !PLATFORM(IOS)
686 - (void)_recursive:(BOOL)recurse displayRectIgnoringOpacity:(NSRect)displayRect inContext:(NSGraphicsContext *)context topView:(BOOL)topView;
687 - (void)_recursive:(BOOL)recurseX displayRectIgnoringOpacity:(NSRect)displayRect inGraphicsContext:(NSGraphicsContext *)graphicsContext CGContext:(CGContextRef)ctx topView:(BOOL)isTopView shouldChangeFontReferenceColor:(BOOL)shouldChangeFontReferenceColor;
688 #endif
689 - (NSRect)_dirtyRect;
690 - (void)_setDrawsOwnDescendants:(BOOL)drawsOwnDescendants;
691 - (BOOL)_drawnByAncestor;
692 - (void)_invalidateGStatesForTree;
693 - (void)_propagateDirtyRectsToOpaqueAncestors;
694 - (void)_windowChangedKeyState;
695 #if PLATFORM(IOS)
696 - (void)centerSelectionInVisibleArea:(id)sender;
697 #endif
698 @end
699
700 #if !PLATFORM(IOS)
701
702 @interface NSView (WebSetNeedsDisplayInRect)
703 - (void)_web_setNeedsDisplayInRect:(NSRect)invalidRect;
704 @end
705
706 @implementation NSView (WebSetNeedsDisplayInRect)
707
708 - (void)_web_setNeedsDisplayInRect:(NSRect)invalidRect
709 {
710     // Note that we call method_exchangeImplementations below, so any calls
711     // to _web_setNeedsDisplayInRect: will actually call -[NSView setNeedsDisplayInRect:].
712
713     if (![NSThread isMainThread] || ![self _drawnByAncestor]) {
714         [self _web_setNeedsDisplayInRect:invalidRect];
715         return;
716     }
717
718     static Class webFrameViewClass = [WebFrameView class];
719     WebFrameView *enclosingWebFrameView = (WebFrameView *)self;
720     while (enclosingWebFrameView && ![enclosingWebFrameView isKindOfClass:webFrameViewClass])
721         enclosingWebFrameView = (WebFrameView *)[enclosingWebFrameView superview];
722
723     if (!enclosingWebFrameView) {
724         [self _web_setNeedsDisplayInRect:invalidRect];
725         return;
726     }
727
728     Frame* coreFrame = core([enclosingWebFrameView webFrame]);
729     FrameView* frameView = coreFrame ? coreFrame->view() : 0;
730     if (!frameView || !frameView->isEnclosedInCompositingLayer()) {
731         [self _web_setNeedsDisplayInRect:invalidRect];
732         return;
733     }
734
735     NSRect invalidRectInWebFrameViewCoordinates = [enclosingWebFrameView convertRect:invalidRect fromView:self];
736     IntRect invalidRectInFrameViewCoordinates(invalidRectInWebFrameViewCoordinates);
737     if (![enclosingWebFrameView isFlipped])
738         invalidRectInFrameViewCoordinates.setY(frameView->frameRect().size().height() - invalidRectInFrameViewCoordinates.maxY());
739
740     frameView->invalidateRect(invalidRectInFrameViewCoordinates);
741 }
742
743 @end
744
745 @interface NSApplication (WebNSApplicationDetails)
746 - (void)speakString:(NSString *)string;
747 @end
748
749 @interface NSWindow (WebNSWindowDetails)
750 - (id)_newFirstResponderAfterResigning;
751 @end
752
753 @interface NSAttributedString (WebNSAttributedStringDetails)
754 - (id)_initWithDOMRange:(DOMRange *)range;
755 - (DOMDocumentFragment *)_documentFromRange:(NSRange)range document:(DOMDocument *)document documentAttributes:(NSDictionary *)dict subresources:(NSArray **)subresources;
756 @end
757
758 @interface NSSpellChecker (WebNSSpellCheckerDetails)
759 - (void)learnWord:(NSString *)word;
760 @end
761 #endif // !PLATFORM(IOS)
762
763 // By imaging to a width a little wider than the available pixels,
764 // thin pages will be scaled down a little, matching the way they
765 // print in IE and Camino. This lets them use fewer sheets than they
766 // would otherwise, which is presumably why other browsers do this.
767 // Wide pages will be scaled down more than this.
768 const float _WebHTMLViewPrintingMinimumShrinkFactor = 1.25;
769
770 // This number determines how small we are willing to reduce the page content
771 // in order to accommodate the widest line. If the page would have to be
772 // reduced smaller to make the widest line fit, we just clip instead (this
773 // behavior matches MacIE and Mozilla, at least)
774 const float _WebHTMLViewPrintingMaximumShrinkFactor = 2;
775
776 #define AUTOSCROLL_INTERVAL             0.1f
777
778 // Any non-zero value will do, but using something recognizable might help us debug some day.
779 #define TRACKING_RECT_TAG 0xBADFACE
780
781 // FIXME: This constant is copied from AppKit's _NXSmartPaste constant.
782 #define WebSmartPastePboardType @"NeXT smart paste pasteboard type"
783
784 #define STANDARD_WEIGHT 5
785 #define MIN_BOLD_WEIGHT 7
786 #define STANDARD_BOLD_WEIGHT 9
787
788 // Fake URL scheme.
789 #define WebDataProtocolScheme @"webkit-fake-url"
790
791 // <rdar://problem/4985524> References to WebCoreScrollView as a subview of a WebHTMLView may be present
792 // in some NIB files, so NSUnarchiver must be still able to look up this now-unused class.
793 @interface WebCoreScrollView : NSScrollView
794 @end
795
796 @implementation WebCoreScrollView
797 @end
798
799 #if !PLATFORM(IOS)
800 // We need this to be able to safely reference the CachedImage for the promised drag data
801 static CachedImageClient* promisedDataClient()
802 {
803     static CachedImageClient* staticCachedResourceClient = new CachedImageClient;
804     return staticCachedResourceClient;
805 }
806 #endif
807
808 #if PLATFORM(IOS)
809 static NSString * const WebMarkedTextUpdatedNotification = @"WebMarkedTextUpdated";
810 #endif
811
812 @interface WebHTMLView (WebHTMLViewFileInternal)
813 #if !PLATFORM(IOS)
814 - (BOOL)_imageExistsAtPaths:(NSArray *)paths;
815 - (DOMDocumentFragment *)_documentFragmentFromPasteboard:(NSPasteboard *)pasteboard inContext:(DOMRange *)context allowPlainText:(BOOL)allowPlainText;
816 - (NSString *)_plainTextFromPasteboard:(NSPasteboard *)pasteboard;
817 - (void)_pasteWithPasteboard:(NSPasteboard *)pasteboard allowPlainText:(BOOL)allowPlainText;
818 - (void)_pasteAsPlainTextWithPasteboard:(NSPasteboard *)pasteboard;
819 - (void)_postFakeMouseMovedEventForFlagsChangedEvent:(NSEvent *)flagsChangedEvent;
820 - (void)_removeSuperviewObservers;
821 - (void)_removeWindowObservers;
822 #endif
823 - (BOOL)_shouldInsertFragment:(DOMDocumentFragment *)fragment replacingDOMRange:(DOMRange *)range givenAction:(WebViewInsertAction)action;
824 - (BOOL)_shouldInsertText:(NSString *)text replacingDOMRange:(DOMRange *)range givenAction:(WebViewInsertAction)action;
825 - (BOOL)_shouldReplaceSelectionWithText:(NSString *)text givenAction:(WebViewInsertAction)action;
826 - (DOMRange *)_selectedRange;
827 - (BOOL)_shouldDeleteRange:(DOMRange *)range;
828 #if !PLATFORM(IOS)
829 - (NSView *)_hitViewForEvent:(NSEvent *)event;
830 - (void)_writeSelectionWithPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard cachedAttributedString:(NSAttributedString *)attributedString;
831 #endif
832 - (DOMRange *)_documentRange;
833 #if !PLATFORM(IOS)
834 - (void)_setMouseDownEvent:(NSEvent *)event;
835 #else
836 - (void)_setMouseDownEvent:(WebEvent *)event;
837 #endif
838 - (WebHTMLView *)_topHTMLView;
839 - (BOOL)_isTopHTMLView;
840 #if !PLATFORM(IOS)
841 - (void)_web_setPrintingModeRecursive;
842 - (void)_web_setPrintingModeRecursiveAndAdjustViewSize;
843 - (void)_web_clearPrintingModeRecursive;
844 #endif
845 @end
846
847 @interface WebHTMLView (WebHTMLViewTextCheckingInternal)
848 - (void)orderFrontSubstitutionsPanel:(id)sender;
849 - (BOOL)smartInsertDeleteEnabled;
850 - (void)setSmartInsertDeleteEnabled:(BOOL)flag;
851 - (void)toggleSmartInsertDelete:(id)sender;
852 - (BOOL)isAutomaticQuoteSubstitutionEnabled;
853 - (void)setAutomaticQuoteSubstitutionEnabled:(BOOL)flag;
854 - (void)toggleAutomaticQuoteSubstitution:(id)sender;
855 - (BOOL)isAutomaticLinkDetectionEnabled;
856 - (void)setAutomaticLinkDetectionEnabled:(BOOL)flag;
857 - (void)toggleAutomaticLinkDetection:(id)sender;
858 - (BOOL)isAutomaticDashSubstitutionEnabled;
859 - (void)setAutomaticDashSubstitutionEnabled:(BOOL)flag;
860 - (void)toggleAutomaticDashSubstitution:(id)sender;
861 - (BOOL)isAutomaticTextReplacementEnabled;
862 - (void)setAutomaticTextReplacementEnabled:(BOOL)flag;
863 - (void)toggleAutomaticTextReplacement:(id)sender;
864 - (BOOL)isAutomaticSpellingCorrectionEnabled;
865 - (void)setAutomaticSpellingCorrectionEnabled:(BOOL)flag;
866 - (void)toggleAutomaticSpellingCorrection:(id)sender;
867 @end
868
869 @interface WebHTMLView (WebForwardDeclaration) // FIXME: Put this in a normal category and stop doing the forward declaration trick.
870 - (void)_setPrinting:(BOOL)printing minimumPageLogicalWidth:(float)minPageWidth logicalHeight:(float)minPageHeight originalPageWidth:(float)pageLogicalWidth originalPageHeight:(float)pageLogicalHeight maximumShrinkRatio:(float)maximumShrinkRatio adjustViewSize:(BOOL)adjustViewSize paginateScreenContent:(BOOL)paginateScreenContent;
871 #if !PLATFORM(IOS)
872 - (void)_updateSecureInputState;
873 #endif
874 @end
875
876 #if !PLATFORM(IOS)
877 @class NSTextInputContext;
878 @interface NSResponder (AppKitDetails)
879 - (NSTextInputContext *)inputContext;
880 @end
881
882 @interface NSObject (NSTextInputContextDetails)
883 - (BOOL)wantsToHandleMouseEvents;
884 - (BOOL)handleMouseEvent:(NSEvent *)event;
885 @end
886 #endif
887
888 #if !PLATFORM(IOS)
889 @interface WebHTMLView (WebNSTextInputSupport) <NSTextInput>
890 #else
891 @interface WebHTMLView (WebNSTextInputSupport)
892 #endif
893 - (void)_updateSelectionForInputManager;
894 #if PLATFORM(IOS)
895 - (void)doCommandBySelector:(SEL)selector;
896 #endif
897 @end
898
899 @interface WebHTMLView (WebEditingStyleSupport)
900 - (DOMCSSStyleDeclaration *)_emptyStyle;
901 #if !PLATFORM(IOS)
902 - (NSString *)_colorAsString:(NSColor *)color;
903 #endif
904 @end
905
906 @interface NSView (WebHTMLViewFileInternal)
907 - (void)_web_addDescendantWebHTMLViewsToArray:(NSMutableArray *) array;
908 @end
909
910 @interface NSMutableDictionary (WebHTMLViewFileInternal)
911 - (void)_web_setObjectIfNotNil:(id)object forKey:(id)key;
912 @end
913
914 struct WebHTMLViewInterpretKeyEventsParameters {
915     KeyboardEvent* event;
916     bool eventInterpretationHadSideEffects;
917     bool shouldSaveCommands;
918     bool consumedByIM;
919     bool executingSavedKeypressCommands;
920 };
921
922 @interface WebHTMLViewPrivate : NSObject {
923 @public
924     BOOL closed;
925     BOOL ignoringMouseDraggedEvents;
926     BOOL printing;
927     BOOL paginateScreenContent;
928 #if !PLATFORM(IOS)
929     BOOL observingSuperviewNotifications;
930     BOOL observingWindowNotifications;
931     
932     id savedSubviews;
933     BOOL subviewsSetAside;
934 #endif
935
936     NSView *layerHostingView;
937     BOOL drawingIntoLayer;
938
939 #if !PLATFORM(IOS)
940     NSEvent *mouseDownEvent; // Kept after handling the event.
941 #else
942     WebEvent *mouseDownEvent; // Kept after handling the event.
943 #endif
944     BOOL handlingMouseDownEvent;
945 #if !PLATFORM(IOS)    
946     NSEvent *keyDownEvent; // Kept after handling the event.
947 #else
948     WebEvent *keyDownEvent; // Kept after handling the event.
949 #endif
950
951     // A WebHTMLView has a single input context, but we return nil when in non-editable content to avoid making input methods do their work.
952     // This state is saved each time selection changes, because computing it causes style recalc, which is not always safe to do.
953     BOOL exposeInputContext;
954
955 #if !PLATFORM(IOS)
956     // Track whether the view has set a secure input state.
957     BOOL isInSecureInputState;
958
959     BOOL _forceUpdateSecureInputState;
960 #endif
961
962     NSPoint lastScrollPosition;
963     BOOL inScrollPositionChanged;
964
965     WebPluginController *pluginController;
966     
967     NSString *toolTip;
968 #if !PLATFORM(IOS)
969     NSToolTipTag lastToolTipTag;
970 #endif
971     id trackingRectOwner;
972     void *trackingRectUserData;
973     
974     NSTimer *autoscrollTimer;
975 #if !PLATFORM(IOS)    
976     NSEvent *autoscrollTriggerEvent;
977 #else
978     WebEvent *autoscrollTriggerEvent;
979 #endif
980     
981     NSArray *pageRects;
982
983 #if !PLATFORM(IOS)
984     WebTextCompletionController *completionController;
985 #endif
986     
987     BOOL transparentBackground;
988
989     WebHTMLViewInterpretKeyEventsParameters* interpretKeyEventsParameters;
990     
991     WebDataSource *dataSource;
992 #if !PLATFORM(IOS)
993     WebCore::CachedImage* promisedDragTIFFDataSource;
994 #endif
995
996     SEL selectorForDoCommandBySelector;
997
998 #if !PLATFORM(IOS)
999     BOOL installedTrackingArea;
1000     id flagsChangedEventMonitor;
1001     NSRange softSpaceRange;
1002 #endif
1003
1004 #ifndef NDEBUG
1005     BOOL enumeratingSubviews;
1006 #endif
1007
1008 #if ENABLE(SERVICE_CONTROLS)
1009     RetainPtr<WebSharingServicePickerController> currentSharingServicePickerController;
1010 #endif
1011 }
1012 - (void)clear;
1013 @end
1014
1015 #if !PLATFORM(IOS)
1016 static NSCellStateValue kit(TriState state)
1017 {
1018     switch (state) {
1019         case FalseTriState:
1020             return NSOffState;
1021         case TrueTriState:
1022             return NSOnState;
1023         case MixedTriState:
1024             return NSMixedState;
1025     }
1026     ASSERT_NOT_REACHED();
1027     return NSOffState;
1028 }
1029 #endif
1030
1031 @implementation WebHTMLViewPrivate
1032
1033 + (void)initialize
1034 {
1035 #if !PLATFORM(IOS)
1036     JSC::initializeThreading();
1037     WTF::initializeMainThreadToProcessMainThread();
1038     RunLoop::initializeMainRunLoop();
1039 #endif
1040
1041 #if !PLATFORM(IOS)
1042     if (!oldSetCursorForMouseLocationIMP) {
1043         Method setCursorMethod = class_getInstanceMethod([NSWindow class], @selector(_setCursorForMouseLocation:));
1044         ASSERT(setCursorMethod);
1045         oldSetCursorForMouseLocationIMP = method_setImplementation(setCursorMethod, (IMP)setCursor);
1046         ASSERT(oldSetCursorForMouseLocationIMP);
1047     }
1048
1049     method_exchangeImplementations(class_getInstanceMethod([NSView class], @selector(setNeedsDisplayInRect:)), class_getInstanceMethod([NSView class], @selector(_web_setNeedsDisplayInRect:)));
1050 #endif
1051 }
1052
1053 - (void)dealloc
1054 {
1055     if (WebCoreObjCScheduleDeallocateOnMainThread([WebHTMLViewPrivate class], self))
1056         return;
1057
1058     ASSERT(!autoscrollTimer);
1059     ASSERT(!autoscrollTriggerEvent);
1060     
1061 #if !PLATFORM(IOS)
1062     [mouseDownEvent release];
1063     [keyDownEvent release];
1064 #else
1065     if (mouseDownEvent)
1066         CFRelease (mouseDownEvent);
1067     if (keyDownEvent)
1068         CFRelease(keyDownEvent);
1069 #endif
1070     [pluginController release];
1071     [toolTip release];
1072 #if !PLATFORM(IOS)
1073     [completionController release];
1074 #endif
1075     [dataSource release];
1076 #if !PLATFORM(IOS)
1077     if (promisedDragTIFFDataSource)
1078         promisedDragTIFFDataSource->removeClient(promisedDataClient());
1079 #endif
1080
1081     [super dealloc];
1082 }
1083
1084 - (void)clear
1085 {
1086 #if !PLATFORM(IOS)
1087     [mouseDownEvent release];
1088     [keyDownEvent release];
1089 #else
1090     if (mouseDownEvent)
1091         CFRelease(mouseDownEvent);
1092     if (keyDownEvent)
1093         CFRelease(keyDownEvent);
1094 #endif
1095     [pluginController release];
1096     [toolTip release];
1097 #if !PLATFORM(IOS)
1098     [completionController release];
1099 #endif
1100     [dataSource release];
1101 #if !PLATFORM(IOS)
1102     if (promisedDragTIFFDataSource)
1103         promisedDragTIFFDataSource->removeClient(promisedDataClient());
1104 #endif
1105
1106     mouseDownEvent = nil;
1107     keyDownEvent = nil;
1108     pluginController = nil;
1109     toolTip = nil;
1110 #if !PLATFORM(IOS)
1111     completionController = nil;
1112 #endif
1113     dataSource = nil;
1114 #if !PLATFORM(IOS)
1115     promisedDragTIFFDataSource = 0;
1116 #endif
1117
1118     layerHostingView = nil;
1119 }
1120
1121 @end
1122
1123 @implementation WebHTMLView (WebHTMLViewFileInternal)
1124
1125 - (DOMRange *)_documentRange
1126 {
1127     return [[[self _frame] DOMDocument] _documentRange];
1128 }
1129
1130 #if !PLATFORM(IOS)
1131 - (BOOL)_imageExistsAtPaths:(NSArray *)paths
1132 {
1133     NSEnumerator *enumerator = [paths objectEnumerator];
1134     NSString *path;
1135     
1136     while ((path = [enumerator nextObject]) != nil) {
1137         NSString *MIMEType = [[NSURLFileTypeMappings sharedMappings] MIMETypeForExtension:[path pathExtension]];
1138         if (MIMETypeRegistry::isSupportedImageResourceMIMEType(MIMEType))
1139             return YES;
1140     }
1141     
1142     return NO;
1143 }
1144 #endif
1145
1146 - (WebDataSource *)_dataSource
1147 {
1148     return _private->dataSource;
1149 }
1150
1151 - (WebView *)_webView
1152 {
1153     return [_private->dataSource _webView];
1154 }
1155
1156 - (WebFrameView *)_frameView
1157 {
1158     return [[_private->dataSource webFrame] frameView];
1159 }
1160
1161 #if !PLATFORM(IOS)
1162 - (DOMDocumentFragment *)_documentFragmentWithPaths:(NSArray *)paths
1163 {
1164     DOMDocumentFragment *fragment;
1165     NSEnumerator *enumerator = [paths objectEnumerator];
1166     NSMutableArray *domNodes = [[NSMutableArray alloc] init];
1167     NSString *path;
1168     
1169     while ((path = [enumerator nextObject]) != nil) {
1170         // Non-image file types; _web_userVisibleString is appropriate here because this will
1171         // be pasted as visible text.
1172         NSString *url = [[[NSURL fileURLWithPath:path] _webkit_canonicalize] _web_userVisibleString];
1173         [domNodes addObject:[[[self _frame] DOMDocument] createTextNode: url]];
1174     }
1175     
1176     fragment = [[self _frame] _documentFragmentWithNodesAsParagraphs:domNodes]; 
1177     
1178     [domNodes release];
1179     
1180     return [fragment firstChild] != nil ? fragment : nil;
1181 }
1182
1183 + (NSArray *)_excludedElementsForAttributedStringConversion
1184 {
1185     static NSArray *elements = nil;
1186     if (elements == nil) {
1187         elements = [[NSArray alloc] initWithObjects:
1188             // Omit style since we want style to be inline so the fragment can be easily inserted.
1189             @"style",
1190             // Omit xml so the result is not XHTML.
1191             @"xml", 
1192             // Omit tags that will get stripped when converted to a fragment anyway.
1193             @"doctype", @"html", @"head", @"body",
1194             // Omit deprecated tags.
1195             @"applet", @"basefont", @"center", @"dir", @"font", @"isindex", @"menu", @"s", @"strike", @"u",
1196             // Omit object so no file attachments are part of the fragment.
1197             @"object", nil];
1198         CFRetain(elements);
1199     }
1200     return elements;
1201 }
1202
1203 static NSURL* uniqueURLWithRelativePart(NSString *relativePart)
1204 {
1205     CFUUIDRef UUIDRef = CFUUIDCreate(kCFAllocatorDefault);
1206     NSString *UUIDString = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, UUIDRef);
1207     CFRelease(UUIDRef);
1208     NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:@"%@://%@/%@", WebDataProtocolScheme, UUIDString, relativePart]];
1209     CFRelease(UUIDString);
1210
1211     return URL;
1212 }
1213
1214 - (DOMDocumentFragment *)_documentFragmentFromPasteboard:(NSPasteboard *)pasteboard
1215                                                inContext:(DOMRange *)context
1216                                           allowPlainText:(BOOL)allowPlainText
1217 {
1218     NSArray *types = [pasteboard types];
1219     DOMDocumentFragment *fragment = nil;
1220
1221     if ([types containsObject:WebArchivePboardType] &&
1222         (fragment = [self _documentFragmentFromPasteboard:pasteboard 
1223                                                   forType:WebArchivePboardType
1224                                                 inContext:context
1225                                              subresources:0]))
1226         return fragment;
1227                                            
1228     if ([types containsObject:NSFilenamesPboardType] &&
1229         (fragment = [self _documentFragmentFromPasteboard:pasteboard 
1230                                                   forType:NSFilenamesPboardType
1231                                                 inContext:context
1232                                              subresources:0]))
1233         return fragment;
1234     
1235     if ([types containsObject:NSHTMLPboardType] &&
1236         (fragment = [self _documentFragmentFromPasteboard:pasteboard 
1237                                                   forType:NSHTMLPboardType
1238                                                 inContext:context
1239                                              subresources:0]))
1240         return fragment;
1241     
1242     if ([types containsObject:NSRTFDPboardType] &&
1243         (fragment = [self _documentFragmentFromPasteboard:pasteboard 
1244                                                   forType:NSRTFDPboardType
1245                                                 inContext:context
1246                                              subresources:0]))
1247         return fragment;
1248     
1249     if ([types containsObject:NSRTFPboardType] &&
1250         (fragment = [self _documentFragmentFromPasteboard:pasteboard 
1251                                                   forType:NSRTFPboardType
1252                                                 inContext:context
1253                                              subresources:0]))
1254         return fragment;
1255
1256     if ([types containsObject:NSTIFFPboardType] &&
1257         (fragment = [self _documentFragmentFromPasteboard:pasteboard 
1258                                                   forType:NSTIFFPboardType
1259                                                 inContext:context
1260                                              subresources:0]))
1261         return fragment;
1262
1263     if ([types containsObject:NSPDFPboardType] &&
1264         (fragment = [self _documentFragmentFromPasteboard:pasteboard 
1265                                                   forType:NSPDFPboardType
1266                                                 inContext:context
1267                                              subresources:0]))
1268         return fragment;
1269
1270     if ([types containsObject:(NSString*)kUTTypePNG] &&
1271         (fragment = [self _documentFragmentFromPasteboard:pasteboard 
1272                                                   forType:(NSString*)kUTTypePNG
1273                                                 inContext:context
1274                                              subresources:0]))
1275         return fragment;
1276         
1277     if ([types containsObject:NSURLPboardType] &&
1278         (fragment = [self _documentFragmentFromPasteboard:pasteboard 
1279                                                   forType:NSURLPboardType
1280                                                 inContext:context
1281                                              subresources:0]))
1282         return fragment;
1283         
1284     if (allowPlainText && [types containsObject:NSStringPboardType] &&
1285         (fragment = [self _documentFragmentFromPasteboard:pasteboard
1286                                                   forType:NSStringPboardType
1287                                                 inContext:context
1288                                              subresources:0])) {
1289         return fragment;
1290     }
1291     
1292     return nil;
1293 }
1294
1295 - (NSString *)_plainTextFromPasteboard:(NSPasteboard *)pasteboard
1296 {
1297     NSArray *types = [pasteboard types];
1298     
1299     if ([types containsObject:NSStringPboardType])
1300         return [[pasteboard stringForType:NSStringPboardType] precomposedStringWithCanonicalMapping];
1301     
1302     NSAttributedString *attributedString = nil;
1303     NSString *string;
1304
1305     if ([types containsObject:NSRTFDPboardType])
1306         attributedString = [[NSAttributedString alloc] initWithRTFD:[pasteboard dataForType:NSRTFDPboardType] documentAttributes:NULL];
1307     if (attributedString == nil && [types containsObject:NSRTFPboardType])
1308         attributedString = [[NSAttributedString alloc] initWithRTF:[pasteboard dataForType:NSRTFPboardType] documentAttributes:NULL];
1309     if (attributedString != nil) {
1310         string = [[attributedString string] copy];
1311         [attributedString release];
1312         return [string autorelease];
1313     }
1314     
1315     if ([types containsObject:NSFilenamesPboardType]) {
1316         string = [[pasteboard propertyListForType:NSFilenamesPboardType] componentsJoinedByString:@"\n"];
1317         if (string != nil)
1318             return string;
1319     }
1320     
1321     NSURL *URL;
1322     
1323     if ((URL = [NSURL URLFromPasteboard:pasteboard])) {
1324         string = [URL _web_userVisibleString];
1325         if ([string length] > 0)
1326             return string;
1327     }
1328     
1329     return nil;
1330 }
1331
1332 - (void)_pasteWithPasteboard:(NSPasteboard *)pasteboard allowPlainText:(BOOL)allowPlainText
1333 {
1334     WebView *webView = [[self _webView] retain];
1335     [webView _setInsertionPasteboard:pasteboard];
1336
1337     DOMRange *range = [self _selectedRange];
1338     Frame* coreFrame = core([self _frame]);
1339
1340     DOMDocumentFragment *fragment = [self _documentFragmentFromPasteboard:pasteboard inContext:range allowPlainText:allowPlainText];
1341     if (fragment && [self _shouldInsertFragment:fragment replacingDOMRange:range givenAction:WebViewInsertActionPasted])
1342         coreFrame->editor().pasteAsFragment(*core(fragment), [self _canSmartReplaceWithPasteboard:pasteboard], false);
1343
1344     [webView _setInsertionPasteboard:nil];
1345     [webView release];
1346 }
1347
1348 - (void)_pasteAsPlainTextWithPasteboard:(NSPasteboard *)pasteboard 
1349
1350     WebView *webView = [[self _webView] retain]; 
1351     [webView _setInsertionPasteboard:pasteboard]; 
1352
1353     NSString *text = [self _plainTextFromPasteboard:pasteboard]; 
1354     if ([self _shouldReplaceSelectionWithText:text givenAction:WebViewInsertActionPasted]) 
1355         [[self _frame] _replaceSelectionWithText:text selectReplacement:NO smartReplace:[self _canSmartReplaceWithPasteboard:pasteboard]]; 
1356
1357     [webView _setInsertionPasteboard:nil]; 
1358     [webView release];
1359 }
1360
1361 - (void)_postFakeMouseMovedEventForFlagsChangedEvent:(NSEvent *)flagsChangedEvent
1362 {
1363 #pragma clang diagnostic push
1364 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1365     NSEvent *fakeEvent = [NSEvent mouseEventWithType:NSMouseMoved location:flagsChangedEvent.window.mouseLocationOutsideOfEventStream
1366         modifierFlags:flagsChangedEvent.modifierFlags timestamp:flagsChangedEvent.timestamp windowNumber:flagsChangedEvent.windowNumber
1367         context:nullptr eventNumber:0 clickCount:0 pressure:0];
1368 #pragma clang diagnostic pop
1369     [self mouseMoved:fakeEvent];
1370 }
1371
1372 // This method is needed to support Mac OS X services.
1373 - (BOOL)readSelectionFromPasteboard:(NSPasteboard *)pasteboard 
1374
1375     Frame* coreFrame = core([self _frame]); 
1376     if (!coreFrame) 
1377         return NO; 
1378     if (coreFrame->selection().selection().isContentRichlyEditable())
1379         [self _pasteWithPasteboard:pasteboard allowPlainText:YES]; 
1380     else 
1381         [self _pasteAsPlainTextWithPasteboard:pasteboard]; 
1382     return YES; 
1383 }
1384
1385 - (void)_removeSuperviewObservers
1386 {
1387     if (!_private || !_private->observingSuperviewNotifications)
1388         return;
1389     
1390     NSView *superview = [self superview];
1391     if (!superview || ![self window])
1392         return;
1393     
1394     NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
1395     [notificationCenter removeObserver:self name:NSViewFrameDidChangeNotification object:superview];
1396     [notificationCenter removeObserver:self name:NSViewBoundsDidChangeNotification object:superview];
1397     
1398     _private->observingSuperviewNotifications = false;
1399 }
1400
1401 - (void)_removeWindowObservers
1402 {
1403     if (!_private->observingWindowNotifications)
1404         return;
1405     
1406     NSWindow *window = [self window];
1407     if (!window)
1408         return;
1409     
1410     NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
1411     [notificationCenter removeObserver:self name:NSWindowDidBecomeKeyNotification object:nil];
1412     [notificationCenter removeObserver:self name:NSWindowDidResignKeyNotification object:nil];
1413     [notificationCenter removeObserver:self name:WKWindowWillOrderOnScreenNotification() object:window];
1414     [notificationCenter removeObserver:self name:WKWindowWillOrderOffScreenNotification() object:window];
1415     [notificationCenter removeObserver:self name:NSWindowWillCloseNotification object:window];
1416     
1417     _private->observingWindowNotifications = false;
1418 }
1419 #endif // !PLATFORM(IOS)
1420
1421 - (BOOL)_shouldInsertFragment:(DOMDocumentFragment *)fragment replacingDOMRange:(DOMRange *)range givenAction:(WebViewInsertAction)action
1422 {
1423     WebView *webView = [self _webView];
1424     DOMNode *child = [fragment firstChild];
1425     if ([fragment lastChild] == child && [child isKindOfClass:[DOMCharacterData class]])
1426         return [[webView _editingDelegateForwarder] webView:webView shouldInsertText:[(DOMCharacterData *)child data] replacingDOMRange:range givenAction:action];
1427     return [[webView _editingDelegateForwarder] webView:webView shouldInsertNode:fragment replacingDOMRange:range givenAction:action];
1428 }
1429
1430 - (BOOL)_shouldInsertText:(NSString *)text replacingDOMRange:(DOMRange *)range givenAction:(WebViewInsertAction)action
1431 {
1432     WebView *webView = [self _webView];
1433     return [[webView _editingDelegateForwarder] webView:webView shouldInsertText:text replacingDOMRange:range givenAction:action];
1434 }
1435
1436 - (BOOL)_shouldReplaceSelectionWithText:(NSString *)text givenAction:(WebViewInsertAction)action
1437 {
1438     return [self _shouldInsertText:text replacingDOMRange:[self _selectedRange] givenAction:action];
1439 }
1440
1441 - (DOMRange *)_selectedRange
1442 {
1443     Frame* coreFrame = core([self _frame]);
1444     return coreFrame ? kit(coreFrame->selection().toNormalizedRange().get()) : nil;
1445 }
1446
1447 - (BOOL)_shouldDeleteRange:(DOMRange *)range
1448 {
1449     Frame* coreFrame = core([self _frame]);
1450     return coreFrame && coreFrame->editor().shouldDeleteRange(core(range));
1451 }
1452
1453 #if !PLATFORM(IOS)
1454 - (NSView *)_hitViewForEvent:(NSEvent *)event
1455 {
1456     // Usually, we hack AK's hitTest method to catch all events at the topmost WebHTMLView.  
1457     // Callers of this method, however, want to query the deepest view instead.
1458     forceNSViewHitTest = YES;
1459     NSView *hitView = [(NSView *)[[self window] contentView] hitTest:[event locationInWindow]];
1460     forceNSViewHitTest = NO;    
1461     return hitView;
1462 }
1463 #endif
1464
1465 #if !PLATFORM(IOS)
1466 - (void)_writeSelectionWithPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard cachedAttributedString:(NSAttributedString *)attributedString
1467 {
1468     // Put HTML on the pasteboard.
1469     if ([types containsObject:WebArchivePboardType]) {
1470         if (RefPtr<LegacyWebArchive> coreArchive = LegacyWebArchive::createFromSelection(core([self _frame]))) {
1471             if (RetainPtr<CFDataRef> data = coreArchive ? coreArchive->rawDataRepresentation() : 0)
1472                 [pasteboard setData:(NSData *)data.get() forType:WebArchivePboardType];
1473         }
1474     }
1475     
1476     // Put the attributed string on the pasteboard (RTF/RTFD format).
1477     if ([types containsObject:NSRTFDPboardType]) {
1478         if (attributedString == nil) {
1479             attributedString = [self selectedAttributedString];
1480         }        
1481         NSData *RTFDData = [attributedString RTFDFromRange:NSMakeRange(0, [attributedString length]) documentAttributes:@{ }];
1482         [pasteboard setData:RTFDData forType:NSRTFDPboardType];
1483     }        
1484     if ([types containsObject:NSRTFPboardType]) {
1485         if (!attributedString)
1486             attributedString = [self selectedAttributedString];
1487         if ([attributedString containsAttachments])
1488             attributedString = attributedStringByStrippingAttachmentCharacters(attributedString);
1489         NSData *RTFData = [attributedString RTFFromRange:NSMakeRange(0, [attributedString length]) documentAttributes:@{ }];
1490         [pasteboard setData:RTFData forType:NSRTFPboardType];
1491     }
1492     
1493     // Put plain string on the pasteboard.
1494     if ([types containsObject:NSStringPboardType]) {
1495         // Map &nbsp; to a plain old space because this is better for source code, other browsers do it,
1496         // and because HTML forces you to do this any time you want two spaces in a row.
1497         NSMutableString *s = [[self selectedString] mutableCopy];
1498         const unichar NonBreakingSpaceCharacter = 0xA0;
1499         NSString *NonBreakingSpaceString = [NSString stringWithCharacters:&NonBreakingSpaceCharacter length:1];
1500         [s replaceOccurrencesOfString:NonBreakingSpaceString withString:@" " options:0 range:NSMakeRange(0, [s length])];
1501         [pasteboard setString:s forType:NSStringPboardType];
1502         [s release];
1503     }
1504     
1505     if ([self _canSmartCopyOrDelete] && [types containsObject:WebSmartPastePboardType]) {
1506         [pasteboard setData:nil forType:WebSmartPastePboardType];
1507     }
1508 }
1509 #endif // !PLATFORM(IOS)
1510
1511 #if !PLATFORM(IOS)
1512 - (void)_setMouseDownEvent:(NSEvent *)event
1513 #else
1514 - (void)_setMouseDownEvent:(WebEvent *)event
1515 #endif
1516 {
1517 #if !PLATFORM(IOS)
1518 #pragma clang diagnostic push
1519 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1520     ASSERT(!event || [event type] == NSLeftMouseDown || [event type] == NSRightMouseDown || [event type] == NSOtherMouseDown);
1521 #pragma clang diagnostic pop
1522 #else
1523     ASSERT(!event || event.type == WebEventMouseDown);
1524 #endif
1525
1526     if (event == _private->mouseDownEvent)
1527         return;
1528
1529     [event retain];
1530     [_private->mouseDownEvent release];
1531     _private->mouseDownEvent = event;
1532 }
1533
1534 - (WebHTMLView *)_topHTMLView
1535 {
1536     // FIXME: this can fail if the dataSource is nil, which happens when the WebView is tearing down from the window closing.
1537     WebHTMLView *view = (WebHTMLView *)[[[[_private->dataSource _webView] mainFrame] frameView] documentView];
1538     ASSERT(!view || [view isKindOfClass:[WebHTMLView class]]);
1539     return view;
1540 }
1541
1542 - (BOOL)_isTopHTMLView
1543 {
1544     // FIXME: this should be a cached boolean that doesn't rely on _topHTMLView since that can fail (see _topHTMLView).
1545     return self == [self _topHTMLView];
1546 }
1547
1548 #if !PLATFORM(IOS)
1549 - (void)_web_setPrintingModeRecursive
1550 {
1551     [self _setPrinting:YES minimumPageLogicalWidth:0 logicalHeight:0 originalPageWidth:0 originalPageHeight:0 maximumShrinkRatio:0 adjustViewSize:NO paginateScreenContent:[self _isInScreenPaginationMode]];
1552
1553 #ifndef NDEBUG
1554     _private->enumeratingSubviews = YES;
1555 #endif
1556
1557     NSMutableArray *descendantWebHTMLViews = [[NSMutableArray alloc] init];
1558
1559     [self _web_addDescendantWebHTMLViewsToArray:descendantWebHTMLViews];
1560
1561     unsigned count = [descendantWebHTMLViews count];
1562     for (unsigned i = 0; i < count; ++i)
1563         [[descendantWebHTMLViews objectAtIndex:i] _setPrinting:YES minimumPageLogicalWidth:0 logicalHeight:0 originalPageWidth:0 originalPageHeight:0 maximumShrinkRatio:0 adjustViewSize:NO paginateScreenContent:[self _isInScreenPaginationMode]];
1564
1565     [descendantWebHTMLViews release];
1566
1567 #ifndef NDEBUG
1568     _private->enumeratingSubviews = NO;
1569 #endif
1570 }
1571
1572 - (void)_web_clearPrintingModeRecursive
1573 {
1574     [self _setPrinting:NO minimumPageLogicalWidth:0 logicalHeight:0 originalPageWidth:0 originalPageHeight:0 maximumShrinkRatio:0 adjustViewSize:NO paginateScreenContent:[self _isInScreenPaginationMode]];
1575
1576 #ifndef NDEBUG
1577     _private->enumeratingSubviews = YES;
1578 #endif
1579
1580     NSMutableArray *descendantWebHTMLViews = [[NSMutableArray alloc] init];
1581
1582     [self _web_addDescendantWebHTMLViewsToArray:descendantWebHTMLViews];
1583
1584     unsigned count = [descendantWebHTMLViews count];
1585     for (unsigned i = 0; i < count; ++i)
1586         [[descendantWebHTMLViews objectAtIndex:i] _setPrinting:NO minimumPageLogicalWidth:0 logicalHeight:0 originalPageWidth:0 originalPageHeight:0 maximumShrinkRatio:0 adjustViewSize:NO paginateScreenContent:[self _isInScreenPaginationMode]];
1587
1588     [descendantWebHTMLViews release];
1589
1590 #ifndef NDEBUG
1591     _private->enumeratingSubviews = NO;
1592 #endif
1593 }
1594
1595 - (void)_web_setPrintingModeRecursiveAndAdjustViewSize
1596 {
1597     [self _setPrinting:YES minimumPageLogicalWidth:0 logicalHeight:0 originalPageWidth:0 originalPageHeight:0 maximumShrinkRatio:0 adjustViewSize:YES paginateScreenContent:[self _isInScreenPaginationMode]];
1598
1599 #ifndef NDEBUG
1600     _private->enumeratingSubviews = YES;
1601 #endif
1602
1603     NSMutableArray *descendantWebHTMLViews = [[NSMutableArray alloc] init];
1604
1605     [self _web_addDescendantWebHTMLViewsToArray:descendantWebHTMLViews];
1606
1607     unsigned count = [descendantWebHTMLViews count];
1608     for (unsigned i = 0; i < count; ++i)
1609         [[descendantWebHTMLViews objectAtIndex:i] _setPrinting:YES minimumPageLogicalWidth:0 logicalHeight:0 originalPageWidth:0 originalPageHeight:0 maximumShrinkRatio:0 adjustViewSize:YES paginateScreenContent:[self _isInScreenPaginationMode]];
1610
1611     [descendantWebHTMLViews release];
1612
1613 #ifndef NDEBUG
1614     _private->enumeratingSubviews = NO;
1615 #endif
1616 }
1617 #endif // !PLATFORM(IOS)
1618
1619 @end
1620
1621 @implementation WebHTMLView (WebPrivate)
1622
1623 + (NSArray *)supportedMIMETypes
1624 {
1625     return [WebHTMLRepresentation supportedMIMETypes];
1626 }
1627
1628 + (NSArray *)supportedMediaMIMETypes
1629 {
1630     return [WebHTMLRepresentation supportedMediaMIMETypes];
1631 }
1632
1633 + (NSArray *)supportedImageMIMETypes
1634 {
1635     return [WebHTMLRepresentation supportedImageMIMETypes];
1636 }
1637
1638 + (NSArray *)supportedNonImageMIMETypes
1639 {
1640     return [WebHTMLRepresentation supportedNonImageMIMETypes];
1641 }
1642
1643 + (NSArray *)unsupportedTextMIMETypes
1644 {
1645     return [WebHTMLRepresentation unsupportedTextMIMETypes];
1646 }
1647
1648 #if PLATFORM(IOS)
1649 - (void)mouseMoved:(WebEvent *)event
1650 {
1651     Frame* frame = core([self _frame]);
1652     if (frame)
1653         frame->eventHandler().mouseMoved(event);
1654 }
1655 #endif
1656
1657 #if !PLATFORM(IOS)
1658 + (void)_postFlagsChangedEvent:(NSEvent *)flagsChangedEvent
1659 {
1660     // This is obsolete SPI needed only for older versions of Safari
1661 }
1662
1663 - (id)_bridge
1664 {
1665     // This method exists to maintain compatibility with Leopard's Dictionary.app, since it
1666     // calls _bridge to get access to convertNSRangeToDOMRange: and convertDOMRangeToNSRange:.
1667     // Return the WebFrame, which implements the compatibility methods. <rdar://problem/6002160>
1668     return [self _frame];
1669 }
1670
1671 - (void)_updateMouseoverWithFakeEvent
1672 {
1673 #pragma clang diagnostic push
1674 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1675     NSEvent *fakeEvent = [NSEvent mouseEventWithType:NSMouseMoved
1676         location:[[self window] convertScreenToBase:[NSEvent mouseLocation]]
1677         modifierFlags:[[NSApp currentEvent] modifierFlags]
1678         timestamp:[NSDate timeIntervalSinceReferenceDate]
1679         windowNumber:[[self window] windowNumber]
1680         context:nullptr
1681         eventNumber:0 clickCount:0 pressure:0];
1682 #pragma clang diagnostic pop
1683
1684     [self _updateMouseoverWithEvent:fakeEvent];
1685 }
1686 #endif // !PLATFORM(IOS)
1687
1688 - (void)_frameOrBoundsChanged
1689 {
1690     WebView *webView = [self _webView];
1691     WebDynamicScrollBarsView *scrollView = [[[webView mainFrame] frameView] _scrollView];
1692
1693     NSPoint origin = [[self superview] bounds].origin;
1694     if (!NSEqualPoints(_private->lastScrollPosition, origin) && ![scrollView inProgrammaticScroll]) {
1695         if (Frame* coreFrame = core([self _frame])) {
1696             if (FrameView* coreView = coreFrame->view()) {
1697                 _private->inScrollPositionChanged = YES;
1698                 coreView->scrollOffsetChangedViaPlatformWidget(IntPoint(_private->lastScrollPosition), IntPoint(origin));
1699                 _private->inScrollPositionChanged = NO;
1700             }
1701         }
1702     
1703 #if !PLATFORM(IOS)
1704         [_private->completionController endRevertingChange:NO moveLeft:NO];
1705 #endif
1706         
1707         [[webView _UIDelegateForwarder] webView:webView didScrollDocumentInFrameView:[self _frameView]];
1708     }
1709     _private->lastScrollPosition = origin;
1710 }
1711
1712 - (void)_setAsideSubviews
1713 {
1714 #if !PLATFORM(IOS)
1715     ASSERT(!_private->subviewsSetAside);
1716     ASSERT(_private->savedSubviews == nil);
1717     _private->savedSubviews = _subviews;
1718     // We need to keep the layer-hosting view in the subviews, otherwise the layers flash.
1719     if (_private->layerHostingView) {
1720         NSArray* newSubviews = [[NSArray alloc] initWithObjects:_private->layerHostingView, nil];
1721         _subviews = newSubviews;
1722     } else
1723         _subviews = nil;
1724     _private->subviewsSetAside = YES;
1725 #endif
1726  }
1727  
1728  - (void)_restoreSubviews
1729  {
1730 #if !PLATFORM(IOS)
1731     ASSERT(_private->subviewsSetAside);
1732     if (_private->layerHostingView) {
1733         [_subviews release];
1734         _subviews = _private->savedSubviews;
1735     } else {
1736         ASSERT(_subviews == nil);
1737         _subviews = _private->savedSubviews;
1738     }
1739     _private->savedSubviews = nil;
1740     _private->subviewsSetAside = NO;
1741 #endif
1742 }
1743
1744 #ifndef NDEBUG
1745
1746 - (void)didAddSubview:(NSView *)subview
1747 {
1748     if (_private->enumeratingSubviews)
1749         LOG(View, "A view of class %s was added during subview enumeration for layout or printing mode change. This view might paint without first receiving layout.", object_getClassName([subview class]));
1750 }
1751 #endif
1752
1753
1754 - (void)viewWillDraw
1755 {
1756     // On window close we will be called when the datasource is nil, then hit an assert in _topHTMLView
1757     // So check if the dataSource is nil before calling [self _isTopHTMLView], this can be removed
1758     // once the FIXME in _isTopHTMLView is fixed.
1759     if (_private->dataSource && [self _isTopHTMLView]) {
1760         [self _web_updateLayoutAndStyleIfNeededRecursive];
1761         [[self _webView] _flushCompositingChanges];
1762     }
1763
1764     [super viewWillDraw];
1765 }
1766
1767
1768 #if !PLATFORM(IOS)
1769 // Don't let AppKit even draw subviews. We take care of that.
1770 - (void)_recursiveDisplayRectIfNeededIgnoringOpacity:(NSRect)rect isVisibleRect:(BOOL)isVisibleRect rectIsVisibleRectForView:(NSView *)visibleView topView:(BOOL)topView
1771 {
1772     // This helps when we print as part of a larger print process.
1773     // If the WebHTMLView itself is what we're printing, then we will never have to do this.
1774     BOOL wasInPrintingMode = _private->printing;
1775     BOOL isPrinting = ![NSGraphicsContext currentContextDrawingToScreen];
1776     if (isPrinting) {
1777         if (!wasInPrintingMode)
1778             [self _web_setPrintingModeRecursive];
1779         else
1780             [self _web_updateLayoutAndStyleIfNeededRecursive];
1781     } else if (wasInPrintingMode)
1782         [self _web_clearPrintingModeRecursive];
1783
1784     // There are known cases where -viewWillDraw is not called on all views being drawn.
1785     // See <rdar://problem/6964278> for example. Performing layout at this point prevents us from
1786     // trying to paint without layout (which WebCore now refuses to do, instead bailing out without
1787     // drawing at all), but we may still fail to update any regions dirtied by the layout which are
1788     // not already dirty. 
1789     if ([self _needsLayout]) {
1790         NSInteger rectCount;
1791         [self getRectsBeingDrawn:0 count:&rectCount];
1792         if (rectCount) {
1793             LOG_ERROR("View needs layout. Either -viewWillDraw wasn't called or layout was invalidated during the display operation. Performing layout now.");
1794             [self _web_updateLayoutAndStyleIfNeededRecursive];
1795         }
1796     }
1797
1798     [self _setAsideSubviews];
1799     [super _recursiveDisplayRectIfNeededIgnoringOpacity:rect isVisibleRect:isVisibleRect rectIsVisibleRectForView:visibleView topView:topView];
1800     [self _restoreSubviews];
1801
1802     if (wasInPrintingMode != isPrinting) {
1803         if (wasInPrintingMode)
1804             [self _web_setPrintingModeRecursive];
1805         else
1806             [self _web_clearPrintingModeRecursive];
1807     }
1808 }
1809
1810 // Don't let AppKit even draw subviews. We take care of that.
1811 - (void)_recursiveDisplayAllDirtyWithLockFocus:(BOOL)needsLockFocus visRect:(NSRect)visRect
1812 {
1813     BOOL needToSetAsideSubviews = !_private->subviewsSetAside;
1814
1815     BOOL wasInPrintingMode = _private->printing;
1816     BOOL isPrinting = ![NSGraphicsContext currentContextDrawingToScreen];
1817
1818     if (needToSetAsideSubviews) {
1819         // This helps when we print as part of a larger print process.
1820         // If the WebHTMLView itself is what we're printing, then we will never have to do this.
1821         if (isPrinting) {
1822             if (!wasInPrintingMode)
1823                 [self _web_setPrintingModeRecursive];
1824             else
1825                 [self _web_updateLayoutAndStyleIfNeededRecursive];
1826         } else if (wasInPrintingMode)
1827             [self _web_clearPrintingModeRecursive];
1828
1829
1830         [self _setAsideSubviews];
1831     }
1832
1833     [super _recursiveDisplayAllDirtyWithLockFocus:needsLockFocus visRect:visRect];
1834
1835     if (needToSetAsideSubviews) {
1836         if (wasInPrintingMode != isPrinting) {
1837             if (wasInPrintingMode)
1838                 [self _web_setPrintingModeRecursive];
1839             else
1840                 [self _web_clearPrintingModeRecursive];
1841         }
1842
1843         [self _restoreSubviews];
1844     }
1845 }
1846
1847 // Don't let AppKit even draw subviews. We take care of that.
1848 - (void)_recursive:(BOOL)recurse displayRectIgnoringOpacity:(NSRect)displayRect inContext:(NSGraphicsContext *)context topView:(BOOL)topView
1849 {
1850     [self _setAsideSubviews];
1851     [super _recursive:recurse displayRectIgnoringOpacity:displayRect inContext:context topView:topView];
1852     [self _restoreSubviews];
1853 }
1854
1855 // Don't let AppKit even draw subviews. We take care of that.
1856 - (void)_recursive:(BOOL)recurseX displayRectIgnoringOpacity:(NSRect)displayRect inGraphicsContext:(NSGraphicsContext *)graphicsContext CGContext:(CGContextRef)ctx topView:(BOOL)isTopView shouldChangeFontReferenceColor:(BOOL)shouldChangeFontReferenceColor
1857 {
1858     BOOL didSetAsideSubviews = NO;
1859
1860     if (!_private->subviewsSetAside) {
1861         [self _setAsideSubviews];
1862         didSetAsideSubviews = YES;
1863     }
1864     
1865     [super _recursive:recurseX displayRectIgnoringOpacity:displayRect inGraphicsContext:graphicsContext CGContext:ctx topView:isTopView shouldChangeFontReferenceColor:shouldChangeFontReferenceColor];
1866
1867     if (didSetAsideSubviews)
1868         [self _restoreSubviews];
1869 }
1870 #endif // !PLATFORM(IOS)
1871
1872 - (BOOL)_insideAnotherHTMLView
1873 {
1874     return self != [self _topHTMLView];
1875 }
1876
1877 #if !PLATFORM(IOS)
1878 static BOOL isQuickLookEvent(NSEvent *event)
1879 {
1880 #pragma clang diagnostic push
1881 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1882     const int kCGSEventSystemSubtypeHotKeyCombinationReleased = 9;
1883     return [event type] == NSSystemDefined && [event subtype] == kCGSEventSystemSubtypeHotKeyCombinationReleased && [event data1] == 'lkup';
1884 #pragma clang diagnostic pop
1885 }
1886 #endif
1887
1888 - (NSView *)hitTest:(NSPoint)point
1889 {
1890     // WebHTMLView objects handle all events for objects inside them.
1891     // To get those events, we prevent hit testing from AppKit.
1892
1893     // But there are three exceptions to this:
1894     //   1) For right mouse clicks and control clicks we don't yet have an implementation
1895     //      that works for nested views, so we let the hit testing go through the
1896     //      standard NSView code path (needs to be fixed, see bug 4361618).
1897     //   2) Java depends on doing a hit test inside it's mouse moved handling,
1898     //      so we let the hit testing go through the standard NSView code path
1899     //      when the current event is a mouse move (except when we are calling
1900     //      from _updateMouseoverWithEvent, so we have to use a global,
1901     //      forceWebHTMLViewHitTest, for that)
1902     //   3) The acceptsFirstMouse: and shouldDelayWindowOrderingForEvent: methods
1903     //      both need to figure out which view to check with inside the WebHTMLView.
1904     //      They use a global to change the behavior of hitTest: so they can get the
1905     //      right view. The global is forceNSViewHitTest and the method they use to
1906     //      do the hit testing is _hitViewForEvent:. (But this does not work correctly
1907     //      when there is HTML overlapping the view, see bug 4361626)
1908     //   4) NSAccessibilityHitTest relies on this for checking the cursor position.
1909     //      Our check for that is whether the event is NSFlagsChanged.  This works
1910     //      for VoiceOver's Control-Option-F5 command (move focus to item under cursor)
1911     //      and Dictionary's Command-Control-D (open dictionary popup for item under cursor).
1912     //      This is of course a hack.
1913
1914     if (_private->closed)
1915         return nil;
1916
1917 #if PLATFORM(IOS)
1918     // Preserve <rdar://problem/7992472> behavior for third party applications. See <rdar://problem/8463725>.
1919     if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_MULTIPLE_IFRAME_TOUCH_EVENT_DISPATCH)) {
1920         WebEvent *event = [WAKWindow currentEvent];
1921         if (event != NULL && event.type == WebEventMouseDown && [self mouse:point inRect:[self frame]])
1922             return self;
1923         NSView *view = [super hitTest:point];
1924         
1925         // Find the clicked document view
1926         while (view && ![view conformsToProtocol:@protocol(WebDocumentView)])
1927             view = [view superview];
1928             
1929         return view;
1930     }
1931 #else
1932     BOOL captureHitsOnSubviews;
1933     if (forceNSViewHitTest)
1934         captureHitsOnSubviews = NO;
1935     else if (forceWebHTMLViewHitTest)
1936         captureHitsOnSubviews = YES;
1937     else {
1938         // FIXME: Why doesn't this include mouse entered/exited events, or other mouse button events?
1939         NSEvent *event = [[self window] currentEvent];
1940 #pragma clang diagnostic push
1941 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1942         captureHitsOnSubviews = !([event type] == NSMouseMoved
1943             || [event type] == NSRightMouseDown
1944             || ([event type] == NSLeftMouseDown && ([event modifierFlags] & NSControlKeyMask) != 0)
1945             || [event type] == NSFlagsChanged
1946             || isQuickLookEvent(event));
1947 #pragma clang diagnostic pop
1948     }
1949
1950     if (!captureHitsOnSubviews) {
1951         NSView* hitView = [super hitTest:point];
1952         if (_private && hitView == _private->layerHostingView)
1953             hitView = self;
1954         return hitView;
1955     }
1956 #endif // !PLATFORM(IOS)
1957
1958     if ([[self superview] mouse:point inRect:[self frame]])
1959         return self;
1960     return nil;
1961 }
1962
1963 - (void)_clearLastHitViewIfSelf
1964 {
1965     if (lastHitView == self)
1966         lastHitView = nil;
1967 }
1968
1969 #if !PLATFORM(IOS)
1970 - (NSTrackingRectTag)addTrackingRect:(NSRect)rect owner:(id)owner userData:(void *)data assumeInside:(BOOL)assumeInside
1971 {
1972     ASSERT(_private->trackingRectOwner == nil);
1973     _private->trackingRectOwner = owner;
1974     _private->trackingRectUserData = data;
1975     return TRACKING_RECT_TAG;
1976 }
1977
1978 - (NSTrackingRectTag)_addTrackingRect:(NSRect)rect owner:(id)owner userData:(void *)data assumeInside:(BOOL)assumeInside useTrackingNum:(int)tag
1979 {
1980     ASSERT(tag == 0 || tag == TRACKING_RECT_TAG);
1981     ASSERT(_private->trackingRectOwner == nil);
1982     _private->trackingRectOwner = owner;
1983     _private->trackingRectUserData = data;
1984     return TRACKING_RECT_TAG;
1985 }
1986
1987 - (void)_addTrackingRects:(NSRect *)rects owner:(id)owner userDataList:(void **)userDataList assumeInsideList:(BOOL *)assumeInsideList trackingNums:(NSTrackingRectTag *)trackingNums count:(int)count
1988 {
1989     ASSERT(count == 1);
1990     ASSERT(trackingNums[0] == 0 || trackingNums[0] == TRACKING_RECT_TAG);
1991     ASSERT(_private->trackingRectOwner == nil);
1992     _private->trackingRectOwner = owner;
1993     _private->trackingRectUserData = userDataList[0];
1994     trackingNums[0] = TRACKING_RECT_TAG;
1995 }
1996
1997 - (void)removeTrackingRect:(NSTrackingRectTag)tag
1998 {
1999     if (tag == 0)
2000         return;
2001     
2002     if (_private && (tag == TRACKING_RECT_TAG)) {
2003         _private->trackingRectOwner = nil;
2004         return;
2005     }
2006     
2007     if (_private && (tag == _private->lastToolTipTag)) {
2008         [super removeTrackingRect:tag];
2009         _private->lastToolTipTag = 0;
2010         return;
2011     }
2012     
2013     // If any other tracking rect is being removed, we don't know how it was created
2014     // and it's possible there's a leak involved (see 3500217)
2015     ASSERT_NOT_REACHED();
2016 }
2017
2018 - (void)_removeTrackingRects:(NSTrackingRectTag *)tags count:(int)count
2019 {
2020     int i;
2021     for (i = 0; i < count; ++i) {
2022         int tag = tags[i];
2023         if (tag == 0)
2024             continue;
2025         ASSERT(tag == TRACKING_RECT_TAG);
2026         if (_private != nil) {
2027             _private->trackingRectOwner = nil;
2028         }
2029     }
2030 }
2031
2032 - (void)_sendToolTipMouseExited
2033 {
2034     // Nothing matters except window, trackingNumber, and userData.
2035 #pragma clang diagnostic push
2036 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
2037     NSEvent *fakeEvent = [NSEvent enterExitEventWithType:NSMouseExited
2038         location:NSMakePoint(0, 0)
2039         modifierFlags:0
2040         timestamp:0
2041         windowNumber:[[self window] windowNumber]
2042         context:NULL
2043         eventNumber:0
2044         trackingNumber:TRACKING_RECT_TAG
2045         userData:_private->trackingRectUserData];
2046 #pragma clang diagnostic pop
2047     [_private->trackingRectOwner mouseExited:fakeEvent];
2048 }
2049
2050 - (void)_sendToolTipMouseEntered
2051 {
2052 #pragma clang diagnostic push
2053 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
2054     // Nothing matters except window, trackingNumber, and userData.
2055     NSEvent *fakeEvent = [NSEvent enterExitEventWithType:NSMouseEntered
2056         location:NSMakePoint(0, 0)
2057         modifierFlags:0
2058         timestamp:0
2059         windowNumber:[[self window] windowNumber]
2060         context:NULL
2061         eventNumber:0
2062         trackingNumber:TRACKING_RECT_TAG
2063         userData:_private->trackingRectUserData];
2064     [_private->trackingRectOwner mouseEntered:fakeEvent];
2065 #pragma clang diagnostic pop
2066 }
2067 #endif // !PLATFORM(IOS)
2068
2069 - (void)_setToolTip:(NSString *)string
2070 {
2071 #if !PLATFORM(IOS)
2072     NSString *toolTip = [string length] == 0 ? nil : string;
2073     NSString *oldToolTip = _private->toolTip;
2074     if ((toolTip == nil || oldToolTip == nil) ? toolTip == oldToolTip : [toolTip isEqualToString:oldToolTip]) {
2075         return;
2076     }
2077     if (oldToolTip) {
2078         [self _sendToolTipMouseExited];
2079         [oldToolTip release];
2080     }
2081     _private->toolTip = [toolTip copy];
2082     if (toolTip) {
2083         // See radar 3500217 for why we remove all tooltips rather than just the single one we created.
2084         [self removeAllToolTips];
2085         NSRect wideOpenRect = NSMakeRect(-100000, -100000, 200000, 200000);
2086         _private->lastToolTipTag = [self addToolTipRect:wideOpenRect owner:self userData:NULL];
2087         [self _sendToolTipMouseEntered];
2088     }
2089 #endif
2090 }
2091
2092 #if !PLATFORM(IOS)
2093 - (NSString *)view:(NSView *)view stringForToolTip:(NSToolTipTag)tag point:(NSPoint)point userData:(void *)data
2094 {
2095     return [[_private->toolTip copy] autorelease];
2096 }
2097
2098 static bool mouseEventIsPartOfClickOrDrag(NSEvent *event)
2099 {
2100     switch ([event type]) {
2101 #pragma clang diagnostic push
2102 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
2103         case NSLeftMouseDown:
2104         case NSLeftMouseUp:
2105         case NSLeftMouseDragged:
2106         case NSRightMouseDown:
2107         case NSRightMouseUp:
2108         case NSRightMouseDragged:
2109         case NSOtherMouseDown:
2110         case NSOtherMouseUp:
2111         case NSOtherMouseDragged:
2112 #pragma clang diagnostic pop
2113             return true;
2114         default:
2115             return false;
2116     }
2117 }
2118
2119 - (void)_updateMouseoverWithEvent:(NSEvent *)event
2120 {
2121     if (_private->closed)
2122         return;
2123
2124     NSView *contentView = [[event window] contentView];
2125     NSPoint locationForHitTest = [[contentView superview] convertPoint:[event locationInWindow] fromView:nil];
2126     
2127     forceWebHTMLViewHitTest = YES;
2128     NSView *hitView = [contentView hitTest:locationForHitTest];
2129     forceWebHTMLViewHitTest = NO;
2130     
2131     WebHTMLView *view = nil;
2132     if ([hitView isKindOfClass:[WebHTMLView class]])
2133         view = (WebHTMLView *)hitView;    
2134
2135     if (view)
2136         [view retain];
2137
2138     if (lastHitView != view && lastHitView && [lastHitView _frame]) {
2139         // If we are moving out of a view (or frame), let's pretend the mouse moved
2140         // all the way out of that view. But we have to account for scrolling, because
2141         // WebCore doesn't understand our clipping.
2142         NSRect visibleRect = [[[[lastHitView _frame] frameView] _scrollView] documentVisibleRect];
2143         float yScroll = visibleRect.origin.y;
2144         float xScroll = visibleRect.origin.x;
2145
2146 #pragma clang diagnostic push
2147 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
2148         NSEvent *event = [NSEvent mouseEventWithType:NSMouseMoved
2149             location:NSMakePoint(-1 - xScroll, -1 - yScroll)
2150             modifierFlags:[[NSApp currentEvent] modifierFlags]
2151             timestamp:[NSDate timeIntervalSinceReferenceDate]
2152             windowNumber:[[view window] windowNumber]
2153             context:nullptr
2154             eventNumber:0 clickCount:0 pressure:0];
2155 #pragma clang diagnostic pop
2156         if (Frame* lastHitCoreFrame = core([lastHitView _frame]))
2157             lastHitCoreFrame->eventHandler().mouseMoved(event, [[self _webView] _pressureEvent]);
2158     }
2159
2160     lastHitView = view;
2161
2162     if (view) {
2163         if (Frame* coreFrame = core([view _frame])) {
2164             // We need to do a full, normal hit test during this mouse event if the page is active or if a mouse
2165             // button is currently pressed. It is possible that neither of those things will be true on Lion and
2166             // newer when legacy scrollbars are enabled, because then WebKit receives mouse events all the time. 
2167             // If it is one of those cases where the page is not active and the mouse is not pressed, then we can
2168             // fire a much more restricted and efficient scrollbars-only version of the event.
2169
2170             if ([[self window] isKeyWindow] 
2171                 || mouseEventIsPartOfClickOrDrag(event)
2172 #if ENABLE(DASHBOARD_SUPPORT)
2173                 || [[self _webView] _dashboardBehavior:WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows]
2174 #endif
2175                 ) {
2176                 coreFrame->eventHandler().mouseMoved(event, [[self _webView] _pressureEvent]);
2177             } else {
2178                 [self removeAllToolTips];
2179                 coreFrame->eventHandler().passMouseMovedEventToScrollbars(event, [[self _webView] _pressureEvent]);
2180             }
2181         }
2182
2183         [view release];
2184     }
2185 }
2186
2187 + (NSArray *)_insertablePasteboardTypes
2188 {
2189     static NSArray *types = nil;
2190     if (!types) {
2191         types = [[NSArray alloc] initWithObjects:WebArchivePboardType, NSHTMLPboardType, NSFilenamesPboardType, NSTIFFPboardType, NSPDFPboardType,
2192             NSURLPboardType, NSRTFDPboardType, NSRTFPboardType, NSStringPboardType, NSColorPboardType, kUTTypePNG, nil];
2193         CFRetain(types);
2194     }
2195     return types;
2196 }
2197
2198 + (NSArray *)_selectionPasteboardTypes
2199 {
2200     // FIXME: We should put data for NSHTMLPboardType on the pasteboard but Microsoft Excel doesn't like our format of HTML (3640423).
2201     return [NSArray arrayWithObjects:WebArchivePboardType, NSRTFDPboardType, NSRTFPboardType, NSStringPboardType, nil];
2202 }
2203
2204 - (void)pasteboardChangedOwner:(NSPasteboard *)pasteboard
2205 {
2206     [self setPromisedDragTIFFDataSource:0];
2207 }
2208
2209 - (void)pasteboard:(NSPasteboard *)pasteboard provideDataForType:(NSString *)type
2210 {
2211     if ([type isEqual:NSRTFDPboardType] && [[pasteboard types] containsObject:WebArchivePboardType]) {
2212         WebArchive *archive = [[WebArchive alloc] initWithData:[pasteboard dataForType:WebArchivePboardType]];
2213         [pasteboard _web_writePromisedRTFDFromArchive:archive containsImage:[[pasteboard types] containsObject:NSTIFFPboardType]];
2214         [archive release];
2215     } else if ([type isEqual:NSTIFFPboardType] && [self promisedDragTIFFDataSource]) {
2216         if (Image* image = [self promisedDragTIFFDataSource]->image())
2217             [pasteboard setData:(NSData *)image->getTIFFRepresentation() forType:NSTIFFPboardType];
2218         [self setPromisedDragTIFFDataSource:0];
2219     }
2220 }
2221
2222 - (void)_handleAutoscrollForMouseDragged:(NSEvent *)event 
2223
2224     [self autoscroll:event]; 
2225     [self _startAutoscrollTimer:event]; 
2226
2227 #endif // !PLATFORM(IOS)
2228
2229 - (WebPluginController *)_pluginController
2230 {
2231     return _private->pluginController;
2232 }
2233
2234 #if PLATFORM(IOS)
2235 // WAKView override.
2236 - (void)layoutIfNeeded
2237 {
2238     [self _layoutIfNeeded];
2239 }
2240
2241 // WAKView override.
2242 - (void)setScale:(float)scale
2243 {
2244     [super setScale:scale];
2245     Frame* coreFrame = core([self _frame]);
2246     if (!coreFrame)
2247         return;
2248
2249     if (Page* page = coreFrame->page())
2250         page->setPageScaleFactor(scale, IntPoint());
2251
2252     [[self _webView] _documentScaleChanged];
2253 }
2254
2255 #endif
2256
2257 #if !PLATFORM(IOS)
2258 - (void)_layoutForPrinting
2259 {
2260     // Set printing mode temporarily so we can adjust the size of the view. This will allow
2261     // AppKit's pagination code to use the correct height for the page content. Leaving printing
2262     // mode on indefinitely would interfere with Mail's printing mechanism (at least), so we just
2263     // turn it off again after adjusting the size.
2264     [self _web_setPrintingModeRecursiveAndAdjustViewSize];
2265     [self _web_clearPrintingModeRecursive];
2266 }
2267 #endif
2268
2269 #if !PLATFORM(IOS)
2270 - (void)_smartInsertForString:(NSString *)pasteString replacingRange:(DOMRange *)rangeToReplace beforeString:(NSString **)beforeString afterString:(NSString **)afterString
2271 {
2272     if (!pasteString || !rangeToReplace || ![[self _webView] smartInsertDeleteEnabled]) {
2273         if (beforeString)
2274             *beforeString = nil;
2275         if (afterString)
2276             *afterString = nil;
2277         return;
2278     }
2279     
2280     [[self _frame] _smartInsertForString:pasteString replacingRange:rangeToReplace beforeString:beforeString afterString:afterString];
2281 }
2282
2283 - (BOOL)_canSmartReplaceWithPasteboard:(NSPasteboard *)pasteboard
2284 {
2285     return [[self _webView] smartInsertDeleteEnabled] && [[pasteboard types] containsObject:WebSmartPastePboardType];
2286 }
2287
2288 - (void)_startAutoscrollTimer:(NSEvent *)triggerEvent
2289 #else
2290 - (void)_startAutoscrollTimer: (WebEvent *)triggerEvent
2291 #endif
2292 {
2293     if (_private->autoscrollTimer == nil) {
2294         _private->autoscrollTimer = [[NSTimer scheduledTimerWithTimeInterval:AUTOSCROLL_INTERVAL
2295             target:self selector:@selector(_autoscroll) userInfo:nil repeats:YES] retain];
2296         _private->autoscrollTriggerEvent = [triggerEvent retain];
2297     }
2298 }
2299
2300 // FIXME: _selectionRect is deprecated in favor of selectionRect, which is in protocol WebDocumentSelection.
2301 // We can't remove this yet because it's still in use by Mail.
2302 - (NSRect)_selectionRect
2303 {
2304     return [self selectionRect];
2305 }
2306
2307 - (void)_stopAutoscrollTimer
2308 {
2309     NSTimer *timer = _private->autoscrollTimer;
2310     _private->autoscrollTimer = nil;
2311 #if !PLATFORM(IOS)
2312     [_private->autoscrollTriggerEvent release];
2313 #else
2314     if (_private->autoscrollTriggerEvent)
2315         CFRelease (_private->autoscrollTriggerEvent);
2316 #endif
2317     _private->autoscrollTriggerEvent = nil;
2318     [timer invalidate];
2319     [timer release];
2320 }
2321
2322 - (void)_autoscroll
2323 {
2324     // Guarantee that the autoscroll timer is invalidated, even if we don't receive
2325     // a mouse up event.
2326 #if !PLATFORM(IOS)
2327     BOOL isStillDown = CGEventSourceButtonState(kCGEventSourceStateCombinedSessionState, kCGMouseButtonLeft);   
2328 #else
2329     BOOL isStillDown = NO;
2330 #endif
2331     if (!isStillDown){
2332         [self _stopAutoscrollTimer];
2333         return;
2334     }
2335
2336 #if !PLATFORM(IOS)
2337 #pragma clang diagnostic push
2338 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
2339     NSEvent *fakeEvent = [NSEvent mouseEventWithType:NSLeftMouseDragged
2340         location:[[self window] convertScreenToBase:[NSEvent mouseLocation]]
2341         modifierFlags:[[NSApp currentEvent] modifierFlags]
2342         timestamp:[NSDate timeIntervalSinceReferenceDate]
2343         windowNumber:[[self window] windowNumber]
2344         context:nullptr
2345         eventNumber:0 clickCount:0 pressure:0];
2346 #pragma clang diagnostic pop
2347     [self mouseDragged:fakeEvent];
2348 #endif
2349 }
2350
2351 - (BOOL)_canEdit
2352 {
2353     Frame* coreFrame = core([self _frame]);
2354     return coreFrame && coreFrame->editor().canEdit();
2355 }
2356
2357 - (BOOL)_canEditRichly
2358 {
2359     Frame* coreFrame = core([self _frame]);
2360     return coreFrame && coreFrame->editor().canEditRichly();
2361 }
2362
2363 - (BOOL)_canAlterCurrentSelection
2364 {
2365     return [self _hasSelectionOrInsertionPoint] && [self _isEditable];
2366 }
2367
2368 - (BOOL)_hasSelection
2369 {
2370     Frame* coreFrame = core([self _frame]);
2371     return coreFrame && coreFrame->selection().selection().isRange();
2372 }
2373
2374 - (BOOL)_hasSelectionOrInsertionPoint
2375 {
2376     Frame* coreFrame = core([self _frame]);
2377     return coreFrame && coreFrame->selection().selection().isCaretOrRange();
2378 }
2379
2380 - (BOOL)_hasInsertionPoint
2381 {
2382     Frame* coreFrame = core([self _frame]);
2383     return coreFrame && coreFrame->selection().selection().isCaret();
2384 }
2385
2386 - (BOOL)_isEditable
2387 {
2388     Frame* coreFrame = core([self _frame]);
2389     return coreFrame && coreFrame->selection().selection().isContentEditable();
2390 }
2391
2392 - (BOOL)_transparentBackground
2393 {
2394     return _private->transparentBackground;
2395 }
2396
2397 - (void)_setTransparentBackground:(BOOL)f
2398 {
2399     _private->transparentBackground = f;
2400 }
2401
2402 #if !PLATFORM(IOS)
2403 - (NSImage *)_selectionDraggingImage
2404 {
2405     if (![self _hasSelection])
2406         return nil;
2407
2408     Frame* coreFrame = core([self _frame]);
2409     if (!coreFrame)
2410         return nil;
2411
2412     auto dragImage = createDragImageForSelection(*coreFrame);
2413     [dragImage _web_dissolveToFraction:WebDragImageAlpha];
2414
2415     return dragImage.autorelease();
2416 }
2417
2418 - (NSRect)_selectionDraggingRect
2419 {
2420     // Mail currently calls this method. We can eliminate it when Mail no longer calls it.
2421     return [self selectionRect];
2422 }
2423 #endif
2424
2425 - (DOMNode *)_insertOrderedList
2426 {
2427     Frame* coreFrame = core([self _frame]);
2428     return coreFrame ? kit(coreFrame->editor().insertOrderedList().get()) : nil;
2429 }
2430
2431 - (DOMNode *)_insertUnorderedList
2432 {
2433     Frame* coreFrame = core([self _frame]);
2434     return coreFrame ? kit(coreFrame->editor().insertUnorderedList().get()) : nil;
2435 }
2436
2437 - (BOOL)_canIncreaseSelectionListLevel
2438 {
2439     Frame* coreFrame = core([self _frame]);
2440     return coreFrame && coreFrame->editor().canIncreaseSelectionListLevel();
2441 }
2442
2443 - (BOOL)_canDecreaseSelectionListLevel
2444 {
2445     Frame* coreFrame = core([self _frame]);
2446     return coreFrame && coreFrame->editor().canDecreaseSelectionListLevel();
2447 }
2448
2449 - (DOMNode *)_increaseSelectionListLevel
2450 {
2451     Frame* coreFrame = core([self _frame]);
2452     return coreFrame ? kit(coreFrame->editor().increaseSelectionListLevel().get()) : nil;
2453 }
2454
2455 - (DOMNode *)_increaseSelectionListLevelOrdered
2456 {
2457     Frame* coreFrame = core([self _frame]);
2458     return coreFrame ? kit(coreFrame->editor().increaseSelectionListLevelOrdered().get()) : nil;
2459 }
2460
2461 - (DOMNode *)_increaseSelectionListLevelUnordered
2462 {
2463     Frame* coreFrame = core([self _frame]);
2464     return coreFrame ? kit(coreFrame->editor().increaseSelectionListLevelUnordered().get()) : nil;
2465 }
2466
2467 - (void)_decreaseSelectionListLevel
2468 {
2469     Frame* coreFrame = core([self _frame]);
2470     if (coreFrame)
2471         coreFrame->editor().decreaseSelectionListLevel();
2472 }
2473
2474 #if !PLATFORM(IOS)
2475 - (void)_writeSelectionToPasteboard:(NSPasteboard *)pasteboard
2476 {
2477     ASSERT([self _hasSelection]);
2478     NSArray *types = [self pasteboardTypesForSelection];
2479
2480     // Don't write RTFD to the pasteboard when the copied attributed string has no attachments.
2481     NSAttributedString *attributedString = [self selectedAttributedString];
2482     NSMutableArray *mutableTypes = nil;
2483     if (![attributedString containsAttachments]) {
2484         mutableTypes = [types mutableCopy];
2485         [mutableTypes removeObject:NSRTFDPboardType];
2486         types = mutableTypes;
2487     }
2488
2489     [pasteboard declareTypes:types owner:[self _topHTMLView]];
2490     [self _writeSelectionWithPasteboardTypes:types toPasteboard:pasteboard cachedAttributedString:attributedString];
2491     [mutableTypes release];
2492 }
2493 #endif
2494
2495 - (void)close
2496 {
2497     // Check for a nil _private here in case we were created with initWithCoder. In that case, the WebView is just throwing
2498     // out the archived WebHTMLView and recreating a new one if needed. So close doesn't need to do anything in that case.
2499     if (!_private || _private->closed)
2500         return;
2501
2502     _private->closed = YES;
2503
2504     [self _clearLastHitViewIfSelf];
2505 #if !PLATFORM(IOS)
2506     [self _removeWindowObservers];
2507     [self _removeSuperviewObservers];
2508 #endif
2509     [_private->pluginController destroyAllPlugins];
2510     [_private->pluginController setDataSource:nil];
2511 #if !PLATFORM(IOS)
2512     // remove tooltips before clearing _private so removeTrackingRect: will work correctly
2513     [self removeAllToolTips];
2514
2515     if (_private->isInSecureInputState) {
2516         DisableSecureEventInput();
2517         _private->isInSecureInputState = NO;
2518     }
2519 #endif
2520
2521     [_private clear];
2522 }
2523
2524 - (BOOL)_hasHTMLDocument
2525 {
2526     Frame* coreFrame = core([self _frame]);
2527     if (!coreFrame)
2528         return NO;
2529     Document* document = coreFrame->document();
2530     return document && document->isHTMLDocument();
2531 }
2532
2533 #if !PLATFORM(IOS)
2534 - (DOMDocumentFragment *)_documentFragmentFromPasteboard:(NSPasteboard *)pasteboard
2535                                                  forType:(NSString *)pboardType
2536                                                inContext:(DOMRange *)context
2537                                             subresources:(NSArray **)subresources
2538 {
2539     if (pboardType == WebArchivePboardType) {
2540         WebArchive *archive = [[WebArchive alloc] initWithData:[pasteboard dataForType:WebArchivePboardType]];
2541         if (subresources)
2542             *subresources = [archive subresources];
2543         DOMDocumentFragment *fragment = [[self _dataSource] _documentFragmentWithArchive:archive];
2544         [archive release];
2545         return fragment;
2546     }
2547     if (pboardType == NSFilenamesPboardType)
2548         return [self _documentFragmentWithPaths:[pasteboard propertyListForType:NSFilenamesPboardType]];
2549         
2550     if (pboardType == NSHTMLPboardType) {
2551         NSString *HTMLString = [pasteboard stringForType:NSHTMLPboardType];
2552         // This is a hack to make Microsoft's HTML pasteboard data work. See 3778785.
2553         if ([HTMLString hasPrefix:@"Version:"]) {
2554             NSRange range = [HTMLString rangeOfString:@"<html" options:NSCaseInsensitiveSearch];
2555             if (range.location != NSNotFound)
2556                 HTMLString = [HTMLString substringFromIndex:range.location];
2557         }
2558         if ([HTMLString length] == 0)
2559             return nil;
2560         
2561         return [[self _frame] _documentFragmentWithMarkupString:HTMLString baseURLString:nil];
2562     }
2563
2564     // The _hasHTMLDocument clause here is a workaround for a bug in NSAttributedString: Radar 5052369.
2565     // If we call _documentFromRange on an XML document we'll get "setInnerHTML: method not found".
2566     // FIXME: Remove this once bug 5052369 is fixed.
2567     if ([self _hasHTMLDocument] && (pboardType == NSRTFPboardType || pboardType == NSRTFDPboardType)) {
2568         NSAttributedString *string = nil;
2569         if (pboardType == NSRTFDPboardType)
2570             string = [[NSAttributedString alloc] initWithRTFD:[pasteboard dataForType:NSRTFDPboardType] documentAttributes:NULL];
2571         if (string == nil)
2572             string = [[NSAttributedString alloc] initWithRTF:[pasteboard dataForType:NSRTFPboardType] documentAttributes:NULL];
2573         if (string == nil)
2574             return nil;
2575             
2576         NSDictionary *documentAttributes = [[NSDictionary alloc] initWithObjectsAndKeys:
2577             [[self class] _excludedElementsForAttributedStringConversion], NSExcludedElementsDocumentAttribute,
2578             self, @"WebResourceHandler", nil];
2579         NSArray *s;
2580         
2581         BOOL wasDeferringCallbacks = [[self _webView] defersCallbacks];
2582         if (!wasDeferringCallbacks)
2583             [[self _webView] setDefersCallbacks:YES];
2584             
2585         DOMDocumentFragment *fragment = [string _documentFromRange:NSMakeRange(0, [string length]) 
2586                                                           document:[[self _frame] DOMDocument] 
2587                                                 documentAttributes:documentAttributes
2588                                                       subresources:&s];
2589         if (subresources)
2590             *subresources = s;
2591         
2592         NSEnumerator *e = [s objectEnumerator];
2593         WebResource *r;
2594         while ((r = [e nextObject]))
2595             [[self _dataSource] addSubresource:r];
2596         
2597         if (!wasDeferringCallbacks)
2598             [[self _webView] setDefersCallbacks:NO];
2599         
2600         [documentAttributes release];
2601         [string release];
2602         return fragment;
2603     }
2604     if (pboardType == NSTIFFPboardType) {
2605         WebResource *resource = [[WebResource alloc] initWithData:[pasteboard dataForType:NSTIFFPboardType]
2606                                                               URL:uniqueURLWithRelativePart(@"image.tiff")
2607                                                          MIMEType:@"image/tiff" 
2608                                                  textEncodingName:nil
2609                                                         frameName:nil];
2610         DOMDocumentFragment *fragment = [[self _dataSource] _documentFragmentWithImageResource:resource];
2611         [resource release];
2612         return fragment;
2613     }
2614     if (pboardType == NSPDFPboardType) {
2615         WebResource *resource = [[WebResource alloc] initWithData:[pasteboard dataForType:NSPDFPboardType]
2616                                                               URL:uniqueURLWithRelativePart(@"application.pdf")
2617                                                          MIMEType:@"application/pdf" 
2618                                                  textEncodingName:nil
2619                                                         frameName:nil];
2620         DOMDocumentFragment *fragment = [[self _dataSource] _documentFragmentWithImageResource:resource];
2621         [resource release];
2622         return fragment;
2623     }
2624
2625     if ([pboardType isEqualToString:(NSString*)kUTTypePNG]) {
2626         WebResource *resource = [[WebResource alloc] initWithData:[pasteboard dataForType:(NSString*)kUTTypePNG]
2627                                                               URL:uniqueURLWithRelativePart(@"image.png")
2628                                                          MIMEType:@"image/png" 
2629                                                  textEncodingName:nil
2630                                                         frameName:nil];
2631         DOMDocumentFragment *fragment = [[self _dataSource] _documentFragmentWithImageResource:resource];
2632         [resource release];
2633         return fragment;
2634     }
2635     if (pboardType == NSURLPboardType) {
2636         NSURL *URL = [NSURL URLFromPasteboard:pasteboard];
2637         DOMDocument* document = [[self _frame] DOMDocument];
2638         ASSERT(document);
2639         if (!document)
2640             return nil;
2641         DOMHTMLAnchorElement *anchor = (DOMHTMLAnchorElement *)[document createElement:@"a"];
2642         NSString *URLString = [URL _web_originalDataAsString]; // Original data is ASCII-only, so there is no need to precompose.
2643         if ([URLString length] == 0)
2644             return nil;
2645         NSString *URLTitleString = [[pasteboard stringForType:WebURLNamePboardType] precomposedStringWithCanonicalMapping];
2646         DOMText *text = [document createTextNode:URLTitleString];
2647         [anchor setHref:URLString];
2648         [anchor appendChild:text];
2649         DOMDocumentFragment *fragment = [document createDocumentFragment];
2650         [fragment appendChild:anchor];
2651         return fragment;
2652     }
2653     if (pboardType == NSStringPboardType) {
2654         if (!context)
2655             return nil;
2656         return kit(createFragmentFromText(*core(context), [[pasteboard stringForType:NSStringPboardType] precomposedStringWithCanonicalMapping]).ptr());
2657     }
2658     return nil;
2659 }
2660 #endif // !PLATFORM(IOS)
2661
2662 #if ENABLE(NETSCAPE_PLUGIN_API) 
2663 - (void)_pauseNullEventsForAllNetscapePlugins 
2664
2665     NSArray *subviews = [self subviews]; 
2666     unsigned int subviewCount = [subviews count]; 
2667     unsigned int subviewIndex; 
2668     
2669     for (subviewIndex = 0; subviewIndex < subviewCount; subviewIndex++) { 
2670         NSView *subview = [subviews objectAtIndex:subviewIndex]; 
2671         if ([subview isKindOfClass:[WebBaseNetscapePluginView class]]) 
2672             [(WebBaseNetscapePluginView *)subview stopTimers];
2673     } 
2674
2675 #endif 
2676
2677 #if ENABLE(NETSCAPE_PLUGIN_API) 
2678 - (void)_resumeNullEventsForAllNetscapePlugins 
2679
2680     NSArray *subviews = [self subviews]; 
2681     unsigned int subviewCount = [subviews count]; 
2682     unsigned int subviewIndex; 
2683     
2684     for (subviewIndex = 0; subviewIndex < subviewCount; subviewIndex++) { 
2685         NSView *subview = [subviews objectAtIndex:subviewIndex]; 
2686         if ([subview isKindOfClass:[WebBaseNetscapePluginView class]]) 
2687             [(WebBaseNetscapePluginView *)subview restartTimers]; 
2688     } 
2689
2690 #endif 
2691
2692 - (BOOL)_isUsingAcceleratedCompositing
2693 {
2694     return _private->layerHostingView != nil;
2695 }
2696
2697 - (NSView *)_compositingLayersHostingView
2698 {
2699     return _private->layerHostingView;
2700 }
2701
2702 - (BOOL)_isInPrintMode
2703 {
2704     return _private->printing;
2705 }
2706
2707 - (BOOL)_beginPrintModeWithMinimumPageWidth:(CGFloat)minimumPageWidth height:(CGFloat)minimumPageHeight maximumPageWidth:(CGFloat)maximumPageWidth
2708 {
2709     Frame* frame = core([self _frame]);
2710     if (!frame)
2711         return NO;
2712
2713     if (frame->document() && frame->document()->isFrameSet()) {
2714         minimumPageWidth = 0;
2715         minimumPageHeight = 0;
2716     }
2717
2718     float maximumShrinkRatio = 0;
2719     if (minimumPageWidth > 0.0)
2720         maximumShrinkRatio = maximumPageWidth / minimumPageWidth;
2721
2722     [self _setPrinting:YES minimumPageLogicalWidth:minimumPageWidth logicalHeight:minimumPageHeight originalPageWidth:minimumPageWidth originalPageHeight:minimumPageHeight maximumShrinkRatio:maximumShrinkRatio adjustViewSize:YES paginateScreenContent:[self _isInScreenPaginationMode]];
2723     return YES;
2724 }
2725
2726 - (BOOL)_beginPrintModeWithPageWidth:(float)pageWidth height:(float)pageHeight shrinkToFit:(BOOL)shrinkToFit
2727 {
2728     Frame* frame = core([self _frame]);
2729     if (!frame)
2730         return NO;
2731
2732     Document* document = frame->document();
2733     bool isHorizontal = !document || !document->renderView() || document->renderView()->style().isHorizontalWritingMode();
2734
2735     float pageLogicalWidth = isHorizontal ? pageWidth : pageHeight;
2736     float pageLogicalHeight = isHorizontal ? pageHeight : pageWidth;
2737     FloatSize minLayoutSize(pageLogicalWidth, pageLogicalHeight);
2738     float maximumShrinkRatio = 1;
2739
2740     // If we are a frameset just print with the layout we have onscreen, otherwise relayout
2741     // according to the page width.
2742     if (shrinkToFit && (!frame->document() || !frame->document()->isFrameSet())) {
2743         minLayoutSize = frame->resizePageRectsKeepingRatio(FloatSize(pageLogicalWidth, pageLogicalHeight), FloatSize(pageLogicalWidth * _WebHTMLViewPrintingMinimumShrinkFactor, pageLogicalHeight * _WebHTMLViewPrintingMinimumShrinkFactor));
2744         maximumShrinkRatio = _WebHTMLViewPrintingMaximumShrinkFactor / _WebHTMLViewPrintingMinimumShrinkFactor;
2745     }
2746
2747     [self _setPrinting:YES minimumPageLogicalWidth:minLayoutSize.width() logicalHeight:minLayoutSize.height() originalPageWidth:pageLogicalWidth originalPageHeight:pageLogicalHeight maximumShrinkRatio:maximumShrinkRatio adjustViewSize:YES paginateScreenContent:[self _isInScreenPaginationMode]];
2748
2749     return YES;
2750 }
2751
2752 - (void)_endPrintMode
2753 {
2754     [self _setPrinting:NO minimumPageLogicalWidth:0 logicalHeight:0 originalPageWidth:0 originalPageHeight:0 maximumShrinkRatio:0 adjustViewSize:YES paginateScreenContent:[self _isInScreenPaginationMode]];
2755 }
2756
2757 - (BOOL)_isInScreenPaginationMode
2758 {
2759     return _private->paginateScreenContent;
2760 }
2761
2762 - (BOOL)_beginScreenPaginationModeWithPageSize:(CGSize)pageSize shrinkToFit:(BOOL)shrinkToFit
2763 {
2764     Frame* frame = core([self _frame]);
2765     if (!frame)
2766         return NO;
2767
2768     Document* document = frame->document();
2769     bool isHorizontal = !document || !document->renderView() || document->renderView()->style().isHorizontalWritingMode();
2770
2771     float pageLogicalWidth = isHorizontal ? pageSize.width : pageSize.height;
2772     float pageLogicalHeight = isHorizontal ? pageSize.height : pageSize.width;
2773     FloatSize minLayoutSize(pageLogicalWidth, pageLogicalHeight);
2774     float maximumShrinkRatio = 1;
2775
2776     // If we are a frameset just print with the layout we have onscreen, otherwise relayout
2777     // according to the page width.
2778     if (shrinkToFit && (!frame->document() || !frame->document()->isFrameSet())) {
2779         minLayoutSize = frame->resizePageRectsKeepingRatio(FloatSize(pageLogicalWidth, pageLogicalHeight), FloatSize(pageLogicalWidth * _WebHTMLViewPrintingMinimumShrinkFactor, pageLogicalHeight * _WebHTMLViewPrintingMinimumShrinkFactor));
2780         maximumShrinkRatio = _WebHTMLViewPrintingMaximumShrinkFactor / _WebHTMLViewPrintingMinimumShrinkFactor;
2781     }
2782
2783     [self _setPrinting:[self _isInPrintMode] minimumPageLogicalWidth:minLayoutSize.width() logicalHeight:minLayoutSize.height() originalPageWidth:pageLogicalWidth originalPageHeight:pageLogicalHeight maximumShrinkRatio:maximumShrinkRatio adjustViewSize:YES paginateScreenContent:[self _isInScreenPaginationMode]];
2784
2785     return YES;
2786 }
2787
2788 - (void)_endScreenPaginationMode
2789 {
2790     [self _setPrinting:[self _isInPrintMode] minimumPageLogicalWidth:0 logicalHeight:0 originalPageWidth:0 originalPageHeight:0 maximumShrinkRatio:0 adjustViewSize:YES paginateScreenContent:NO];
2791 }
2792
2793 - (CGFloat)_adjustedBottomOfPageWithTop:(CGFloat)top bottom:(CGFloat)bottom limit:(CGFloat)bottomLimit
2794 {
2795     Frame* frame = core([self _frame]);
2796     if (!frame)
2797         return bottom;
2798
2799     FrameView* view = frame->view();
2800     if (!view)
2801         return bottom;
2802
2803     float newBottom;
2804     view->adjustPageHeightDeprecated(&newBottom, top, bottom, bottomLimit);
2805
2806 #ifdef __LP64__
2807     // If the new bottom is equal to the old bottom (when both are treated as floats), we just return the original
2808     // bottom. This prevents rounding errors that can occur when converting newBottom to a double.
2809     if (WTF::areEssentiallyEqual(static_cast<float>(bottom), newBottom))
2810         return bottom;
2811     else
2812 #endif
2813         return newBottom;
2814 }
2815
2816 #if PLATFORM(IOS)
2817 - (id)accessibilityRootElement
2818 {
2819     return [[self _frame] accessibilityRoot];
2820 }
2821 #endif
2822
2823 @end
2824
2825 @implementation NSView (WebHTMLViewFileInternal)
2826
2827 - (void)_web_addDescendantWebHTMLViewsToArray:(NSMutableArray *)array
2828 {
2829 #if PLATFORM(IOS)
2830     NSArray* _subviews = [self subviews];
2831 #endif
2832     unsigned count = [_subviews count];
2833     for (unsigned i = 0; i < count; ++i) {
2834         NSView *child = [_subviews objectAtIndex:i];
2835         if ([child isKindOfClass:[WebHTMLView class]])
2836             [array addObject:child];
2837         [child _web_addDescendantWebHTMLViewsToArray:array];
2838     }
2839 }
2840
2841 @end
2842
2843 @implementation NSMutableDictionary (WebHTMLViewFileInternal)
2844
2845 - (void)_web_setObjectIfNotNil:(id)object forKey:(id)key
2846 {
2847     if (object == nil) {
2848         [self removeObjectForKey:key];
2849     } else {
2850         [self setObject:object forKey:key];
2851     }
2852 }
2853
2854 @end
2855
2856 @implementation WebHTMLView
2857
2858 + (void)initialize
2859 {
2860 #if !PLATFORM(IOS)
2861     [NSApp registerServicesMenuSendTypes:[[self class] _selectionPasteboardTypes] 
2862                              returnTypes:[[self class] _insertablePasteboardTypes]];
2863     JSC::initializeThreading();
2864     WTF::initializeMainThreadToProcessMainThread();
2865     RunLoop::initializeMainRunLoop();
2866 #endif
2867 }
2868
2869 - (id)initWithFrame:(NSRect)frame
2870 {
2871     self = [super initWithFrame:frame];
2872     if (!self)
2873         return nil;
2874     
2875 #if !PLATFORM(IOS)
2876     [self setFocusRingType:NSFocusRingTypeNone];
2877 #endif
2878     
2879     // Make all drawing go through us instead of subviews.
2880     [self _setDrawsOwnDescendants:YES];
2881     
2882     _private = [[WebHTMLViewPrivate alloc] init];
2883
2884     _private->pluginController = [[WebPluginController alloc] initWithDocumentView:self];
2885 #if PLATFORM(IOS)
2886     [[NSNotificationCenter defaultCenter] 
2887             addObserver:self selector:@selector(markedTextUpdate:) 
2888                    name:WebMarkedTextUpdatedNotification object:nil];
2889 #else
2890     _private->softSpaceRange = NSMakeRange(NSNotFound, 0);
2891 #endif
2892     
2893     return self;
2894 }
2895
2896 - (void)dealloc
2897 {
2898     if (WebCoreObjCScheduleDeallocateOnMainThread([WebHTMLView class], self))
2899         return;
2900
2901 #if PLATFORM(IOS)
2902     [[NSNotificationCenter defaultCenter] removeObserver:self name:WebMarkedTextUpdatedNotification object:nil];
2903 #endif
2904
2905     // We can't assert that close has already been called because
2906     // this view can be removed from it's superview, even though
2907     // it could be needed later, so close if needed.
2908     [self close];
2909     [_private release];
2910     _private = nil;
2911     [super dealloc];
2912 }
2913
2914 // Returns YES if the delegate returns YES (so we should do no more work).
2915 - (BOOL)callDelegateDoCommandBySelectorIfNeeded:(SEL)selector
2916 {
2917     BOOL callerAlreadyCalledDelegate = _private->selectorForDoCommandBySelector == selector;
2918     _private->selectorForDoCommandBySelector = 0;
2919     if (callerAlreadyCalledDelegate)
2920         return NO;
2921     WebView *webView = [self _webView];
2922     return [[webView _editingDelegateForwarder] webView:webView doCommandBySelector:selector];
2923 }
2924
2925 typedef HashMap<SEL, String> SelectorNameMap;
2926
2927 // Map selectors into Editor command names.
2928 // This is not needed for any selectors that have the same name as the Editor command.
2929 static const SelectorNameMap* createSelectorExceptionMap()
2930 {
2931     SelectorNameMap* map = new HashMap<SEL, String>;
2932
2933     map->add(@selector(insertNewlineIgnoringFieldEditor:), "InsertNewline");
2934     map->add(@selector(insertParagraphSeparator:), "InsertNewline");
2935     map->add(@selector(insertTabIgnoringFieldEditor:), "InsertTab");
2936     map->add(@selector(pageDown:), "MovePageDown");
2937     map->add(@selector(pageDownAndModifySelection:), "MovePageDownAndModifySelection");
2938     map->add(@selector(pageUp:), "MovePageUp");
2939     map->add(@selector(pageUpAndModifySelection:), "MovePageUpAndModifySelection");
2940
2941     return map;
2942 }
2943
2944 static String commandNameForSelector(SEL selector)
2945 {
2946     // Check the exception map first.
2947     static const SelectorNameMap* exceptionMap = createSelectorExceptionMap();
2948     SelectorNameMap::const_iterator it = exceptionMap->find(selector);
2949     if (it != exceptionMap->end())
2950         return it->value;
2951
2952     // Remove the trailing colon.
2953     // No need to capitalize the command name since Editor command names are
2954     // not case sensitive.
2955     const char* selectorName = sel_getName(selector);
2956     size_t selectorNameLength = strlen(selectorName);
2957     if (selectorNameLength < 2 || selectorName[selectorNameLength - 1] != ':')
2958         return String();
2959     return String(selectorName, selectorNameLength - 1);
2960 }
2961
2962 - (Editor::Command)coreCommandBySelector:(SEL)selector
2963 {
2964     Frame* coreFrame = core([self _frame]);
2965     if (!coreFrame)
2966         return Editor::Command();
2967     return coreFrame->editor().command(commandNameForSelector(selector));
2968 }
2969
2970 - (Editor::Command)coreCommandByName:(const char*)name
2971 {
2972     Frame* coreFrame = core([self _frame]);
2973     if (!coreFrame)
2974         return Editor::Command();
2975     return coreFrame->editor().command(name);
2976 }
2977
2978 - (void)executeCoreCommandBySelector:(SEL)selector
2979 {
2980     if ([self callDelegateDoCommandBySelectorIfNeeded:selector])
2981         return;
2982     [self coreCommandBySelector:selector].execute();
2983 }
2984
2985 - (void)executeCoreCommandByName:(const char*)name
2986 {
2987     [self coreCommandByName:name].execute();
2988 }
2989
2990 // These commands are forwarded to the Editor object in WebCore.
2991 // Ideally we'd do this for all editing commands; more of the code
2992 // should be moved from here to there, and more commands should be
2993 // added to this list.
2994
2995 // FIXME: Maybe we should set things up so that all these share a single method implementation function.
2996 // The functions are identical.
2997
2998 #define WEBCORE_COMMAND(command) - (void)command:(id)sender { [self executeCoreCommandBySelector:_cmd]; }
2999
3000 WEBCORE_COMMAND(alignCenter)
3001 WEBCORE_COMMAND(alignJustified)
3002 WEBCORE_COMMAND(alignLeft)
3003 WEBCORE_COMMAND(alignRight)
3004 WEBCORE_COMMAND(copy)
3005 WEBCORE_COMMAND(cut)
3006 WEBCORE_COMMAND(paste)
3007 WEBCORE_COMMAND(delete)
3008 WEBCORE_COMMAND(deleteBackward)
3009 WEBCORE_COMMAND(deleteBackwardByDecomposingPreviousCharacter)
3010 WEBCORE_COMMAND(deleteForward)
3011 WEBCORE_COMMAND(deleteToBeginningOfLine)
3012 WEBCORE_COMMAND(deleteToBeginningOfParagraph)
3013 WEBCORE_COMMAND(deleteToEndOfLine)
3014 WEBCORE_COMMAND(deleteToEndOfParagraph)
3015 WEBCORE_COMMAND(deleteToMark)
3016 WEBCORE_COMMAND(deleteWordBackward)
3017 WEBCORE_COMMAND(deleteWordForward)
3018 WEBCORE_COMMAND(ignoreSpelling)
3019 WEBCORE_COMMAND(indent)
3020 WEBCORE_COMMAND(insertBacktab)
3021 WEBCORE_COMMAND(insertLineBreak)
3022 WEBCORE_COMMAND(insertNewline)
3023 WEBCORE_COMMAND(insertNewlineIgnoringFieldEditor)
3024 WEBCORE_COMMAND(insertParagraphSeparator)
3025 WEBCORE_COMMAND(insertTab)
3026 WEBCORE_COMMAND(insertTabIgnoringFieldEditor)
3027 WEBCORE_COMMAND(makeTextWritingDirectionLeftToRight)
3028 WEBCORE_COMMAND(makeTextWritingDirectionNatural)
3029 WEBCORE_COMMAND(makeTextWritingDirectionRightToLeft)
3030 WEBCORE_COMMAND(moveBackward)
3031 WEBCORE_COMMAND(moveBackwardAndModifySelection)
3032 WEBCORE_COMMAND(moveDown)
3033 WEBCORE_COMMAND(moveDownAndModifySelection)
3034 WEBCORE_COMMAND(moveForward)
3035 WEBCORE_COMMAND(moveForwardAndModifySelection)
3036 WEBCORE_COMMAND(moveLeft)
3037 WEBCORE_COMMAND(moveLeftAndModifySelection)
3038 WEBCORE_COMMAND(moveParagraphBackwardAndModifySelection)
3039 WEBCORE_COMMAND(moveParagraphForwardAndModifySelection)
3040 WEBCORE_COMMAND(moveRight)
3041 WEBCORE_COMMAND(moveRightAndModifySelection)
3042 WEBCORE_COMMAND(moveToBeginningOfDocument)
3043 WEBCORE_COMMAND(moveToBeginningOfDocumentAndModifySelection)
3044 WEBCORE_COMMAND(moveToBeginningOfLine)
3045 WEBCORE_COMMAND(moveToBeginningOfLineAndModifySelection)
3046 WEBCORE_COMMAND(moveToBeginningOfParagraph)
3047 WEBCORE_COMMAND(moveToBeginningOfParagraphAndModifySelection)
3048 WEBCORE_COMMAND(moveToBeginningOfSentence)
3049 WEBCORE_COMMAND(moveToBeginningOfSentenceAndModifySelection)
3050 WEBCORE_COMMAND(moveToEndOfDocument)
3051 WEBCORE_COMMAND(moveToEndOfDocumentAndModifySelection)
3052 WEBCORE_COMMAND(moveToEndOfLine)
3053 WEBCORE_COMMAND(moveToEndOfLineAndModifySelection)
3054 WEBCORE_COMMAND(moveToEndOfParagraph)
3055 WEBCORE_COMMAND(moveToEndOfParagraphAndModifySelection)
3056 WEBCORE_COMMAND(moveToEndOfSentence)
3057 WEBCORE_COMMAND(moveToEndOfSentenceAndModifySelection)
3058 WEBCORE_COMMAND(moveToLeftEndOfLine)
3059 WEBCORE_COMMAND(moveToLeftEndOfLineAndModifySelection)
3060 WEBCORE_COMMAND(moveToRightEndOfLine)
3061 WEBCORE_COMMAND(moveToRightEndOfLineAndModifySelection)
3062 WEBCORE_COMMAND(moveUp)
3063 WEBCORE_COMMAND(moveUpAndModifySelection)
3064 WEBCORE_COMMAND(moveWordBackward)
3065 WEBCORE_COMMAND(moveWordBackwardAndModifySelection)
3066 WEBCORE_COMMAND(moveWordForward)
3067 WEBCORE_COMMAND(moveWordForwardAndModifySelection)
3068 WEBCORE_COMMAND(moveWordLeft)
3069 WEBCORE_COMMAND(moveWordLeftAndModifySelection)
3070 WEBCORE_COMMAND(moveWordRight)
3071 WEBCORE_COMMAND(moveWordRightAndModifySelection)
3072 WEBCORE_COMMAND(outdent)
3073 WEBCORE_COMMAND(overWrite)
3074 WEBCORE_COMMAND(pageDown)
3075 WEBCORE_COMMAND(pageDownAndModifySelection)
3076 WEBCORE_COMMAND(pageUp)
3077 WEBCORE_COMMAND(pageUpAndModifySelection)
3078 WEBCORE_COMMAND(pasteAsPlainText)
3079 WEBCORE_COMMAND(selectAll)
3080 WEBCORE_COMMAND(selectLine)
3081 WEBCORE_COMMAND(selectParagraph)
3082 WEBCORE_COMMAND(selectSentence)
3083 WEBCORE_COMMAND(selectToMark)
3084 WEBCORE_COMMAND(selectWord)
3085 WEBCORE_COMMAND(setMark)
3086 WEBCORE_COMMAND(subscript)
3087 WEBCORE_COMMAND(superscript)
3088 WEBCORE_COMMAND(swapWithMark)
3089 WEBCORE_COMMAND(transpose)
3090 WEBCORE_COMMAND(underline)
3091 WEBCORE_COMMAND(unscript)
3092 WEBCORE_COMMAND(yank)
3093 WEBCORE_COMMAND(yankAndSelect)
3094
3095 #if PLATFORM(IOS)
3096 WEBCORE_COMMAND(clearText)
3097 WEBCORE_COMMAND(toggleBold)
3098 WEBCORE_COMMAND(toggleItalic)
3099 WEBCORE_COMMAND(toggleUnderline)
3100 #endif
3101
3102 #undef WEBCORE_COMMAND
3103
3104 #define COMMAND_PROLOGUE if ([self callDelegateDoCommandBySelectorIfNeeded:_cmd]) return;
3105
3106 #if !PLATFORM(IOS)
3107 - (IBAction)takeFindStringFromSelection:(id)sender
3108 {
3109     COMMAND_PROLOGUE
3110
3111     if (![self _hasSelection]) {
3112         NSBeep();
3113         return;
3114     }
3115
3116     [NSPasteboard _web_setFindPasteboardString:[self selectedString] withOwner:self];
3117 }
3118
3119 // This method is needed to support Mac OS X services.
3120 - (BOOL)writeSelectionToPasteboard:(NSPasteboard *)pasteboard types:(NSArray *)types
3121 {
3122     [pasteboard declareTypes:types owner:[self _topHTMLView]];
3123     [self writeSelectionWithPasteboardTypes:types toPasteboard:pasteboard];
3124     return YES;
3125 }
3126
3127 - (id)validRequestorForSendType:(NSString *)sendType returnType:(NSString *)returnType
3128 {
3129     BOOL isSendTypeOK = !sendType || ([[self pasteboardTypesForSelection] containsObject:sendType] && [self _hasSelection]);
3130     BOOL isReturnTypeOK = NO;
3131     if (!returnType)
3132         isReturnTypeOK = YES;
3133     else if ([[[self class] _insertablePasteboardTypes] containsObject:returnType] && [self _isEditable]) {
3134         // We can insert strings in any editable context.  We can insert other types, like images, only in rich edit contexts.
3135         isReturnTypeOK = [returnType isEqualToString:NSStringPboardType] || [self _canEditRichly];
3136     }
3137     if (isSendTypeOK && isReturnTypeOK)
3138         return self;
3139     return [[self nextResponder] validRequestorForSendType:sendType returnType:returnType];
3140 }
3141 #endif
3142
3143 // jumpToSelection is the old name for what AppKit now calls centerSelectionInVisibleArea. Safari
3144 // was using the old jumpToSelection selector in its menu. Newer versions of Safari will use the
3145 // selector centerSelectionInVisibleArea. We'll leave the old selector in place for two reasons:
3146 // (1) Compatibility between older Safari and newer WebKit; (2) other WebKit-based applications
3147 // might be using the selector, and we don't want to break them.
3148 - (void)jumpToSelection:(id)sender
3149 {
3150     COMMAND_PROLOGUE
3151
3152     if (Frame* coreFrame = core([self _frame]))
3153         coreFrame->selection().revealSelection(ScrollAlignment::alignCenterAlways);
3154 }
3155
3156 #if !PLATFORM(IOS)
3157 - (BOOL)validateUserInterfaceItemWithoutDelegate:(id <NSValidatedUserInterfaceItem>)item
3158 {
3159     SEL action = [item action];
3160     RefPtr<Frame> frame = core([self _frame]);
3161
3162     if (!frame)
3163         return NO;
3164     
3165     if (Document* doc = frame->document()) {
3166         if (doc->isPluginDocument())
3167             return NO;
3168         if (doc->isImageDocument()) {            
3169             if (action == @selector(copy:))
3170                 return frame->loader().isComplete();
3171             return NO;
3172         }
3173     }
3174
3175     if (action == @selector(changeSpelling:)
3176             || action == @selector(_changeSpellingFromMenu:)
3177             || action == @selector(checkSpelling:)
3178             || action == @selector(complete:)
3179             || action == @selector(pasteFont:))
3180         return [self _canEdit];
3181
3182     if (action == @selector(showGuessPanel:)) {
3183         // Match OS X AppKit behavior for post-Tiger. Don't change Tiger behavior.
3184         NSMenuItem *menuItem = (NSMenuItem *)item;
3185         if ([menuItem isKindOfClass:[NSMenuItem class]]) {
3186             BOOL panelShowing = [[[NSSpellChecker sharedSpellChecker] spellingPanel] isVisible];
3187             [menuItem setTitle:panelShowing
3188                 ? UI_STRING_INTERNAL("Hide Spelling and Grammar", "menu item title")
3189                 : UI_STRING_INTERNAL("Show Spelling and Grammar", "menu item title")];
3190         }
3191         return [self _canEdit];
3192     }
3193     
3194     if (action == @selector(changeBaseWritingDirection:)
3195             || action == @selector(makeBaseWritingDirectionLeftToRight:)
3196             || action == @selector(makeBaseWritingDirectionRightToLeft:)) {
3197         NSWritingDirection writingDirection;
3198
3199         if (action == @selector(changeBaseWritingDirection:)) {
3200             writingDirection = static_cast<NSWritingDirection>([item tag]);
3201             if (writingDirection == NSWritingDirectionNatural)
3202                 return NO;
3203         } else if (action == @selector(makeBaseWritingDirectionLeftToRight:))
3204             writingDirection = NSWritingDirectionLeftToRight;
3205         else
3206             writingDirection = NSWritingDirectionRightToLeft;
3207
3208         NSMenuItem *menuItem = (NSMenuItem *)item;
3209         if ([menuItem isKindOfClass:[NSMenuItem class]]) {
3210             String direction = writingDirection == NSWritingDirectionLeftToRight ? "ltr" : "rtl";
3211             [menuItem setState:frame->editor().selectionHasStyle(CSSPropertyDirection, direction)];
3212         }
3213         return [self _canEdit];
3214     }
3215
3216     if (action == @selector(makeBaseWritingDirectionNatural:)) {
3217         NSMenuItem *menuItem = (NSMenuItem *)item;
3218         if ([menuItem isKindOfClass:[NSMenuItem class]])
3219             [menuItem setState:NSOffState];
3220         return NO;
3221     }
3222
3223     if (action == @selector(toggleBaseWritingDirection:)) {
3224         NSMenuItem *menuItem = (NSMenuItem *)item;
3225         if ([menuItem isKindOfClass:[NSMenuItem class]]) {
3226             // Take control of the title of the menu item instead of just checking/unchecking it because
3227             // a check would be ambiguous.
3228             [menuItem setTitle:frame->editor().selectionHasStyle(CSSPropertyDirection, "rtl")
3229                 ? UI_STRING_INTERNAL("Left to Right", "Left to Right context menu item")
3230                 : UI_STRING_INTERNAL("Right to Left", "Right to Left context menu item")];
3231         }
3232         return [self _canEdit];
3233     } 
3234     
3235     if (action == @selector(changeAttributes:)
3236             || action == @selector(changeColor:)        
3237             || action == @selector(changeFont:))
3238         return [self _canEditRichly];
3239     
3240     if (action == @selector(capitalizeWord:)
3241                || action == @selector(lowercaseWord:)
3242                || action == @selector(uppercaseWord:))
3243         return [self _hasSelection] && [self _isEditable];
3244
3245     if (action == @selector(centerSelectionInVisibleArea:)
3246                || action == @selector(jumpToSelection:)
3247                || action == @selector(copyFont:))
3248         return [self _hasSelection] || ([self _isEditable] && [self _hasInsertionPoint]);
3249     
3250     if (action == @selector(changeDocumentBackgroundColor:))
3251         return [[self _webView] isEditable] && [self _canEditRichly];
3252     
3253     if (action == @selector(_ignoreSpellingFromMenu:)
3254             || action == @selector(_learnSpellingFromMenu:)
3255             || action == @selector(takeFindStringFromSelection:))
3256         return [self _hasSelection];
3257     
3258     if (action == @selector(paste:) || action == @selector(pasteAsPlainText:))
3259         return frame && (frame->editor().canDHTMLPaste() || frame->editor().canPaste());
3260     
3261     if (action == @selector(pasteAsRichText:))
3262         return frame && (frame->editor().canDHTMLPaste()
3263             || (frame->editor().canPaste() && frame->selection().selection().isContentRichlyEditable()));
3264     
3265     if (action == @selector(performFindPanelAction:))
3266         return NO;
3267     
3268     if (action == @selector(_lookUpInDictionaryFromMenu:))
3269         return [self _hasSelection];
3270
3271     if (action == @selector(stopSpeaking:))
3272         return [NSApp isSpeaking];
3273
3274     if (action == @selector(toggleGrammarChecking:)) {
3275         // FIXME 4799134: WebView is the bottleneck for this grammar-checking logic, but we must validate 
3276         // the selector here because we implement it here, and we must implement it here because the AppKit 
3277         // code checks the first responder.
3278         NSMenuItem *menuItem = (NSMenuItem *)item;
3279         if ([menuItem isKindOfClass:[NSMenuItem class]])
3280             [menuItem setState:[self isGrammarCheckingEnabled] ? NSOnState : NSOffState];
3281         return YES;
3282     }
3283
3284     if (action == @selector(orderFrontSubstitutionsPanel:)) {
3285         NSMenuItem *menuItem = (NSMenuItem *)item;
3286         if ([menuItem isKindOfClass:[NSMenuItem class]]) {
3287             BOOL panelShowing = [[[NSSpellChecker sharedSpellChecker] substitutionsPanel] isVisible];
3288             [menuItem setTitle:panelShowing
3289                 ? UI_STRING_INTERNAL("Hide Substitutions", "menu item title")
3290                 : UI_STRING_INTERNAL("Show Substitutions", "menu item title")];
3291         }
3292         return [self _canEdit];
3293     }
3294     // FIXME 4799134: WebView is the bottleneck for this logic, but we must validate 
3295     // the selector here because we implement it here, and we must implement it here because the AppKit 
3296     // code checks the first responder.
3297     if (action == @selector(toggleSmartInsertDelete:)) {
3298         NSMenuItem *menuItem = (NSMenuItem *)item;
3299         if ([menuItem isKindOfClass:[NSMenuItem class]])
3300             [menuItem setState:[self smartInsertDeleteEnabled] ? NSOnState : NSOffState];
3301         return [self _canEdit];
3302     }
3303     if (action == @selector(toggleAutomaticQuoteSubstitution:)) {
3304         NSMenuItem *menuItem = (NSMenuItem *)item;
3305         if ([menuItem isKindOfClass:[NSMenuItem class]])
3306             [menuItem setState:[self isAutomaticQuoteSubstitutionEnabled] ? NSOnState : NSOffState];
3307         return [self _canEdit];
3308     }
3309     if (action == @selector(toggleAutomaticLinkDetection:)) {
3310         NSMenuItem *menuItem = (NSMenuItem *)item;
3311         if ([menuItem isKindOfClass:[NSMenuItem class]])
3312             [menuItem setState:[self isAutomaticLinkDetectionEnabled] ? NSOnState : NSOffState];
3313         return [self _canEdit];
3314     }
3315     if (action == @selector(toggleAutomaticDashSubstitution:)) {
3316         NSMenuItem *menuItem = (NSMenuItem *)item;
3317         if ([menuItem isKindOfClass:[NSMenuItem class]])
3318             [menuItem setState:[self isAutomaticDashSubstitutionEnabled] ? NSOnState : NSOffState];
3319         return [self _canEdit];
3320     }
3321     if (action == @selector(toggleAutomaticTextReplacement:)) {
3322         NSMenuItem *menuItem = (NSMenuItem *)item;
3323         if ([menuItem isKindOfClass:[NSMenuItem class]])
3324             [menuItem setState:[self isAutomaticTextReplacementEnabled] ? NSOnState : NSOffState];
3325         return [self _canEdit];
3326     }
3327     if (action == @selector(toggleAutomaticSpellingCorrection:)) {
3328         NSMenuItem *menuItem = (NSMenuItem *)item;
3329         if ([menuItem isKindOfClass:[NSMenuItem class]])
3330             [menuItem setState:[self isAutomaticSpellingCorrectionEnabled] ? NSOnState : NSOffState];
3331         return [self _canEdit];
3332     }
3333
3334     Editor::Command command = [self coreCommandBySelector:action];
3335     if (command.isSupported()) {
3336         NSMenuItem *menuItem = (NSMenuItem *)item;
3337         if ([menuItem isKindOfClass:[NSMenuItem class]])
3338             [menuItem setState:kit(command.state())];
3339         return command.isEnabled();
3340     }
3341
3342     return YES;
3343 }
3344
3345 - (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item
3346 {
3347     // This can be called during teardown when _webView is nil. Return NO when this happens, because CallUIDelegateReturningBoolean
3348     // assumes the WebVIew is non-nil.
3349     if (![self _webView])
3350         return NO;
3351     BOOL result = [self validateUserInterfaceItemWithoutDelegate:item];
3352     return CallUIDelegateReturningBoolean(result, [self _webView], @selector(webView:validateUserInterfaceItem:defaultValidation:), item, result);
3353 }
3354 #endif // !PLATFORM(IOS)
3355
3356 - (BOOL)acceptsFirstResponder
3357 {
3358     // Don't accept first responder when we first click on this view.
3359     // We have to pass the event down through WebCore first to be sure we don't hit a subview.
3360     // Do accept first responder at any other time, for example from keyboard events,
3361     // or from calls back from WebCore once we begin mouse-down event handling.
3362 #if !PLATFORM(IOS)            
3363     NSEvent *event = [NSApp currentEvent];
3364 #pragma clang diagnostic push
3365 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
3366     if ([event type] == NSLeftMouseDown
3367             && !_private->handlingMouseDownEvent
3368             && NSPointInRect([event locationInWindow], [self convertRect:[self visibleRect] toView:nil])) {
3369 #pragma clang diagnostic pop
3370         return NO;
3371     }
3372 #else
3373     WebEvent *event = [WAKWindow currentEvent];
3374     if (event && event.type == WebEventMouseDown
3375             && !_private->handlingMouseDownEvent
3376             && NSPointInRect([event locationInWindow], [self convertRect:[self visibleRect] toView:nil]))
3377         return NO;
3378 #endif
3379     return YES;
3380 }
3381
3382 - (BOOL)maintainsInactiveSelection
3383 {
3384 #if USE(UIKIT_EDITING)
3385     // We want to maintain an inactive selection, when in editable content.
3386     if ([[self _webView] maintainsInactiveSelection])
3387         return YES;
3388
3389     if ([[self window] _newFirstResponderAfterResigning] == self)
3390         return YES;
3391     
3392     Frame* coreFrame = core([self _frame]);
3393     return coreFrame && coreFrame->selection().selection().isContentEditable();
3394 #else
3395     // This method helps to determine whether the WebHTMLView should maintain
3396     // an inactive selection when it's not first responder.
3397     // Traditionally, these views have not maintained such selections,
3398     // clearing them when the view was not first responder. However,
3399     // to fix bugs like this one:
3400     // <rdar://problem/3672088>: "Editable WebViews should maintain a selection even 
3401     //                            when they're not firstResponder"
3402     // it was decided to add a switch to act more like an NSTextView.
3403
3404     if ([[self _webView] maintainsInactiveSelection])
3405         return YES;
3406
3407     // Predict the case where we are losing first responder status only to
3408     // gain it back again. Want to keep the selection in that case.
3409     id nextResponder = [[self window] _newFirstResponderAfterResigning];
3410     if ([nextResponder isKindOfClass:[NSScrollView class]]) {
3411         id contentView = [nextResponder contentView];
3412         if (contentView)
3413             nextResponder = contentView;
3414     }
3415     if ([nextResponder isKindOfClass:[NSClipView class]]) {
3416         id documentView = [nextResponder documentView];
3417         if (documentView)
3418             nextResponder = documentView;
3419     }
3420     if (nextResponder == self)
3421         return YES;
3422
3423     Frame* coreFrame = core([self _frame]);
3424     bool selectionIsEditable = coreFrame && coreFrame->selection().selection().isContentEditable();
3425     bool nextResponderIsInWebView = [nextResponder isKindOfClass:[NSView class]]
3426         && [nextResponder isDescendantOf:[[[self _webView] mainFrame] frameView]];
3427
3428     return selectionIsEditable && nextResponderIsInWebView;
3429 #endif
3430 }
3431
3432 #if !PLATFORM(IOS)
3433 - (void)addSuperviewObservers
3434 {
3435     if (_private->observingSuperviewNotifications)
3436         return;
3437
3438     NSView *superview = [self superview];
3439     if (!superview || ![self window])
3440         return;
3441     
3442     NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
3443     [notificationCenter addObserver:self selector:@selector(_frameOrBoundsChanged) name:NSViewFrameDidChangeNotification object:superview];
3444     [notificationCenter addObserver:self selector:@selector(_frameOrBoundsChanged) name:NSViewBoundsDidChangeNotification object:superview];
3445     
3446     // In addition to registering for frame/bounds change notifications, call -_frameOrBoundsChanged.
3447     // It will check the current scroll against the previous layout's scroll.  We need to
3448     // do this here to catch the case where the WebView is laid out at one size, removed from its
3449     // window, resized, and inserted into another window.  Our frame/bounds changed notifications
3450     // will not be sent in that situation, since we only watch for changes while in the view hierarchy.
3451     [self _frameOrBoundsChanged];
3452     
3453     _private->observingSuperviewNotifications = true;
3454 }
3455
3456 - (void)addWindowObservers
3457 {
3458     if (_private->observingWindowNotifications)
3459         return;
3460     
3461     NSWindow *window = [self window];
3462     if (!window)
3463         return;
3464     
3465     NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
3466     [notificationCenter addObserver:self selector:@selector(windowDidBecomeKey:) name:NSWindowDidBecomeKeyNotification object:nil];
3467     [notificationCenter addObserver:self selector:@selector(windowDidResignKey:) name:NSWindowDidResignKeyNotification object:nil];
3468     [notificationCenter addObserver:self selector:@selector(windowWillOrderOnScreen:) name:WKWindowWillOrderOnScreenNotification() object:window];
3469     [notificationCenter addObserver:self selector:@selector(windowWillOrderOffScreen:) name:WKWindowWillOrderOffScreenNotification() object:window];
3470     [notificationCenter addObserver:self selector:@selector(windowWillClose:) name:NSWindowWillCloseNotification object:window];
3471     
3472     _private->observingWindowNotifications = true;
3473 }
3474
3475 - (void)viewWillMoveToSuperview:(NSView *)newSuperview
3476 {