Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/renderer/autofill/autofill_agent.h" | 5 #include "chrome/renderer/autofill/autofill_agent.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
| 9 #include "base/time.h" | 9 #include "base/time.h" |
| 10 #include "base/utf_string_conversions.h" | 10 #include "base/utf_string_conversions.h" |
| 11 #include "chrome/common/autofill_messages.h" | 11 #include "chrome/common/autofill_messages.h" |
| 12 #include "chrome/common/chrome_constants.h" | 12 #include "chrome/common/chrome_constants.h" |
| 13 #include "chrome/renderer/autofill/form_autofill_util.h" | 13 #include "chrome/renderer/autofill/form_autofill_util.h" |
| 14 #include "chrome/renderer/autofill/password_autofill_manager.h" | 14 #include "chrome/renderer/autofill/password_autofill_manager.h" |
| 15 #include "content/public/renderer/render_view.h" | 15 #include "content/public/renderer/render_view.h" |
| 16 #include "grit/generated_resources.h" | 16 #include "grit/generated_resources.h" |
| 17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" | 17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" |
| 18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFormControlElement .h" | 18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFormControlElement .h" |
| 19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" | 19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" |
| 20 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h" | 20 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h" |
| 21 #include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h" | 21 #include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h" |
| 22 #include "third_party/WebKit/Source/WebKit/chromium/public/WebRect.h" | |
| 22 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" | 23 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" |
| 23 #include "ui/base/keycodes/keyboard_codes.h" | 24 #include "ui/base/keycodes/keyboard_codes.h" |
| 24 #include "ui/base/l10n/l10n_util.h" | 25 #include "ui/base/l10n/l10n_util.h" |
| 25 #include "webkit/glue/form_data.h" | 26 #include "webkit/glue/form_data.h" |
| 26 #include "webkit/glue/form_data_predictions.h" | 27 #include "webkit/glue/form_data_predictions.h" |
| 27 #include "webkit/glue/form_field.h" | 28 #include "webkit/glue/form_field.h" |
| 28 #include "webkit/glue/password_form.h" | 29 #include "webkit/glue/password_form.h" |
| 29 | 30 |
| 30 using WebKit::WebFormControlElement; | 31 using WebKit::WebFormControlElement; |
| 31 using WebKit::WebFormElement; | 32 using WebKit::WebFormElement; |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 52 PasswordAutofillManager* password_autofill_manager) | 53 PasswordAutofillManager* password_autofill_manager) |
| 53 : content::RenderViewObserver(render_view), | 54 : content::RenderViewObserver(render_view), |
| 54 password_autofill_manager_(password_autofill_manager), | 55 password_autofill_manager_(password_autofill_manager), |
| 55 autofill_query_id_(0), | 56 autofill_query_id_(0), |
| 56 autofill_action_(AUTOFILL_NONE), | 57 autofill_action_(AUTOFILL_NONE), |
| 57 display_warning_if_disabled_(false), | 58 display_warning_if_disabled_(false), |
| 58 was_query_node_autofilled_(false), | 59 was_query_node_autofilled_(false), |
| 59 suggestions_clear_index_(-1), | 60 suggestions_clear_index_(-1), |
| 60 suggestions_options_index_(-1), | 61 suggestions_options_index_(-1), |
| 61 has_shown_autofill_popup_for_current_edit_(false), | 62 has_shown_autofill_popup_for_current_edit_(false), |
| 63 has_external_delegate_(false), | |
| 62 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { | 64 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { |
| 63 render_view->GetWebView()->setAutofillClient(this); | 65 render_view->GetWebView()->setAutofillClient(this); |
| 64 } | 66 } |
| 65 | 67 |
| 66 AutofillAgent::~AutofillAgent() {} | 68 AutofillAgent::~AutofillAgent() {} |
| 67 | 69 |
| 68 bool AutofillAgent::OnMessageReceived(const IPC::Message& message) { | 70 bool AutofillAgent::OnMessageReceived(const IPC::Message& message) { |
| 69 bool handled = true; | 71 bool handled = true; |
| 70 IPC_BEGIN_MESSAGE_MAP(AutofillAgent, message) | 72 IPC_BEGIN_MESSAGE_MAP(AutofillAgent, message) |
| 71 IPC_MESSAGE_HANDLER(AutofillMsg_SuggestionsReturned, OnSuggestionsReturned) | 73 IPC_MESSAGE_HANDLER(AutofillMsg_SuggestionsReturned, OnSuggestionsReturned) |
| 72 IPC_MESSAGE_HANDLER(AutofillMsg_FormDataFilled, OnFormDataFilled) | 74 IPC_MESSAGE_HANDLER(AutofillMsg_FormDataFilled, OnFormDataFilled) |
| 73 IPC_MESSAGE_HANDLER(AutofillMsg_FieldTypePredictionsAvailable, | 75 IPC_MESSAGE_HANDLER(AutofillMsg_FieldTypePredictionsAvailable, |
| 74 OnFieldTypePredictionsAvailable) | 76 OnFieldTypePredictionsAvailable) |
| 75 IPC_MESSAGE_HANDLER(AutofillMsg_SelectAutofillSuggestionAtIndex, | 77 IPC_MESSAGE_HANDLER(AutofillMsg_SelectAutofillSuggestionAtIndex, |
| 76 OnSelectAutofillSuggestionAtIndex) | 78 OnSelectAutofillSuggestionAtIndex) |
| 79 IPC_MESSAGE_HANDLER(AutofillMsg_HasExternalDelegate, | |
| 80 HasExternalDelegate) | |
| 77 IPC_MESSAGE_UNHANDLED(handled = false) | 81 IPC_MESSAGE_UNHANDLED(handled = false) |
| 78 IPC_END_MESSAGE_MAP() | 82 IPC_END_MESSAGE_MAP() |
| 79 return handled; | 83 return handled; |
| 80 } | 84 } |
| 81 | 85 |
| 82 void AutofillAgent::DidFinishDocumentLoad(WebFrame* frame) { | 86 void AutofillAgent::DidFinishDocumentLoad(WebFrame* frame) { |
| 83 // The document has now been fully loaded. Scan for forms to be sent up to | 87 // The document has now been fully loaded. Scan for forms to be sent up to |
| 84 // the browser. | 88 // the browser. |
| 85 std::vector<webkit_glue::FormData> forms; | 89 std::vector<webkit_glue::FormData> forms; |
| 86 form_cache_.ExtractForms(*frame, &forms); | 90 form_cache_.ExtractForms(*frame, &forms); |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 117 bool AutofillAgent::InputElementClicked(const WebInputElement& element, | 121 bool AutofillAgent::InputElementClicked(const WebInputElement& element, |
| 118 bool was_focused, | 122 bool was_focused, |
| 119 bool is_focused) { | 123 bool is_focused) { |
| 120 if (was_focused) | 124 if (was_focused) |
| 121 ShowSuggestions(element, true, false, true); | 125 ShowSuggestions(element, true, false, true); |
| 122 | 126 |
| 123 return false; | 127 return false; |
| 124 } | 128 } |
| 125 | 129 |
| 126 bool AutofillAgent::InputElementLostFocus() { | 130 bool AutofillAgent::InputElementLostFocus() { |
| 131 if (has_external_delegate_) | |
| 132 Send(new AutofillDelegateMsg_HideAutofillPopup(routing_id())); | |
| 133 | |
| 127 return false; | 134 return false; |
| 128 } | 135 } |
| 129 | 136 |
| 130 void AutofillAgent::didAcceptAutofillSuggestion(const WebNode& node, | 137 void AutofillAgent::didAcceptAutofillSuggestion(const WebNode& node, |
| 131 const WebString& value, | 138 const WebString& value, |
| 132 const WebString& label, | 139 const WebString& label, |
| 133 int unique_id, | 140 int unique_id, |
| 134 unsigned index) { | 141 unsigned index) { |
| 135 if (password_autofill_manager_->DidAcceptAutofillSuggestion(node, value)) | 142 if (password_autofill_manager_->DidAcceptAutofillSuggestion(node, value)) |
| 136 return; | 143 return; |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 245 const std::vector<string16>& labels, | 252 const std::vector<string16>& labels, |
| 246 const std::vector<string16>& icons, | 253 const std::vector<string16>& icons, |
| 247 const std::vector<int>& unique_ids) { | 254 const std::vector<int>& unique_ids) { |
| 248 WebKit::WebView* web_view = render_view()->GetWebView(); | 255 WebKit::WebView* web_view = render_view()->GetWebView(); |
| 249 if (!web_view || query_id != autofill_query_id_) | 256 if (!web_view || query_id != autofill_query_id_) |
| 250 return; | 257 return; |
| 251 | 258 |
| 252 if (values.empty()) { | 259 if (values.empty()) { |
| 253 // No suggestions, any popup currently showing is obsolete. | 260 // No suggestions, any popup currently showing is obsolete. |
| 254 web_view->hidePopups(); | 261 web_view->hidePopups(); |
| 262 if (has_external_delegate_) | |
| 263 Send(new AutofillDelegateMsg_HideAutofillPopup(routing_id())); | |
|
Ilya Sherman
2011/11/07 21:48:49
This call shouldn't be necessary -- all the releva
csharp1
2011/11/08 19:59:00
Done.
| |
| 255 return; | 264 return; |
| 256 } | 265 } |
| 257 | 266 |
| 258 std::vector<string16> v(values); | 267 std::vector<string16> v(values); |
| 259 std::vector<string16> l(labels); | 268 std::vector<string16> l(labels); |
| 260 std::vector<string16> i(icons); | 269 std::vector<string16> i(icons); |
| 261 std::vector<int> ids(unique_ids); | 270 std::vector<int> ids(unique_ids); |
| 262 int separator_index = -1; | 271 int separator_index = -1; |
| 263 | 272 |
| 264 DCHECK_GT(ids.size(), 0U); | 273 DCHECK_GT(ids.size(), 0U); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 308 // Append the 'Chrome Autofill options' menu item; | 317 // Append the 'Chrome Autofill options' menu item; |
| 309 v.push_back(l10n_util::GetStringFUTF16(IDS_AUTOFILL_OPTIONS_POPUP, | 318 v.push_back(l10n_util::GetStringFUTF16(IDS_AUTOFILL_OPTIONS_POPUP, |
| 310 WideToUTF16(chrome::kBrowserAppName))); | 319 WideToUTF16(chrome::kBrowserAppName))); |
| 311 l.push_back(string16()); | 320 l.push_back(string16()); |
| 312 i.push_back(string16()); | 321 i.push_back(string16()); |
| 313 ids.push_back(0); | 322 ids.push_back(0); |
| 314 suggestions_options_index_ = v.size() - 1; | 323 suggestions_options_index_ = v.size() - 1; |
| 315 separator_index = values.size(); | 324 separator_index = values.size(); |
| 316 } | 325 } |
| 317 | 326 |
| 318 // Send to WebKit for display. | |
| 319 if (!v.empty() && !autofill_query_element_.isNull() && | 327 if (!v.empty() && !autofill_query_element_.isNull() && |
| 320 autofill_query_element_.isFocusable()) { | 328 autofill_query_element_.isFocusable()) { |
| 321 web_view->applyAutofillSuggestions( | 329 if (has_external_delegate_) { |
| 322 autofill_query_element_, v, l, i, ids, separator_index); | 330 // Send to an external delegate for display. |
| 331 WebKit::WebRect autofill_element_rect = | |
| 332 autofill_query_element_.getRect(); | |
| 333 | |
| 334 Send(new AutofillDelegateMsg_AutofillElementBounds( | |
| 335 routing_id(), | |
| 336 autofill_element_rect.x, | |
| 337 autofill_element_rect.y, | |
| 338 autofill_element_rect.width, | |
| 339 autofill_element_rect.height)); | |
| 340 | |
| 341 Send(new AutofillDelegateMsg_ShowAutofillSuggestions( | |
| 342 routing_id(), query_id, v, l, i, ids)); | |
|
Ilya Sherman
2011/11/07 21:48:49
We'll need to rework how warnings are handled; but
csharp1
2011/11/08 19:59:00
So if I understand correctly, you are suggesting t
Ilya Sherman
2011/11/08 21:06:16
Right. Once the transition to the browser-side UI
csharp
2011/11/09 16:18:37
Ok, I've added a todo to copy the logic over. I qu
| |
| 343 } else { | |
| 344 // Send to WebKit for display. | |
| 345 web_view->applyAutofillSuggestions( | |
| 346 autofill_query_element_, v, l, i, ids, separator_index); | |
| 347 } | |
| 348 } else { | |
| 349 if (has_external_delegate_) | |
| 350 Send(new AutofillDelegateMsg_HideAutofillPopup(routing_id())); | |
| 323 } | 351 } |
| 324 | 352 |
| 325 Send(new AutofillHostMsg_DidShowAutofillSuggestions( | 353 Send(new AutofillHostMsg_DidShowAutofillSuggestions( |
| 326 routing_id(), | 354 routing_id(), |
| 327 has_autofill_item && !has_shown_autofill_popup_for_current_edit_)); | 355 has_autofill_item && !has_shown_autofill_popup_for_current_edit_)); |
| 328 has_shown_autofill_popup_for_current_edit_ |= has_autofill_item; | 356 has_shown_autofill_popup_for_current_edit_ |= has_autofill_item; |
| 329 } | 357 } |
| 330 | 358 |
| 331 void AutofillAgent::OnFormDataFilled(int query_id, | 359 void AutofillAgent::OnFormDataFilled(int query_id, |
| 332 const webkit_glue::FormData& form) { | 360 const webkit_glue::FormData& form) { |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 355 form_cache_.ShowPredictions(forms[i]); | 383 form_cache_.ShowPredictions(forms[i]); |
| 356 } | 384 } |
| 357 } | 385 } |
| 358 | 386 |
| 359 void AutofillAgent::OnSelectAutofillSuggestionAtIndex(int listIndex) { | 387 void AutofillAgent::OnSelectAutofillSuggestionAtIndex(int listIndex) { |
| 360 NOTIMPLEMENTED(); | 388 NOTIMPLEMENTED(); |
| 361 // TODO(jrg): enable once changes land in WebKit | 389 // TODO(jrg): enable once changes land in WebKit |
| 362 // render_view()->webview()->selectAutofillSuggestionAtIndex(listIndex); | 390 // render_view()->webview()->selectAutofillSuggestionAtIndex(listIndex); |
| 363 } | 391 } |
| 364 | 392 |
| 393 void AutofillAgent::HasExternalDelegate(bool has_external_delegate) { | |
| 394 has_external_delegate_ = has_external_delegate; | |
| 395 } | |
| 396 | |
| 365 void AutofillAgent::ShowSuggestions(const WebInputElement& element, | 397 void AutofillAgent::ShowSuggestions(const WebInputElement& element, |
| 366 bool autofill_on_empty_values, | 398 bool autofill_on_empty_values, |
| 367 bool requires_caret_at_end, | 399 bool requires_caret_at_end, |
| 368 bool display_warning_if_disabled) { | 400 bool display_warning_if_disabled) { |
| 369 // If autocomplete is disabled at the form level, then we might want to show | 401 // If autocomplete is disabled at the form level, then we might want to show |
| 370 // a warning in place of suggestions. However, if autocomplete is disabled | 402 // a warning in place of suggestions. However, if autocomplete is disabled |
| 371 // specifically for this field, we never want to show a warning. Otherwise, | 403 // specifically for this field, we never want to show a warning. Otherwise, |
| 372 // we might interfere with custom popups (e.g. search suggestions) used by | 404 // we might interfere with custom popups (e.g. search suggestions) used by |
| 373 // the website. | 405 // the website. |
| 374 const WebFormElement form = element.form(); | 406 const WebFormElement form = element.form(); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 431 return; | 463 return; |
| 432 } | 464 } |
| 433 | 465 |
| 434 autofill_action_ = action; | 466 autofill_action_ = action; |
| 435 was_query_node_autofilled_ = field.is_autofilled; | 467 was_query_node_autofilled_ = field.is_autofilled; |
| 436 Send(new AutofillHostMsg_FillAutofillFormData( | 468 Send(new AutofillHostMsg_FillAutofillFormData( |
| 437 routing_id(), autofill_query_id_, form, field, unique_id)); | 469 routing_id(), autofill_query_id_, form, field, unique_id)); |
| 438 } | 470 } |
| 439 | 471 |
| 440 } // namespace autofill | 472 } // namespace autofill |
| OLD | NEW |