diff options
-rw-r--r-- | chrome/chrome_renderer.gypi | 2 | ||||
-rw-r--r-- | chrome/renderer/autofill_helper.cc | 239 | ||||
-rw-r--r-- | chrome/renderer/autofill_helper.h | 124 | ||||
-rw-r--r-- | chrome/renderer/password_autocomplete_manager.cc | 47 | ||||
-rw-r--r-- | chrome/renderer/password_autocomplete_manager.h | 11 | ||||
-rw-r--r-- | chrome/renderer/render_view.cc | 215 | ||||
-rw-r--r-- | chrome/renderer/render_view.h | 52 |
7 files changed, 441 insertions, 249 deletions
diff --git a/chrome/chrome_renderer.gypi b/chrome/chrome_renderer.gypi index 1f98725..4cb668d 100644 --- a/chrome/chrome_renderer.gypi +++ b/chrome/chrome_renderer.gypi @@ -42,6 +42,8 @@ # But app/ is the wrong directory for them. # Better is to remove the dep of *_tests on renderer, but in the # short term I'd like the build to work. + 'renderer/autofill_helper.cc', + 'renderer/autofill_helper.h', 'renderer/automation/dom_automation_controller.cc', 'renderer/automation/dom_automation_controller.h', 'renderer/automation/dom_automation_v8_extension.cc', diff --git a/chrome/renderer/autofill_helper.cc b/chrome/renderer/autofill_helper.cc new file mode 100644 index 0000000..2c6d6c8 --- /dev/null +++ b/chrome/renderer/autofill_helper.cc @@ -0,0 +1,239 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/renderer/autofill_helper.h" + +#include "app/l10n_util.h" +#include "chrome/renderer/form_manager.h" +#include "chrome/renderer/render_view.h" +#include "grit/generated_resources.h" +#include "third_party/WebKit/WebKit/chromium/public/WebDocument.h" +#include "third_party/WebKit/WebKit/chromium/public/WebFormControlElement.h" +#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h" +#include "webkit/glue/password_form.h" + +using WebKit::WebFormControlElement; +using WebKit::WebFormElement; +using WebKit::WebFrame; +using WebKit::WebInputElement; +using WebKit::WebNode; +using WebKit::WebString; + +AutoFillHelper::AutoFillHelper(RenderView* render_view) + : render_view_(render_view), + autofill_query_id_(0), + autofill_action_(AUTOFILL_NONE), + suggestions_clear_index_(-1), + suggestions_options_index_(-1) { +} + +void AutoFillHelper::QueryAutocompleteSuggestions(const WebNode& node, + const WebString& name, + const WebString& value) { + static int query_counter = 0; + autofill_query_id_ = query_counter++; + autofill_query_node_ = node; + + const WebFormControlElement& element = node.toConst<WebFormControlElement>(); + webkit_glue::FormField field; + FormManager::WebFormControlElementToFormField(element, true, &field); + + // WebFormControlElementToFormField does not scrape the DOM for the field + // label, so find the label here. + // TODO(jhawkins): Add form and field identities so we can use the cached form + // data in FormManager. + field.set_label(FormManager::LabelForElement(element)); + + bool form_autofilled = form_manager_.FormWithNodeIsAutoFilled(node); + render_view_->Send(new ViewHostMsg_QueryFormFieldAutoFill( + render_view_->routing_id(), autofill_query_id_, form_autofilled, field)); +} + +void AutoFillHelper::RemoveAutocompleteSuggestion( + const WebKit::WebString& name, const WebKit::WebString& value) { + // The index of clear & options will have shifted down. + if (suggestions_clear_index_ != -1) + suggestions_clear_index_--; + if (suggestions_options_index_ != -1) + suggestions_options_index_--; + + render_view_->Send(new ViewHostMsg_RemoveAutocompleteEntry( + render_view_->routing_id(), name, value)); +} + +void AutoFillHelper::SuggestionsReceived(int query_id, + const std::vector<string16>& values, + const std::vector<string16>& labels, + const std::vector<int>& unique_ids) { + WebKit::WebView* web_view = render_view_->webview(); + if (!web_view || query_id != autofill_query_id_) + return; + + // Any popup currently showing is now obsolete. + web_view->hidePopups(); + + // No suggestions: nothing to do. + if (values.empty()) + return; + + std::vector<string16> v(values); + std::vector<string16> l(labels); + std::vector<int> ids(unique_ids); + int separator_index = -1; + + // The form has been auto-filled, so give the user the chance to clear the + // form. Append the 'Clear form' menu item. + if (form_manager_.FormWithNodeIsAutoFilled(autofill_query_node_)) { + v.push_back(l10n_util::GetStringUTF16(IDS_AUTOFILL_CLEAR_FORM_MENU_ITEM)); + l.push_back(string16()); + ids.push_back(0); + suggestions_clear_index_ = v.size() - 1; + separator_index = values.size(); + } + + // Only include "AutoFill Options" special menu item if we have AutoFill + // items, identified by |unique_ids| having at least one valid value. + bool show_options = false; + for (size_t i = 0; i < ids.size(); ++i) { + if (ids[i] != 0) { + show_options = true; + break; + } + } + if (show_options) { + // Append the 'AutoFill Options...' menu item. + v.push_back(l10n_util::GetStringUTF16(IDS_AUTOFILL_OPTIONS)); + l.push_back(string16()); + ids.push_back(0); + suggestions_options_index_ = v.size() - 1; + separator_index = values.size(); + } + + // Send to WebKit for display. + if (!v.empty()) { + web_view->applyAutoFillSuggestions( + autofill_query_node_, v, l, ids, separator_index); + } +} + +void AutoFillHelper::FormDataFilled(int query_id, + const webkit_glue::FormData& form) { + if (!render_view_->webview() || query_id != autofill_query_id_) + return; + + switch (autofill_action_) { + case AUTOFILL_FILL: + form_manager_.FillForm(form, autofill_query_node_); + break; + case AUTOFILL_PREVIEW: + form_manager_.PreviewForm(form); + break; + default: + NOTREACHED(); + } + autofill_action_ = AUTOFILL_NONE; +} + +void AutoFillHelper::DidSelectAutoFillSuggestion(const WebNode& node, + const WebString& value, + const WebString& label, + int unique_id) { + DidClearAutoFillSelection(node); + QueryAutoFillFormData(node, value, label, unique_id, AUTOFILL_PREVIEW); +} + +void AutoFillHelper::DidAcceptAutoFillSuggestion(const WebNode& node, + const WebString& value, + const WebString& label, + int unique_id, + unsigned index) { + if (suggestions_options_index_ != -1 && + index == static_cast<unsigned>(suggestions_options_index_)) { + // User selected 'AutoFill Options'. + render_view_->Send(new ViewHostMsg_ShowAutoFillDialog( + render_view_->routing_id())); + } else if (suggestions_clear_index_ != -1 && + index == static_cast<unsigned>(suggestions_clear_index_)) { + // User selected 'Clear form'. + // The form has been auto-filled, so give the user the chance to clear the + // form. + form_manager_.ClearFormWithNode(node); + } else if (form_manager_.FormWithNodeIsAutoFilled(node) || !unique_id) { + // User selected an Autocomplete entry, so we fill directly. + WebInputElement element = node.toConst<WebInputElement>(); + element.setValue(value); + + WebFrame* webframe = node.document().frame(); + if (webframe) + webframe->notifiyPasswordListenerOfAutocomplete(element); + } else { + // Fill the values for the whole form. + QueryAutoFillFormData(node, value, label, unique_id, AUTOFILL_FILL); + } + + suggestions_clear_index_ = -1; + suggestions_options_index_ = -1; +} + +void AutoFillHelper::DidClearAutoFillSelection(const WebNode& node) { + webkit_glue::FormData form; + const WebFormControlElement element = node.toConst<WebFormControlElement>(); + if (!form_manager_.FindFormWithFormControlElement( + element, FormManager::REQUIRE_NONE, &form)) { + return; + } + form_manager_.ClearPreviewedForm(form); +} + +void AutoFillHelper::FrameContentsAvailable(WebFrame* frame) { + form_manager_.ExtractForms(frame); + SendForms(frame); +} + +void AutoFillHelper::FrameWillClose(WebFrame* frame) { + form_manager_.ResetFrame(frame); +} + +void AutoFillHelper::QueryAutoFillFormData(const WebNode& node, + const WebString& value, + const WebString& label, + int unique_id, + AutoFillAction action) { + static int query_counter = 0; + autofill_query_id_ = query_counter++; + + webkit_glue::FormData form; + const WebInputElement element = node.toConst<WebInputElement>(); + if (!form_manager_.FindFormWithFormControlElement( + element, FormManager::REQUIRE_NONE, &form)) + return; + + autofill_action_ = action; + render_view_->Send(new ViewHostMsg_FillAutoFillFormData( + render_view_->routing_id(), autofill_query_id_, form, value, label, + unique_id)); +} + +void AutoFillHelper::SendForms(WebFrame* frame) { + // TODO(jhawkins): Use FormManager once we have strict ordering of form + // control elements in the cache. + WebKit::WebVector<WebFormElement> web_forms; + frame->forms(web_forms); + + std::vector<webkit_glue::FormData> forms; + for (size_t i = 0; i < web_forms.size(); ++i) { + const WebFormElement& web_form = web_forms[i]; + + webkit_glue::FormData form; + if (FormManager::WebFormElementToFormData( + web_form, FormManager::REQUIRE_NONE, false, &form)) { + forms.push_back(form); + } + } + + if (!forms.empty()) { + render_view_->Send(new ViewHostMsg_FormsSeen(render_view_->routing_id(), + forms)); + } +} diff --git a/chrome/renderer/autofill_helper.h b/chrome/renderer/autofill_helper.h new file mode 100644 index 0000000..4395144 --- /dev/null +++ b/chrome/renderer/autofill_helper.h @@ -0,0 +1,124 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_RENDERER_AUTOFILL_HELPER_H_ +#define CHROME_RENDERER_AUTOFILL_HELPER_H_ + +#include <vector> + +#include "base/basictypes.h" +#include "chrome/renderer/form_manager.h" +#include "third_party/WebKit/WebKit/chromium/public/WebNode.h" + +class RenderView; + +namespace WebKit { +class WebInputElement; +class WebString; +} + +// AutoFillHelper deals with autofill related communications between WebKit and +// the browser. There is one AutofillHelper per RenderView. +// This code was originally part of RenderView. +// Note that autofill encompasses: +// - single text field suggestions, that we usually refer to as Autocomplete +// - entire form fill based on one field entry, refered as form AutoFill. + +class AutoFillHelper { + public: + explicit AutoFillHelper(RenderView* render_view); + + // Queries the browser for Autocomplete suggestion for the given |node|. + // (Autocomplete means suggestions for a single text input.) + void QueryAutocompleteSuggestions(const WebKit::WebNode& node, + const WebKit::WebString& name, + const WebKit::WebString& value); + + // Removes the Autocomplete suggestion |value| for the field names |name|. + void RemoveAutocompleteSuggestion(const WebKit::WebString& name, + const WebKit::WebString& value); + + // Called when we have received Autofill suggestions from the browser. + void SuggestionsReceived(int query_id, + const std::vector<string16>& values, + const std::vector<string16>& labels, + const std::vector<int>& unique_ids); + + // Called when we have received suggestions for an entire form from the + // browser. + void FormDataFilled(int query_id, const webkit_glue::FormData& form); + + // Called by Webkit when the user has selected a suggestion in the popup (this + // happens when the user hovers over an suggestion or navigates the popup with + // the arrow keys). + void DidSelectAutoFillSuggestion(const WebKit::WebNode& node, + const WebKit::WebString& value, + const WebKit::WebString& label, + int unique_id); + + // Called by Webkit when the user has accepted a suggestion in the popup. + void DidAcceptAutoFillSuggestion(const WebKit::WebNode& node, + const WebKit::WebString& value, + const WebKit::WebString& label, + int unique_id, + unsigned index); + + // Called by WebKit when the user has cleared the selection from the AutoFill + // suggestions popup. This happens when a user uses the arrow keys to + // navigate outside the range of possible selections, or when the popup + // closes. + void DidClearAutoFillSelection(const WebKit::WebNode& node); + + // Called when the frame contents are available. Extracts the forms from that + // frame and sends them to the browser for parsing. + void FrameContentsAvailable(WebKit::WebFrame* frame); + + // Called before a frame is closed. Gives us an oppotunity to clean-up. + void FrameWillClose(WebKit::WebFrame* frame); + + private: + enum AutoFillAction { + AUTOFILL_NONE, // No state set. + AUTOFILL_FILL, // Fill the AutoFill form data. + AUTOFILL_PREVIEW, // Preview the AutoFill form data. + }; + + // Queries the AutoFillManager for form data for the form containing |node|. + // |value| is the current text in the field, and |unique_id| is the selected + // profile's unique ID. |action| specifies whether to Fill or Preview the + // values returned from the AutoFillManager. + void QueryAutoFillFormData(const WebKit::WebNode& node, + const WebKit::WebString& value, + const WebKit::WebString& label, + int unique_id, + AutoFillAction action); + + // Scans the given frame for forms and sends them up to the browser. + void SendForms(WebKit::WebFrame* frame); + + // Weak reference. + RenderView* render_view_; + + FormManager form_manager_; + + // The ID of the last request sent for form field AutoFill. Used to ignore + // out of date responses. + int autofill_query_id_; + + // The node corresponding to the last request sent for form field AutoFill. + WebKit::WebNode autofill_query_node_; + + // The action to take when receiving AutoFill data from the AutoFillManager. + AutoFillAction autofill_action_; + + // The menu index of the "Clear" menu item. + int suggestions_clear_index_; + + // The menu index of the "AutoFill options..." menu item. + int suggestions_options_index_; + + DISALLOW_COPY_AND_ASSIGN(AutoFillHelper); +}; + +#endif // CHROME_RENDERER_AUTOFILL_HELPER_H_ diff --git a/chrome/renderer/password_autocomplete_manager.cc b/chrome/renderer/password_autocomplete_manager.cc index f8f10ec..0cc3732 100644 --- a/chrome/renderer/password_autocomplete_manager.cc +++ b/chrome/renderer/password_autocomplete_manager.cc @@ -7,14 +7,18 @@ #include "base/keyboard_codes.h" #include "base/message_loop.h" #include "base/scoped_ptr.h" +#include "chrome/common/render_messages.h" +#include "chrome/renderer/render_view.h" #include "third_party/WebKit/WebKit/chromium/public/WebDocument.h" #include "third_party/WebKit/WebKit/chromium/public/WebElement.h" #include "third_party/WebKit/WebKit/chromium/public/WebFormElement.h" #include "third_party/WebKit/WebKit/chromium/public/WebFrame.h" #include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h" +#include "third_party/WebKit/WebKit/chromium/public/WebSecurityOrigin.h" #include "third_party/WebKit/WebKit/chromium/public/WebVector.h" #include "third_party/WebKit/WebKit/chromium/public/WebView.h" #include "webkit/glue/form_field.h" +#include "webkit/glue/password_form.h" #include "webkit/glue/password_form_dom_manager.h" namespace { @@ -166,7 +170,8 @@ bool DoUsernamesMatch(const string16& username1, PasswordAutocompleteManager::PasswordAutocompleteManager( RenderView* render_view) - : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { + : render_view_(render_view), + ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { } PasswordAutocompleteManager::~PasswordAutocompleteManager() { @@ -338,6 +343,43 @@ void PasswordAutocompleteManager::PerformInlineAutocomplete( FillUserNameAndPassword(&username, &password, fill_data, false); } +void PasswordAutocompleteManager::SendPasswordForms(WebKit::WebFrame* frame, + bool only_visible) { + // Make sure that this security origin is allowed to use password manager. + WebKit::WebSecurityOrigin security_origin = frame->securityOrigin(); + if (!security_origin.canAccessPasswordManager()) + return; + + WebKit::WebVector<WebKit::WebFormElement> forms; + frame->forms(forms); + + std::vector<webkit_glue::PasswordForm> password_forms; + for (size_t i = 0; i < forms.size(); ++i) { + const WebKit::WebFormElement& form = forms[i]; + + // Respect autocomplete=off. + if (!form.autoComplete()) + continue; + if (only_visible && !form.hasNonEmptyBoundingBox()) + continue; + scoped_ptr<webkit_glue::PasswordForm> password_form( + webkit_glue::PasswordFormDomManager::CreatePasswordForm(form)); + if (password_form.get()) + password_forms.push_back(*password_form); + } + + if (password_forms.empty()) + return; + + if (only_visible) { + render_view_->Send( + new ViewHostMsg_PasswordFormsVisible(GetRoutingID(), password_forms)); + } else { + render_view_->Send( + new ViewHostMsg_PasswordFormsFound(GetRoutingID(), password_forms)); + } +} + //////////////////////////////////////////////////////////////////////////////// // PasswordAutocompleteManager, private: @@ -414,3 +456,6 @@ bool PasswordAutocompleteManager::FillUserNameAndPassword( return true; } +int PasswordAutocompleteManager::GetRoutingID() const { + return render_view_->routing_id(); +} diff --git a/chrome/renderer/password_autocomplete_manager.h b/chrome/renderer/password_autocomplete_manager.h index 5e2eee2..297decc 100644 --- a/chrome/renderer/password_autocomplete_manager.h +++ b/chrome/renderer/password_autocomplete_manager.h @@ -48,6 +48,10 @@ class PasswordAutocompleteManager { const WebKit::WebInputElement& password, const webkit_glue::PasswordFormFillData& fill_data); + // Scans the given frame for password forms and sends them up to the browser. + // If |only_visible| is true, only forms visible in the layout are sent. + void SendPasswordForms(WebKit::WebFrame* frame, bool only_visible); + // WebViewClient editor related calls forwarded by the RenderView. void TextFieldDidBeginEditing(const WebKit::WebInputElement& element); void TextFieldDidEndEditing(const WebKit::WebInputElement& element); @@ -79,6 +83,13 @@ class PasswordAutocompleteManager { const webkit_glue::PasswordFormFillData& fill_data, bool exact_username_match); + // Convenience method that returns the routing ID of the render view we are + // associated with. + int GetRoutingID() const; + + // Weak reference. + RenderView* render_view_; + // The logins we have filled so far with their associated info. LoginToPasswordInfoMap login_to_password_info_; diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index e6eccfa..55fa0c2 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -123,7 +123,6 @@ #include "webkit/glue/media/buffered_data_source.h" #include "webkit/glue/media/simple_data_source.h" #include "webkit/glue/media/video_renderer_impl.h" -#include "webkit/glue/password_form.h" #include "webkit/glue/plugins/default_plugin_shared.h" #include "webkit/glue/plugins/pepper_webplugin_impl.h" #include "webkit/glue/plugins/plugin_list.h" @@ -434,14 +433,11 @@ RenderView::RenderView(RenderThreadBase* render_thread, spelling_panel_visible_(false), view_type_(ViewType::INVALID), browser_window_id_(-1), - autofill_query_id_(0), - autofill_action_(AUTOFILL_NONE), - suggestions_clear_index_(-1), - suggestions_options_index_(-1), ALLOW_THIS_IN_INITIALIZER_LIST(pepper_delegate_(this)), ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)), ALLOW_THIS_IN_INITIALIZER_LIST(translate_helper_(this)), ALLOW_THIS_IN_INITIALIZER_LIST(password_autocomplete_manager_(this)), + ALLOW_THIS_IN_INITIALIZER_LIST(autofill_helper_(this)), ALLOW_THIS_IN_INITIALIZER_LIST(cookie_jar_(this)), ALLOW_THIS_IN_INITIALIZER_LIST( notification_provider_(new NotificationProvider(this))), @@ -1520,68 +1516,12 @@ void RenderView::OnAutoFillSuggestionsReturned( const std::vector<string16>& values, const std::vector<string16>& labels, const std::vector<int>& unique_ids) { - if (!webview() || query_id != autofill_query_id_) - return; - - // Any popup currently showing is now obsolete. - webview()->hidePopups(); - - // No suggestions: nothing to do. - if (values.empty()) - return; - - std::vector<string16> v(values); - std::vector<string16> l(labels); - std::vector<int> ids(unique_ids); - int separator_index = -1; - - // The form has been auto-filled, so give the user the chance to clear the - // form. Append the 'Clear form' menu item. - if (form_manager_.FormWithNodeIsAutoFilled(autofill_query_node_)) { - v.push_back(l10n_util::GetStringUTF16(IDS_AUTOFILL_CLEAR_FORM_MENU_ITEM)); - l.push_back(string16()); - ids.push_back(0); - suggestions_clear_index_ = v.size() - 1; - separator_index = values.size(); - } - - size_t autofill_item_count = 0; - for (size_t i = 0; i < ids.size(); ++i) { - if (ids[i] != 0) - autofill_item_count++; - } - - // Only include "AutoFill Options" special menu item if we have AutoFill - // items, identified by |unique_ids| having at least one valid value. - if (autofill_item_count > 0) { - // Append the 'AutoFill Options...' menu item. - v.push_back(l10n_util::GetStringUTF16(IDS_AUTOFILL_OPTIONS)); - l.push_back(string16()); - ids.push_back(0); - suggestions_options_index_ = v.size() - 1; - separator_index = values.size(); - } - - // Send to WebKit for display. - if (!v.empty()) { - webview()->applyAutoFillSuggestions( - autofill_query_node_, v, l, ids, separator_index); - } + autofill_helper_.SuggestionsReceived(query_id, values, labels, unique_ids); } void RenderView::OnAutoFillFormDataFilled(int query_id, const webkit_glue::FormData& form) { - if (!webview() || query_id != autofill_query_id_) - return; - - DCHECK_NE(AUTOFILL_NONE, autofill_action_); - - if (autofill_action_ == AUTOFILL_FILL) - form_manager_.FillForm(form, autofill_query_node_); - else if (autofill_action_ == AUTOFILL_PREVIEW) - form_manager_.PreviewForm(form); - - autofill_action_ = AUTOFILL_NONE; + autofill_helper_.FormDataFilled(query_id, form); } void RenderView::OnAllowScriptToClose(bool script_can_close) { @@ -2146,36 +2086,12 @@ void RenderView::didUpdateInspectorSetting(const WebString& key, void RenderView::queryAutofillSuggestions(const WebNode& node, const WebString& name, const WebString& value) { - static int query_counter = 0; - autofill_query_id_ = query_counter++; - autofill_query_node_ = node; - - const WebFormControlElement& element = - node.toConst<WebFormControlElement>(); - - webkit_glue::FormField field; - FormManager::WebFormControlElementToFormField(element, true, &field); - - // WebFormControlElementToFormField does not scrape the DOM for the field - // label, so find the label here. - // TODO(jhawkins): Add form and field identities so we can use the cached form - // data in FormManager. - field.set_label(FormManager::LabelForElement(element)); - - bool form_autofilled = form_manager_.FormWithNodeIsAutoFilled(node); - Send(new ViewHostMsg_QueryFormFieldAutoFill( - routing_id_, autofill_query_id_, form_autofilled, field)); + autofill_helper_.QueryAutocompleteSuggestions(node, name, value); } void RenderView::removeAutofillSuggestions(const WebString& name, const WebString& value) { - // The index of clear & options will have shifted down. - if (suggestions_clear_index_ != -1) - suggestions_clear_index_--; - if (suggestions_options_index_ != -1) - suggestions_options_index_--; - - Send(new ViewHostMsg_RemoveAutocompleteEntry(routing_id_, name, value)); + autofill_helper_.RemoveAutocompleteSuggestion(name, value); } void RenderView::didAcceptAutoFillSuggestion(const WebKit::WebNode& node, @@ -2183,49 +2099,19 @@ void RenderView::didAcceptAutoFillSuggestion(const WebKit::WebNode& node, const WebKit::WebString& label, int unique_id, unsigned index) { - if (suggestions_options_index_ != -1 && - index == static_cast<unsigned>(suggestions_options_index_)) { - // User selected 'AutoFill Options'. - Send(new ViewHostMsg_ShowAutoFillDialog(routing_id_)); - } else if (suggestions_clear_index_ != -1 && - index == static_cast<unsigned>(suggestions_clear_index_)) { - // User selected 'Clear form'. - // The form has been auto-filled, so give the user the chance to clear the - // form. - form_manager_.ClearFormWithNode(node); - } else if (form_manager_.FormWithNodeIsAutoFilled(node) || !unique_id) { - // User selected an Autocomplete entry, so we fill directly. - WebInputElement element = node.toConst<WebInputElement>(); - element.setValue(value); - - WebFrame* webframe = node.document().frame(); - if (webframe) { - webframe->notifiyPasswordListenerOfAutocomplete(element); - } - } else { - // Fill the values for the whole form. - QueryAutoFillFormData(node, value, label, unique_id, AUTOFILL_FILL); - } - - suggestions_clear_index_ = -1; - suggestions_options_index_ = -1; + autofill_helper_.DidAcceptAutoFillSuggestion(node, value, label, unique_id, + index); } void RenderView::didSelectAutoFillSuggestion(const WebKit::WebNode& node, const WebKit::WebString& value, const WebKit::WebString& label, int unique_id) { - didClearAutoFillSelection(node); - QueryAutoFillFormData(node, value, label, unique_id, AUTOFILL_PREVIEW); + autofill_helper_.DidSelectAutoFillSuggestion(node, value, label, unique_id); } void RenderView::didClearAutoFillSelection(const WebKit::WebNode& node) { - webkit_glue::FormData form; - const WebFormControlElement element = node.toConst<WebFormControlElement>(); - if (!form_manager_.FindFormWithFormControlElement( - element, FormManager::REQUIRE_NONE, &form)) - return; - form_manager_.ClearPreviewedForm(form); + autofill_helper_.DidClearAutoFillSelection(node); } void RenderView::didAcceptAutocompleteSuggestion( @@ -2421,7 +2307,7 @@ void RenderView::willClose(WebFrame* frame) { NavigationState* navigation_state = NavigationState::FromDataSource(ds); navigation_state->user_script_idle_scheduler()->Cancel(); - form_manager_.ResetFrame(frame); + autofill_helper_.FrameWillClose(frame); } bool RenderView::allowImages(WebFrame* frame, bool enabled_per_settings) { @@ -2947,10 +2833,8 @@ void RenderView::didFinishDocumentLoad(WebFrame* frame) { // The document has now been fully loaded. Scan for forms to be sent up to // the browser. - // TODO(jhawkins): Make these use the FormManager. - form_manager_.ExtractForms(frame); - SendForms(frame); - SendPasswordForms(frame, false); + autofill_helper_.FrameContentsAvailable(frame); + password_autocomplete_manager_.SendPasswordForms(frame, false); // Check whether we have new encoding name. UpdateEncoding(frame, frame->view()->pageEncoding().utf8()); @@ -2997,7 +2881,7 @@ void RenderView::didFinishLoad(WebFrame* frame) { navigation_state->user_script_idle_scheduler()->DidFinishLoad(); // Let the password manager know which password forms are actually visible. - SendPasswordForms(frame, true); + password_autocomplete_manager_.SendPasswordForms(frame, true); } void RenderView::didNavigateWithinPage( @@ -5013,26 +4897,6 @@ void RenderView::focusAccessibilityObject( #endif } -void RenderView::SendForms(WebFrame* frame) { - // TODO(jhawkins): Use FormManager once we have strict ordering of form - // control elements in the cache. - WebVector<WebFormElement> web_forms; - frame->forms(web_forms); - - std::vector<FormData> forms; - for (size_t i = 0; i < web_forms.size(); ++i) { - const WebFormElement& web_form = web_forms[i]; - - FormData form; - if (FormManager::WebFormElementToFormData( - web_form, FormManager::REQUIRE_NONE, false, &form)) - forms.push_back(form); - } - - if (!forms.empty()) - Send(new ViewHostMsg_FormsSeen(routing_id_, forms)); -} - void RenderView::didChangeAccessibilityObjectState( const WebKit::WebAccessibilityObject& acc_obj) { #if defined(OS_WIN) @@ -5058,38 +4922,6 @@ void RenderView::didChangeAccessibilityObjectState( #endif } -void RenderView::SendPasswordForms(WebFrame* frame, bool only_visible) { - // Make sure that this security origin is allowed to use password manager. - WebSecurityOrigin security_origin = frame->securityOrigin(); - if (!security_origin.canAccessPasswordManager()) - return; - - WebVector<WebFormElement> forms; - frame->forms(forms); - - std::vector<PasswordForm> password_forms; - for (size_t i = 0; i < forms.size(); ++i) { - const WebFormElement& form = forms[i]; - - // Respect autocomplete=off. - if (!form.autoComplete()) - continue; - if (only_visible && !form.hasNonEmptyBoundingBox()) - continue; - scoped_ptr<PasswordForm> password_form( - PasswordFormDomManager::CreatePasswordForm(form)); - if (password_form.get()) - password_forms.push_back(*password_form); - } - - if (password_forms.empty()) - return; - if (only_visible) - Send(new ViewHostMsg_PasswordFormsVisible(routing_id_, password_forms)); - else - Send(new ViewHostMsg_PasswordFormsFound(routing_id_, password_forms)); -} - void RenderView::Print(WebFrame* frame, bool script_initiated) { DCHECK(frame); if (print_helper_.get() == NULL) { @@ -5306,8 +5138,7 @@ void RenderView::OnPageTranslated() { return; // The page is translated, so try to extract the form data again. - form_manager_.ExtractForms(frame); - SendForms(frame); + autofill_helper_.FrameContentsAvailable(frame); } WebKit::WebGeolocationService* RenderView::geolocationService() { @@ -5355,21 +5186,3 @@ bool RenderView::IsNonLocalTopLevelNavigation( return false; } -void RenderView::QueryAutoFillFormData(const WebKit::WebNode& node, - const WebKit::WebString& value, - const WebKit::WebString& label, - int unique_id, - AutoFillAction action) { - static int query_counter = 0; - autofill_query_id_ = query_counter++; - - webkit_glue::FormData form; - const WebInputElement element = node.toConst<WebInputElement>(); - if (!form_manager_.FindFormWithFormControlElement( - element, FormManager::REQUIRE_NONE, &form)) - return; - - autofill_action_ = action; - Send(new ViewHostMsg_FillAutoFillFormData( - routing_id_, autofill_query_id_, form, value, label, unique_id)); -} diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h index 72bdad5..4974d1c 100644 --- a/chrome/renderer/render_view.h +++ b/chrome/renderer/render_view.h @@ -31,11 +31,11 @@ #include "chrome/common/renderer_preferences.h" #include "chrome/common/translate_errors.h" #include "chrome/common/view_types.h" +#include "chrome/renderer/autofill_helper.h" #include "chrome/renderer/automation/dom_automation_controller.h" #include "chrome/renderer/dom_ui_bindings.h" #include "chrome/renderer/extensions/extension_process_bindings.h" #include "chrome/renderer/external_host_bindings.h" -#include "chrome/renderer/form_manager.h" #include "chrome/renderer/notification_provider.h" #include "chrome/renderer/password_autocomplete_manager.h" #include "chrome/renderer/pepper_plugin_delegate_impl.h" @@ -603,18 +603,10 @@ class RenderView : public RenderWidget, #endif FRIEND_TEST(RenderViewTest, JSBlockSentAfterPageLoad); FRIEND_TEST(RenderViewTest, UpdateTargetURLWithInvalidURL); - FRIEND_TEST(RenderViewTest, SendForms); - FRIEND_TEST(RenderViewTest, FillFormElement); typedef std::map<GURL, ContentSettings> HostContentSettings; typedef std::map<GURL, int> HostZoomLevels; - enum AutoFillAction { - AUTOFILL_NONE, // No state set. - AUTOFILL_FILL, // Fill the AutoFill form data. - AUTOFILL_PREVIEW, // Preview the AutoFill form data. - }; - enum ErrorPageType { DNS_ERROR, HTTP_404, @@ -939,23 +931,6 @@ class RenderView : public RenderWidget, void Print(WebKit::WebFrame* frame, bool script_initiated); - // Queries the AutoFillManager for form data for the form containing |node|. - // |value| is the current text in the field, and |unique_id| is the selected - // profile's unique ID. |action| specifies whether to Fill or Preview the - // values returned from the AutoFillManager. - void QueryAutoFillFormData(const WebKit::WebNode& node, - const WebKit::WebString& value, - const WebKit::WebString& label, - int unique_id, - AutoFillAction action); - - // Scans the given frame for forms and sends them up to the browser. - void SendForms(WebKit::WebFrame* frame); - - // Scans the given frame for password forms and sends them up to the browser. - // If |only_visible| is true, only forms visible in the layout are sent - void SendPasswordForms(WebKit::WebFrame* frame, bool only_visible); - // Returns whether the page associated with |document| is a candidate for // translation. Some pages can explictly specify (via a meta-tag) that they // should not be translated. @@ -1173,25 +1148,6 @@ class RenderView : public RenderWidget, // https://bugs.webkit.org/show_bug.cgi?id=32807. base::RepeatingTimer<RenderView> preferred_size_change_timer_; - // AutoFill ------------------------------------------------------------------ - - // The id of the last request sent for form field AutoFill. Used to ignore - // out of date responses. - int autofill_query_id_; - - // The id of the node corresponding to the last request sent for form field - // AutoFill. - WebKit::WebNode autofill_query_node_; - - // The action to take when receiving AutoFill data from the AutoFillManager. - AutoFillAction autofill_action_; - - // The menu index of the "Clear" menu item. - int suggestions_clear_index_; - - // The menu index of the "AutoFill options..." menu item. - int suggestions_options_index_; - // Plugins ------------------------------------------------------------------- // Remember the first uninstalled plugin, so that we can ask the plugin @@ -1213,8 +1169,6 @@ class RenderView : public RenderWidget, // Helper objects ------------------------------------------------------------ - FormManager form_manager_; - ScopedRunnableMethodFactory<RenderView> method_factory_; // Responsible for translating the page contents to other languages. @@ -1223,6 +1177,10 @@ class RenderView : public RenderWidget, // Responsible for automatically filling login and password textfields. PasswordAutocompleteManager password_autocomplete_manager_; + // Responsible for filling forms (AutoFill) and single text entries + // (Autocomplete). + AutoFillHelper autofill_helper_; + RendererWebCookieJarImpl cookie_jar_; // Provides access to this renderer from the remote Inspector UI. |