Chromium Code Reviews| Index: Source/core/page/ContextMenuController.cpp |
| diff --git a/Source/core/page/ContextMenuController.cpp b/Source/core/page/ContextMenuController.cpp |
| index 70834f7af31086cb733cf031ed43c7c7478fc55c..67e23bec72e483973bae09eec511815055f821f7 100644 |
| --- a/Source/core/page/ContextMenuController.cpp |
| +++ b/Source/core/page/ContextMenuController.cpp |
| @@ -28,50 +28,19 @@ |
| #include "core/page/ContextMenuController.h" |
| #include "core/dom/Document.h" |
| -#include "core/dom/DocumentFragment.h" |
| #include "core/dom/Event.h" |
| #include "core/dom/EventNames.h" |
| -#include "core/dom/ExceptionCodePlaceholder.h" |
| #include "core/dom/MouseEvent.h" |
| #include "core/dom/Node.h" |
| -#include "core/dom/UserTypingGestureIndicator.h" |
| -#include "core/editing/Editor.h" |
| #include "core/editing/FrameSelection.h" |
| -#include "core/editing/ReplaceSelectionCommand.h" |
| -#include "core/editing/TextIterator.h" |
| -#include "core/editing/TypingCommand.h" |
| -#include "core/editing/markup.h" |
| -#include "core/history/BackForwardController.h" |
| -#include "core/html/HTMLFormElement.h" |
| -#include "core/inspector/InspectorController.h" |
| -#include "core/loader/DocumentLoader.h" |
| -#include "core/loader/FormState.h" |
| -#include "core/loader/FrameLoadRequest.h" |
| -#include "core/loader/FrameLoader.h" |
| -#include "core/loader/FrameLoaderClient.h" |
| -#include "core/loader/NavigationAction.h" |
| -#include "core/page/Chrome.h" |
| #include "core/page/ContextMenuClient.h" |
| #include "core/page/ContextMenuProvider.h" |
| -#include "core/page/EditorClient.h" |
| #include "core/page/EventHandler.h" |
| #include "core/page/Frame.h" |
| #include "core/page/Page.h" |
| -#include "core/page/Settings.h" |
| -#include "core/page/WindowFeatures.h" |
| #include "core/platform/ContextMenu.h" |
| #include "core/platform/ContextMenuItem.h" |
| -#include "core/platform/LocalizedStrings.h" |
| -#include "core/platform/PlatformEvent.h" |
| -#include "core/platform/network/ResourceRequest.h" |
| -#include "core/rendering/HitTestRequest.h" |
| #include "core/rendering/HitTestResult.h" |
| -#include "core/rendering/RenderObject.h" |
| -#include <wtf/unicode/CharacterNames.h> |
| -#include <wtf/unicode/Unicode.h> |
| - |
| -using namespace WTF; |
| -using namespace Unicode; |
| namespace WebCore { |
| @@ -106,16 +75,9 @@ void ContextMenuController::handleContextMenuEvent(Event* event) |
| if (!m_contextMenu) |
| return; |
| - populate(); |
| - |
| showContextMenu(event); |
| } |
| -static PassOwnPtr<ContextMenuItem> separatorItem() |
| -{ |
| - return adoptPtr(new ContextMenuItem(SeparatorType, ContextMenuItemTagNoAction, String())); |
| -} |
| - |
| void ContextMenuController::showContextMenu(Event* event, PassRefPtr<ContextMenuProvider> menuProvider) |
| { |
| m_menuProvider = menuProvider; |
| @@ -127,10 +89,6 @@ void ContextMenuController::showContextMenu(Event* event, PassRefPtr<ContextMenu |
| } |
| m_menuProvider->populateContextMenu(m_contextMenu.get()); |
| - if (m_hitTestResult.isSelected()) { |
| - appendItem(*separatorItem(), m_contextMenu.get()); |
| - populate(); |
| - } |
| showContextMenu(event); |
| } |
| @@ -157,714 +115,19 @@ PassOwnPtr<ContextMenu> ContextMenuController::createContextMenu(Event* event) |
| void ContextMenuController::showContextMenu(Event* event) |
| { |
| - addInspectElementItem(); |
| - |
| - m_contextMenu = m_client->customizeMenu(m_contextMenu.release()); |
| + m_client->showContextMenu(m_contextMenu.get()); |
| event->setDefaultHandled(); |
| } |
| -static void openNewWindow(const KURL& urlToLoad, Frame* frame) |
| -{ |
| - if (Page* oldPage = frame->page()) { |
| - FrameLoadRequest request(frame->document()->securityOrigin(), ResourceRequest(urlToLoad, frame->loader()->outgoingReferrer())); |
| - Page* newPage = oldPage; |
| - if (!frame->settings() || frame->settings()->supportsMultipleWindows()) { |
| - newPage = oldPage->chrome()->createWindow(frame, request, WindowFeatures(), NavigationAction(request.resourceRequest())); |
| - if (!newPage) |
| - return; |
| - newPage->chrome()->show(); |
| - } |
| - newPage->mainFrame()->loader()->loadFrameRequest(request, false, 0, 0, MaybeSendReferrer); |
| - } |
| -} |
| - |
| void ContextMenuController::contextMenuItemSelected(const ContextMenuItem* item) |
| { |
| ASSERT(item->type() == ActionType || item->type() == CheckableActionType); |
| - if (item->action() >= ContextMenuItemBaseApplicationTag) |
| - return; |
| - |
| - if (item->action() >= ContextMenuItemBaseCustomTag) { |
| - ASSERT(m_menuProvider); |
| - m_menuProvider->contextMenuItemSelected(item); |
| - return; |
| - } |
| - |
| - Frame* frame = m_hitTestResult.innerNonSharedNode()->document()->frame(); |
| - if (!frame) |
| + if (item->action() < ContextMenuItemBaseCustomTag || item->action() > ContextMenuItemLastCustomTag) |
| return; |
| - switch (item->action()) { |
| - case ContextMenuItemTagOpenLinkInNewWindow: |
| - openNewWindow(m_hitTestResult.absoluteLinkURL(), frame); |
| - break; |
| - case ContextMenuItemTagDownloadLinkToDisk: |
| - break; |
| - case ContextMenuItemTagCopyLinkToClipboard: |
| - frame->editor()->copyURL(m_hitTestResult.absoluteLinkURL(), m_hitTestResult.textContent()); |
| - break; |
| - case ContextMenuItemTagOpenImageInNewWindow: |
| - openNewWindow(m_hitTestResult.absoluteImageURL(), frame); |
| - break; |
| - case ContextMenuItemTagDownloadImageToDisk: |
| - break; |
| - case ContextMenuItemTagCopyImageToClipboard: |
| - // FIXME: The Pasteboard class is not written yet |
| - // For now, call into the client. This is temporary! |
| - frame->editor()->copyImage(m_hitTestResult); |
| - break; |
| - case ContextMenuItemTagOpenMediaInNewWindow: |
| - openNewWindow(m_hitTestResult.absoluteMediaURL(), frame); |
| - break; |
| - case ContextMenuItemTagCopyMediaLinkToClipboard: |
| - frame->editor()->copyURL(m_hitTestResult.absoluteMediaURL(), m_hitTestResult.textContent()); |
| - break; |
| - case ContextMenuItemTagToggleMediaControls: |
| - m_hitTestResult.toggleMediaControlsDisplay(); |
| - break; |
| - case ContextMenuItemTagToggleMediaLoop: |
| - m_hitTestResult.toggleMediaLoopPlayback(); |
| - break; |
| - case ContextMenuItemTagEnterVideoFullscreen: |
| - m_hitTestResult.enterFullscreenForVideo(); |
| - break; |
| - case ContextMenuItemTagMediaPlayPause: |
| - m_hitTestResult.toggleMediaPlayState(); |
| - break; |
| - case ContextMenuItemTagMediaMute: |
| - m_hitTestResult.toggleMediaMuteState(); |
| - break; |
| - case ContextMenuItemTagOpenFrameInNewWindow: { |
| - DocumentLoader* loader = frame->loader()->documentLoader(); |
| - if (!loader->unreachableURL().isEmpty()) |
| - openNewWindow(loader->unreachableURL(), frame); |
| - else |
| - openNewWindow(loader->url(), frame); |
| - break; |
| - } |
| - case ContextMenuItemTagCopy: |
| - frame->editor()->copy(); |
| - break; |
| - case ContextMenuItemTagGoBack: |
| - if (Page* page = frame->page()) |
| - page->backForward()->goBackOrForward(-1); |
| - break; |
| - case ContextMenuItemTagGoForward: |
| - if (Page* page = frame->page()) |
| - page->backForward()->goBackOrForward(1); |
| - break; |
| - case ContextMenuItemTagStop: |
| - frame->loader()->stop(); |
| - break; |
| - case ContextMenuItemTagReload: |
| - frame->loader()->reload(); |
| - break; |
| - case ContextMenuItemTagCut: |
| - frame->editor()->command("Cut").execute(); |
| - break; |
| - case ContextMenuItemTagPaste: |
| - frame->editor()->command("Paste").execute(); |
| - break; |
| - case ContextMenuItemTagSpellingGuess: { |
| - FrameSelection* frameSelection = frame->selection(); |
| - if (frame->editor()->shouldInsertText(item->title(), frameSelection->toNormalizedRange().get(), EditorInsertActionPasted)) { |
| - Document* document = frame->document(); |
| - ReplaceSelectionCommand::CommandOptions replaceOptions = ReplaceSelectionCommand::MatchStyle | ReplaceSelectionCommand::PreventNesting | ReplaceSelectionCommand::SelectReplacement; |
| - ASSERT(frame->editor()->selectedText().length()); |
| - RefPtr<ReplaceSelectionCommand> command = ReplaceSelectionCommand::create(document, createFragmentFromMarkup(document, item->title(), ""), replaceOptions); |
| - applyCommand(command); |
| - frameSelection->revealSelection(ScrollAlignment::alignToEdgeIfNeeded); |
| - } |
| - break; |
| - } |
| - case ContextMenuItemTagIgnoreSpelling: |
| - frame->editor()->ignoreSpelling(); |
| - break; |
| - case ContextMenuItemTagLearnSpelling: |
| - frame->editor()->learnSpelling(); |
| - break; |
| - case ContextMenuItemTagSearchWeb: |
| - break; |
| - case ContextMenuItemTagLookUpInDictionary: |
| - break; |
| - case ContextMenuItemTagOpenLink: |
| - if (Frame* targetFrame = m_hitTestResult.targetFrame()) |
| - targetFrame->loader()->loadFrameRequest(FrameLoadRequest(frame->document()->securityOrigin(), ResourceRequest(m_hitTestResult.absoluteLinkURL(), frame->loader()->outgoingReferrer())), false, 0, 0, MaybeSendReferrer); |
| - else |
| - openNewWindow(m_hitTestResult.absoluteLinkURL(), frame); |
| - break; |
| - case ContextMenuItemTagOpenLinkInThisWindow: |
| - frame->loader()->loadFrameRequest(FrameLoadRequest(frame->document()->securityOrigin(), ResourceRequest(m_hitTestResult.absoluteLinkURL(), frame->loader()->outgoingReferrer())), false, 0, 0, MaybeSendReferrer); |
| - break; |
| - case ContextMenuItemTagBold: |
| - frame->editor()->command("ToggleBold").execute(); |
| - break; |
| - case ContextMenuItemTagItalic: |
| - frame->editor()->command("ToggleItalic").execute(); |
| - break; |
| - case ContextMenuItemTagUnderline: |
| - frame->editor()->toggleUnderline(); |
| - break; |
| - case ContextMenuItemTagOutline: |
| - // We actually never enable this because CSS does not have a way to specify an outline font, |
| - // which may make this difficult to implement. Maybe a special case of text-shadow? |
| - break; |
| - case ContextMenuItemTagStartSpeaking: |
| - break; |
| - case ContextMenuItemTagStopSpeaking: |
| - break; |
| - case ContextMenuItemTagDefaultDirection: |
| - frame->editor()->setBaseWritingDirection(NaturalWritingDirection); |
| - break; |
| - case ContextMenuItemTagLeftToRight: |
| - frame->editor()->setBaseWritingDirection(LeftToRightWritingDirection); |
| - break; |
| - case ContextMenuItemTagRightToLeft: |
| - frame->editor()->setBaseWritingDirection(RightToLeftWritingDirection); |
| - break; |
| - case ContextMenuItemTagTextDirectionDefault: |
| - frame->editor()->command("MakeTextWritingDirectionNatural").execute(); |
| - break; |
| - case ContextMenuItemTagTextDirectionLeftToRight: |
| - frame->editor()->command("MakeTextWritingDirectionLeftToRight").execute(); |
| - break; |
| - case ContextMenuItemTagTextDirectionRightToLeft: |
| - frame->editor()->command("MakeTextWritingDirectionRightToLeft").execute(); |
| - break; |
| - case ContextMenuItemTagShowSpellingPanel: |
| - frame->editor()->showSpellingGuessPanel(); |
| - break; |
| - case ContextMenuItemTagCheckSpelling: |
| - frame->editor()->advanceToNextMisspelling(); |
| - break; |
| - case ContextMenuItemTagCheckSpellingWhileTyping: |
| - frame->editor()->toggleContinuousSpellChecking(); |
| - break; |
| - case ContextMenuItemTagCheckGrammarWithSpelling: |
| - break; |
| - case ContextMenuItemTagInspectElement: |
| - if (Page* page = frame->page()) |
| - page->inspectorController()->inspect(m_hitTestResult.innerNonSharedNode()); |
| - break; |
| - default: |
| - break; |
| - } |
| -} |
| - |
| -void ContextMenuController::appendItem(ContextMenuItem& menuItem, ContextMenu* parentMenu) |
| -{ |
| - checkOrEnableIfNeeded(menuItem); |
| - if (parentMenu) |
| - parentMenu->appendItem(menuItem); |
| -} |
| - |
| -void ContextMenuController::createAndAppendFontSubMenu(ContextMenuItem& fontMenuItem) |
| -{ |
| - ContextMenu fontMenu; |
| - |
| - ContextMenuItem bold(CheckableActionType, ContextMenuItemTagBold, contextMenuItemTagBold()); |
| - ContextMenuItem italic(CheckableActionType, ContextMenuItemTagItalic, contextMenuItemTagItalic()); |
| - ContextMenuItem underline(CheckableActionType, ContextMenuItemTagUnderline, contextMenuItemTagUnderline()); |
| - ContextMenuItem outline(ActionType, ContextMenuItemTagOutline, contextMenuItemTagOutline()); |
| - appendItem(bold, &fontMenu); |
| - appendItem(italic, &fontMenu); |
| - appendItem(underline, &fontMenu); |
| - appendItem(outline, &fontMenu); |
| - |
| - fontMenuItem.setSubMenu(&fontMenu); |
| -} |
| - |
| - |
| -void ContextMenuController::createAndAppendSpellingAndGrammarSubMenu(ContextMenuItem& spellingAndGrammarMenuItem) |
| -{ |
| - ContextMenu spellingAndGrammarMenu; |
| - |
| - ContextMenuItem showSpellingPanel(ActionType, ContextMenuItemTagShowSpellingPanel, |
| - contextMenuItemTagShowSpellingPanel(true)); |
| - ContextMenuItem checkSpelling(ActionType, ContextMenuItemTagCheckSpelling, |
| - contextMenuItemTagCheckSpelling()); |
| - ContextMenuItem checkAsYouType(CheckableActionType, ContextMenuItemTagCheckSpellingWhileTyping, |
| - contextMenuItemTagCheckSpellingWhileTyping()); |
| - ContextMenuItem grammarWithSpelling(CheckableActionType, ContextMenuItemTagCheckGrammarWithSpelling, |
| - contextMenuItemTagCheckGrammarWithSpelling()); |
| - |
| - appendItem(showSpellingPanel, &spellingAndGrammarMenu); |
| - appendItem(checkSpelling, &spellingAndGrammarMenu); |
| - appendItem(checkAsYouType, &spellingAndGrammarMenu); |
| - appendItem(grammarWithSpelling, &spellingAndGrammarMenu); |
| - |
| - spellingAndGrammarMenuItem.setSubMenu(&spellingAndGrammarMenu); |
| -} |
| - |
| -void ContextMenuController::createAndAppendWritingDirectionSubMenu(ContextMenuItem& writingDirectionMenuItem) |
| -{ |
| - ContextMenu writingDirectionMenu; |
| - |
| - ContextMenuItem defaultItem(ActionType, ContextMenuItemTagDefaultDirection, |
| - contextMenuItemTagDefaultDirection()); |
| - ContextMenuItem ltr(CheckableActionType, ContextMenuItemTagLeftToRight, contextMenuItemTagLeftToRight()); |
| - ContextMenuItem rtl(CheckableActionType, ContextMenuItemTagRightToLeft, contextMenuItemTagRightToLeft()); |
| - |
| - appendItem(defaultItem, &writingDirectionMenu); |
| - appendItem(ltr, &writingDirectionMenu); |
| - appendItem(rtl, &writingDirectionMenu); |
| - |
| - writingDirectionMenuItem.setSubMenu(&writingDirectionMenu); |
| -} |
| - |
| -void ContextMenuController::createAndAppendTextDirectionSubMenu(ContextMenuItem& textDirectionMenuItem) |
| -{ |
| - ContextMenu textDirectionMenu; |
| - |
| - ContextMenuItem defaultItem(ActionType, ContextMenuItemTagTextDirectionDefault, contextMenuItemTagDefaultDirection()); |
| - ContextMenuItem ltr(CheckableActionType, ContextMenuItemTagTextDirectionLeftToRight, contextMenuItemTagLeftToRight()); |
| - ContextMenuItem rtl(CheckableActionType, ContextMenuItemTagTextDirectionRightToLeft, contextMenuItemTagRightToLeft()); |
| - |
| - appendItem(defaultItem, &textDirectionMenu); |
| - appendItem(ltr, &textDirectionMenu); |
| - appendItem(rtl, &textDirectionMenu); |
| - |
| - textDirectionMenuItem.setSubMenu(&textDirectionMenu); |
| -} |
| - |
| -static bool selectionContainsPossibleWord(Frame* frame) |
| -{ |
| - // Current algorithm: look for a character that's not just a separator. |
| - for (TextIterator it(frame->selection()->toNormalizedRange().get()); !it.atEnd(); it.advance()) { |
| - int length = it.length(); |
| - for (int i = 0; i < length; ++i) |
| - if (!(category(it.characterAt(i)) & (Separator_Space | Separator_Line | Separator_Paragraph))) |
| - return true; |
| - } |
| - return false; |
| -} |
| - |
| -void ContextMenuController::populate() |
| -{ |
| - ContextMenuItem OpenLinkItem(ActionType, ContextMenuItemTagOpenLink, contextMenuItemTagOpenLink()); |
| - ContextMenuItem OpenLinkInNewWindowItem(ActionType, ContextMenuItemTagOpenLinkInNewWindow, |
| - contextMenuItemTagOpenLinkInNewWindow()); |
| - ContextMenuItem DownloadFileItem(ActionType, ContextMenuItemTagDownloadLinkToDisk, |
| - contextMenuItemTagDownloadLinkToDisk()); |
| - ContextMenuItem CopyLinkItem(ActionType, ContextMenuItemTagCopyLinkToClipboard, |
| - contextMenuItemTagCopyLinkToClipboard()); |
| - ContextMenuItem OpenImageInNewWindowItem(ActionType, ContextMenuItemTagOpenImageInNewWindow, |
| - contextMenuItemTagOpenImageInNewWindow()); |
| - ContextMenuItem DownloadImageItem(ActionType, ContextMenuItemTagDownloadImageToDisk, |
| - contextMenuItemTagDownloadImageToDisk()); |
| - ContextMenuItem CopyImageItem(ActionType, ContextMenuItemTagCopyImageToClipboard, |
| - contextMenuItemTagCopyImageToClipboard()); |
| - ContextMenuItem OpenMediaInNewWindowItem(ActionType, ContextMenuItemTagOpenMediaInNewWindow, String()); |
| - ContextMenuItem CopyMediaLinkItem(ActionType, ContextMenuItemTagCopyMediaLinkToClipboard, |
| - String()); |
| - ContextMenuItem MediaPlayPause(ActionType, ContextMenuItemTagMediaPlayPause, |
| - contextMenuItemTagMediaPlay()); |
| - ContextMenuItem MediaMute(ActionType, ContextMenuItemTagMediaMute, |
| - contextMenuItemTagMediaMute()); |
| - ContextMenuItem ToggleMediaControls(CheckableActionType, ContextMenuItemTagToggleMediaControls, |
| - contextMenuItemTagToggleMediaControls()); |
| - ContextMenuItem ToggleMediaLoop(CheckableActionType, ContextMenuItemTagToggleMediaLoop, |
| - contextMenuItemTagToggleMediaLoop()); |
| - ContextMenuItem EnterVideoFullscreen(ActionType, ContextMenuItemTagEnterVideoFullscreen, |
| - contextMenuItemTagEnterVideoFullscreen()); |
| - ContextMenuItem SearchWebItem(ActionType, ContextMenuItemTagSearchWeb, contextMenuItemTagSearchWeb()); |
| - ContextMenuItem CopyItem(ActionType, ContextMenuItemTagCopy, contextMenuItemTagCopy()); |
| - ContextMenuItem BackItem(ActionType, ContextMenuItemTagGoBack, contextMenuItemTagGoBack()); |
| - ContextMenuItem ForwardItem(ActionType, ContextMenuItemTagGoForward, contextMenuItemTagGoForward()); |
| - ContextMenuItem StopItem(ActionType, ContextMenuItemTagStop, contextMenuItemTagStop()); |
| - ContextMenuItem ReloadItem(ActionType, ContextMenuItemTagReload, contextMenuItemTagReload()); |
| - ContextMenuItem OpenFrameItem(ActionType, ContextMenuItemTagOpenFrameInNewWindow, |
| - contextMenuItemTagOpenFrameInNewWindow()); |
| - ContextMenuItem NoGuessesItem(ActionType, ContextMenuItemTagNoGuessesFound, |
| - contextMenuItemTagNoGuessesFound()); |
| - ContextMenuItem IgnoreSpellingItem(ActionType, ContextMenuItemTagIgnoreSpelling, |
| - contextMenuItemTagIgnoreSpelling()); |
| - ContextMenuItem LearnSpellingItem(ActionType, ContextMenuItemTagLearnSpelling, |
| - contextMenuItemTagLearnSpelling()); |
| - ContextMenuItem IgnoreGrammarItem(ActionType, ContextMenuItemTagIgnoreGrammar, |
| - contextMenuItemTagIgnoreGrammar()); |
| - ContextMenuItem CutItem(ActionType, ContextMenuItemTagCut, contextMenuItemTagCut()); |
| - ContextMenuItem PasteItem(ActionType, ContextMenuItemTagPaste, contextMenuItemTagPaste()); |
| - |
| - Node* node = m_hitTestResult.innerNonSharedNode(); |
| - if (!node) |
| - return; |
| - Frame* frame = node->document()->frame(); |
| - if (!frame) |
| - return; |
| - |
| - if (!m_hitTestResult.isContentEditable()) { |
| - FrameLoader* loader = frame->loader(); |
| - KURL linkURL = m_hitTestResult.absoluteLinkURL(); |
| - if (!linkURL.isEmpty()) { |
| - if (loader->client()->canHandleRequest(ResourceRequest(linkURL))) { |
| - appendItem(OpenLinkItem, m_contextMenu.get()); |
| - appendItem(OpenLinkInNewWindowItem, m_contextMenu.get()); |
| - appendItem(DownloadFileItem, m_contextMenu.get()); |
| - } |
| - appendItem(CopyLinkItem, m_contextMenu.get()); |
| - } |
| - |
| - KURL imageURL = m_hitTestResult.absoluteImageURL(); |
| - if (!imageURL.isEmpty()) { |
| - if (!linkURL.isEmpty()) |
| - appendItem(*separatorItem(), m_contextMenu.get()); |
| - |
| - appendItem(OpenImageInNewWindowItem, m_contextMenu.get()); |
| - appendItem(DownloadImageItem, m_contextMenu.get()); |
| - if (imageURL.isLocalFile() || m_hitTestResult.image()) |
| - appendItem(CopyImageItem, m_contextMenu.get()); |
| - } |
| - |
| - KURL mediaURL = m_hitTestResult.absoluteMediaURL(); |
| - if (!mediaURL.isEmpty()) { |
| - if (!linkURL.isEmpty() || !imageURL.isEmpty()) |
| - appendItem(*separatorItem(), m_contextMenu.get()); |
| - |
| - appendItem(MediaPlayPause, m_contextMenu.get()); |
| - appendItem(MediaMute, m_contextMenu.get()); |
| - appendItem(ToggleMediaControls, m_contextMenu.get()); |
| - appendItem(ToggleMediaLoop, m_contextMenu.get()); |
| - appendItem(EnterVideoFullscreen, m_contextMenu.get()); |
| - |
| - appendItem(*separatorItem(), m_contextMenu.get()); |
| - appendItem(CopyMediaLinkItem, m_contextMenu.get()); |
| - appendItem(OpenMediaInNewWindowItem, m_contextMenu.get()); |
| - } |
| - |
| - if (imageURL.isEmpty() && linkURL.isEmpty() && mediaURL.isEmpty()) { |
| - if (m_hitTestResult.isSelected()) { |
| - if (selectionContainsPossibleWord(frame)) { |
| - appendItem(SearchWebItem, m_contextMenu.get()); |
| - appendItem(*separatorItem(), m_contextMenu.get()); |
| - } |
| - |
| - appendItem(CopyItem, m_contextMenu.get()); |
| - } else { |
| - if (!(frame->page() && frame->page()->inspectorController()->hasInspectorFrontendClient())) { |
| - if (frame->page() && frame->page()->backForward()->canGoBackOrForward(-1)) |
| - appendItem(BackItem, m_contextMenu.get()); |
| - |
| - if (frame->page() && frame->page()->backForward()->canGoBackOrForward(1)) |
| - appendItem(ForwardItem, m_contextMenu.get()); |
| - |
| - // use isLoadingInAPISense rather than isLoading because Stop/Reload are |
| - // intended to match WebKit's API, not WebCore's internal notion of loading status |
| - if (loader->documentLoader()->isLoadingInAPISense()) |
| - appendItem(StopItem, m_contextMenu.get()); |
| - else |
| - appendItem(ReloadItem, m_contextMenu.get()); |
| - } |
| - |
| - if (frame->page() && frame != frame->page()->mainFrame()) |
| - appendItem(OpenFrameItem, m_contextMenu.get()); |
| - } |
| - } |
| - } else { // Make an editing context menu |
| - FrameSelection* selection = frame->selection(); |
| - bool inPasswordField = selection->isInPasswordField(); |
| - if (!inPasswordField) { |
| - bool haveContextMenuItemsForMisspellingOrGrammer = false; |
| - bool spellCheckingEnabled = frame->editor()->isSpellCheckingEnabledFor(node); |
| - if (spellCheckingEnabled) { |
| - // Consider adding spelling-related or grammar-related context menu items (never both, since a single selected range |
| - // is never considered a misspelling and bad grammar at the same time) |
| - bool misspelling; |
| - bool badGrammar; |
| - Vector<String> guesses = frame->editor()->guessesForMisspelledOrUngrammatical(misspelling, badGrammar); |
|
adamk
2013/05/14 00:30:52
Just happened to be looking at the code for guesse
groby-ooo-7-16
2013/05/14 00:57:54
I'm not sure what side effects you're seeing there
adamk
2013/05/14 01:05:12
The call sequence I'm worried about is:
Editor::g
|
| - if (misspelling || badGrammar) { |
| - size_t size = guesses.size(); |
| - if (!size) { |
| - // If there's bad grammar but no suggestions (e.g., repeated word), just leave off the suggestions |
| - // list and trailing separator rather than adding a "No Guesses Found" item (matches AppKit) |
| - if (misspelling) { |
| - appendItem(NoGuessesItem, m_contextMenu.get()); |
| - appendItem(*separatorItem(), m_contextMenu.get()); |
| - } |
| - } else { |
| - for (unsigned i = 0; i < size; i++) { |
| - const String &guess = guesses[i]; |
| - if (!guess.isEmpty()) { |
| - ContextMenuItem item(ActionType, ContextMenuItemTagSpellingGuess, guess); |
| - appendItem(item, m_contextMenu.get()); |
| - } |
| - } |
| - appendItem(*separatorItem(), m_contextMenu.get()); |
| - } |
| - if (misspelling) { |
| - appendItem(IgnoreSpellingItem, m_contextMenu.get()); |
| - appendItem(LearnSpellingItem, m_contextMenu.get()); |
| - } else |
| - appendItem(IgnoreGrammarItem, m_contextMenu.get()); |
| - appendItem(*separatorItem(), m_contextMenu.get()); |
| - haveContextMenuItemsForMisspellingOrGrammer = true; |
| - } |
| - } |
| - } |
| - |
| - FrameLoader* loader = frame->loader(); |
| - KURL linkURL = m_hitTestResult.absoluteLinkURL(); |
| - if (!linkURL.isEmpty()) { |
| - if (loader->client()->canHandleRequest(ResourceRequest(linkURL))) { |
| - appendItem(OpenLinkItem, m_contextMenu.get()); |
| - appendItem(OpenLinkInNewWindowItem, m_contextMenu.get()); |
| - appendItem(DownloadFileItem, m_contextMenu.get()); |
| - } |
| - appendItem(CopyLinkItem, m_contextMenu.get()); |
| - appendItem(*separatorItem(), m_contextMenu.get()); |
| - } |
| - |
| - if (m_hitTestResult.isSelected() && !inPasswordField && selectionContainsPossibleWord(frame)) { |
| - appendItem(SearchWebItem, m_contextMenu.get()); |
| - appendItem(*separatorItem(), m_contextMenu.get()); |
| - } |
| - |
| - appendItem(CutItem, m_contextMenu.get()); |
| - appendItem(CopyItem, m_contextMenu.get()); |
| - appendItem(PasteItem, m_contextMenu.get()); |
| - |
| - if (!inPasswordField) { |
| - appendItem(*separatorItem(), m_contextMenu.get()); |
| - ContextMenuItem SpellingAndGrammarMenuItem(SubmenuType, ContextMenuItemTagSpellingMenu, |
| - contextMenuItemTagSpellingMenu()); |
| - createAndAppendSpellingAndGrammarSubMenu(SpellingAndGrammarMenuItem); |
| - appendItem(SpellingAndGrammarMenuItem, m_contextMenu.get()); |
| - bool shouldShowFontMenu = true; |
| - if (shouldShowFontMenu) { |
| - ContextMenuItem FontMenuItem(SubmenuType, ContextMenuItemTagFontMenu, |
| - contextMenuItemTagFontMenu()); |
| - createAndAppendFontSubMenu(FontMenuItem); |
| - appendItem(FontMenuItem, m_contextMenu.get()); |
| - } |
| - ContextMenuItem WritingDirectionMenuItem(SubmenuType, ContextMenuItemTagWritingDirectionMenu, |
| - contextMenuItemTagWritingDirectionMenu()); |
| - createAndAppendWritingDirectionSubMenu(WritingDirectionMenuItem); |
| - appendItem(WritingDirectionMenuItem, m_contextMenu.get()); |
| - if (Page* page = frame->page()) { |
| - if (Settings* settings = page->settings()) { |
| - bool includeTextDirectionSubmenu = settings->textDirectionSubmenuInclusionBehavior() == TextDirectionSubmenuAlwaysIncluded |
| - || (settings->textDirectionSubmenuInclusionBehavior() == TextDirectionSubmenuAutomaticallyIncluded && frame->editor()->hasBidiSelection()); |
| - if (includeTextDirectionSubmenu) { |
| - ContextMenuItem TextDirectionMenuItem(SubmenuType, ContextMenuItemTagTextDirectionMenu, |
| - contextMenuItemTagTextDirectionMenu()); |
| - createAndAppendTextDirectionSubMenu(TextDirectionMenuItem); |
| - appendItem(TextDirectionMenuItem, m_contextMenu.get()); |
| - } |
| - } |
| - } |
| - } |
| - } |
| -} |
| - |
| -void ContextMenuController::addInspectElementItem() |
| -{ |
| - Node* node = m_hitTestResult.innerNonSharedNode(); |
| - if (!node) |
| - return; |
| - |
| - Frame* frame = node->document()->frame(); |
| - if (!frame) |
| - return; |
| - |
| - Page* page = frame->page(); |
| - if (!page) |
| - return; |
| - |
| - if (!page->inspectorController()) |
| - return; |
| - |
| - ContextMenuItem InspectElementItem(ActionType, ContextMenuItemTagInspectElement, contextMenuItemTagInspectElement()); |
| - if (m_contextMenu && !m_contextMenu->items().isEmpty()) |
| - appendItem(*separatorItem(), m_contextMenu.get()); |
| - appendItem(InspectElementItem, m_contextMenu.get()); |
| -} |
| - |
| -void ContextMenuController::checkOrEnableIfNeeded(ContextMenuItem& item) const |
| -{ |
| - if (item.type() == SeparatorType) |
| - return; |
| - |
| - Frame* frame = m_hitTestResult.innerNonSharedNode()->document()->frame(); |
| - if (!frame) |
| - return; |
| - |
| - // Custom items already have proper checked and enabled values. |
| - if (ContextMenuItemBaseCustomTag <= item.action() && item.action() <= ContextMenuItemLastCustomTag) |
| - return; |
| - |
| - bool shouldEnable = true; |
| - bool shouldCheck = false; |
| - |
| - switch (item.action()) { |
| - case ContextMenuItemTagCheckSpelling: |
| - shouldEnable = frame->editor()->canEdit(); |
| - break; |
| - case ContextMenuItemTagDefaultDirection: |
| - shouldCheck = false; |
| - shouldEnable = false; |
| - break; |
| - case ContextMenuItemTagLeftToRight: |
| - case ContextMenuItemTagRightToLeft: { |
| - String direction = item.action() == ContextMenuItemTagLeftToRight ? "ltr" : "rtl"; |
| - shouldCheck = frame->editor()->selectionHasStyle(CSSPropertyDirection, direction) != FalseTriState; |
| - shouldEnable = true; |
| - break; |
| - } |
| - case ContextMenuItemTagTextDirectionDefault: { |
| - Editor::Command command = frame->editor()->command("MakeTextWritingDirectionNatural"); |
| - shouldCheck = command.state() == TrueTriState; |
| - shouldEnable = command.isEnabled(); |
| - break; |
| - } |
| - case ContextMenuItemTagTextDirectionLeftToRight: { |
| - Editor::Command command = frame->editor()->command("MakeTextWritingDirectionLeftToRight"); |
| - shouldCheck = command.state() == TrueTriState; |
| - shouldEnable = command.isEnabled(); |
| - break; |
| - } |
| - case ContextMenuItemTagTextDirectionRightToLeft: { |
| - Editor::Command command = frame->editor()->command("MakeTextWritingDirectionRightToLeft"); |
| - shouldCheck = command.state() == TrueTriState; |
| - shouldEnable = command.isEnabled(); |
| - break; |
| - } |
| - case ContextMenuItemTagCopy: |
| - shouldEnable = frame->editor()->canDHTMLCopy() || frame->editor()->canCopy(); |
| - break; |
| - case ContextMenuItemTagCut: |
| - shouldEnable = frame->editor()->canDHTMLCut() || frame->editor()->canCut(); |
| - break; |
| - case ContextMenuItemTagIgnoreSpelling: |
| - case ContextMenuItemTagLearnSpelling: |
| - shouldEnable = frame->selection()->isRange(); |
| - break; |
| - case ContextMenuItemTagPaste: |
| - shouldEnable = frame->editor()->canDHTMLPaste() || frame->editor()->canPaste(); |
| - break; |
| - case ContextMenuItemTagUnderline: { |
| - shouldCheck = frame->editor()->selectionHasStyle(CSSPropertyWebkitTextDecorationsInEffect, "underline") != FalseTriState; |
| - shouldEnable = frame->editor()->canEditRichly(); |
| - break; |
| - } |
| - case ContextMenuItemTagLookUpInDictionary: |
| - shouldEnable = frame->selection()->isRange(); |
| - break; |
| - case ContextMenuItemTagCheckGrammarWithSpelling: |
| - if (frame->editor()->isGrammarCheckingEnabled()) |
| - shouldCheck = true; |
| - shouldEnable = true; |
| - break; |
| - case ContextMenuItemTagItalic: { |
| - shouldCheck = frame->editor()->selectionHasStyle(CSSPropertyFontStyle, "italic") != FalseTriState; |
| - shouldEnable = frame->editor()->canEditRichly(); |
| - break; |
| - } |
| - case ContextMenuItemTagBold: { |
| - shouldCheck = frame->editor()->selectionHasStyle(CSSPropertyFontWeight, "bold") != FalseTriState; |
| - shouldEnable = frame->editor()->canEditRichly(); |
| - break; |
| - } |
| - case ContextMenuItemTagOutline: |
| - shouldEnable = false; |
| - break; |
| - case ContextMenuItemTagShowSpellingPanel: |
| - if (frame->editor()->spellingPanelIsShowing()) |
| - item.setTitle(contextMenuItemTagShowSpellingPanel(false)); |
| - else |
| - item.setTitle(contextMenuItemTagShowSpellingPanel(true)); |
| - shouldEnable = frame->editor()->canEdit(); |
| - break; |
| - case ContextMenuItemTagNoGuessesFound: |
| - shouldEnable = false; |
| - break; |
| - case ContextMenuItemTagCheckSpellingWhileTyping: |
| - shouldCheck = frame->editor()->isContinuousSpellCheckingEnabled(); |
| - break; |
| - case ContextMenuItemTagStopSpeaking: |
| - break; |
| - case ContextMenuItemTagGoBack: |
| - case ContextMenuItemTagGoForward: |
| - case ContextMenuItemTagStop: |
| - case ContextMenuItemTagReload: |
| - case ContextMenuItemTagFontMenu: |
| - case ContextMenuItemTagNoAction: |
| - case ContextMenuItemTagOpenLinkInNewWindow: |
| - case ContextMenuItemTagOpenLinkInThisWindow: |
| - case ContextMenuItemTagDownloadLinkToDisk: |
| - case ContextMenuItemTagCopyLinkToClipboard: |
| - case ContextMenuItemTagOpenImageInNewWindow: |
| - case ContextMenuItemTagDownloadImageToDisk: |
| - case ContextMenuItemTagCopyImageToClipboard: |
| - break; |
| - case ContextMenuItemTagOpenMediaInNewWindow: |
| - if (m_hitTestResult.mediaIsVideo()) |
| - item.setTitle(contextMenuItemTagOpenVideoInNewWindow()); |
| - else |
| - item.setTitle(contextMenuItemTagOpenAudioInNewWindow()); |
| - break; |
| - case ContextMenuItemTagCopyMediaLinkToClipboard: |
| - if (m_hitTestResult.mediaIsVideo()) |
| - item.setTitle(contextMenuItemTagCopyVideoLinkToClipboard()); |
| - else |
| - item.setTitle(contextMenuItemTagCopyAudioLinkToClipboard()); |
| - break; |
| - case ContextMenuItemTagToggleMediaControls: |
| - shouldCheck = m_hitTestResult.mediaControlsEnabled(); |
| - break; |
| - case ContextMenuItemTagToggleMediaLoop: |
| - shouldCheck = m_hitTestResult.mediaLoopEnabled(); |
| - break; |
| - case ContextMenuItemTagEnterVideoFullscreen: |
| - shouldEnable = m_hitTestResult.mediaSupportsFullscreen(); |
| - break; |
| - case ContextMenuItemTagOpenFrameInNewWindow: |
| - case ContextMenuItemTagSpellingGuess: |
| - case ContextMenuItemTagOther: |
| - case ContextMenuItemTagSearchInSpotlight: |
| - case ContextMenuItemTagSearchWeb: |
| - case ContextMenuItemTagOpenWithDefaultApplication: |
| - case ContextMenuItemPDFActualSize: |
| - case ContextMenuItemPDFZoomIn: |
| - case ContextMenuItemPDFZoomOut: |
| - case ContextMenuItemPDFAutoSize: |
| - case ContextMenuItemPDFSinglePage: |
| - case ContextMenuItemPDFFacingPages: |
| - case ContextMenuItemPDFContinuous: |
| - case ContextMenuItemPDFNextPage: |
| - case ContextMenuItemPDFPreviousPage: |
| - case ContextMenuItemTagOpenLink: |
| - case ContextMenuItemTagIgnoreGrammar: |
| - case ContextMenuItemTagSpellingMenu: |
| - case ContextMenuItemTagShowFonts: |
| - case ContextMenuItemTagStyles: |
| - case ContextMenuItemTagShowColors: |
| - case ContextMenuItemTagSpeechMenu: |
| - case ContextMenuItemTagStartSpeaking: |
| - case ContextMenuItemTagWritingDirectionMenu: |
| - case ContextMenuItemTagTextDirectionMenu: |
| - case ContextMenuItemTagPDFSinglePageScrolling: |
| - case ContextMenuItemTagPDFFacingPagesScrolling: |
| - case ContextMenuItemTagInspectElement: |
| - case ContextMenuItemBaseCustomTag: |
| - case ContextMenuItemCustomTagNoAction: |
| - case ContextMenuItemLastCustomTag: |
| - case ContextMenuItemBaseApplicationTag: |
| - break; |
| - case ContextMenuItemTagMediaPlayPause: |
| - if (m_hitTestResult.mediaPlaying()) |
| - item.setTitle(contextMenuItemTagMediaPause()); |
| - else |
| - item.setTitle(contextMenuItemTagMediaPlay()); |
| - break; |
| - case ContextMenuItemTagMediaMute: |
| - shouldEnable = m_hitTestResult.mediaHasAudio(); |
| - shouldCheck = shouldEnable && m_hitTestResult.mediaMuted(); |
| - break; |
| - } |
| - |
| - item.setChecked(shouldCheck); |
| - item.setEnabled(shouldEnable); |
| + ASSERT(m_menuProvider); |
| + m_menuProvider->contextMenuItemSelected(item); |
| } |
| } // namespace WebCore |