WinCairo build fails to link.
[WebKit-https.git] / Source / WebKit / chromium / src / EditorClientImpl.cpp
index 68694c2..1d13c8e 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2006, 2007 Apple, Inc.  All rights reserved.
- * Copyright (C) 2010 Google, Inc.  All rights reserved.
+ * Copyright (C) 2012 Google, Inc.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -28,7 +28,6 @@
 #include "EditorClientImpl.h"
 
 #include "Document.h"
-#include "EditCommand.h"
 #include "Editor.h"
 #include "EventHandler.h"
 #include "EventNames.h"
 #include "HTMLNames.h"
 #include "KeyboardCodes.h"
 #include "KeyboardEvent.h"
+#include "NotImplemented.h"
+#include "Page.h"
 #include "PlatformKeyboardEvent.h"
-#include "PlatformString.h"
 #include "RenderObject.h"
+#include "Settings.h"
+#include "SpellChecker.h"
+#include "UndoStep.h"
 
 #include "DOMUtilitiesPrivate.h"
-#include "WebAutoFillClient.h"
+#include "WebAutofillClient.h"
 #include "WebEditingAction.h"
 #include "WebElement.h"
 #include "WebFrameClient.h"
 #include "WebFrameImpl.h"
-#include "WebKit.h"
 #include "WebInputElement.h"
 #include "WebInputEventConversion.h"
+#include "WebKit.h"
 #include "WebNode.h"
-#include "WebPasswordAutocompleteListener.h"
+#include "WebPermissionClient.h"
 #include "WebRange.h"
+#include "WebSpellCheckClient.h"
 #include "WebTextAffinity.h"
+#include "WebTextCheckingCompletionImpl.h"
+#include "WebTextCheckingResult.h"
 #include "WebViewClient.h"
 #include "WebViewImpl.h"
+#include <wtf/text/WTFString.h>
 
 using namespace WebCore;
 
@@ -67,16 +74,10 @@ namespace WebKit {
 // into a single action.
 static const size_t maximumUndoStackDepth = 1000;
 
-// The size above which we stop triggering autofill for an input text field
-// (so to avoid sending long strings through IPC).
-static const size_t maximumTextSizeForAutofill = 1000;
-
 EditorClientImpl::EditorClientImpl(WebViewImpl* webview)
     : m_webView(webview)
     , m_inRedo(false)
-    , m_backspaceOrDeletePressed(false)
     , m_spellCheckThisFieldStatus(SpellCheckAutomatic)
-    , m_autofillTimer(this, &EditorClientImpl::doAutofill)
 {
 }
 
@@ -89,31 +90,22 @@ void EditorClientImpl::pageDestroyed()
     // Our lifetime is bound to the WebViewImpl.
 }
 
-bool EditorClientImpl::shouldShowDeleteInterface(HTMLElement* elem)
+void EditorClientImpl::frameWillDetachPage(WebCore::Frame* frame)
 {
-    // Normally, we don't care to show WebCore's deletion UI, so we only enable
-    // it if in testing mode and the test specifically requests it by using this
-    // magic class name.
-    return layoutTestMode()
-           && elem->getAttribute(HTMLNames::classAttr) == "needsDeletionUI";
 }
 
 bool EditorClientImpl::smartInsertDeleteEnabled()
 {
-    if (m_webView->client())
-        return m_webView->client()->isSmartInsertDeleteEnabled();
-    return true;
+    if (m_webView->page())
+        return m_webView->page()->settings()->smartInsertDeleteEnabled();
+    return false;
 }
 
 bool EditorClientImpl::isSelectTrailingWhitespaceEnabled()
 {
-    if (m_webView->client())
-        return m_webView->client()->isSelectTrailingWhitespaceEnabled();
-#if OS(WINDOWS)
-    return true;
-#else
+    if (m_webView->page())
+        return m_webView->page()->settings()->selectTrailingWhitespaceEnabled();
     return false;
-#endif
 }
 
 bool EditorClientImpl::shouldSpellcheckByDefault()
@@ -162,16 +154,12 @@ void EditorClientImpl::toggleContinuousSpellChecking()
         m_spellCheckThisFieldStatus = SpellCheckForcedOff;
     else
         m_spellCheckThisFieldStatus = SpellCheckForcedOn;
