Update ANGLE
[WebKit-https.git] / Source / WebCore / page / ContextMenuController.cpp
1 /*
2  * Copyright (C) 2006-2016 Apple Inc. All rights reserved.
3  * Copyright (C) 2010 Igalia S.L
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  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
25  */
26
27 #include "config.h"
28 #include "ContextMenuController.h"
29
30 #if ENABLE(CONTEXT_MENUS)
31
32 #include "BackForwardController.h"
33 #include "Chrome.h"
34 #include "ContextMenu.h"
35 #include "ContextMenuClient.h"
36 #include "ContextMenuItem.h"
37 #include "ContextMenuProvider.h"
38 #include "CustomHeaderFields.h"
39 #include "Document.h"
40 #include "DocumentFragment.h"
41 #include "DocumentLoader.h"
42 #include "Editor.h"
43 #include "EditorClient.h"
44 #include "Event.h"
45 #include "EventHandler.h"
46 #include "FormState.h"
47 #include "Frame.h"
48 #include "FrameLoadRequest.h"
49 #include "FrameLoader.h"
50 #include "FrameLoaderClient.h"
51 #include "FrameSelection.h"
52 #include "HTMLFormControlElement.h"
53 #include "HTMLFormElement.h"
54 #include "HitTestRequest.h"
55 #include "HitTestResult.h"
56 #include "InspectorController.h"
57 #include "LocalizedStrings.h"
58 #include "MouseEvent.h"
59 #include "NavigationAction.h"
60 #include "Node.h"
61 #include "Page.h"
62 #include "PlatformEvent.h"
63 #include "RenderImage.h"
64 #include "ReplaceSelectionCommand.h"
65 #include "ResourceRequest.h"
66 #include "Settings.h"
67 #include "TextIterator.h"
68 #include "TypingCommand.h"
69 #include "UserTypingGestureIndicator.h"
70 #include "WindowFeatures.h"
71 #include "markup.h"
72 #include <wtf/SetForScope.h>
73 #include <wtf/WallTime.h>
74 #include <wtf/unicode/CharacterNames.h>
75
76
77 namespace WebCore {
78
79 using namespace WTF::Unicode;
80
81 ContextMenuController::ContextMenuController(Page& page, ContextMenuClient& client)
82     : m_page(page)
83     , m_client(client)
84 {
85 }
86
87 ContextMenuController::~ContextMenuController()
88 {
89     m_client.contextMenuDestroyed();
90 }
91
92 void ContextMenuController::clearContextMenu()
93 {
94     m_contextMenu = nullptr;
95     if (m_menuProvider)
96         m_menuProvider->contextMenuCleared();
97     m_menuProvider = nullptr;
98 }
99
100 void ContextMenuController::handleContextMenuEvent(Event& event)
101 {
102     if (m_isHandlingContextMenuEvent)
103         return;
104
105     SetForScope<bool> isHandlingContextMenuEventForScope(m_isHandlingContextMenuEvent, true);
106
107     m_contextMenu = maybeCreateContextMenu(event);
108     if (!m_contextMenu)
109         return;
110
111     populate();
112
113     showContextMenu(event);
114 }
115
116 static std::unique_ptr<ContextMenuItem> separatorItem()
117 {
118     return std::unique_ptr<ContextMenuItem>(new ContextMenuItem(SeparatorType, ContextMenuItemTagNoAction, String()));
119 }
120
121 void ContextMenuController::showContextMenu(Event& event, ContextMenuProvider& provider)
122 {
123     m_menuProvider = &provider;
124
125     m_contextMenu = maybeCreateContextMenu(event);
126     if (!m_contextMenu) {
127         clearContextMenu();
128         return;
129     }
130
131     provider.populateContextMenu(m_contextMenu.get());
132     if (m_context.hitTestResult().isSelected()) {
133         appendItem(*separatorItem(), m_contextMenu.get());
134         populate();
135     }
136     showContextMenu(event);
137 }
138
139 #if ENABLE(SERVICE_CONTROLS)
140
141 static Image* imageFromImageElementNode(Node& node)
142 {
143     auto* renderer = node.renderer();
144     if (!is<RenderImage>(renderer))
145         return nullptr;
146     auto* image = downcast<RenderImage>(*renderer).cachedImage();
147     if (!image || image->errorOccurred())
148         return nullptr;
149     return image->imageForRenderer(renderer);
150 }
151
152 #endif
153
154 std::unique_ptr<ContextMenu> ContextMenuController::maybeCreateContextMenu(Event& event)
155 {
156     if (!is<MouseEvent>(event))
157         return nullptr;
158
159     auto& mouseEvent = downcast<MouseEvent>(event);
160     if (!is<Node>(mouseEvent.target()))
161         return nullptr;
162     auto& node = downcast<Node>(*mouseEvent.target());
163     auto* frame = node.document().frame();
164     if (!frame)
165         return nullptr;
166
167     auto result = frame->eventHandler().hitTestResultAtPoint(mouseEvent.absoluteLocation(), HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::DisallowUserAgentShadowContent | HitTestRequest::AllowChildFrameContent);
168     if (!result.innerNonSharedNode())
169         return nullptr;
170
171     m_context = ContextMenuContext(result);
172
173 #if ENABLE(SERVICE_CONTROLS)
174     if (node.isImageControlsButtonElement()) {
175         if (auto* image = imageFromImageElementNode(*result.innerNonSharedNode()))
176             m_context.setControlledImage(image);
177
178         // FIXME: If we couldn't get the image then we shouldn't try to show the image controls menu for it.
179         return nullptr;
180     }
181 #endif
182
183     return std::make_unique<ContextMenu>();
184 }
185
186 void ContextMenuController::showContextMenu(Event& event)
187 {
188     if (m_page.inspectorController().enabled())
189         addInspectElementItem();
190
191     event.setDefaultHandled();
192 }
193
194 static void openNewWindow(const URL& urlToLoad, Frame& frame, ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy)
195 {
196     Page* oldPage = frame.page();
197     if (!oldPage)
198         return;
199
200     FrameLoadRequest frameLoadRequest { *frame.document(), frame.document()->securityOrigin(), ResourceRequest(urlToLoad, frame.loader().outgoingReferrer()), { }, LockHistory::No, LockBackForwardList::No, MaybeSendReferrer, AllowNavigationToInvalidURL::Yes, NewFrameOpenerPolicy::Suppress, shouldOpenExternalURLsPolicy, InitiatedByMainFrame::Unknown };
201
202     Page* newPage = oldPage->chrome().createWindow(frame, frameLoadRequest, { }, { *frame.document(), frameLoadRequest.resourceRequest(), frameLoadRequest.initiatedByMainFrame() });
203     if (!newPage)
204         return;
205     newPage->chrome().show();
206     newPage->mainFrame().loader().loadFrameRequest(WTFMove(frameLoadRequest), nullptr, { });
207 }
208
209 #if PLATFORM(GTK)
210
211 static void insertUnicodeCharacter(UChar character, Frame& frame)
212 {
213     String text(&character, 1);
214     if (!frame.editor().shouldInsertText(text, frame.selection().toNormalizedRange().get(), EditorInsertAction::Typed))
215         return;
216
217     ASSERT(frame.document());
218     TypingCommand::insertText(*frame.document(), text, 0, TypingCommand::TextCompositionNone);
219 }
220
221 #endif
222
223 void ContextMenuController::contextMenuItemSelected(ContextMenuAction action, const String& title)
224 {
225     if (action >= ContextMenuItemBaseCustomTag) {
226         ASSERT(m_menuProvider);
227         m_menuProvider->contextMenuItemSelected(action, title);
228         return;
229     }
230
231     Frame* frame = m_context.hitTestResult().innerNonSharedNode()->document().frame();
232     if (!frame)
233         return;
234
235     Ref<Frame> protector(*frame);
236
237     switch (action) {
238     case ContextMenuItemTagOpenLinkInNewWindow:
239         openNewWindow(m_context.hitTestResult().absoluteLinkURL(), *frame, ShouldOpenExternalURLsPolicy::ShouldAllowExternalSchemes);
240         break;
241     case ContextMenuItemTagDownloadLinkToDisk:
242         // FIXME: Some day we should be able to do this from within WebCore. (Bug 117709)
243         m_client.downloadURL(m_context.hitTestResult().absoluteLinkURL());
244         break;
245     case ContextMenuItemTagCopyLinkToClipboard:
246         frame->editor().copyURL(m_context.hitTestResult().absoluteLinkURL(), m_context.hitTestResult().textContent());
247         break;
248     case ContextMenuItemTagOpenImageInNewWindow:
249         openNewWindow(m_context.hitTestResult().absoluteImageURL(), *frame, ShouldOpenExternalURLsPolicy::ShouldNotAllow);
250         break;
251     case ContextMenuItemTagDownloadImageToDisk:
252         // FIXME: Some day we should be able to do this from within WebCore. (Bug 117709)
253         m_client.downloadURL(m_context.hitTestResult().absoluteImageURL());
254         break;
255     case ContextMenuItemTagCopyImageToClipboard:
256         // FIXME: The Pasteboard class is not written yet
257         // For now, call into the client. This is temporary!
258         frame->editor().copyImage(m_context.hitTestResult());
259         break;
260 #if PLATFORM(GTK)
261     case ContextMenuItemTagCopyImageUrlToClipboard:
262         frame->editor().copyURL(m_context.hitTestResult().absoluteImageURL(), m_context.hitTestResult().textContent());
263         break;
264 #endif
265     case ContextMenuItemTagOpenMediaInNewWindow:
266         openNewWindow(m_context.hitTestResult().absoluteMediaURL(), *frame, ShouldOpenExternalURLsPolicy::ShouldNotAllow);
267         break;
268     case ContextMenuItemTagDownloadMediaToDisk:
269         // FIXME: Some day we should be able to do this from within WebCore. (Bug 117709)
270         m_client.downloadURL(m_context.hitTestResult().absoluteMediaURL());
271         break;
272     case ContextMenuItemTagCopyMediaLinkToClipboard:
273         frame->editor().copyURL(m_context.hitTestResult().absoluteMediaURL(), m_context.hitTestResult().textContent());
274         break;
275     case ContextMenuItemTagToggleMediaControls:
276         m_context.hitTestResult().toggleMediaControlsDisplay();
277         break;
278     case ContextMenuItemTagToggleMediaLoop:
279         m_context.hitTestResult().toggleMediaLoopPlayback();
280         break;
281     case ContextMenuItemTagToggleVideoFullscreen:
282         m_context.hitTestResult().toggleMediaFullscreenState();
283         break;
284     case ContextMenuItemTagEnterVideoFullscreen:
285         m_context.hitTestResult().enterFullscreenForVideo();
286         break;
287     case ContextMenuItemTagMediaPlayPause:
288         m_context.hitTestResult().toggleMediaPlayState();
289         break;
290     case ContextMenuItemTagMediaMute:
291         m_context.hitTestResult().toggleMediaMuteState();
292         break;
293     case ContextMenuItemTagToggleVideoEnhancedFullscreen:
294         m_context.hitTestResult().toggleEnhancedFullscreenForVideo();
295         break;
296     case ContextMenuItemTagOpenFrameInNewWindow: {
297         DocumentLoader* loader = frame->loader().documentLoader();
298         if (!loader->unreachableURL().isEmpty())
299             openNewWindow(loader->unreachableURL(), *frame, ShouldOpenExternalURLsPolicy::ShouldNotAllow);
300         else
301             openNewWindow(loader->url(), *frame, ShouldOpenExternalURLsPolicy::ShouldNotAllow);
302         break;
303     }
304     case ContextMenuItemTagCopy:
305         frame->editor().copy();
306         break;
307     case ContextMenuItemTagGoBack:
308         if (Page* page = frame->page())
309             page->backForward().goBackOrForward(-1);
310         break;
311     case ContextMenuItemTagGoForward:
312         if (Page* page = frame->page())
313             page->backForward().goBackOrForward(1);
314         break;
315     case ContextMenuItemTagStop:
316         frame->loader().stop();
317         break;
318     case ContextMenuItemTagReload:
319         frame->loader().reload();
320         break;
321     case ContextMenuItemTagCut:
322         frame->editor().command("Cut").execute();
323         break;
324     case ContextMenuItemTagPaste:
325         frame->editor().command("Paste").execute();
326         break;
327 #if PLATFORM(GTK)
328     case ContextMenuItemTagDelete:
329         frame->editor().performDelete();
330         break;
331     case ContextMenuItemTagUnicodeInsertLRMMark:
332         insertUnicodeCharacter(leftToRightMark, *frame);
333         break;
334     case ContextMenuItemTagUnicodeInsertRLMMark:
335         insertUnicodeCharacter(rightToLeftMark, *frame);
336         break;
337     case ContextMenuItemTagUnicodeInsertLREMark:
338         insertUnicodeCharacter(leftToRightEmbed, *frame);
339         break;
340     case ContextMenuItemTagUnicodeInsertRLEMark:
341         insertUnicodeCharacter(rightToLeftEmbed, *frame);
342         break;
343     case ContextMenuItemTagUnicodeInsertLROMark:
344         insertUnicodeCharacter(leftToRightOverride, *frame);
345         break;
346     case ContextMenuItemTagUnicodeInsertRLOMark:
347         insertUnicodeCharacter(rightToLeftOverride, *frame);
348         break;
349     case ContextMenuItemTagUnicodeInsertPDFMark:
350         insertUnicodeCharacter(popDirectionalFormatting, *frame);
351         break;
352     case ContextMenuItemTagUnicodeInsertZWSMark:
353         insertUnicodeCharacter(zeroWidthSpace, *frame);
354         break;
355     case ContextMenuItemTagUnicodeInsertZWJMark:
356         insertUnicodeCharacter(zeroWidthJoiner, *frame);
357         break;
358     case ContextMenuItemTagUnicodeInsertZWNJMark:
359         insertUnicodeCharacter(zeroWidthNonJoiner, *frame);
360         break;
361     case ContextMenuItemTagSelectAll:
362         frame->editor().command("SelectAll").execute();
363         break;
364     case ContextMenuItemTagInsertEmoji:
365         m_client.insertEmoji(*frame);
366         break;
367 #endif
368     case ContextMenuItemTagSpellingGuess: {
369         VisibleSelection selection = frame->selection().selection();
370         if (frame->editor().shouldInsertText(title, selection.toNormalizedRange().get(), EditorInsertAction::Pasted)) {
371             OptionSet<ReplaceSelectionCommand::CommandOption> replaceOptions { ReplaceSelectionCommand::MatchStyle, ReplaceSelectionCommand::PreventNesting };
372
373             if (frame->editor().behavior().shouldAllowSpellingSuggestionsWithoutSelection()) {
374                 ASSERT(selection.isCaretOrRange());
375                 VisibleSelection wordSelection(selection.base());
376                 wordSelection.expandUsingGranularity(WordGranularity);
377                 frame->selection().setSelection(wordSelection);
378             } else {
379                 ASSERT(frame->editor().selectedText().length());
380                 replaceOptions.add(ReplaceSelectionCommand::SelectReplacement);
381             }
382
383             Document* document = frame->document();
384             ASSERT(document);
385             auto command = ReplaceSelectionCommand::create(*document, createFragmentFromMarkup(*document, title, emptyString()), replaceOptions);
386             command->apply();
387             frame->selection().revealSelection(SelectionRevealMode::Reveal, ScrollAlignment::alignToEdgeIfNeeded);
388         }
389         break;
390     }
391     case ContextMenuItemTagIgnoreSpelling:
392         frame->editor().ignoreSpelling();
393         break;
394     case ContextMenuItemTagLearnSpelling:
395         frame->editor().learnSpelling();
396         break;
397     case ContextMenuItemTagSearchWeb:
398         m_client.searchWithGoogle(frame);
399         break;
400     case ContextMenuItemTagLookUpInDictionary:
401         // FIXME: Some day we may be able to do this from within WebCore.
402         m_client.lookUpInDictionary(frame);
403         break;
404     case ContextMenuItemTagOpenLink:
405         if (Frame* targetFrame = m_context.hitTestResult().targetFrame()) {
406             ResourceRequest resourceRequest { m_context.hitTestResult().absoluteLinkURL(), frame->loader().outgoingReferrer() };
407             FrameLoadRequest frameLoadRequest { *frame->document(), frame->document()->securityOrigin(), resourceRequest, { }, LockHistory::No, LockBackForwardList::No, MaybeSendReferrer, AllowNavigationToInvalidURL::Yes, NewFrameOpenerPolicy::Suppress, targetFrame->isMainFrame() ? ShouldOpenExternalURLsPolicy::ShouldAllow : ShouldOpenExternalURLsPolicy::ShouldNotAllow, InitiatedByMainFrame::Unknown };
408             targetFrame->loader().loadFrameRequest(WTFMove(frameLoadRequest), nullptr,  { });
409         } else
410             openNewWindow(m_context.hitTestResult().absoluteLinkURL(), *frame, ShouldOpenExternalURLsPolicy::ShouldAllow);
411         break;
412     case ContextMenuItemTagBold:
413         frame->editor().command("ToggleBold").execute();
414         break;
415     case ContextMenuItemTagItalic:
416         frame->editor().command("ToggleItalic").execute();
417         break;
418     case ContextMenuItemTagUnderline:
419         frame->editor().toggleUnderline();
420         break;
421     case ContextMenuItemTagOutline:
422         // We actually never enable this because CSS does not have a way to specify an outline font,
423         // which may make this difficult to implement. Maybe a special case of text-shadow?
424         break;
425     case ContextMenuItemTagStartSpeaking: {
426         RefPtr<Range> selectedRange = frame->selection().toNormalizedRange();
427         if (!selectedRange || selectedRange->collapsed()) {
428             auto& document = m_context.hitTestResult().innerNonSharedNode()->document();
429             selectedRange = document.createRange();
430             if (auto* element = document.documentElement())
431                 selectedRange->selectNode(*element);
432         }
433         m_client.speak(plainText(selectedRange.get()));
434         break;
435     }
436     case ContextMenuItemTagStopSpeaking:
437         m_client.stopSpeaking();
438         break;
439     case ContextMenuItemTagDefaultDirection:
440         frame->editor().setBaseWritingDirection(WritingDirection::Natural);
441         break;
442     case ContextMenuItemTagLeftToRight:
443         frame->editor().setBaseWritingDirection(WritingDirection::LeftToRight);
444         break;
445     case ContextMenuItemTagRightToLeft:
446         frame->editor().setBaseWritingDirection(WritingDirection::RightToLeft);
447         break;
448     case ContextMenuItemTagTextDirectionDefault:
449         frame->editor().command("MakeTextWritingDirectionNatural").execute();
450         break;
451     case ContextMenuItemTagTextDirectionLeftToRight:
452         frame->editor().command("MakeTextWritingDirectionLeftToRight").execute();
453         break;
454     case ContextMenuItemTagTextDirectionRightToLeft:
455         frame->editor().command("MakeTextWritingDirectionRightToLeft").execute();
456         break;
457 #if PLATFORM(COCOA)
458     case ContextMenuItemTagSearchInSpotlight:
459         m_client.searchWithSpotlight();
460         break;
461 #endif
462     case ContextMenuItemTagShowSpellingPanel:
463         frame->editor().showSpellingGuessPanel();
464         break;
465     case ContextMenuItemTagCheckSpelling:
466         frame->editor().advanceToNextMisspelling();
467         break;
468     case ContextMenuItemTagCheckSpellingWhileTyping:
469         frame->editor().toggleContinuousSpellChecking();
470         break;
471     case ContextMenuItemTagCheckGrammarWithSpelling:
472         frame->editor().toggleGrammarChecking();
473         break;
474 #if PLATFORM(COCOA)
475     case ContextMenuItemTagShowFonts:
476         frame->editor().showFontPanel();
477         break;
478     case ContextMenuItemTagStyles:
479         frame->editor().showStylesPanel();
480         break;
481     case ContextMenuItemTagShowColors:
482         frame->editor().showColorPanel();
483         break;
484 #endif
485 #if USE(APPKIT)
486     case ContextMenuItemTagMakeUpperCase:
487         frame->editor().uppercaseWord();
488         break;
489     case ContextMenuItemTagMakeLowerCase:
490         frame->editor().lowercaseWord();
491         break;
492     case ContextMenuItemTagCapitalize:
493         frame->editor().capitalizeWord();
494         break;
495 #endif
496 #if PLATFORM(COCOA)
497     case ContextMenuItemTagChangeBack:
498         frame->editor().changeBackToReplacedString(m_context.hitTestResult().replacedString());
499         break;
500 #endif
501 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
502     case ContextMenuItemTagShowSubstitutions:
503         frame->editor().showSubstitutionsPanel();
504         break;
505     case ContextMenuItemTagSmartCopyPaste:
506         frame->editor().toggleSmartInsertDelete();
507         break;
508     case ContextMenuItemTagSmartQuotes:
509         frame->editor().toggleAutomaticQuoteSubstitution();
510         break;
511     case ContextMenuItemTagSmartDashes:
512         frame->editor().toggleAutomaticDashSubstitution();
513         break;
514     case ContextMenuItemTagSmartLinks:
515         frame->editor().toggleAutomaticLinkDetection();
516         break;
517     case ContextMenuItemTagTextReplacement:
518         frame->editor().toggleAutomaticTextReplacement();
519         break;
520     case ContextMenuItemTagCorrectSpellingAutomatically:
521         frame->editor().toggleAutomaticSpellingCorrection();
522         break;
523 #endif
524     case ContextMenuItemTagInspectElement:
525         if (Page* page = frame->page())
526             page->inspectorController().inspect(m_context.hitTestResult().innerNonSharedNode());
527         break;
528     case ContextMenuItemTagDictationAlternative:
529         frame->editor().applyDictationAlternativelternative(title);
530         break;
531     default:
532         break;
533     }
534 }
535
536 void ContextMenuController::appendItem(ContextMenuItem& menuItem, ContextMenu* parentMenu)
537 {
538     checkOrEnableIfNeeded(menuItem);
539     if (parentMenu)
540         parentMenu->appendItem(menuItem);
541 }
542
543 void ContextMenuController::createAndAppendFontSubMenu(ContextMenuItem& fontMenuItem)
544 {
545     ContextMenu fontMenu;
546
547 #if PLATFORM(COCOA)
548     ContextMenuItem showFonts(ActionType, ContextMenuItemTagShowFonts, contextMenuItemTagShowFonts());
549 #endif
550     ContextMenuItem bold(CheckableActionType, ContextMenuItemTagBold, contextMenuItemTagBold());
551     ContextMenuItem italic(CheckableActionType, ContextMenuItemTagItalic, contextMenuItemTagItalic());
552     ContextMenuItem underline(CheckableActionType, ContextMenuItemTagUnderline, contextMenuItemTagUnderline());
553     ContextMenuItem outline(ActionType, ContextMenuItemTagOutline, contextMenuItemTagOutline());
554 #if PLATFORM(COCOA)
555     ContextMenuItem styles(ActionType, ContextMenuItemTagStyles, contextMenuItemTagStyles());
556     ContextMenuItem showColors(ActionType, ContextMenuItemTagShowColors, contextMenuItemTagShowColors());
557 #endif
558
559 #if PLATFORM(COCOA)
560     appendItem(showFonts, &fontMenu);
561 #endif
562     appendItem(bold, &fontMenu);
563     appendItem(italic, &fontMenu);
564     appendItem(underline, &fontMenu);
565     appendItem(outline, &fontMenu);
566 #if PLATFORM(COCOA)
567     appendItem(styles, &fontMenu);
568     appendItem(*separatorItem(), &fontMenu);
569     appendItem(showColors, &fontMenu);
570 #endif
571
572     fontMenuItem.setSubMenu(&fontMenu);
573 }
574
575
576 #if !PLATFORM(GTK)
577
578 void ContextMenuController::createAndAppendSpellingAndGrammarSubMenu(ContextMenuItem& spellingAndGrammarMenuItem)
579 {
580     ContextMenu spellingAndGrammarMenu;
581
582     ContextMenuItem showSpellingPanel(ActionType, ContextMenuItemTagShowSpellingPanel, 
583         contextMenuItemTagShowSpellingPanel(true));
584     ContextMenuItem checkSpelling(ActionType, ContextMenuItemTagCheckSpelling, 
585         contextMenuItemTagCheckSpelling());
586     ContextMenuItem checkAsYouType(CheckableActionType, ContextMenuItemTagCheckSpellingWhileTyping, 
587         contextMenuItemTagCheckSpellingWhileTyping());
588     ContextMenuItem grammarWithSpelling(CheckableActionType, ContextMenuItemTagCheckGrammarWithSpelling, 
589         contextMenuItemTagCheckGrammarWithSpelling());
590 #if PLATFORM(COCOA)
591     ContextMenuItem correctSpelling(CheckableActionType, ContextMenuItemTagCorrectSpellingAutomatically, 
592         contextMenuItemTagCorrectSpellingAutomatically());
593 #endif
594
595     appendItem(showSpellingPanel, &spellingAndGrammarMenu);
596     appendItem(checkSpelling, &spellingAndGrammarMenu);
597 #if PLATFORM(COCOA)
598     appendItem(*separatorItem(), &spellingAndGrammarMenu);
599 #endif
600     appendItem(checkAsYouType, &spellingAndGrammarMenu);
601     appendItem(grammarWithSpelling, &spellingAndGrammarMenu);
602 #if PLATFORM(COCOA)
603     appendItem(correctSpelling, &spellingAndGrammarMenu);
604 #endif
605
606     spellingAndGrammarMenuItem.setSubMenu(&spellingAndGrammarMenu);
607 }
608
609 #endif // !PLATFORM(GTK)
610
611
612 #if PLATFORM(COCOA)
613
614 void ContextMenuController::createAndAppendSpeechSubMenu(ContextMenuItem& speechMenuItem)
615 {
616     ContextMenu speechMenu;
617
618     ContextMenuItem start(ActionType, ContextMenuItemTagStartSpeaking, contextMenuItemTagStartSpeaking());
619     ContextMenuItem stop(ActionType, ContextMenuItemTagStopSpeaking, contextMenuItemTagStopSpeaking());
620
621     appendItem(start, &speechMenu);
622     appendItem(stop, &speechMenu);
623
624     speechMenuItem.setSubMenu(&speechMenu);
625 }
626
627 #endif
628  
629 #if PLATFORM(GTK)
630
631 void ContextMenuController::createAndAppendUnicodeSubMenu(ContextMenuItem& unicodeMenuItem)
632 {
633     ContextMenu unicodeMenu;
634
635     ContextMenuItem leftToRightMarkMenuItem(ActionType, ContextMenuItemTagUnicodeInsertLRMMark, contextMenuItemTagUnicodeInsertLRMMark());
636     ContextMenuItem rightToLeftMarkMenuItem(ActionType, ContextMenuItemTagUnicodeInsertRLMMark, contextMenuItemTagUnicodeInsertRLMMark());
637     ContextMenuItem leftToRightEmbedMenuItem(ActionType, ContextMenuItemTagUnicodeInsertLREMark, contextMenuItemTagUnicodeInsertLREMark());
638     ContextMenuItem rightToLeftEmbedMenuItem(ActionType, ContextMenuItemTagUnicodeInsertRLEMark, contextMenuItemTagUnicodeInsertRLEMark());
639     ContextMenuItem leftToRightOverrideMenuItem(ActionType, ContextMenuItemTagUnicodeInsertLROMark, contextMenuItemTagUnicodeInsertLROMark());
640     ContextMenuItem rightToLeftOverrideMenuItem(ActionType, ContextMenuItemTagUnicodeInsertRLOMark, contextMenuItemTagUnicodeInsertRLOMark());
641     ContextMenuItem popDirectionalFormattingMenuItem(ActionType, ContextMenuItemTagUnicodeInsertPDFMark, contextMenuItemTagUnicodeInsertPDFMark());
642     ContextMenuItem zeroWidthSpaceMenuItem(ActionType, ContextMenuItemTagUnicodeInsertZWSMark, contextMenuItemTagUnicodeInsertZWSMark());
643     ContextMenuItem zeroWidthJoinerMenuItem(ActionType, ContextMenuItemTagUnicodeInsertZWJMark, contextMenuItemTagUnicodeInsertZWJMark());
644     ContextMenuItem zeroWidthNonJoinerMenuItem(ActionType, ContextMenuItemTagUnicodeInsertZWNJMark, contextMenuItemTagUnicodeInsertZWNJMark());
645
646     appendItem(leftToRightMarkMenuItem, &unicodeMenu);
647     appendItem(rightToLeftMarkMenuItem, &unicodeMenu);
648     appendItem(leftToRightEmbedMenuItem, &unicodeMenu);
649     appendItem(rightToLeftEmbedMenuItem, &unicodeMenu);
650     appendItem(leftToRightOverrideMenuItem, &unicodeMenu);
651     appendItem(rightToLeftOverrideMenuItem, &unicodeMenu);
652     appendItem(popDirectionalFormattingMenuItem, &unicodeMenu);
653     appendItem(zeroWidthSpaceMenuItem, &unicodeMenu);
654     appendItem(zeroWidthJoinerMenuItem, &unicodeMenu);
655     appendItem(zeroWidthNonJoinerMenuItem, &unicodeMenu);
656
657     unicodeMenuItem.setSubMenu(&unicodeMenu);
658 }
659
660 #else
661
662 void ContextMenuController::createAndAppendWritingDirectionSubMenu(ContextMenuItem& writingDirectionMenuItem)
663 {
664     ContextMenu writingDirectionMenu;
665
666     ContextMenuItem defaultItem(ActionType, ContextMenuItemTagDefaultDirection, 
667         contextMenuItemTagDefaultDirection());
668     ContextMenuItem ltr(CheckableActionType, ContextMenuItemTagLeftToRight, contextMenuItemTagLeftToRight());
669     ContextMenuItem rtl(CheckableActionType, ContextMenuItemTagRightToLeft, contextMenuItemTagRightToLeft());
670
671     appendItem(defaultItem, &writingDirectionMenu);
672     appendItem(ltr, &writingDirectionMenu);
673     appendItem(rtl, &writingDirectionMenu);
674
675     writingDirectionMenuItem.setSubMenu(&writingDirectionMenu);
676 }
677
678 void ContextMenuController::createAndAppendTextDirectionSubMenu(ContextMenuItem& textDirectionMenuItem)
679 {
680     ContextMenu textDirectionMenu;
681
682     ContextMenuItem defaultItem(ActionType, ContextMenuItemTagTextDirectionDefault, contextMenuItemTagDefaultDirection());
683     ContextMenuItem ltr(CheckableActionType, ContextMenuItemTagTextDirectionLeftToRight, contextMenuItemTagLeftToRight());
684     ContextMenuItem rtl(CheckableActionType, ContextMenuItemTagTextDirectionRightToLeft, contextMenuItemTagRightToLeft());
685
686     appendItem(defaultItem, &textDirectionMenu);
687     appendItem(ltr, &textDirectionMenu);
688     appendItem(rtl, &textDirectionMenu);
689
690     textDirectionMenuItem.setSubMenu(&textDirectionMenu);
691 }
692
693 #endif
694
695 #if PLATFORM(COCOA)
696
697 void ContextMenuController::createAndAppendSubstitutionsSubMenu(ContextMenuItem& substitutionsMenuItem)
698 {
699     ContextMenu substitutionsMenu;
700
701     ContextMenuItem showSubstitutions(ActionType, ContextMenuItemTagShowSubstitutions, contextMenuItemTagShowSubstitutions(true));
702     ContextMenuItem smartCopyPaste(CheckableActionType, ContextMenuItemTagSmartCopyPaste, contextMenuItemTagSmartCopyPaste());
703     ContextMenuItem smartQuotes(CheckableActionType, ContextMenuItemTagSmartQuotes, contextMenuItemTagSmartQuotes());
704     ContextMenuItem smartDashes(CheckableActionType, ContextMenuItemTagSmartDashes, contextMenuItemTagSmartDashes());
705     ContextMenuItem smartLinks(CheckableActionType, ContextMenuItemTagSmartLinks, contextMenuItemTagSmartLinks());
706     ContextMenuItem textReplacement(CheckableActionType, ContextMenuItemTagTextReplacement, contextMenuItemTagTextReplacement());
707
708     appendItem(showSubstitutions, &substitutionsMenu);
709     appendItem(*separatorItem(), &substitutionsMenu);
710     appendItem(smartCopyPaste, &substitutionsMenu);
711     appendItem(smartQuotes, &substitutionsMenu);
712     appendItem(smartDashes, &substitutionsMenu);
713     appendItem(smartLinks, &substitutionsMenu);
714     appendItem(textReplacement, &substitutionsMenu);
715
716     substitutionsMenuItem.setSubMenu(&substitutionsMenu);
717 }
718
719 void ContextMenuController::createAndAppendTransformationsSubMenu(ContextMenuItem& transformationsMenuItem)
720 {
721     ContextMenu transformationsMenu;
722
723     ContextMenuItem makeUpperCase(ActionType, ContextMenuItemTagMakeUpperCase, contextMenuItemTagMakeUpperCase());
724     ContextMenuItem makeLowerCase(ActionType, ContextMenuItemTagMakeLowerCase, contextMenuItemTagMakeLowerCase());
725     ContextMenuItem capitalize(ActionType, ContextMenuItemTagCapitalize, contextMenuItemTagCapitalize());
726
727     appendItem(makeUpperCase, &transformationsMenu);
728     appendItem(makeLowerCase, &transformationsMenu);
729     appendItem(capitalize, &transformationsMenu);
730
731     transformationsMenuItem.setSubMenu(&transformationsMenu);
732 }
733
734 #endif
735
736 #if PLATFORM(COCOA)
737 #define SUPPORTS_TOGGLE_VIDEO_FULLSCREEN 1
738 #else
739 #define SUPPORTS_TOGGLE_VIDEO_FULLSCREEN 0
740 #endif
741
742 #if PLATFORM(COCOA)
743 #define SUPPORTS_TOGGLE_SHOW_HIDE_MEDIA_CONTROLS 1
744 #else
745 #define SUPPORTS_TOGGLE_SHOW_HIDE_MEDIA_CONTROLS 0
746 #endif
747
748 void ContextMenuController::populate()
749 {
750     ContextMenuItem OpenLinkItem(ActionType, ContextMenuItemTagOpenLink, contextMenuItemTagOpenLink());
751     ContextMenuItem OpenLinkInNewWindowItem(ActionType, ContextMenuItemTagOpenLinkInNewWindow, 
752         contextMenuItemTagOpenLinkInNewWindow());
753     ContextMenuItem DownloadFileItem(ActionType, ContextMenuItemTagDownloadLinkToDisk, 
754         contextMenuItemTagDownloadLinkToDisk());
755     ContextMenuItem CopyLinkItem(ActionType, ContextMenuItemTagCopyLinkToClipboard, 
756         contextMenuItemTagCopyLinkToClipboard());
757     ContextMenuItem OpenImageInNewWindowItem(ActionType, ContextMenuItemTagOpenImageInNewWindow, 
758         contextMenuItemTagOpenImageInNewWindow());
759     ContextMenuItem DownloadImageItem(ActionType, ContextMenuItemTagDownloadImageToDisk, 
760         contextMenuItemTagDownloadImageToDisk());
761     ContextMenuItem CopyImageItem(ActionType, ContextMenuItemTagCopyImageToClipboard, 
762         contextMenuItemTagCopyImageToClipboard());
763 #if PLATFORM(GTK)
764     ContextMenuItem CopyImageUrlItem(ActionType, ContextMenuItemTagCopyImageUrlToClipboard, 
765         contextMenuItemTagCopyImageUrlToClipboard());
766 #endif
767     ContextMenuItem OpenMediaInNewWindowItem(ActionType, ContextMenuItemTagOpenMediaInNewWindow, String());
768     ContextMenuItem DownloadMediaItem(ActionType, ContextMenuItemTagDownloadMediaToDisk, String());
769     ContextMenuItem CopyMediaLinkItem(ActionType, ContextMenuItemTagCopyMediaLinkToClipboard, String());
770     ContextMenuItem MediaPlayPause(ActionType, ContextMenuItemTagMediaPlayPause, 
771         contextMenuItemTagMediaPlay());
772     ContextMenuItem MediaMute(ActionType, ContextMenuItemTagMediaMute, 
773         contextMenuItemTagMediaMute());
774 #if SUPPORTS_TOGGLE_SHOW_HIDE_MEDIA_CONTROLS
775     ContextMenuItem ToggleMediaControls(ActionType, ContextMenuItemTagToggleMediaControls,
776         contextMenuItemTagHideMediaControls());
777 #else
778     ContextMenuItem ToggleMediaControls(CheckableActionType, ContextMenuItemTagToggleMediaControls, 
779         contextMenuItemTagToggleMediaControls());
780 #endif
781     ContextMenuItem ToggleMediaLoop(CheckableActionType, ContextMenuItemTagToggleMediaLoop, 
782         contextMenuItemTagToggleMediaLoop());
783     ContextMenuItem EnterVideoFullscreen(ActionType, ContextMenuItemTagEnterVideoFullscreen,
784         contextMenuItemTagEnterVideoFullscreen());
785     ContextMenuItem ToggleVideoFullscreen(ActionType, ContextMenuItemTagToggleVideoFullscreen,
786         contextMenuItemTagEnterVideoFullscreen());
787 #if PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE)
788     ContextMenuItem ToggleVideoEnhancedFullscreen(ActionType, ContextMenuItemTagToggleVideoEnhancedFullscreen, contextMenuItemTagEnterVideoEnhancedFullscreen());
789 #endif
790 #if PLATFORM(COCOA)
791     ContextMenuItem SearchSpotlightItem(ActionType, ContextMenuItemTagSearchInSpotlight, 
792         contextMenuItemTagSearchInSpotlight());
793 #endif
794 #if !PLATFORM(GTK)
795     ContextMenuItem SearchWebItem(ActionType, ContextMenuItemTagSearchWeb, contextMenuItemTagSearchWeb());
796 #endif
797     ContextMenuItem CopyItem(ActionType, ContextMenuItemTagCopy, contextMenuItemTagCopy());
798     ContextMenuItem BackItem(ActionType, ContextMenuItemTagGoBack, contextMenuItemTagGoBack());
799     ContextMenuItem ForwardItem(ActionType, ContextMenuItemTagGoForward,  contextMenuItemTagGoForward());
800     ContextMenuItem StopItem(ActionType, ContextMenuItemTagStop, contextMenuItemTagStop());
801     ContextMenuItem ReloadItem(ActionType, ContextMenuItemTagReload, contextMenuItemTagReload());
802     ContextMenuItem OpenFrameItem(ActionType, ContextMenuItemTagOpenFrameInNewWindow, 
803         contextMenuItemTagOpenFrameInNewWindow());
804     ContextMenuItem NoGuessesItem(ActionType, ContextMenuItemTagNoGuessesFound, 
805         contextMenuItemTagNoGuessesFound());
806     ContextMenuItem IgnoreSpellingItem(ActionType, ContextMenuItemTagIgnoreSpelling, 
807         contextMenuItemTagIgnoreSpelling());
808     ContextMenuItem LearnSpellingItem(ActionType, ContextMenuItemTagLearnSpelling, 
809         contextMenuItemTagLearnSpelling());
810     ContextMenuItem IgnoreGrammarItem(ActionType, ContextMenuItemTagIgnoreGrammar, 
811         contextMenuItemTagIgnoreGrammar());
812     ContextMenuItem CutItem(ActionType, ContextMenuItemTagCut, contextMenuItemTagCut());
813     ContextMenuItem PasteItem(ActionType, ContextMenuItemTagPaste, contextMenuItemTagPaste());
814 #if PLATFORM(GTK)
815     ContextMenuItem DeleteItem(ActionType, ContextMenuItemTagDelete, contextMenuItemTagDelete());
816     ContextMenuItem SelectAllItem(ActionType, ContextMenuItemTagSelectAll, contextMenuItemTagSelectAll());
817     ContextMenuItem InsertEmojiItem(ActionType, ContextMenuItemTagInsertEmoji, contextMenuItemTagInsertEmoji());
818 #endif
819
820 #if PLATFORM(GTK) || PLATFORM(WIN)
821     ContextMenuItem ShareMenuItem;
822 #else
823     ContextMenuItem ShareMenuItem(SubmenuType, ContextMenuItemTagShareMenu, emptyString());
824 #endif
825
826     Node* node = m_context.hitTestResult().innerNonSharedNode();
827     if (!node)
828         return;
829 #if PLATFORM(GTK)
830     if (!m_context.hitTestResult().isContentEditable() && is<HTMLFormControlElement>(*node))
831         return;
832 #endif
833     Frame* frame = node->document().frame();
834     if (!frame)
835         return;
836
837 #if ENABLE(SERVICE_CONTROLS)
838     // The default image control menu gets populated solely by the platform.
839     if (m_context.controlledImage())
840         return;
841 #endif
842
843     if (!m_context.hitTestResult().isContentEditable()) {
844         String selectedString = m_context.hitTestResult().selectedText();
845         m_context.setSelectedText(selectedString);
846
847         FrameLoader& loader = frame->loader();
848         URL linkURL = m_context.hitTestResult().absoluteLinkURL();
849         if (!linkURL.isEmpty()) {
850             if (loader.client().canHandleRequest(ResourceRequest(linkURL))) {
851                 appendItem(OpenLinkItem, m_contextMenu.get());
852                 appendItem(OpenLinkInNewWindowItem, m_contextMenu.get());
853                 appendItem(DownloadFileItem, m_contextMenu.get());
854             }
855             appendItem(CopyLinkItem, m_contextMenu.get());
856         }
857
858         URL imageURL = m_context.hitTestResult().absoluteImageURL();
859         if (!imageURL.isEmpty()) {
860             if (!linkURL.isEmpty())
861                 appendItem(*separatorItem(), m_contextMenu.get());
862
863             appendItem(OpenImageInNewWindowItem, m_contextMenu.get());
864             appendItem(DownloadImageItem, m_contextMenu.get());
865             if (imageURL.isLocalFile() || m_context.hitTestResult().image())
866                 appendItem(CopyImageItem, m_contextMenu.get());
867 #if PLATFORM(GTK)
868             appendItem(CopyImageUrlItem, m_contextMenu.get());
869 #endif
870         }
871
872         URL mediaURL = m_context.hitTestResult().absoluteMediaURL();
873         if (!mediaURL.isEmpty()) {
874             if (!linkURL.isEmpty() || !imageURL.isEmpty())
875                 appendItem(*separatorItem(), m_contextMenu.get());
876
877             appendItem(MediaPlayPause, m_contextMenu.get());
878             appendItem(MediaMute, m_contextMenu.get());
879             appendItem(ToggleMediaControls, m_contextMenu.get());
880             appendItem(ToggleMediaLoop, m_contextMenu.get());
881 #if SUPPORTS_TOGGLE_VIDEO_FULLSCREEN
882             appendItem(ToggleVideoFullscreen, m_contextMenu.get());
883 #else
884             appendItem(EnterVideoFullscreen, m_contextMenu.get());
885 #endif
886 #if PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE)
887             appendItem(ToggleVideoEnhancedFullscreen, m_contextMenu.get());
888 #endif
889             appendItem(*separatorItem(), m_contextMenu.get());
890             appendItem(CopyMediaLinkItem, m_contextMenu.get());
891             appendItem(OpenMediaInNewWindowItem, m_contextMenu.get());
892             if (m_context.hitTestResult().isDownloadableMedia() && loader.client().canHandleRequest(ResourceRequest(mediaURL)))
893                 appendItem(DownloadMediaItem, m_contextMenu.get());
894         }
895
896         if (imageURL.isEmpty() && linkURL.isEmpty() && mediaURL.isEmpty()) {
897             if (m_context.hitTestResult().isSelected()) {
898                 if (!selectedString.isEmpty()) {
899 #if PLATFORM(COCOA)
900                     ContextMenuItem LookUpInDictionaryItem(ActionType, ContextMenuItemTagLookUpInDictionary, contextMenuItemTagLookUpInDictionary(selectedString));
901
902                     appendItem(LookUpInDictionaryItem, m_contextMenu.get());
903 #endif
904
905 #if !PLATFORM(GTK)
906                     appendItem(SearchWebItem, m_contextMenu.get());
907                     appendItem(*separatorItem(), m_contextMenu.get());
908 #endif
909                 }
910
911                 appendItem(CopyItem, m_contextMenu.get());
912 #if PLATFORM(COCOA)
913                 appendItem(*separatorItem(), m_contextMenu.get());
914
915                 appendItem(ShareMenuItem, m_contextMenu.get());
916                 appendItem(*separatorItem(), m_contextMenu.get());
917
918                 ContextMenuItem SpeechMenuItem(SubmenuType, ContextMenuItemTagSpeechMenu, contextMenuItemTagSpeechMenu());
919                 createAndAppendSpeechSubMenu(SpeechMenuItem);
920                 appendItem(SpeechMenuItem, m_contextMenu.get());
921 #endif                
922             } else {
923                 if (!(frame->page() && (frame->page()->inspectorController().inspectionLevel() > 0 || frame->page()->inspectorController().hasRemoteFrontend()))) {
924
925                 // In GTK+ unavailable items are not hidden but insensitive.
926 #if PLATFORM(GTK)
927                 appendItem(BackItem, m_contextMenu.get());
928                 appendItem(ForwardItem, m_contextMenu.get());
929                 appendItem(StopItem, m_contextMenu.get());
930                 appendItem(ReloadItem, m_contextMenu.get());
931 #else
932                 if (frame->page() && frame->page()->backForward().canGoBackOrForward(-1))
933                     appendItem(BackItem, m_contextMenu.get());
934
935                 if (frame->page() && frame->page()->backForward().canGoBackOrForward(1))
936                     appendItem(ForwardItem, m_contextMenu.get());
937
938                 // use isLoadingInAPISense rather than isLoading because Stop/Reload are
939                 // intended to match WebKit's API, not WebCore's internal notion of loading status
940                 if (loader.documentLoader()->isLoadingInAPISense())
941                     appendItem(StopItem, m_contextMenu.get());
942                 else
943                     appendItem(ReloadItem, m_contextMenu.get());
944 #endif
945                 }
946
947                 if (frame->page() && !frame->isMainFrame())
948                     appendItem(OpenFrameItem, m_contextMenu.get());
949
950                 if (!ShareMenuItem.isNull()) {
951                     appendItem(*separatorItem(), m_contextMenu.get());
952                     appendItem(ShareMenuItem, m_contextMenu.get());
953                 }
954             }
955         } else if (!ShareMenuItem.isNull()) {
956             appendItem(*separatorItem(), m_contextMenu.get());
957             appendItem(ShareMenuItem, m_contextMenu.get());
958         }
959     } else { // Make an editing context menu
960         bool inPasswordField = frame->selection().selection().isInPasswordField();
961         if (!inPasswordField) {
962             bool haveContextMenuItemsForMisspellingOrGrammer = false;
963             bool spellCheckingEnabled = frame->editor().isSpellCheckingEnabledFor(node);
964             if (spellCheckingEnabled) {
965                 // Consider adding spelling-related or grammar-related context menu items (never both, since a single selected range
966                 // is never considered a misspelling and bad grammar at the same time)
967                 bool misspelling;
968                 bool badGrammar;
969                 Vector<String> guesses = frame->editor().guessesForMisspelledOrUngrammatical(misspelling, badGrammar);
970                 if (misspelling || badGrammar) {
971                     if (guesses.isEmpty()) {
972                         // If there's bad grammar but no suggestions (e.g., repeated word), just leave off the suggestions
973                         // list and trailing separator rather than adding a "No Guesses Found" item (matches AppKit)
974                         if (misspelling) {
975                             appendItem(NoGuessesItem, m_contextMenu.get());
976                             appendItem(*separatorItem(), m_contextMenu.get());
977                         }
978                     } else {
979                         for (const auto& guess : guesses) {
980                             if (!guess.isEmpty()) {
981                                 ContextMenuItem item(ActionType, ContextMenuItemTagSpellingGuess, guess);
982                                 appendItem(item, m_contextMenu.get());
983                             }
984                         }
985                         appendItem(*separatorItem(), m_contextMenu.get());
986                     }
987                     if (misspelling) {
988                         appendItem(IgnoreSpellingItem, m_contextMenu.get());
989                         appendItem(LearnSpellingItem, m_contextMenu.get());
990                     } else
991                         appendItem(IgnoreGrammarItem, m_contextMenu.get());
992                     appendItem(*separatorItem(), m_contextMenu.get());
993                     haveContextMenuItemsForMisspellingOrGrammer = true;
994 #if PLATFORM(COCOA)
995                 } else {
996                     // If the string was autocorrected, generate a contextual menu item allowing it to be changed back.
997                     String replacedString = m_context.hitTestResult().replacedString();
998                     if (!replacedString.isEmpty()) {
999                         ContextMenuItem item(ActionType, ContextMenuItemTagChangeBack, contextMenuItemTagChangeBack(replacedString));
1000                         appendItem(item, m_contextMenu.get());
1001                         appendItem(*separatorItem(), m_contextMenu.get());
1002                         haveContextMenuItemsForMisspellingOrGrammer = true;
1003                     }
1004 #endif
1005                 }
1006             }
1007
1008             if (!haveContextMenuItemsForMisspellingOrGrammer) {
1009                 // Spelling and grammar checking is mutually exclusive with dictation alternatives.
1010                 Vector<String> dictationAlternatives = m_context.hitTestResult().dictationAlternatives();
1011                 if (!dictationAlternatives.isEmpty()) {
1012                     for (auto& alternative : dictationAlternatives) {
1013                         ContextMenuItem item(ActionType, ContextMenuItemTagDictationAlternative, alternative);
1014                         appendItem(item, m_contextMenu.get());
1015                     }
1016                     appendItem(*separatorItem(), m_contextMenu.get());
1017                 }
1018             }
1019         }
1020
1021         FrameLoader& loader = frame->loader();
1022         URL linkURL = m_context.hitTestResult().absoluteLinkURL();
1023         if (!linkURL.isEmpty()) {
1024             if (loader.client().canHandleRequest(ResourceRequest(linkURL))) {
1025                 appendItem(OpenLinkItem, m_contextMenu.get());
1026                 appendItem(OpenLinkInNewWindowItem, m_contextMenu.get());
1027                 appendItem(DownloadFileItem, m_contextMenu.get());
1028             }
1029             appendItem(CopyLinkItem, m_contextMenu.get());
1030             appendItem(*separatorItem(), m_contextMenu.get());
1031         }
1032
1033         String selectedText = m_context.hitTestResult().selectedText();
1034         if (m_context.hitTestResult().isSelected() && !inPasswordField && !selectedText.isEmpty()) {
1035 #if PLATFORM(COCOA)
1036             ContextMenuItem LookUpInDictionaryItem(ActionType, ContextMenuItemTagLookUpInDictionary, contextMenuItemTagLookUpInDictionary(selectedText));
1037
1038             appendItem(LookUpInDictionaryItem, m_contextMenu.get());
1039 #endif
1040
1041 #if !PLATFORM(GTK)
1042             appendItem(SearchWebItem, m_contextMenu.get());
1043             appendItem(*separatorItem(), m_contextMenu.get());
1044 #endif
1045         }
1046
1047         appendItem(CutItem, m_contextMenu.get());
1048         appendItem(CopyItem, m_contextMenu.get());
1049         appendItem(PasteItem, m_contextMenu.get());
1050 #if PLATFORM(GTK)
1051         appendItem(DeleteItem, m_contextMenu.get());
1052         appendItem(*separatorItem(), m_contextMenu.get());
1053         appendItem(SelectAllItem, m_contextMenu.get());
1054         appendItem(InsertEmojiItem, m_contextMenu.get());
1055 #endif
1056
1057         if (!inPasswordField) {
1058 #if !PLATFORM(GTK)
1059             appendItem(*separatorItem(), m_contextMenu.get());
1060             ContextMenuItem SpellingAndGrammarMenuItem(SubmenuType, ContextMenuItemTagSpellingMenu, 
1061                 contextMenuItemTagSpellingMenu());
1062             createAndAppendSpellingAndGrammarSubMenu(SpellingAndGrammarMenuItem);
1063             appendItem(SpellingAndGrammarMenuItem, m_contextMenu.get());
1064 #endif
1065 #if PLATFORM(COCOA)
1066             ContextMenuItem substitutionsMenuItem(SubmenuType, ContextMenuItemTagSubstitutionsMenu, 
1067                 contextMenuItemTagSubstitutionsMenu());
1068             createAndAppendSubstitutionsSubMenu(substitutionsMenuItem);
1069             appendItem(substitutionsMenuItem, m_contextMenu.get());
1070             ContextMenuItem transformationsMenuItem(SubmenuType, ContextMenuItemTagTransformationsMenu, 
1071                 contextMenuItemTagTransformationsMenu());
1072             createAndAppendTransformationsSubMenu(transformationsMenuItem);
1073             appendItem(transformationsMenuItem, m_contextMenu.get());
1074 #endif
1075 #if PLATFORM(GTK)
1076             bool shouldShowFontMenu = frame->editor().canEditRichly();
1077 #else
1078             bool shouldShowFontMenu = true;
1079 #endif
1080             if (shouldShowFontMenu) {
1081                 ContextMenuItem FontMenuItem(SubmenuType, ContextMenuItemTagFontMenu, 
1082                     contextMenuItemTagFontMenu());
1083                 createAndAppendFontSubMenu(FontMenuItem);
1084                 appendItem(FontMenuItem, m_contextMenu.get());
1085             }
1086 #if PLATFORM(COCOA)
1087             ContextMenuItem SpeechMenuItem(SubmenuType, ContextMenuItemTagSpeechMenu, contextMenuItemTagSpeechMenu());
1088             createAndAppendSpeechSubMenu(SpeechMenuItem);
1089             appendItem(SpeechMenuItem, m_contextMenu.get());
1090 #endif
1091 #if PLATFORM(GTK)
1092             EditorClient* client = frame->editor().client();
1093             if (client && client->shouldShowUnicodeMenu()) {
1094                 ContextMenuItem UnicodeMenuItem(SubmenuType, ContextMenuItemTagUnicode, contextMenuItemTagUnicode());
1095                 createAndAppendUnicodeSubMenu(UnicodeMenuItem);
1096                 appendItem(*separatorItem(), m_contextMenu.get());
1097                 appendItem(UnicodeMenuItem, m_contextMenu.get());
1098             }
1099 #else
1100             ContextMenuItem WritingDirectionMenuItem(SubmenuType, ContextMenuItemTagWritingDirectionMenu, 
1101                 contextMenuItemTagWritingDirectionMenu());
1102             createAndAppendWritingDirectionSubMenu(WritingDirectionMenuItem);
1103             appendItem(WritingDirectionMenuItem, m_contextMenu.get());
1104             if (Page* page = frame->page()) {
1105                 bool includeTextDirectionSubmenu = page->settings().textDirectionSubmenuInclusionBehavior() == TextDirectionSubmenuAlwaysIncluded
1106                     || (page->settings().textDirectionSubmenuInclusionBehavior() == TextDirectionSubmenuAutomaticallyIncluded && frame->editor().hasBidiSelection());
1107                 if (includeTextDirectionSubmenu) {
1108                     ContextMenuItem TextDirectionMenuItem(SubmenuType, ContextMenuItemTagTextDirectionMenu, contextMenuItemTagTextDirectionMenu());
1109                     createAndAppendTextDirectionSubMenu(TextDirectionMenuItem);
1110                     appendItem(TextDirectionMenuItem, m_contextMenu.get());
1111                 }
1112             }
1113 #endif
1114         }
1115
1116         if (!ShareMenuItem.isNull()) {
1117             appendItem(*separatorItem(), m_contextMenu.get());
1118             appendItem(ShareMenuItem, m_contextMenu.get());
1119         }
1120     }
1121 }
1122
1123 void ContextMenuController::addInspectElementItem()
1124 {
1125     Node* node = m_context.hitTestResult().innerNonSharedNode();
1126     if (!node)
1127         return;
1128
1129     Frame* frame = node->document().frame();
1130     if (!frame)
1131         return;
1132
1133     Page* page = frame->page();
1134     if (!page)
1135         return;
1136
1137     ContextMenuItem InspectElementItem(ActionType, ContextMenuItemTagInspectElement, contextMenuItemTagInspectElement());
1138     if (m_contextMenu && !m_contextMenu->items().isEmpty())
1139         appendItem(*separatorItem(), m_contextMenu.get());
1140     appendItem(InspectElementItem, m_contextMenu.get());
1141 }
1142
1143 void ContextMenuController::checkOrEnableIfNeeded(ContextMenuItem& item) const
1144 {
1145     if (item.type() == SeparatorType)
1146         return;
1147     
1148     Frame* frame = m_context.hitTestResult().innerNonSharedNode()->document().frame();
1149     if (!frame)
1150         return;
1151
1152     // Custom items already have proper checked and enabled values.
1153     if (ContextMenuItemBaseCustomTag <= item.action() && item.action() <= ContextMenuItemLastCustomTag)
1154         return;
1155
1156     bool shouldEnable = true;
1157     bool shouldCheck = false; 
1158
1159     switch (item.action()) {
1160         case ContextMenuItemTagCheckSpelling:
1161             shouldEnable = frame->editor().canEdit();
1162             break;
1163         case ContextMenuItemTagDefaultDirection:
1164             shouldCheck = false;
1165             shouldEnable = false;
1166             break;
1167         case ContextMenuItemTagLeftToRight:
1168         case ContextMenuItemTagRightToLeft: {
1169             String direction = item.action() == ContextMenuItemTagLeftToRight ? "ltr" : "rtl";
1170             shouldCheck = frame->editor().selectionHasStyle(CSSPropertyDirection, direction) != FalseTriState;
1171             shouldEnable = true;
1172             break;
1173         }
1174         case ContextMenuItemTagTextDirectionDefault: {
1175             Editor::Command command = frame->editor().command("MakeTextWritingDirectionNatural");
1176             shouldCheck = command.state() == TrueTriState;
1177             shouldEnable = command.isEnabled();
1178             break;
1179         }
1180         case ContextMenuItemTagTextDirectionLeftToRight: {
1181             Editor::Command command = frame->editor().command("MakeTextWritingDirectionLeftToRight");
1182             shouldCheck = command.state() == TrueTriState;
1183             shouldEnable = command.isEnabled();
1184             break;
1185         }
1186         case ContextMenuItemTagTextDirectionRightToLeft: {
1187             Editor::Command command = frame->editor().command("MakeTextWritingDirectionRightToLeft");
1188             shouldCheck = command.state() == TrueTriState;
1189             shouldEnable = command.isEnabled();
1190             break;
1191         }
1192         case ContextMenuItemTagCopy:
1193             shouldEnable = frame->editor().canDHTMLCopy() || frame->editor().canCopy();
1194             break;
1195         case ContextMenuItemTagCut:
1196             shouldEnable = frame->editor().canDHTMLCut() || frame->editor().canCut();
1197             break;
1198         case ContextMenuItemTagIgnoreSpelling:
1199         case ContextMenuItemTagLearnSpelling:
1200             shouldEnable = frame->selection().isRange();
1201             break;
1202         case ContextMenuItemTagPaste:
1203             shouldEnable = frame->editor().canDHTMLPaste() || frame->editor().canPaste();
1204             break;
1205 #if PLATFORM(GTK)
1206         case ContextMenuItemTagDelete:
1207             shouldEnable = frame->editor().canDelete();
1208             break;
1209         case ContextMenuItemTagInsertEmoji:
1210             shouldEnable = frame->editor().canEdit();
1211             break;
1212         case ContextMenuItemTagSelectAll:
1213         case ContextMenuItemTagInputMethods:
1214         case ContextMenuItemTagUnicode:
1215         case ContextMenuItemTagUnicodeInsertLRMMark:
1216         case ContextMenuItemTagUnicodeInsertRLMMark:
1217         case ContextMenuItemTagUnicodeInsertLREMark:
1218         case ContextMenuItemTagUnicodeInsertRLEMark:
1219         case ContextMenuItemTagUnicodeInsertLROMark:
1220         case ContextMenuItemTagUnicodeInsertRLOMark:
1221         case ContextMenuItemTagUnicodeInsertPDFMark:
1222         case ContextMenuItemTagUnicodeInsertZWSMark:
1223         case ContextMenuItemTagUnicodeInsertZWJMark:
1224         case ContextMenuItemTagUnicodeInsertZWNJMark:
1225             shouldEnable = true;
1226             break;
1227 #endif
1228         case ContextMenuItemTagUnderline: {
1229             shouldCheck = frame->editor().selectionHasStyle(CSSPropertyWebkitTextDecorationsInEffect, "underline") != FalseTriState;
1230             shouldEnable = frame->editor().canEditRichly();
1231             break;
1232         }
1233         case ContextMenuItemTagLookUpInDictionary:
1234             shouldEnable = frame->selection().isRange();
1235             break;
1236         case ContextMenuItemTagCheckGrammarWithSpelling:
1237             if (frame->editor().isGrammarCheckingEnabled())
1238                 shouldCheck = true;
1239             shouldEnable = true;
1240             break;
1241         case ContextMenuItemTagItalic: {
1242             shouldCheck = frame->editor().selectionHasStyle(CSSPropertyFontStyle, "italic") != FalseTriState;
1243             shouldEnable = frame->editor().canEditRichly();
1244             break;
1245         }
1246         case ContextMenuItemTagBold: {
1247             shouldCheck = frame->editor().selectionHasStyle(CSSPropertyFontWeight, "bold") != FalseTriState;
1248             shouldEnable = frame->editor().canEditRichly();
1249             break;
1250         }
1251         case ContextMenuItemTagOutline:
1252             shouldEnable = false;
1253             break;
1254         case ContextMenuItemTagShowSpellingPanel:
1255             if (frame->editor().spellingPanelIsShowing())
1256                 item.setTitle(contextMenuItemTagShowSpellingPanel(false));
1257             else
1258                 item.setTitle(contextMenuItemTagShowSpellingPanel(true));
1259             shouldEnable = frame->editor().canEdit();
1260             break;
1261         case ContextMenuItemTagNoGuessesFound:
1262             shouldEnable = false;
1263             break;
1264         case ContextMenuItemTagCheckSpellingWhileTyping:
1265             shouldCheck = frame->editor().isContinuousSpellCheckingEnabled();
1266             break;
1267 #if PLATFORM(COCOA)
1268         case ContextMenuItemTagSubstitutionsMenu:
1269         case ContextMenuItemTagTransformationsMenu:
1270             break;
1271         case ContextMenuItemTagShowSubstitutions:
1272             if (frame->editor().substitutionsPanelIsShowing())
1273                 item.setTitle(contextMenuItemTagShowSubstitutions(false));
1274             else
1275                 item.setTitle(contextMenuItemTagShowSubstitutions(true));
1276             shouldEnable = frame->editor().canEdit();
1277             break;
1278         case ContextMenuItemTagMakeUpperCase:
1279         case ContextMenuItemTagMakeLowerCase:
1280         case ContextMenuItemTagCapitalize:
1281         case ContextMenuItemTagChangeBack:
1282             shouldEnable = frame->editor().canEdit();
1283             break;
1284         case ContextMenuItemTagCorrectSpellingAutomatically:
1285             shouldCheck = frame->editor().isAutomaticSpellingCorrectionEnabled();
1286             break;
1287         case ContextMenuItemTagSmartCopyPaste:
1288             shouldCheck = frame->editor().smartInsertDeleteEnabled();
1289             break;
1290         case ContextMenuItemTagSmartQuotes:
1291             shouldCheck = frame->editor().isAutomaticQuoteSubstitutionEnabled();
1292             break;
1293         case ContextMenuItemTagSmartDashes:
1294             shouldCheck = frame->editor().isAutomaticDashSubstitutionEnabled();
1295             break;
1296         case ContextMenuItemTagSmartLinks:
1297             shouldCheck = frame->editor().isAutomaticLinkDetectionEnabled();
1298             break;
1299         case ContextMenuItemTagTextReplacement:
1300             shouldCheck = frame->editor().isAutomaticTextReplacementEnabled();
1301             break;
1302         case ContextMenuItemTagStopSpeaking:
1303             shouldEnable = m_client.isSpeaking();
1304             break;
1305 #else // PLATFORM(COCOA) ends here
1306         case ContextMenuItemTagStopSpeaking:
1307             break;
1308 #endif
1309 #if PLATFORM(GTK)
1310         case ContextMenuItemTagGoBack:
1311             shouldEnable = frame->page() && frame->page()->backForward().canGoBackOrForward(-1);
1312             break;
1313         case ContextMenuItemTagGoForward:
1314             shouldEnable = frame->page() && frame->page()->backForward().canGoBackOrForward(1);
1315             break;
1316         case ContextMenuItemTagStop:
1317             shouldEnable = frame->loader().documentLoader()->isLoadingInAPISense();
1318             break;
1319         case ContextMenuItemTagReload:
1320             shouldEnable = !frame->loader().documentLoader()->isLoadingInAPISense();
1321             break;
1322         case ContextMenuItemTagFontMenu:
1323             shouldEnable = frame->editor().canEditRichly();
1324             break;
1325 #else
1326         case ContextMenuItemTagGoBack:
1327         case ContextMenuItemTagGoForward:
1328         case ContextMenuItemTagStop:
1329         case ContextMenuItemTagReload:
1330         case ContextMenuItemTagFontMenu:
1331 #endif
1332         case ContextMenuItemTagNoAction:
1333         case ContextMenuItemTagOpenLinkInNewWindow:
1334         case ContextMenuItemTagDownloadLinkToDisk:
1335         case ContextMenuItemTagCopyLinkToClipboard:
1336         case ContextMenuItemTagOpenImageInNewWindow:
1337         case ContextMenuItemTagCopyImageToClipboard:
1338 #if PLATFORM(GTK)
1339         case ContextMenuItemTagCopyImageUrlToClipboard:
1340 #endif
1341             break;
1342         case ContextMenuItemTagDownloadImageToDisk:
1343 #if PLATFORM(MAC)
1344             if (WTF::protocolIs(m_context.hitTestResult().absoluteImageURL(), "file"))
1345                 shouldEnable = false;
1346 #endif
1347             break;
1348         case ContextMenuItemTagOpenMediaInNewWindow:
1349             if (m_context.hitTestResult().mediaIsVideo())
1350                 item.setTitle(contextMenuItemTagOpenVideoInNewWindow());
1351             else
1352                 item.setTitle(contextMenuItemTagOpenAudioInNewWindow());
1353             break;
1354         case ContextMenuItemTagDownloadMediaToDisk:
1355             if (m_context.hitTestResult().mediaIsVideo())
1356                 item.setTitle(contextMenuItemTagDownloadVideoToDisk());
1357             else
1358                 item.setTitle(contextMenuItemTagDownloadAudioToDisk());
1359             if (WTF::protocolIs(m_context.hitTestResult().absoluteImageURL(), "file"))
1360                 shouldEnable = false;
1361             break;
1362         case ContextMenuItemTagCopyMediaLinkToClipboard:
1363             if (m_context.hitTestResult().mediaIsVideo())
1364                 item.setTitle(contextMenuItemTagCopyVideoLinkToClipboard());
1365             else
1366                 item.setTitle(contextMenuItemTagCopyAudioLinkToClipboard());
1367             break;
1368         case ContextMenuItemTagToggleMediaControls:
1369 #if SUPPORTS_TOGGLE_SHOW_HIDE_MEDIA_CONTROLS
1370             item.setTitle(m_context.hitTestResult().mediaControlsEnabled() ? contextMenuItemTagHideMediaControls() : contextMenuItemTagShowMediaControls());
1371 #else
1372             shouldCheck = m_context.hitTestResult().mediaControlsEnabled();
1373 #endif
1374             break;
1375         case ContextMenuItemTagToggleMediaLoop:
1376             shouldCheck = m_context.hitTestResult().mediaLoopEnabled();
1377             break;
1378         case ContextMenuItemTagToggleVideoFullscreen:
1379 #if SUPPORTS_TOGGLE_VIDEO_FULLSCREEN
1380             item.setTitle(m_context.hitTestResult().mediaIsInFullscreen() ? contextMenuItemTagExitVideoFullscreen() : contextMenuItemTagEnterVideoFullscreen());
1381             break;
1382 #endif
1383         case ContextMenuItemTagEnterVideoFullscreen:
1384             shouldEnable = m_context.hitTestResult().mediaSupportsFullscreen();
1385             break;
1386         case ContextMenuItemTagToggleVideoEnhancedFullscreen:
1387 #if PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE)
1388             item.setTitle(m_context.hitTestResult().mediaIsInEnhancedFullscreen() ? contextMenuItemTagExitVideoEnhancedFullscreen() : contextMenuItemTagEnterVideoEnhancedFullscreen());
1389 #endif
1390             shouldEnable = m_context.hitTestResult().mediaSupportsEnhancedFullscreen();
1391             break;
1392         case ContextMenuItemTagOpenFrameInNewWindow:
1393         case ContextMenuItemTagSpellingGuess:
1394         case ContextMenuItemTagOther:
1395         case ContextMenuItemTagSearchInSpotlight:
1396         case ContextMenuItemTagSearchWeb:
1397         case ContextMenuItemTagOpenWithDefaultApplication:
1398         case ContextMenuItemPDFActualSize:
1399         case ContextMenuItemPDFZoomIn:
1400         case ContextMenuItemPDFZoomOut:
1401         case ContextMenuItemPDFAutoSize:
1402         case ContextMenuItemPDFSinglePage:
1403         case ContextMenuItemPDFFacingPages:
1404         case ContextMenuItemPDFContinuous:
1405         case ContextMenuItemPDFNextPage:
1406         case ContextMenuItemPDFPreviousPage:
1407         case ContextMenuItemTagOpenLink:
1408         case ContextMenuItemTagIgnoreGrammar:
1409         case ContextMenuItemTagSpellingMenu:
1410         case ContextMenuItemTagShowFonts:
1411         case ContextMenuItemTagStyles:
1412         case ContextMenuItemTagShowColors:
1413         case ContextMenuItemTagSpeechMenu:
1414         case ContextMenuItemTagStartSpeaking:
1415         case ContextMenuItemTagWritingDirectionMenu:
1416         case ContextMenuItemTagTextDirectionMenu:
1417         case ContextMenuItemTagPDFSinglePageScrolling:
1418         case ContextMenuItemTagPDFFacingPagesScrolling:
1419         case ContextMenuItemTagInspectElement:
1420         case ContextMenuItemBaseCustomTag:
1421         case ContextMenuItemLastCustomTag:
1422         case ContextMenuItemBaseApplicationTag:
1423         case ContextMenuItemTagDictationAlternative:
1424         case ContextMenuItemTagShareMenu:
1425             break;
1426         case ContextMenuItemTagMediaPlayPause:
1427             if (m_context.hitTestResult().mediaPlaying())
1428                 item.setTitle(contextMenuItemTagMediaPause());
1429             else
1430                 item.setTitle(contextMenuItemTagMediaPlay());
1431             break;
1432         case ContextMenuItemTagMediaMute:
1433             shouldEnable = m_context.hitTestResult().mediaHasAudio();
1434             shouldCheck = shouldEnable &&  m_context.hitTestResult().mediaMuted();
1435             break;
1436     }
1437
1438     item.setChecked(shouldCheck);
1439     item.setEnabled(shouldEnable);
1440 }
1441
1442 #if USE(ACCESSIBILITY_CONTEXT_MENUS)
1443
1444 void ContextMenuController::showContextMenuAt(Frame& frame, const IntPoint& clickPoint)
1445 {
1446     clearContextMenu();
1447     
1448     // Simulate a click in the middle of the accessibility object.
1449     PlatformMouseEvent mouseEvent(clickPoint, clickPoint, RightButton, PlatformEvent::MousePressed, 1, false, false, false, false, WallTime::now(), ForceAtClick, NoTap);
1450     frame.eventHandler().handleMousePressEvent(mouseEvent);
1451     bool handled = frame.eventHandler().sendContextMenuEvent(mouseEvent);
1452     if (handled)
1453         m_client.showContextMenu();
1454 }
1455
1456 #endif
1457
1458 #if ENABLE(SERVICE_CONTROLS)
1459
1460 void ContextMenuController::showImageControlsMenu(Event& event)
1461 {
1462     clearContextMenu();
1463     handleContextMenuEvent(event);
1464     m_client.showContextMenu();
1465 }
1466
1467 #endif
1468
1469 } // namespace WebCore
1470
1471 #endif // ENABLE(CONTEXT_MENUS)