OSDN Git Service

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