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