-
-    WebFrameImpl* webframe = WebFrameImpl::fromFrame(
-        m_webView->focusedWebCoreFrame());
-    if (webframe)
-        webframe->client()->didToggleContinuousSpellChecking(webframe);
 }
 
 bool EditorClientImpl::isGrammarCheckingEnabled()
 {
-    return false;
+    const Frame* frame = m_webView->focusedWebCoreFrame();
+    return frame && frame->settings() && (frame->settings()->asynchronousSpellCheckingEnabled() || frame->settings()->unifiedTextCheckerEnabled());
 }
 
 void EditorClientImpl::toggleGrammarChecking()
@@ -185,11 +173,6 @@ int EditorClientImpl::spellCheckerDocumentTag()
     return 0;
 }
 
-bool EditorClientImpl::isEditable()
-{
-    return false;
-}
-
 bool EditorClientImpl::shouldBeginEditing(Range* range)
 {
     if (m_webView->client())
@@ -250,13 +233,11 @@ bool EditorClientImpl::shouldChangeSelectedRange(Range* fromRange,
     return true;
 }
 
-bool EditorClientImpl::shouldApplyStyle(CSSStyleDeclaration* style,
-                                        Range* range)
+bool EditorClientImpl::shouldApplyStyle(StylePropertySet* style, Range* range)
 {
     if (m_webView->client()) {
         // FIXME: Pass a reference to the CSSStyleDeclaration somehow.
-        return m_webView->client()->shouldApplyStyle(WebString(),
-                                                     WebRange(range));
+        return m_webView->client()->shouldApplyStyle(WebString(), WebRange(range));
     }
     return true;
 }
@@ -273,12 +254,14 @@ void EditorClientImpl::didBeginEditing()
         m_webView->client()->didBeginEditing();
 }
 
-void EditorClientImpl::respondToChangedSelection()
+void EditorClientImpl::respondToChangedSelection(Frame* frame)
 {
     if (m_webView->client()) {
-        Frame* frame = m_webView->focusedWebCoreFrame();
-        if (frame)
+        if (frame) {
             m_webView->client()->didChangeSelection(!frame->selection()->isRange());
+            if (frame->editor()->cancelCompositionIfSelectionIsInvalid())
+                m_webView->client()->didCancelCompositionOnSelectionChange();
+        }
     }
 }
 
@@ -298,22 +281,30 @@ void EditorClientImpl::didWriteSelectionToPasteboard()
 {
 }
 
+void EditorClientImpl::willWriteSelectionToPasteboard(WebCore::Range*)
+{
+}
+
+void EditorClientImpl::getClientPasteboardDataForRange(WebCore::Range*, Vector<String>&, Vector<RefPtr<WebCore::SharedBuffer> >&)
+{
+}
+
 void EditorClientImpl::didSetSelectionTypesForPasteboard()
 {
 }
 
-void EditorClientImpl::registerCommandForUndo(PassRefPtr<EditCommand> command)
+void EditorClientImpl::registerUndoStep(PassRefPtr<UndoStep> step)
 {
     if (m_undoStack.size() == maximumUndoStackDepth)
         m_undoStack.removeFirst(); // drop oldest item off the far end
     if (!m_inRedo)
         m_redoStack.clear();
-    m_undoStack.append(command);
+    m_undoStack.append(step);
 }
 
-void EditorClientImpl::registerCommandForRedo(PassRefPtr<EditCommand> command)
+void EditorClientImpl::registerRedoStep(PassRefPtr<UndoStep> step)
 {
-    m_redoStack.append(command);
+    m_redoStack.append(step);
 }
 
 void EditorClientImpl::clearUndoRedoOperations()
@@ -322,6 +313,20 @@ void EditorClientImpl::clearUndoRedoOperations()
     m_redoStack.clear();
 }
 
