Home | History | Annotate | Download | only in WebCoreSupport
      1 /*
      2  * Copyright (C) 2010 Apple Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
     14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
     17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     23  * THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 #include "WebEditorClient.h"
     28 
     29 #include "EditorState.h"
     30 #include "WebCoreArgumentCoders.h"
     31 #include "WebFrameLoaderClient.h"
     32 #include "WebPage.h"
     33 #include "WebPageProxy.h"
     34 #include "WebPageProxyMessages.h"
     35 #include "WebProcess.h"
     36 #include <WebCore/ArchiveResource.h>
     37 #include <WebCore/DocumentFragment.h>
     38 #include <WebCore/EditCommand.h>
     39 #include <WebCore/FocusController.h>
     40 #include <WebCore/Frame.h>
     41 #include <WebCore/HTMLInputElement.h>
     42 #include <WebCore/HTMLNames.h>
     43 #include <WebCore/HTMLTextAreaElement.h>
     44 #include <WebCore/KeyboardEvent.h>
     45 #include <WebCore/NotImplemented.h>
     46 #include <WebCore/Page.h>
     47 #include <WebCore/UserTypingGestureIndicator.h>
     48 
     49 using namespace WebCore;
     50 using namespace HTMLNames;
     51 
     52 namespace WebKit {
     53 
     54 void WebEditorClient::pageDestroyed()
     55 {
     56     delete this;
     57 }
     58 
     59 bool WebEditorClient::shouldDeleteRange(Range* range)
     60 {
     61     bool result = m_page->injectedBundleEditorClient().shouldDeleteRange(m_page, range);
     62     notImplemented();
     63     return result;
     64 }
     65 
     66 bool WebEditorClient::shouldShowDeleteInterface(HTMLElement*)
     67 {
     68     notImplemented();
     69     return false;
     70 }
     71 
     72 bool WebEditorClient::smartInsertDeleteEnabled()
     73 {
     74     // FIXME: Why isn't this Mac specific like toggleSmartInsertDeleteEnabled?
     75 #if PLATFORM(MAC)
     76     return m_page->isSmartInsertDeleteEnabled();
     77 #else
     78     return true;
     79 #endif
     80 }
     81 
     82 bool WebEditorClient::isSelectTrailingWhitespaceEnabled()
     83 {
     84     notImplemented();
     85     return false;
     86 }
     87 
     88 bool WebEditorClient::isContinuousSpellCheckingEnabled()
     89 {
     90     return WebProcess::shared().textCheckerState().isContinuousSpellCheckingEnabled;
     91 }
     92 
     93 void WebEditorClient::toggleContinuousSpellChecking()
     94 {
     95     notImplemented();
     96 }
     97 
     98 bool WebEditorClient::isGrammarCheckingEnabled()
     99 {
    100     return WebProcess::shared().textCheckerState().isGrammarCheckingEnabled;
    101 }
    102 
    103 void WebEditorClient::toggleGrammarChecking()
    104 {
    105     notImplemented();
    106 }
    107 
    108 int WebEditorClient::spellCheckerDocumentTag()
    109 {
    110     notImplemented();
    111     return false;
    112 }
    113 
    114 
    115 bool WebEditorClient::isEditable()
    116 {
    117     notImplemented();
    118     return false;
    119 }
    120 
    121 
    122 bool WebEditorClient::shouldBeginEditing(Range* range)
    123 {
    124     bool result = m_page->injectedBundleEditorClient().shouldBeginEditing(m_page, range);
    125     notImplemented();
    126     return result;
    127 }
    128 
    129 bool WebEditorClient::shouldEndEditing(Range* range)
    130 {
    131     bool result = m_page->injectedBundleEditorClient().shouldEndEditing(m_page, range);
    132     notImplemented();
    133     return result;
    134 }
    135 
    136 bool WebEditorClient::shouldInsertNode(Node* node, Range* rangeToReplace, EditorInsertAction action)
    137 {
    138     bool result = m_page->injectedBundleEditorClient().shouldInsertNode(m_page, node, rangeToReplace, action);
    139     notImplemented();
    140     return result;
    141 }
    142 
    143 bool WebEditorClient::shouldInsertText(const String& text, Range* rangeToReplace, EditorInsertAction action)
    144 {
    145     bool result = m_page->injectedBundleEditorClient().shouldInsertText(m_page, text.impl(), rangeToReplace, action);
    146     notImplemented();
    147     return result;
    148 }
    149 
    150 bool WebEditorClient::shouldChangeSelectedRange(Range* fromRange, Range* toRange, EAffinity affinity, bool stillSelecting)
    151 {
    152     bool result = m_page->injectedBundleEditorClient().shouldChangeSelectedRange(m_page, fromRange, toRange, affinity, stillSelecting);
    153     notImplemented();
    154     return result;
    155 }
    156 
    157 bool WebEditorClient::shouldApplyStyle(CSSStyleDeclaration* style, Range* range)
    158 {
    159     bool result = m_page->injectedBundleEditorClient().shouldApplyStyle(m_page, style, range);
    160     notImplemented();
    161     return result;
    162 }
    163 
    164 bool WebEditorClient::shouldMoveRangeAfterDelete(Range*, Range*)
    165 {
    166     notImplemented();
    167     return true;
    168 }
    169 
    170 void WebEditorClient::didBeginEditing()
    171 {
    172     // FIXME: What good is a notification name, if it's always the same?
    173     DEFINE_STATIC_LOCAL(String, WebViewDidBeginEditingNotification, ("WebViewDidBeginEditingNotification"));
    174     m_page->injectedBundleEditorClient().didBeginEditing(m_page, WebViewDidBeginEditingNotification.impl());
    175     notImplemented();
    176 }
    177 
    178 void WebEditorClient::respondToChangedContents()
    179 {
    180     DEFINE_STATIC_LOCAL(String, WebViewDidChangeNotification, ("WebViewDidChangeNotification"));
    181     m_page->injectedBundleEditorClient().didChange(m_page, WebViewDidChangeNotification.impl());
    182     notImplemented();
    183 }
    184 
    185 void WebEditorClient::respondToChangedSelection()
    186 {
    187     DEFINE_STATIC_LOCAL(String, WebViewDidChangeSelectionNotification, ("WebViewDidChangeSelectionNotification"));
    188     m_page->injectedBundleEditorClient().didChangeSelection(m_page, WebViewDidChangeSelectionNotification.impl());
    189     Frame* frame = m_page->corePage()->focusController()->focusedFrame();
    190     if (!frame)
    191         return;
    192 
    193     m_page->send(Messages::WebPageProxy::EditorStateChanged(m_page->editorState()));
    194 
    195 #if PLATFORM(WIN)
    196     // FIXME: This should also go into the selection state.
    197     if (!frame->editor()->hasComposition() || frame->editor()->ignoreCompositionSelectionChange())
    198         return;
    199 
    200     unsigned start;
    201     unsigned end;
    202     m_page->send(Messages::WebPageProxy::DidChangeCompositionSelection(frame->editor()->getCompositionSelection(start, end)));
    203 #endif
    204 }
    205 
    206 void WebEditorClient::didEndEditing()
    207 {
    208     DEFINE_STATIC_LOCAL(String, WebViewDidEndEditingNotification, ("WebViewDidEndEditingNotification"));
    209     m_page->injectedBundleEditorClient().didEndEditing(m_page, WebViewDidEndEditingNotification.impl());
    210     notImplemented();
    211 }
    212 
    213 void WebEditorClient::didWriteSelectionToPasteboard()
    214 {
    215     notImplemented();
    216 }
    217 
    218 void WebEditorClient::didSetSelectionTypesForPasteboard()
    219 {
    220     notImplemented();
    221 }
    222 
    223 void WebEditorClient::registerCommandForUndo(PassRefPtr<EditCommand> command)
    224 {
    225     // FIXME: Add assertion that the command being reapplied is the same command that is
    226     // being passed to us.
    227     if (m_page->isInRedo())
    228         return;
    229 
    230     RefPtr<WebEditCommand> webCommand = WebEditCommand::create(command);
    231     m_page->addWebEditCommand(webCommand->commandID(), webCommand.get());
    232     uint32_t editAction = static_cast<uint32_t>(webCommand->command()->editingAction());
    233 
    234     m_page->send(Messages::WebPageProxy::RegisterEditCommandForUndo(webCommand->commandID(), editAction));
    235 }
    236 
    237 void WebEditorClient::registerCommandForRedo(PassRefPtr<EditCommand>)
    238 {
    239 }
    240 
    241 void WebEditorClient::clearUndoRedoOperations()
    242 {
    243     m_page->send(Messages::WebPageProxy::ClearAllEditCommands());
    244 }
    245 
    246 bool WebEditorClient::canCopyCut(bool defaultValue) const
    247 {
    248     return defaultValue;
    249 }
    250 
    251 bool WebEditorClient::canPaste(bool defaultValue) const
    252 {
    253     return defaultValue;
    254 }
    255 
    256 bool WebEditorClient::canUndo() const
    257 {
    258     bool result = false;
    259     m_page->sendSync(Messages::WebPageProxy::CanUndoRedo(static_cast<uint32_t>(WebPageProxy::Undo)), Messages::WebPageProxy::CanUndoRedo::Reply(result));
    260     return result;
    261 }
    262 
    263 bool WebEditorClient::canRedo() const
    264 {
    265     bool result = false;
    266     m_page->sendSync(Messages::WebPageProxy::CanUndoRedo(static_cast<uint32_t>(WebPageProxy::Redo)), Messages::WebPageProxy::CanUndoRedo::Reply(result));
    267     return result;
    268 }
    269 
    270 void WebEditorClient::undo()
    271 {
    272     bool result = false;
    273     m_page->sendSync(Messages::WebPageProxy::ExecuteUndoRedo(static_cast<uint32_t>(WebPageProxy::Undo)), Messages::WebPageProxy::ExecuteUndoRedo::Reply(result));
    274 }
    275 
    276 void WebEditorClient::redo()
    277 {
    278     bool result = false;
    279     m_page->sendSync(Messages::WebPageProxy::ExecuteUndoRedo(static_cast<uint32_t>(WebPageProxy::Redo)), Messages::WebPageProxy::ExecuteUndoRedo::Reply(result));
    280 }
    281 
    282 #if !PLATFORM(GTK) && !PLATFORM(MAC)
    283 void WebEditorClient::handleKeyboardEvent(KeyboardEvent* event)
    284 {
    285     if (m_page->handleEditingKeyboardEvent(event))
    286         event->setDefaultHandled();
    287 }
    288 
    289 void WebEditorClient::handleInputMethodKeydown(KeyboardEvent*)
    290 {
    291     notImplemented();
    292 }
    293 #endif
    294 
    295 void WebEditorClient::textFieldDidBeginEditing(Element* element)
    296 {
    297     if (!element->hasTagName(inputTag))
    298         return;
    299 
    300     WebFrame* webFrame =  static_cast<WebFrameLoaderClient*>(element->document()->frame()->loader()->client())->webFrame();
    301     m_page->injectedBundleFormClient().textFieldDidBeginEditing(m_page, static_cast<HTMLInputElement*>(element), webFrame);
    302 }
    303 
    304 void WebEditorClient::textFieldDidEndEditing(Element* element)
    305 {
    306     if (!element->hasTagName(inputTag))
    307         return;
    308 
    309     WebFrame* webFrame =  static_cast<WebFrameLoaderClient*>(element->document()->frame()->loader()->client())->webFrame();
    310     m_page->injectedBundleFormClient().textFieldDidEndEditing(m_page, static_cast<HTMLInputElement*>(element), webFrame);
    311 }
    312 
    313 void WebEditorClient::textDidChangeInTextField(Element* element)
    314 {
    315     if (!element->hasTagName(inputTag))
    316         return;
    317 
    318     if (!UserTypingGestureIndicator::processingUserTypingGesture() || UserTypingGestureIndicator::focusedElementAtGestureStart() != element)
    319         return;
    320 
    321     WebFrame* webFrame =  static_cast<WebFrameLoaderClient*>(element->document()->frame()->loader()->client())->webFrame();
    322     m_page->injectedBundleFormClient().textDidChangeInTextField(m_page, static_cast<HTMLInputElement*>(element), webFrame);
    323 }
    324 
    325 void WebEditorClient::textDidChangeInTextArea(Element* element)
    326 {
    327     if (!element->hasTagName(textareaTag))
    328         return;
    329 
    330     WebFrame* webFrame =  static_cast<WebFrameLoaderClient*>(element->document()->frame()->loader()->client())->webFrame();
    331     m_page->injectedBundleFormClient().textDidChangeInTextArea(m_page, static_cast<HTMLTextAreaElement*>(element), webFrame);
    332 }
    333 
    334 static bool getActionTypeForKeyEvent(KeyboardEvent* event, WKInputFieldActionType& type)
    335 {
    336     String key = event->keyIdentifier();
    337     if (key == "Up")
    338         type = WKInputFieldActionTypeMoveUp;
    339     else if (key == "Down")
    340         type = WKInputFieldActionTypeMoveDown;
    341     else if (key == "U+001B")
    342         type = WKInputFieldActionTypeCancel;
    343     else if (key == "U+0009") {
    344         if (event->shiftKey())
    345             type = WKInputFieldActionTypeInsertBacktab;
    346         else
    347             type = WKInputFieldActionTypeInsertTab;
    348     } else if (key == "Enter")
    349         type = WKInputFieldActionTypeInsertNewline;
    350     else
    351         return false;
    352 
    353     return true;
    354 }
    355 
    356 bool WebEditorClient::doTextFieldCommandFromEvent(Element* element, KeyboardEvent* event)
    357 {
    358     if (!element->hasTagName(inputTag))
    359         return false;
    360 
    361     WKInputFieldActionType actionType = static_cast<WKInputFieldActionType>(0);
    362     if (!getActionTypeForKeyEvent(event, actionType))
    363         return false;
    364 
    365     WebFrame* webFrame =  static_cast<WebFrameLoaderClient*>(element->document()->frame()->loader()->client())->webFrame();
    366     return m_page->injectedBundleFormClient().shouldPerformActionInTextField(m_page, static_cast<HTMLInputElement*>(element), actionType, webFrame);
    367 }
    368 
    369 void WebEditorClient::textWillBeDeletedInTextField(Element* element)
    370 {
    371     if (!element->hasTagName(inputTag))
    372         return;
    373 
    374     WebFrame* webFrame =  static_cast<WebFrameLoaderClient*>(element->document()->frame()->loader()->client())->webFrame();
    375     m_page->injectedBundleFormClient().shouldPerformActionInTextField(m_page, static_cast<HTMLInputElement*>(element), WKInputFieldActionTypeInsertDelete, webFrame);
    376 }
    377 
    378 void WebEditorClient::ignoreWordInSpellDocument(const String& word)
    379 {
    380     m_page->send(Messages::WebPageProxy::IgnoreWord(word));
    381 }
    382 
    383 void WebEditorClient::learnWord(const String& word)
    384 {
    385     m_page->send(Messages::WebPageProxy::LearnWord(word));
    386 }
    387 
    388 void WebEditorClient::checkSpellingOfString(const UChar* text, int length, int* misspellingLocation, int* misspellingLength)
    389 {
    390     int32_t resultLocation = -1;
    391     int32_t resultLength = 0;
    392     // FIXME: It would be nice if we wouldn't have to copy the text here.
    393     m_page->sendSync(Messages::WebPageProxy::CheckSpellingOfString(String(text, length)),
    394         Messages::WebPageProxy::CheckSpellingOfString::Reply(resultLocation, resultLength));
    395     *misspellingLocation = resultLocation;
    396     *misspellingLength = resultLength;
    397 }
    398 
    399 String WebEditorClient::getAutoCorrectSuggestionForMisspelledWord(const String&)
    400 {
    401     notImplemented();
    402     return String();
    403 }
    404 
    405 void WebEditorClient::checkGrammarOfString(const UChar* text, int length, Vector<WebCore::GrammarDetail>& grammarDetails, int* badGrammarLocation, int* badGrammarLength)
    406 {
    407     int32_t resultLocation = -1;
    408     int32_t resultLength = 0;
    409     // FIXME: It would be nice if we wouldn't have to copy the text here.
    410     m_page->sendSync(Messages::WebPageProxy::CheckGrammarOfString(String(text, length)),
    411         Messages::WebPageProxy::CheckGrammarOfString::Reply(grammarDetails, resultLocation, resultLength));
    412     *badGrammarLocation = resultLocation;
    413     *badGrammarLength = resultLength;
    414 }
    415 
    416 void WebEditorClient::updateSpellingUIWithGrammarString(const String& badGrammarPhrase, const GrammarDetail& grammarDetail)
    417 {
    418     m_page->send(Messages::WebPageProxy::UpdateSpellingUIWithGrammarString(badGrammarPhrase, grammarDetail));
    419 }
    420 
    421 void WebEditorClient::updateSpellingUIWithMisspelledWord(const String& misspelledWord)
    422 {
    423     m_page->send(Messages::WebPageProxy::UpdateSpellingUIWithMisspelledWord(misspelledWord));
    424 }
    425 
    426 void WebEditorClient::showSpellingUI(bool)
    427 {
    428     notImplemented();
    429 }
    430 
    431 bool WebEditorClient::spellingUIIsShowing()
    432 {
    433     bool isShowing = false;
    434     m_page->sendSync(Messages::WebPageProxy::SpellingUIIsShowing(), Messages::WebPageProxy::SpellingUIIsShowing::Reply(isShowing));
    435     return isShowing;
    436 }
    437 
    438 void WebEditorClient::getGuessesForWord(const String& word, const String& context, Vector<String>& guesses)
    439 {
    440     m_page->sendSync(Messages::WebPageProxy::GetGuessesForWord(word, context), Messages::WebPageProxy::GetGuessesForWord::Reply(guesses));
    441 }
    442 
    443 void WebEditorClient::willSetInputMethodState()
    444 {
    445     notImplemented();
    446 }
    447 
    448 void WebEditorClient::setInputMethodState(bool)
    449 {
    450     notImplemented();
    451 }
    452 
    453 void WebEditorClient::requestCheckingOfString(WebCore::SpellChecker*, int, WebCore::TextCheckingTypeMask, const WTF::String&)
    454 {
    455     notImplemented();
    456 }
    457 
    458 } // namespace WebKit
    459