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