+bool EditorClientImpl::canCopyCut(Frame* frame, bool defaultValue) const
+{
+    if (!m_webView->permissionClient())
+        return defaultValue;
+    return m_webView->permissionClient()->allowWriteToClipboard(WebFrameImpl::fromFrame(frame), defaultValue);
+}
+
+bool EditorClientImpl::canPaste(Frame* frame, bool defaultValue) const
+{
+    if (!m_webView->permissionClient())
+        return defaultValue;
+    return m_webView->permissionClient()->allowReadFromClipboard(WebFrameImpl::fromFrame(frame), defaultValue);
+}
+
 bool EditorClientImpl::canUndo() const
 {
     return !m_undoStack.isEmpty();
@@ -335,10 +340,10 @@ bool EditorClientImpl::canRedo() const
 void EditorClientImpl::undo()
 {
     if (canUndo()) {
-        EditCommandStack::iterator back = --m_undoStack.end();
-        RefPtr<EditCommand> command(*back);
+        UndoManagerStack::iterator back = --m_undoStack.end();
+        RefPtr<UndoStep> step(*back);
         m_undoStack.remove(back);
-        command->unapply();
+        step->unapply();
         // unapply will call us back to push this command onto the redo stack.
     }
 }
@@ -346,13 +351,13 @@ void EditorClientImpl::undo()
 void EditorClientImpl::redo()
 {
     if (canRedo()) {
-        EditCommandStack::iterator back = --m_redoStack.end();
-        RefPtr<EditCommand> command(*back);
+        UndoManagerStack::iterator back = --m_redoStack.end();
+        RefPtr<UndoStep> step(*back);
         m_redoStack.remove(back);
 
         ASSERT(!m_inRedo);
         m_inRedo = true;
-        command->reapply();
+        step->reapply();
         // reapply will call us back to push this command onto the undo stack.
         m_inRedo = false;
     }
@@ -544,7 +549,7 @@ const char* EditorClientImpl::interpretKeyEvent(const KeyboardEvent* evt)
     if (keyEvent->metaKey())
         modifiers |= MetaKey;
 
-    if (keyEvent->type() == PlatformKeyboardEvent::RawKeyDown) {
+    if (keyEvent->type() == PlatformEvent::RawKeyDown) {
         int mapKey = modifiers << 16 | evt->keyCode();
         return mapKey ? keyDownCommandsMap->get(mapKey) : 0;
     }
@@ -567,7 +572,7 @@ bool EditorClientImpl::handleEditingKeyboardEvent(KeyboardEvent* evt)
     String commandName = interpretKeyEvent(evt);
     Editor::Command command = frame->editor()->command(commandName);
 
-    if (keyEvent->type() == PlatformKeyboardEvent::RawKeyDown) {
+    if (keyEvent->type() == PlatformEvent::RawKeyDown) {
         // WebKit doesn't have enough information about mode to decide how
         // commands that just insert text if executed via Editor should be treated,
         // so we leave it upon WebCore to either handle them immediately
@@ -635,12 +640,6 @@ bool EditorClientImpl::handleEditingKeyboardEvent(KeyboardEvent* evt)
 
 void EditorClientImpl::handleKeyboardEvent(KeyboardEvent* evt)
 {
-    if (evt->keyCode() == VKEY_DOWN
-        || evt->keyCode() == VKEY_UP) {
-        ASSERT(evt->target()->toNode());
-        showFormAutofillForNode(evt->target()->toNode());
-    }
-
     // Give the embedder a chance to handle the keyboard event.
     if ((m_webView->client()
          && m_webView->client()->handleCurrentKeyboardEvent())
@@ -655,178 +654,38 @@ void EditorClientImpl::handleInputMethodKeydown(KeyboardEvent* keyEvent)
 
 void EditorClientImpl::textFieldDidBeginEditing(Element* element)
 {
-    HTMLInputElement* inputElement = toHTMLInputElement(element);
-    if (m_webView->autoFillClient() && inputElement)
-        m_webView->autoFillClient()->textFieldDidBeginEditing(WebInputElement(inputElement));
 }
 
 void EditorClientImpl::textFieldDidEndEditing(Element* element)
 {
     HTMLInputElement* inputElement = toHTMLInputElement(element);
-    if (m_webView->autoFillClient() && inputElement)
-        m_webView->autoFillClient()->textFieldDidEndEditing(WebInputElement(inputElement));
+    if (m_webView->autofillClient() && inputElement)
+        m_webView->autofillClient()->textFieldDidEndEditing(WebInputElement(inputElement));
 
     // Notification that focus was lost.  Be careful with this, it's also sent
     // when the page is being closed.
 
-    // Cancel any pending DoAutofill call.
-    m_autofillArgs.clear();
-    m_autofillTimer.stop();
-
     // Hide any showing popup.
-    m_webView->hideAutoFillPopup();
-
-    if (!m_webView->client())
-        return; // The page is getting closed, don't fill the password.
-
-    // Notify any password-listener of the focus change.
-    if (!inputElement)
-        return;
-
-    WebFrameImpl* webframe = WebFrameImpl::fromFrame(inputElement->document()->frame());
-    if (!webframe)
-        return;
-
-    WebPasswordAutocompleteListener* listener = webframe->getPasswordListener(inputElement);
-    if (!listener)
-        return;
-
-    listener->didBlurInputElement(inputElement->value());
+    m_webView->hideAutofillPopup();
 }
 
 void EditorClientImpl::textDidChangeInTextField(Element* element)
 {
     ASSERT(element->hasLocalName(HTMLNames::inputTag));
     HTMLInputElement* inputElement = static_cast<HTMLInputElement*>(element);
-    if (m_webView->autoFillClient())
-        m_webView->autoFillClient()->textFieldDidChange(WebInputElement(inputElement));
-
-    // Note that we only show the autofill popup in this case if the caret is at
-    // the end.  This matches FireFox and Safari but not IE.
-    autofill(inputElement, false, false, true);
-}
-
-bool EditorClientImpl::showFormAutofillForNode(Node* node)
-{
-    HTMLInputElement* inputElement = toHTMLInputElement(node);
-    if (inputElement)
-        return autofill(inputElement, true, true, false);
-    return false;
-}
-
-bool EditorClientImpl::autofill(HTMLInputElement* inputElement,
-                                bool autofillFormOnly,
-                                bool autofillOnEmptyValue,
-                                bool requireCaretAtEnd)
-{
-    // Cancel any pending DoAutofill call.
-    m_autofillArgs.clear();
-    m_autofillTimer.stop();
-
-    // FIXME: Remove the extraneous isEnabledFormControl call below.
-    // Let's try to trigger autofill for that field, if applicable.
-    if (!inputElement->isEnabledFormControl() || !inputElement->isTextField()
-        || inputElement->isPasswordField() || !inputElement->autoComplete()
-        || !inputElement->isEnabledFormControl()
-        || inputElement->isReadOnlyFormControl())
-        return false;
-
-    WebString name = WebInputElement(inputElement).nameForAutofill();
-    if (name.isEmpty()) // If the field has no name, then we won't have values.
-        return false;
-
-    // Don't attempt to autofill with values that are too large.
-    if (inputElement->value().length() > maximumTextSizeForAutofill)
-        return false;
-
-    m_autofillArgs = new AutofillArgs();
-    m_autofillArgs->inputElement = inputElement;
-    m_autofillArgs->autofillFormOnly = autofillFormOnly;
-    m_autofillArgs->autofillOnEmptyValue = autofillOnEmptyValue;
-    m_autofillArgs->requireCaretAtEnd = requireCaretAtEnd;
-    m_autofillArgs->backspaceOrDeletePressed = m_backspaceOrDeletePressed;
-
-    if (!requireCaretAtEnd)
-        doAutofill(0);
-    else {
-        // We post a task for doing the autofill as the caret position is not set
-        // properly at this point (http://bugs.webkit.org/show_bug.cgi?id=16976)
-        // and we need it to determine whether or not to trigger autofill.
-        m_autofillTimer.startOneShot(0.0);
-    }
-    return true;
-}
-
-void EditorClientImpl::doAutofill(Timer<EditorClientImpl>* timer)
-{
-    OwnPtr<AutofillArgs> args(m_autofillArgs.release());
-    HTMLInputElement* inputElement = args->inputElement.get();
-
-    const String& value = inputElement->value();
-
-    // Enforce autofill_on_empty_value and caret_at_end.
-
-    bool isCaretAtEnd = true;
-    if (args->requireCaretAtEnd)
-        isCaretAtEnd = inputElement->selectionStart() == inputElement->selectionEnd()
-                       && inputElement->selectionEnd() == static_cast<int>(value.length());
-
-    if ((!args->autofillOnEmptyValue && value.isEmpty()) || !isCaretAtEnd) {
-        m_webView->hideAutoFillPopup();
-        return;
-    }
-
-    // First let's see if there is a password listener for that element.
-    // We won't trigger form autofill in that case, as having both behavior on
-    // a node would be confusing.
-    WebFrameImpl* webframe = WebFrameImpl::fromFrame(inputElement->document()->frame());
-    if (!webframe)
-        return;
-    WebPasswordAutocompleteListener* listener = webframe->getPasswordListener(inputElement);
-    if (listener) {
-        if (args->autofillFormOnly)
-            return;
-
-        listener->performInlineAutocomplete(value,
-                                            args->backspaceOrDeletePressed,
-                                            true);
-        return;
-    }
-}
-
-void EditorClientImpl::cancelPendingAutofill()
-{
-    m_autofillArgs.clear();
-    m_autofillTimer.stop();
-}
-
-void EditorClientImpl::onAutocompleteSuggestionAccepted(HTMLInputElement* textField)
-{
-    if (m_webView->autoFillClient())
-        m_webView->autoFillClient()->didAcceptAutocompleteSuggestion(WebInputElement(textField));
-
-    WebFrameImpl* webframe = WebFrameImpl::fromFrame(textField->document()->frame());
-    if (!webframe)
-        return;
-
-    webframe->notifiyPasswordListenerOfAutocomplete(WebInputElement(textField));
+    if (m_webView->autofillClient())
+        m_webView->autofillClient()->textFieldDidChange(WebInputElement(inputElement));
 }
 
 bool EditorClientImpl::doTextFieldCommandFromEvent(Element* element,
                                                    KeyboardEvent* event)
 {
     HTMLInputElement* inputElement = toHTMLInputElement(element);
-    if (m_webView->autoFillClient() && inputElement) {
-        m_webView->autoFillClient()->textFieldDidReceiveKeyDown(WebInputElement(inputElement),
+    if (m_webView->autofillClient() && inputElement) {
+        m_webView->autofillClient()->textFieldDidReceiveKeyDown(WebInputElement(inputElement),
                                                                 WebKeyboardEventBuilder(*event));
     }
 
-    // Remember if backspace was pressed for the autofill.  It is not clear how to
-    // find if backspace was pressed from textFieldDidBeginEditing and
-    // textDidChangeInTextField as when these methods are called the value of the
-    // input element already contains the type character.
-    m_backspaceOrDeletePressed = event->keyCode() == VKEY_BACK || event->keyCode() == VKEY_DELETE;
-
     // The Mac code appears to use this method as a hook to implement special
     // keyboard commands specific to Safari's auto-fill implementation.  We
     // just return false to allow the default action.
@@ -841,6 +700,12 @@ void EditorClientImpl::textDidChangeInTextArea(Element*)
 {
 }
 
+bool EditorClientImpl::shouldEraseMarkersAfterChangeSelection(TextCheckingType type) const
+{
+    const Frame* frame = m_webView->focusedWebCoreFrame();
+    return !frame || !frame->settings() || (!frame->settings()->asynchronousSpellCheckingEnabled() && !frame->settings()->unifiedTextCheckerEnabled());
+}
+
 void EditorClientImpl::ignoreWordInSpellDocument(const String&)
 {
     notImplemented();
@@ -861,8 +726,8 @@ void EditorClientImpl::checkSpellingOfString(const UChar* text, int length,
     int spellLength = 0;
 
     // Check to see if the provided text is spelled correctly.
-    if (isContinuousSpellCheckingEnabled() && m_webView->client())
-        m_webView->client()->spellCheck(WebString(text, length), spellLocation, spellLength);
+    if (m_webView->spellCheckClient())
+        m_webView->spellCheckClient()->spellCheck(WebString(text, length), spellLocation, spellLength, 0);
     else {
         spellLocation = 0;
         spellLength = 0;
@@ -876,6 +741,14 @@ void EditorClientImpl::checkSpellingOfString(const UChar* text, int length,
         *misspellingLength = spellLength;
 }
 
+void EditorClientImpl::requestCheckingOfString(WTF::PassRefPtr<WebCore::TextCheckingRequest> request)
+{
+    if (m_webView->spellCheckClient()) {
+        String text = request->data().text();
+        m_webView->spellCheckClient()->requestCheckingOfText(text, new WebTextCheckingCompletionImpl(request));
+    }
+}
+
 String EditorClientImpl::getAutoCorrectSuggestionForMisspelledWord(const String& misspelledWord)
 {
     if (!(isContinuousSpellCheckingEnabled() && m_webView->client()))
@@ -888,19 +761,60 @@ String EditorClientImpl::getAutoCorrectSuggestionForMisspelledWord(const String&
             return String();
     }
 
-    return m_webView->client()->autoCorrectWord(WebString(misspelledWord));
+    if (m_webView->spellCheckClient())
+        return m_webView->spellCheckClient()->autoCorrectWord(WebString(misspelledWord));
+    return String();
 }
 
-void EditorClientImpl::checkGrammarOfString(const UChar*, int length,
-                                            WTF::Vector<GrammarDetail>&,
-                                            int* badGrammarLocation,
-                                            int* badGrammarLength)
+void EditorClientImpl::checkGrammarOfString(const UChar* text, int length, WTF::Vector<GrammarDetail>& details, int* badGrammarLocation, int* badGrammarLength)
 {
-    notImplemented();
     if (badGrammarLocation)
-        *badGrammarLocation = 0;
+        *badGrammarLocation = -1;
     if (badGrammarLength)
         *badGrammarLength = 0;
+
+    if (!m_webView->spellCheckClient())
+        return;
+    WebVector<WebTextCheckingResult> webResults;
+    m_webView->spellCheckClient()->checkTextOfParagraph(WebString(text, length), WebTextCheckingTypeGrammar, &webResults);
+    if (!webResults.size())
+        return;
+
+    // Convert a list of WebTextCheckingResults to a list of GrammarDetails. If
+    // the converted vector of GrammarDetails has grammar errors, we set
+    // badGrammarLocation and badGrammarLength to tell WebKit that the input
+    // text has grammar errors.
+    for (size_t i = 0; i < webResults.size(); ++i) {
+        if (webResults[i].type == WebTextCheckingTypeGrammar) {
+            GrammarDetail detail;
+            detail.location = webResults[i].location;
+            detail.length = webResults[i].length;
+            detail.userDescription = webResults[i].replacement;
+            details.append(detail);
+        }
+    }
+    if (!details.size())
+        return;
+    if (badGrammarLocation)
+        *badGrammarLocation = 0;
+    if (badGrammarLength)
+        *badGrammarLength = length;
+}
+
+void EditorClientImpl::checkTextOfParagraph(const UChar* text, int length,
+                                            TextCheckingTypeMask mask,
+                                            WTF::Vector<TextCheckingResult>& results)
+{
+    if (!m_webView->spellCheckClient())
+        return;
+
+    WebTextCheckingTypeMask webMask = static_cast<WebTextCheckingTypeMask>(mask);
+    WebVector<WebTextCheckingResult> webResults;
+    m_webView->spellCheckClient()->checkTextOfParagraph(WebString(text, length), webMask, &webResults);
+
+    results.resize(webResults.size());
+    for (size_t i = 0; i < webResults.size(); ++i)
+        results[i] = webResults[i];
 }
 
 void EditorClientImpl::updateSpellingUIWithGrammarString(const String&,
@@ -911,20 +825,20 @@ void EditorClientImpl::updateSpellingUIWithGrammarString(const String&,
 
 void EditorClientImpl::updateSpellingUIWithMisspelledWord(const String& misspelledWord)
 {
-    if (m_webView->client())
-        m_webView->client()->updateSpellingUIWithMisspelledWord(WebString(misspelledWord));
+    if (m_webView->spellCheckClient())
+        m_webView->spellCheckClient()->updateSpellingUIWithMisspelledWord(WebString(misspelledWord));
 }
 
 void EditorClientImpl::showSpellingUI(bool show)
 {
-    if (m_webView->client())
-        m_webView->client()->showSpellingUI(show);
+    if (m_webView->spellCheckClient())
+        m_webView->spellCheckClient()->showSpellingUI(show);
 }
 
 bool EditorClientImpl::spellingUIIsShowing()
 {
-    if (m_webView->client())
-        return m_webView->client()->isShowingSpellingUI();
+    if (m_webView->spellCheckClient())
+        return m_webView->spellCheckClient()->isShowingSpellingUI();
     return false;
 }
 
@@ -935,6 +849,15 @@ void EditorClientImpl::getGuessesForWord(const String& word,
     notImplemented();
 }
 
+bool EditorClientImpl::supportsGlobalSelection()
+{
+#if OS(UNIX) && !OS(DARWIN)
+    return true;
+#else
+    return false;
+#endif
+}
+
 void EditorClientImpl::willSetInputMethodState()
 {
     if (m_webView->client())