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