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