Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(692)

Unified Diff: webkit/glue/editor_client_impl.cc

Issue 11479: New take at implementing autofill using the editor client API (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 12 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « webkit/glue/editor_client_impl.h ('k') | webkit/glue/form_autocomplete_listener.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webkit/glue/editor_client_impl.cc
===================================================================
--- webkit/glue/editor_client_impl.cc (revision 5576)
+++ webkit/glue/editor_client_impl.cc (working copy)
@@ -17,6 +17,7 @@
#include "EventNames.h"
#include "KeyboardCodes.h"
#include "HTMLInputElement.h"
+#include "HTMLNames.h"
#include "Frame.h"
#include "KeyboardEvent.h"
#include "PlatformKeyboardEvent.h"
@@ -24,6 +25,7 @@
MSVC_POP_WARNING();
#undef LOG
+#include "base/message_loop.h"
#include "base/string_util.h"
#include "webkit/glue/editor_client_impl.h"
#include "webkit/glue/glue_util.h"
@@ -37,6 +39,10 @@
// into a single action.
static const size_t kMaximumUndoStackDepth = 1000;
+// The size above which we stop triggering autofill for an input text field
+// (so to avoid sending long strings through IPC).
+static const size_t kMaximumTextSizeForAutofill = 1000;
+
namespace {
// Record an editor command from the keyDownEntries[] below. We ignore the
@@ -63,8 +69,11 @@
: web_view_(static_cast<WebViewImpl*>(web_view)),
use_editor_delegate_(false),
in_redo_(false),
- preserve_(false),
- pending_inline_autocompleted_element_(NULL) {
+ backspace_pressed_(false),
+// Don't complain about using "this" in initializer list.
+MSVC_PUSH_DISABLE_WARNING(4355)
+ autofill_factory_(this) {
+MSVC_POP_WARNING()
}
EditorClientImpl::~EditorClientImpl() {
@@ -182,10 +191,6 @@
return true;
}
-void EditorClientImpl::PreserveSelection() {
- preserve_ = true;
-}
-
bool EditorClientImpl::shouldChangeSelectedRange(WebCore::Range* fromRange,
WebCore::Range* toRange,
WebCore::EAffinity affinity,
@@ -200,12 +205,6 @@
stillSelecting);
}
}
- // Have we been told to preserve the selection?
- // (See comments for PreserveSelection in header).
- if (preserve_) {
- preserve_ = false;
- return false;
- }
return true;
}
@@ -242,25 +241,6 @@
}
void EditorClientImpl::respondToChangedContents() {
- // Ugly Hack. (See also webkit bug #16976).
- // Something is wrong with webcore's focusController in that when selection
- // is set to a region within a text element when handling an input event, if
- // you don't re-focus the node then it only _APPEARS_ to have successfully
- // changed the selection (the UI "looks" right) but in reality there is no
- // selection of text. And to make matters worse, you can't just re-focus it,
- // you have to re-focus it in code executed after the entire event listener
- // loop has finished; and hence here we are. Oh, and to make matters worse,
- // this sequence of events _doesn't_ happen when you debug through the code
- // -- in that case it works perfectly fine -- because swapping to the debugger
- // causes the refocusing we artificially reproduce here.
- // TODO (timsteele): Clean this up once root webkit problem is identified and
- // the bug is patched.
- if (pending_inline_autocompleted_element_) {
- pending_inline_autocompleted_element_->blur();
- pending_inline_autocompleted_element_->focus();
- pending_inline_autocompleted_element_ = NULL;
- }
-
if (use_editor_delegate_) {
WebViewDelegate* d = web_view_->delegate();
if (d)
@@ -621,17 +601,84 @@
void EditorClientImpl::textFieldDidEndEditing(WebCore::Element*) {
// Notification that focus was lost. Be careful with this, it's also sent
// when the page is being closed.
+
+ // Cancel any pending DoAutofill calls.
+ autofill_factory_.RevokeAll();
}
void EditorClientImpl::textDidChangeInTextField(WebCore::Element* element) {
- // Track the element so we can blur/focus it in respondToChangedContents
- // so that the selected range is properly set. (See respondToChangedContents).
- if (static_cast<WebCore::HTMLInputElement*>(element)->autofilled())
- pending_inline_autocompleted_element_ = element;
+ DCHECK(element->hasLocalName(WebCore::HTMLNames::inputTag));
+
+ // Cancel any pending DoAutofill calls.
+ autofill_factory_.RevokeAll();
+
+ // Let's try to trigger autofill for that field, if applicable.
+ WebCore::HTMLInputElement* input_element =
+ static_cast<WebCore::HTMLInputElement*>(element);
+ if (!input_element->isEnabled() || !input_element->isTextField() ||
+ input_element->isPasswordField() || !input_element->autoComplete()) {
+ return;
+ }
+
+ std::wstring name = webkit_glue::StringToStdWString(input_element->name());
+ if (name.empty()) // If the field has no name, then we won't have values.
+ return;
+
+ // Don't attempt to autofill with values that are too large.
+ if (input_element->value().length() > kMaximumTextSizeForAutofill)
+ return;
+
+ // We post a task for doing the autofill as the caret position is not set
+ // properly at this point ( http://bugs.webkit.org/show_bug.cgi?id=16976)
+ // and we need it to determine whether or not to trigger autofill.
+ std::wstring value = webkit_glue::StringToStdWString(input_element->value());
+ MessageLoop::current()->PostTask(
+ FROM_HERE,
+ autofill_factory_.NewRunnableMethod(&EditorClientImpl::DoAutofill,
+ input_element,
+ backspace_pressed_));
}
-bool EditorClientImpl::doTextFieldCommandFromEvent(WebCore::Element*,
- WebCore::KeyboardEvent*) {
+void EditorClientImpl::DoAutofill(WebCore::HTMLInputElement* input_element,
+ bool backspace) {
+ std::wstring value = webkit_glue::StringToStdWString(input_element->value());
+
+ // Only autofill when there is some text and the caret is at the end.
+ bool caret_at_end =
+ input_element->selectionStart() == input_element->selectionEnd() &&
+ input_element->selectionEnd() == value.length();
+ if (value.empty() || !caret_at_end)
+ return;
+
+ // First let's see if there is a password listener for that element.
+ WebFrameImpl* webframe =
+ WebFrameImpl::FromFrame(input_element->form()->document()->frame());
+ webkit_glue::PasswordAutocompleteListener* listener =
+ webframe->GetPasswordListener(input_element);
+ if (listener) {
+ if (backspace) // No autocomplete for password on backspace.
+ return;
+
+ listener->OnInlineAutocompleteNeeded(input_element, value);
+ return;
+ }
+
+ // Then trigger form autofill.
+ std::wstring name = webkit_glue::StringToStdWString(input_element->
+ name().string());
+ web_view_->delegate()->QueryFormFieldAutofill(name, value,
+ reinterpret_cast<int64>(input_element));
+}
+
+bool EditorClientImpl::doTextFieldCommandFromEvent(
+ WebCore::Element* element,
+ WebCore::KeyboardEvent* event) {
+ // Remember if backspace was pressed for the autofill. It is not clear how to
+ // find if backspace was pressed from textFieldDidBeginEditing and
+ // textDidChangeInTextField as when these methods are called the value of the
+ // input element already contains the type character.
+ backspace_pressed_ = (event->keyCode() == WebCore::VKEY_BACK);
+
// The Mac code appears to use this method as a hook to implement special
// keyboard commands specific to Safari's auto-fill implementation. We
// just return false to allow the default action.
« no previous file with comments | « webkit/glue/editor_client_impl.h ('k') | webkit/glue/form_autocomplete_listener.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698