Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2006, 2007 Apple, Inc.  All rights reserved.
      3  * Copyright (C) 2010 Google, Inc.  All rights reserved.
      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 "EditorClientImpl.h"
     29 
     30 #include "Document.h"
     31 #include "EditCommand.h"
     32 #include "Editor.h"
     33 #include "EventHandler.h"
     34 #include "EventNames.h"
     35 #include "Frame.h"
     36 #include "HTMLInputElement.h"
     37 #include "HTMLNames.h"
     38 #include "KeyboardCodes.h"
     39 #include "KeyboardEvent.h"
     40 #include "PlatformKeyboardEvent.h"
     41 #include "PlatformString.h"
     42 #include "RenderObject.h"
     43 #include "SpellChecker.h"
     44 
     45 #include "DOMUtilitiesPrivate.h"
     46 #include "WebAutoFillClient.h"
     47 #include "WebEditingAction.h"
     48 #include "WebElement.h"
     49 #include "WebFrameClient.h"
     50 #include "WebFrameImpl.h"
     51 #include "WebKit.h"
     52 #include "WebInputElement.h"
     53 #include "WebInputEventConversion.h"
     54 #include "WebNode.h"
     55 #include "WebPasswordAutocompleteListener.h"
     56 #include "WebRange.h"
     57 #include "WebSpellCheckClient.h"
     58 #include "WebTextAffinity.h"
     59 #include "WebTextCheckingCompletionImpl.h"
     60 #include "WebViewClient.h"
     61 #include "WebViewImpl.h"
     62 
     63 using namespace WebCore;
     64 
     65 namespace WebKit {
     66 
     67 // Arbitrary depth limit for the undo stack, to keep it from using
     68 // unbounded memory.  This is the maximum number of distinct undoable
     69 // actions -- unbroken stretches of typed characters are coalesced
     70 // into a single action.
     71 static const size_t maximumUndoStackDepth = 1000;
     72 
     73 // The size above which we stop triggering autofill for an input text field
     74 // (so to avoid sending long strings through IPC).
     75 static const size_t maximumTextSizeForAutofill = 1000;
     76 
     77 EditorClientImpl::EditorClientImpl(WebViewImpl* webview)
     78     : m_webView(webview)
     79     , m_inRedo(false)
     80     , m_backspaceOrDeletePressed(false)
     81     , m_spellCheckThisFieldStatus(SpellCheckAutomatic)
     82     , m_autofillTimer(this, &EditorClientImpl::doAutofill)
     83 {
     84 }
     85 
     86 EditorClientImpl::~EditorClientImpl()
     87 {
     88 }
     89 
     90 void EditorClientImpl::pageDestroyed()
     91 {
     92     // Our lifetime is bound to the WebViewImpl.
     93 }
     94 
     95 bool EditorClientImpl::shouldShowDeleteInterface(HTMLElement* elem)
     96 {
     97     // Normally, we don't care to show WebCore's deletion UI, so we only enable
     98     // it if in testing mode and the test specifically requests it by using this
     99     // magic class name.
    100     return layoutTestMode()
    101            && elem->getAttribute(HTMLNames::classAttr) == "needsDeletionUI";
    102 }
    103 
    104 bool EditorClientImpl::smartInsertDeleteEnabled()
    105 {
    106     if (m_webView->client())
    107         return m_webView->client()->isSmartInsertDeleteEnabled();
    108     return true;
    109 }
    110 
    111 bool EditorClientImpl::isSelectTrailingWhitespaceEnabled()
    112 {
    113     if (m_webView->client())
    114         return m_webView->client()->isSelectTrailingWhitespaceEnabled();
    115 #if OS(WINDOWS)
    116     return true;
    117 #else
    118     return false;
    119 #endif
    120 }
    121 
    122 bool EditorClientImpl::shouldSpellcheckByDefault()
    123 {
    124     // Spellcheck should be enabled for all editable areas (such as textareas,
    125     // contentEditable regions, and designMode docs), except text inputs.
    126     const Frame* frame = m_webView->focusedWebCoreFrame();
    127     if (!frame)
    128         return false;
    129     const Editor* editor = frame->editor();
    130     if (!editor)
    131         return false;
    132     if (editor->isSpellCheckingEnabledInFocusedNode())
    133         return true;
    134     const Document* document = frame->document();
    135     if (!document)
    136         return false;
    137     const Node* node = document->focusedNode();
    138     // If |node| is null, we default to allowing spellchecking. This is done in
    139     // order to mitigate the issue when the user clicks outside the textbox, as a
    140     // result of which |node| becomes null, resulting in all the spell check
    141     // markers being deleted. Also, the Frame will decide not to do spellchecking
    142     // if the user can't edit - so returning true here will not cause any problems
    143     // to the Frame's behavior.
    144     if (!node)
    145         return true;
    146     const RenderObject* renderer = node->renderer();
    147     if (!renderer)
    148         return false;
    149 
    150     return !renderer->isTextField();
    151 }
    152 
    153 bool EditorClientImpl::isContinuousSpellCheckingEnabled()
    154 {
    155     if (m_spellCheckThisFieldStatus == SpellCheckForcedOff)
    156         return false;
    157     if (m_spellCheckThisFieldStatus == SpellCheckForcedOn)
    158         return true;
    159     return shouldSpellcheckByDefault();
    160 }
    161 
    162 void EditorClientImpl::toggleContinuousSpellChecking()
    163 {
    164     if (isContinuousSpellCheckingEnabled())
    165         m_spellCheckThisFieldStatus = SpellCheckForcedOff;
    166     else
    167         m_spellCheckThisFieldStatus = SpellCheckForcedOn;
    168 
    169     WebFrameImpl* webframe = WebFrameImpl::fromFrame(
    170         m_webView->focusedWebCoreFrame());
    171     if (webframe)
    172         webframe->client()->didToggleContinuousSpellChecking(webframe);
    173 }
    174 
    175 bool EditorClientImpl::isGrammarCheckingEnabled()
    176 {
    177     return false;
    178 }
    179 
    180 void EditorClientImpl::toggleGrammarChecking()
    181 {
    182     notImplemented();
    183 }
    184 
    185 int EditorClientImpl::spellCheckerDocumentTag()
    186 {
    187     ASSERT_NOT_REACHED();
    188     return 0;
    189 }
    190 
    191 bool EditorClientImpl::shouldBeginEditing(Range* range)
    192 {
    193     if (m_webView->client())
    194         return m_webView->client()->shouldBeginEditing(WebRange(range));
    195     return true;
    196 }
    197 
    198 bool EditorClientImpl::shouldEndEditing(Range* range)
    199 {
    200     if (m_webView->client())
    201         return m_webView->client()->shouldEndEditing(WebRange(range));
    202     return true;
    203 }
    204 
    205 bool EditorClientImpl::shouldInsertNode(Node* node,
    206                                         Range* range,
    207                                         EditorInsertAction action)
    208 {
    209     if (m_webView->client()) {
    210         return m_webView->client()->shouldInsertNode(WebNode(node),
    211                                                      WebRange(range),
    212                                                      static_cast<WebEditingAction>(action));
    213     }
    214     return true;
    215 }
    216 
    217 bool EditorClientImpl::shouldInsertText(const String& text,
    218                                         Range* range,
    219                                         EditorInsertAction action)
    220 {
    221     if (m_webView->client()) {
    222         return m_webView->client()->shouldInsertText(WebString(text),
    223                                                      WebRange(range),
    224                                                      static_cast<WebEditingAction>(action));
    225     }
    226     return true;
    227 }
    228 
    229 
    230 bool EditorClientImpl::shouldDeleteRange(Range* range)
    231 {
    232     if (m_webView->client())
    233         return m_webView->client()->shouldDeleteRange(WebRange(range));
    234     return true;
    235 }
    236 
    237 bool EditorClientImpl::shouldChangeSelectedRange(Range* fromRange,
    238                                                  Range* toRange,
    239                                                  EAffinity affinity,
    240                                                  bool stillSelecting)
    241 {
    242     if (m_webView->client()) {
    243         return m_webView->client()->shouldChangeSelectedRange(WebRange(fromRange),
    244                                                               WebRange(toRange),
    245                                                               static_cast<WebTextAffinity>(affinity),
    246                                                               stillSelecting);
    247     }
    248     return true;
    249 }
    250 
    251 bool EditorClientImpl::shouldApplyStyle(CSSStyleDeclaration* style,
    252                                         Range* range)
    253 {
    254     if (m_webView->client()) {
    255         // FIXME: Pass a reference to the CSSStyleDeclaration somehow.
    256         return m_webView->client()->shouldApplyStyle(WebString(),
    257                                                      WebRange(range));
    258     }
    259     return true;
    260 }
    261 
    262 bool EditorClientImpl::shouldMoveRangeAfterDelete(Range* range,
    263                                                   Range* rangeToBeReplaced)
    264 {
    265     return true;
    266 }
    267 
    268 void EditorClientImpl::didBeginEditing()
    269 {
    270     if (m_webView->client())
    271         m_webView->client()->didBeginEditing();
    272 }
    273 
    274 void EditorClientImpl::respondToChangedSelection()
    275 {
    276     if (m_webView->client()) {
    277         Frame* frame = m_webView->focusedWebCoreFrame();
    278         if (frame)
    279             m_webView->client()->didChangeSelection(!frame->selection()->isRange());
    280     }
    281 }
    282 
    283 void EditorClientImpl::respondToChangedContents()
    284 {
    285     if (m_webView->client())
    286         m_webView->client()->didChangeContents();
    287 }
    288 
    289 void EditorClientImpl::didEndEditing()
    290 {
    291     if (m_webView->client())
    292         m_webView->client()->didEndEditing();
    293 }
    294 
    295 void EditorClientImpl::didWriteSelectionToPasteboard()
    296 {
    297 }
    298 
    299 void EditorClientImpl::didSetSelectionTypesForPasteboard()
    300 {
    301 }
    302 
    303 void EditorClientImpl::registerCommandForUndo(PassRefPtr<EditCommand> command)
    304 {
    305     if (m_undoStack.size() == maximumUndoStackDepth)
    306         m_undoStack.removeFirst(); // drop oldest item off the far end
    307     if (!m_inRedo)
    308         m_redoStack.clear();
    309     m_undoStack.append(command);
    310 }
    311 
    312 void EditorClientImpl::registerCommandForRedo(PassRefPtr<EditCommand> command)
    313 {
    314     m_redoStack.append(command);
    315 }
    316 
    317 void EditorClientImpl::clearUndoRedoOperations()
    318 {
    319     m_undoStack.clear();
    320     m_redoStack.clear();
    321 }
    322 
    323 bool EditorClientImpl::canCopyCut(bool defaultValue) const
    324 {
    325     return defaultValue;
    326 }
    327 
    328 bool EditorClientImpl::canPaste(bool defaultValue) const
    329 {
    330     return defaultValue;
    331 }
    332 
    333 bool EditorClientImpl::canUndo() const
    334 {
    335     return !m_undoStack.isEmpty();
    336 }
    337 
    338 bool EditorClientImpl::canRedo() const
    339 {
    340     return !m_redoStack.isEmpty();
    341 }
    342 
    343 void EditorClientImpl::undo()
    344 {
    345     if (canUndo()) {
    346         EditCommandStack::iterator back = --m_undoStack.end();
    347         RefPtr<EditCommand> command(*back);
    348         m_undoStack.remove(back);
    349         command->unapply();
    350         // unapply will call us back to push this command onto the redo stack.
    351     }
    352 }
    353 
    354 void EditorClientImpl::redo()
    355 {
    356     if (canRedo()) {
    357         EditCommandStack::iterator back = --m_redoStack.end();
    358         RefPtr<EditCommand> command(*back);
    359         m_redoStack.remove(back);
    360 
    361         ASSERT(!m_inRedo);
    362         m_inRedo = true;
    363         command->reapply();
    364         // reapply will call us back to push this command onto the undo stack.
    365         m_inRedo = false;
    366     }
    367 }
    368 
    369 //
    370 // The below code was adapted from the WebKit file webview.cpp
    371 //
    372 
    373 static const unsigned CtrlKey = 1 << 0;
    374 static const unsigned AltKey = 1 << 1;
    375 static const unsigned ShiftKey = 1 << 2;
    376 static const unsigned MetaKey = 1 << 3;
    377 #if OS(DARWIN)
    378 // Aliases for the generic key defintions to make kbd shortcuts definitions more
    379 // readable on OS X.
    380 static const unsigned OptionKey  = AltKey;
    381 
    382 // Do not use this constant for anything but cursor movement commands. Keys
    383 // with cmd set have their |isSystemKey| bit set, so chances are the shortcut
    384 // will not be executed. Another, less important, reason is that shortcuts
    385 // defined in the renderer do not blink the menu item that they triggered.  See
    386 // http://crbug.com/25856 and the bugs linked from there for details.
    387 static const unsigned CommandKey = MetaKey;
    388 #endif
    389 
    390 // Keys with special meaning. These will be delegated to the editor using
    391 // the execCommand() method
    392 struct KeyDownEntry {
    393     unsigned virtualKey;
    394     unsigned modifiers;
    395     const char* name;
    396 };
    397 
    398 struct KeyPressEntry {
    399     unsigned charCode;
    400     unsigned modifiers;
    401     const char* name;
    402 };
    403 
    404 static const KeyDownEntry keyDownEntries[] = {
    405     { VKEY_LEFT,   0,                  "MoveLeft"                             },
    406     { VKEY_LEFT,   ShiftKey,           "MoveLeftAndModifySelection"           },
    407 #if OS(DARWIN)
    408     { VKEY_LEFT,   OptionKey,          "MoveWordLeft"                         },
    409     { VKEY_LEFT,   OptionKey | ShiftKey,
    410         "MoveWordLeftAndModifySelection"                                      },
    411 #else
    412     { VKEY_LEFT,   CtrlKey,            "MoveWordLeft"                         },
    413     { VKEY_LEFT,   CtrlKey | ShiftKey,
    414         "MoveWordLeftAndModifySelection"                                      },
    415 #endif
    416     { VKEY_RIGHT,  0,                  "MoveRight"                            },
    417     { VKEY_RIGHT,  ShiftKey,           "MoveRightAndModifySelection"          },
    418 #if OS(DARWIN)
    419     { VKEY_RIGHT,  OptionKey,          "MoveWordRight"                        },
    420     { VKEY_RIGHT,  OptionKey | ShiftKey,
    421       "MoveWordRightAndModifySelection"                                       },
    422 #else
    423     { VKEY_RIGHT,  CtrlKey,            "MoveWordRight"                        },
    424     { VKEY_RIGHT,  CtrlKey | ShiftKey,
    425       "MoveWordRightAndModifySelection"                                       },
    426 #endif
    427     { VKEY_UP,     0,                  "MoveUp"                               },
    428     { VKEY_UP,     ShiftKey,           "MoveUpAndModifySelection"             },
    429     { VKEY_PRIOR,  ShiftKey,           "MovePageUpAndModifySelection"         },
    430     { VKEY_DOWN,   0,                  "MoveDown"                             },
    431     { VKEY_DOWN,   ShiftKey,           "MoveDownAndModifySelection"           },
    432     { VKEY_NEXT,   ShiftKey,           "MovePageDownAndModifySelection"       },
    433 #if !OS(DARWIN)
    434     { VKEY_PRIOR,  0,                  "MovePageUp"                           },
    435     { VKEY_NEXT,   0,                  "MovePageDown"                         },
    436 #endif
    437     { VKEY_HOME,   0,                  "MoveToBeginningOfLine"                },
    438     { VKEY_HOME,   ShiftKey,
    439         "MoveToBeginningOfLineAndModifySelection"                             },
    440 #if OS(DARWIN)
    441     { VKEY_LEFT,   CommandKey,         "MoveToBeginningOfLine"                },
    442     { VKEY_LEFT,   CommandKey | ShiftKey,
    443       "MoveToBeginningOfLineAndModifySelection"                               },
    444     { VKEY_PRIOR,  OptionKey,          "MovePageUp"                           },
    445     { VKEY_NEXT,   OptionKey,          "MovePageDown"                         },
    446 #endif
    447 #if OS(DARWIN)
    448     { VKEY_UP,     CommandKey,         "MoveToBeginningOfDocument"            },
    449     { VKEY_UP,     CommandKey | ShiftKey,
    450         "MoveToBeginningOfDocumentAndModifySelection"                         },
    451 #else
    452     { VKEY_HOME,   CtrlKey,            "MoveToBeginningOfDocument"            },
    453     { VKEY_HOME,   CtrlKey | ShiftKey,
    454         "MoveToBeginningOfDocumentAndModifySelection"                         },
    455 #endif
    456     { VKEY_END,    0,                  "MoveToEndOfLine"                      },
    457     { VKEY_END,    ShiftKey,           "MoveToEndOfLineAndModifySelection"    },
    458 #if OS(DARWIN)
    459     { VKEY_DOWN,   CommandKey,         "MoveToEndOfDocument"                  },
    460     { VKEY_DOWN,   CommandKey | ShiftKey,
    461         "MoveToEndOfDocumentAndModifySelection"                               },
    462 #else
    463     { VKEY_END,    CtrlKey,            "MoveToEndOfDocument"                  },
    464     { VKEY_END,    CtrlKey | ShiftKey,
    465         "MoveToEndOfDocumentAndModifySelection"                               },
    466 #endif
    467 #if OS(DARWIN)
    468     { VKEY_RIGHT,  CommandKey,         "MoveToEndOfLine"                      },
    469     { VKEY_RIGHT,  CommandKey | ShiftKey,
    470         "MoveToEndOfLineAndModifySelection"                                   },
    471 #endif
    472     { VKEY_BACK,   0,                  "DeleteBackward"                       },
    473     { VKEY_BACK,   ShiftKey,           "DeleteBackward"                       },
    474     { VKEY_DELETE, 0,                  "DeleteForward"                        },
    475 #if OS(DARWIN)
    476     { VKEY_BACK,   OptionKey,          "DeleteWordBackward"                   },
    477     { VKEY_DELETE, OptionKey,          "DeleteWordForward"                    },
    478 #else
    479     { VKEY_BACK,   CtrlKey,            "DeleteWordBackward"                   },
    480     { VKEY_DELETE, CtrlKey,            "DeleteWordForward"                    },
    481 #endif
    482     { 'B',         CtrlKey,            "ToggleBold"                           },
    483     { 'I',         CtrlKey,            "ToggleItalic"                         },
    484     { 'U',         CtrlKey,            "ToggleUnderline"                      },
    485     { VKEY_ESCAPE, 0,                  "Cancel"                               },
    486     { VKEY_OEM_PERIOD, CtrlKey,        "Cancel"                               },
    487     { VKEY_TAB,    0,                  "InsertTab"                            },
    488     { VKEY_TAB,    ShiftKey,           "InsertBacktab"                        },
    489     { VKEY_RETURN, 0,                  "InsertNewline"                        },
    490     { VKEY_RETURN, CtrlKey,            "InsertNewline"                        },
    491     { VKEY_RETURN, AltKey,             "InsertNewline"                        },
    492     { VKEY_RETURN, AltKey | ShiftKey,  "InsertNewline"                        },
    493     { VKEY_RETURN, ShiftKey,           "InsertLineBreak"                      },
    494     { VKEY_INSERT, CtrlKey,            "Copy"                                 },
    495     { VKEY_INSERT, ShiftKey,           "Paste"                                },
    496     { VKEY_DELETE, ShiftKey,           "Cut"                                  },
    497 #if !OS(DARWIN)
    498     // On OS X, we pipe these back to the browser, so that it can do menu item
    499     // blinking.
    500     { 'C',         CtrlKey,            "Copy"                                 },
    501     { 'V',         CtrlKey,            "Paste"                                },
    502     { 'V',         CtrlKey | ShiftKey, "PasteAndMatchStyle"                   },
    503     { 'X',         CtrlKey,            "Cut"                                  },
    504     { 'A',         CtrlKey,            "SelectAll"                            },
    505     { 'Z',         CtrlKey,            "Undo"                                 },
    506     { 'Z',         CtrlKey | ShiftKey, "Redo"                                 },
    507     { 'Y',         CtrlKey,            "Redo"                                 },
    508 #endif
    509 };
    510 
    511 static const KeyPressEntry keyPressEntries[] = {
    512     { '\t',   0,                  "InsertTab"                                 },
    513     { '\t',   ShiftKey,           "InsertBacktab"                             },
    514     { '\r',   0,                  "InsertNewline"                             },
    515     { '\r',   CtrlKey,            "InsertNewline"                             },
    516     { '\r',   ShiftKey,           "InsertLineBreak"                           },
    517     { '\r',   AltKey,             "InsertNewline"                             },
    518     { '\r',   AltKey | ShiftKey,  "InsertNewline"                             },
    519 };
    520 
    521 const char* EditorClientImpl::interpretKeyEvent(const KeyboardEvent* evt)
    522 {
    523     const PlatformKeyboardEvent* keyEvent = evt->keyEvent();
    524     if (!keyEvent)
    525         return "";
    526 
    527     static HashMap<int, const char*>* keyDownCommandsMap = 0;
    528     static HashMap<int, const char*>* keyPressCommandsMap = 0;
    529 
    530     if (!keyDownCommandsMap) {
    531         keyDownCommandsMap = new HashMap<int, const char*>;
    532         keyPressCommandsMap = new HashMap<int, const char*>;
    533 
    534         for (unsigned i = 0; i < arraysize(keyDownEntries); i++) {
    535             keyDownCommandsMap->set(keyDownEntries[i].modifiers << 16 | keyDownEntries[i].virtualKey,
    536                                     keyDownEntries[i].name);
    537         }
    538 
    539         for (unsigned i = 0; i < arraysize(keyPressEntries); i++) {
    540             keyPressCommandsMap->set(keyPressEntries[i].modifiers << 16 | keyPressEntries[i].charCode,
    541                                      keyPressEntries[i].name);
    542         }
    543     }
    544 
    545     unsigned modifiers = 0;
    546     if (keyEvent->shiftKey())
    547         modifiers |= ShiftKey;
    548     if (keyEvent->altKey())
    549         modifiers |= AltKey;
    550     if (keyEvent->ctrlKey())
    551         modifiers |= CtrlKey;
    552     if (keyEvent->metaKey())
    553         modifiers |= MetaKey;
    554 
    555     if (keyEvent->type() == PlatformKeyboardEvent::RawKeyDown) {
    556         int mapKey = modifiers << 16 | evt->keyCode();
    557         return mapKey ? keyDownCommandsMap->get(mapKey) : 0;
    558     }
    559 
    560     int mapKey = modifiers << 16 | evt->charCode();
    561     return mapKey ? keyPressCommandsMap->get(mapKey) : 0;
    562 }
    563 
    564 bool EditorClientImpl::handleEditingKeyboardEvent(KeyboardEvent* evt)
    565 {
    566     const PlatformKeyboardEvent* keyEvent = evt->keyEvent();
    567     // do not treat this as text input if it's a system key event
    568     if (!keyEvent || keyEvent->isSystemKey())
    569         return false;
    570 
    571     Frame* frame = evt->target()->toNode()->document()->frame();
    572     if (!frame)
    573         return false;
    574 
    575     String commandName = interpretKeyEvent(evt);
    576     Editor::Command command = frame->editor()->command(commandName);
    577 
    578     if (keyEvent->type() == PlatformKeyboardEvent::RawKeyDown) {
    579         // WebKit doesn't have enough information about mode to decide how
    580         // commands that just insert text if executed via Editor should be treated,
    581         // so we leave it upon WebCore to either handle them immediately
    582         // (e.g. Tab that changes focus) or let a keypress event be generated
    583         // (e.g. Tab that inserts a Tab character, or Enter).
    584         if (command.isTextInsertion() || commandName.isEmpty())
    585             return false;
    586         if (command.execute(evt)) {
    587             if (m_webView->client())
    588                 m_webView->client()->didExecuteCommand(WebString(commandName));
    589             return true;
    590         }
    591         return false;
    592     }
    593 
    594     if (command.execute(evt)) {
    595         if (m_webView->client())
    596             m_webView->client()->didExecuteCommand(WebString(commandName));
    597         return true;
    598     }
    599 
    600     // Here we need to filter key events.
    601     // On Gtk/Linux, it emits key events with ASCII text and ctrl on for ctrl-<x>.
    602     // In Webkit, EditorClient::handleKeyboardEvent in
    603     // WebKit/gtk/WebCoreSupport/EditorClientGtk.cpp drop such events.
    604     // On Mac, it emits key events with ASCII text and meta on for Command-<x>.
    605     // These key events should not emit text insert event.
    606     // Alt key would be used to insert alternative character, so we should let
    607     // through. Also note that Ctrl-Alt combination equals to AltGr key which is
    608     // also used to insert alternative character.
    609     // http://code.google.com/p/chromium/issues/detail?id=10846
    610     // Windows sets both alt and meta are on when "Alt" key pressed.
    611     // http://code.google.com/p/chromium/issues/detail?id=2215
    612     // Also, we should not rely on an assumption that keyboards don't
    613     // send ASCII characters when pressing a control key on Windows,
    614     // which may be configured to do it so by user.
    615     // See also http://en.wikipedia.org/wiki/Keyboard_Layout
    616     // FIXME(ukai): investigate more detail for various keyboard layout.
    617     if (evt->keyEvent()->text().length() == 1) {
    618         UChar ch = evt->keyEvent()->text()[0U];
    619 
    620         // Don't insert null or control characters as they can result in
    621         // unexpected behaviour
    622         if (ch < ' ')
    623             return false;
    624 #if !OS(WINDOWS)
    625         // Don't insert ASCII character if ctrl w/o alt or meta is on.
    626         // On Mac, we should ignore events when meta is on (Command-<x>).
    627         if (ch < 0x80) {
    628             if (evt->keyEvent()->ctrlKey() && !evt->keyEvent()->altKey())
    629                 return false;
    630 #if OS(DARWIN)
    631             if (evt->keyEvent()->metaKey())
    632             return false;
    633 #endif
    634         }
    635 #endif
    636     }
    637 
    638     if (!frame->editor()->canEdit())
    639         return false;
    640 
    641     return frame->editor()->insertText(evt->keyEvent()->text(), evt);
    642 }
    643 
    644 void EditorClientImpl::handleKeyboardEvent(KeyboardEvent* evt)
    645 {
    646     if (evt->keyCode() == VKEY_DOWN
    647         || evt->keyCode() == VKEY_UP) {
    648         ASSERT(evt->target()->toNode());
    649         showFormAutofillForNode(evt->target()->toNode());
    650     }
    651 
    652     // Give the embedder a chance to handle the keyboard event.
    653     if ((m_webView->client()
    654          && m_webView->client()->handleCurrentKeyboardEvent())
    655         || handleEditingKeyboardEvent(evt))
    656         evt->setDefaultHandled();
    657 }
    658 
    659 void EditorClientImpl::handleInputMethodKeydown(KeyboardEvent* keyEvent)
    660 {
    661     // We handle IME within chrome.
    662 }
    663 
    664 void EditorClientImpl::textFieldDidBeginEditing(Element* element)
    665 {
    666     HTMLInputElement* inputElement = toHTMLInputElement(element);
    667     if (m_webView->autoFillClient() && inputElement)
    668         m_webView->autoFillClient()->textFieldDidBeginEditing(WebInputElement(inputElement));
    669 }
    670 
    671 void EditorClientImpl::textFieldDidEndEditing(Element* element)
    672 {
    673     HTMLInputElement* inputElement = toHTMLInputElement(element);
    674     if (m_webView->autoFillClient() && inputElement)
    675         m_webView->autoFillClient()->textFieldDidEndEditing(WebInputElement(inputElement));
    676 
    677     // Notification that focus was lost.  Be careful with this, it's also sent
    678     // when the page is being closed.
    679 
    680     // Cancel any pending DoAutofill call.
    681     m_autofillArgs.clear();
    682     m_autofillTimer.stop();
    683 
    684     // Hide any showing popup.
    685     m_webView->hideAutoFillPopup();
    686 
    687     if (!m_webView->client())
    688         return; // The page is getting closed, don't fill the password.
    689 
    690     // Notify any password-listener of the focus change.
    691     if (!inputElement)
    692         return;
    693 
    694     WebFrameImpl* webframe = WebFrameImpl::fromFrame(inputElement->document()->frame());
    695     if (!webframe)
    696         return;
    697 
    698     WebPasswordAutocompleteListener* listener = webframe->getPasswordListener(inputElement);
    699     if (!listener)
    700         return;
    701 
    702     listener->didBlurInputElement(inputElement->value());
    703 }
    704 
    705 void EditorClientImpl::textDidChangeInTextField(Element* element)
    706 {
    707     ASSERT(element->hasLocalName(HTMLNames::inputTag));
    708     HTMLInputElement* inputElement = static_cast<HTMLInputElement*>(element);
    709     if (m_webView->autoFillClient())
    710         m_webView->autoFillClient()->textFieldDidChange(WebInputElement(inputElement));
    711 
    712     // Note that we only show the autofill popup in this case if the caret is at
    713     // the end.  This matches FireFox and Safari but not IE.
    714     autofill(inputElement, false, false, true);
    715 }
    716 
    717 bool EditorClientImpl::showFormAutofillForNode(Node* node)
    718 {
    719     HTMLInputElement* inputElement = toHTMLInputElement(node);
    720     if (inputElement)
    721         return autofill(inputElement, true, true, false);
    722     return false;
    723 }
    724 
    725 bool EditorClientImpl::autofill(HTMLInputElement* inputElement,
    726                                 bool autofillFormOnly,
    727                                 bool autofillOnEmptyValue,
    728                                 bool requireCaretAtEnd)
    729 {
    730     // Cancel any pending DoAutofill call.
    731     m_autofillArgs.clear();
    732     m_autofillTimer.stop();
    733 
    734     // FIXME: Remove the extraneous isEnabledFormControl call below.
    735     // Let's try to trigger autofill for that field, if applicable.
    736     if (!inputElement->isEnabledFormControl() || !inputElement->isTextField()
    737         || inputElement->isPasswordField() || !inputElement->autoComplete()
    738         || !inputElement->isEnabledFormControl()
    739         || inputElement->isReadOnlyFormControl())
    740         return false;
    741 
    742     WebString name = WebInputElement(inputElement).nameForAutofill();
    743     if (name.isEmpty()) // If the field has no name, then we won't have values.
    744         return false;
    745 
    746     // Don't attempt to autofill with values that are too large.
    747     if (inputElement->value().length() > maximumTextSizeForAutofill)
    748         return false;
    749 
    750     m_autofillArgs = new AutofillArgs();
    751     m_autofillArgs->inputElement = inputElement;
    752     m_autofillArgs->autofillFormOnly = autofillFormOnly;
    753     m_autofillArgs->autofillOnEmptyValue = autofillOnEmptyValue;
    754     m_autofillArgs->requireCaretAtEnd = requireCaretAtEnd;
    755     m_autofillArgs->backspaceOrDeletePressed = m_backspaceOrDeletePressed;
    756 
    757     if (!requireCaretAtEnd)
    758         doAutofill(0);
    759     else {
    760         // We post a task for doing the autofill as the caret position is not set
    761         // properly at this point (http://bugs.webkit.org/show_bug.cgi?id=16976)
    762         // and we need it to determine whether or not to trigger autofill.
    763         m_autofillTimer.startOneShot(0.0);
    764     }
    765     return true;
    766 }
    767 
    768 void EditorClientImpl::doAutofill(Timer<EditorClientImpl>* timer)
    769 {
    770     OwnPtr<AutofillArgs> args(m_autofillArgs.release());
    771     HTMLInputElement* inputElement = args->inputElement.get();
    772 
    773     const String& value = inputElement->value();
    774 
    775     // Enforce autofill_on_empty_value and caret_at_end.
    776 
    777     bool isCaretAtEnd = true;
    778     if (args->requireCaretAtEnd)
    779         isCaretAtEnd = inputElement->selectionStart() == inputElement->selectionEnd()
    780                        && inputElement->selectionEnd() == static_cast<int>(value.length());
    781 
    782     if ((!args->autofillOnEmptyValue && value.isEmpty()) || !isCaretAtEnd) {
    783         m_webView->hideAutoFillPopup();
    784         return;
    785     }
    786 
    787     // First let's see if there is a password listener for that element.
    788     // We won't trigger form autofill in that case, as having both behavior on
    789     // a node would be confusing.
    790     WebFrameImpl* webframe = WebFrameImpl::fromFrame(inputElement->document()->frame());
    791     if (!webframe)
    792         return;
    793     WebPasswordAutocompleteListener* listener = webframe->getPasswordListener(inputElement);
    794     if (listener) {
    795         if (args->autofillFormOnly)
    796             return;
    797 
    798         listener->performInlineAutocomplete(value,
    799                                             args->backspaceOrDeletePressed,
    800                                             true);
    801         return;
    802     }
    803 }
    804 
    805 void EditorClientImpl::cancelPendingAutofill()
    806 {
    807     m_autofillArgs.clear();
    808     m_autofillTimer.stop();
    809 }
    810 
    811 bool EditorClientImpl::doTextFieldCommandFromEvent(Element* element,
    812                                                    KeyboardEvent* event)
    813 {
    814     HTMLInputElement* inputElement = toHTMLInputElement(element);
    815     if (m_webView->autoFillClient() && inputElement) {
    816         m_webView->autoFillClient()->textFieldDidReceiveKeyDown(WebInputElement(inputElement),
    817                                                                 WebKeyboardEventBuilder(*event));
    818     }
    819 
    820     // Remember if backspace was pressed for the autofill.  It is not clear how to
    821     // find if backspace was pressed from textFieldDidBeginEditing and
    822     // textDidChangeInTextField as when these methods are called the value of the
    823     // input element already contains the type character.
    824     m_backspaceOrDeletePressed = event->keyCode() == VKEY_BACK || event->keyCode() == VKEY_DELETE;
    825 
    826     // The Mac code appears to use this method as a hook to implement special
    827     // keyboard commands specific to Safari's auto-fill implementation.  We
    828     // just return false to allow the default action.
    829     return false;
    830 }
    831 
    832 void EditorClientImpl::textWillBeDeletedInTextField(Element*)
    833 {
    834 }
    835 
    836 void EditorClientImpl::textDidChangeInTextArea(Element*)
    837 {
    838 }
    839 
    840 void EditorClientImpl::ignoreWordInSpellDocument(const String&)
    841 {
    842     notImplemented();
    843 }
    844 
    845 void EditorClientImpl::learnWord(const String&)
    846 {
    847     notImplemented();
    848 }
    849 
    850 void EditorClientImpl::checkSpellingOfString(const UChar* text, int length,
    851                                              int* misspellingLocation,
    852                                              int* misspellingLength)
    853 {
    854     // SpellCheckWord will write (0, 0) into the output vars, which is what our
    855     // caller expects if the word is spelled correctly.
    856     int spellLocation = -1;
    857     int spellLength = 0;
    858 
    859     // Check to see if the provided text is spelled correctly.
    860     if (isContinuousSpellCheckingEnabled() && m_webView->spellCheckClient())
    861         m_webView->spellCheckClient()->spellCheck(WebString(text, length), spellLocation, spellLength, 0);
    862     else {
    863         spellLocation = 0;
    864         spellLength = 0;
    865     }
    866 
    867     // Note: the Mac code checks if the pointers are null before writing to them,
    868     // so we do too.
    869     if (misspellingLocation)
    870         *misspellingLocation = spellLocation;
    871     if (misspellingLength)
    872         *misspellingLength = spellLength;
    873 }
    874 
    875 void EditorClientImpl::requestCheckingOfString(SpellChecker* sender, int identifier, TextCheckingTypeMask, const String& text)
    876 {
    877     if (m_webView->spellCheckClient())
    878         m_webView->spellCheckClient()->requestCheckingOfText(text, new WebTextCheckingCompletionImpl(identifier, sender));
    879 }
    880 
    881 String EditorClientImpl::getAutoCorrectSuggestionForMisspelledWord(const String& misspelledWord)
    882 {
    883     if (!(isContinuousSpellCheckingEnabled() && m_webView->client()))
    884         return String();
    885 
    886     // Do not autocorrect words with capital letters in it except the
    887     // first letter. This will remove cases changing "IMB" to "IBM".
    888     for (size_t i = 1; i < misspelledWord.length(); i++) {
    889         if (u_isupper(static_cast<UChar32>(misspelledWord[i])))
    890             return String();
    891     }
    892 
    893     if (m_webView->spellCheckClient())
    894         return m_webView->spellCheckClient()->autoCorrectWord(WebString(misspelledWord));
    895     return String();
    896 }
    897 
    898 void EditorClientImpl::checkGrammarOfString(const UChar*, int length,
    899                                             WTF::Vector<GrammarDetail>&,
    900                                             int* badGrammarLocation,
    901                                             int* badGrammarLength)
    902 {
    903     notImplemented();
    904     if (badGrammarLocation)
    905         *badGrammarLocation = 0;
    906     if (badGrammarLength)
    907         *badGrammarLength = 0;
    908 }
    909 
    910 void EditorClientImpl::updateSpellingUIWithGrammarString(const String&,
    911                                                          const GrammarDetail& detail)
    912 {
    913     notImplemented();
    914 }
    915 
    916 void EditorClientImpl::updateSpellingUIWithMisspelledWord(const String& misspelledWord)
    917 {
    918     if (m_webView->spellCheckClient())
    919         m_webView->spellCheckClient()->updateSpellingUIWithMisspelledWord(WebString(misspelledWord));
    920 }
    921 
    922 void EditorClientImpl::showSpellingUI(bool show)
    923 {
    924     if (m_webView->spellCheckClient())
    925         m_webView->spellCheckClient()->showSpellingUI(show);
    926 }
    927 
    928 bool EditorClientImpl::spellingUIIsShowing()
    929 {
    930     if (m_webView->spellCheckClient())
    931         return m_webView->spellCheckClient()->isShowingSpellingUI();
    932     return false;
    933 }
    934 
    935 void EditorClientImpl::getGuessesForWord(const String& word,
    936                                          const String& context,
    937                                          WTF::Vector<String>& guesses)
    938 {
    939     notImplemented();
    940 }
    941 
    942 void EditorClientImpl::willSetInputMethodState()
    943 {
    944     if (m_webView->client())
    945         m_webView->client()->resetInputMethod();
    946 }
    947 
    948 void EditorClientImpl::setInputMethodState(bool)
    949 {
    950 }
    951 
    952 } // namesace WebKit
    953