| 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/message_loop.h" | 7 #include "base/message_loop.h" |
| 8 #include "base/utf_string_conversions.h" | 8 #include "base/utf_string_conversions.h" |
| 9 #include "chrome/common/autofill_messages.h" | 9 #include "chrome/common/autofill_messages.h" |
| 10 #include "chrome/common/chrome_constants.h" | 10 #include "chrome/common/chrome_constants.h" |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 227 web_view->hidePopups(); | 227 web_view->hidePopups(); |
| 228 return; | 228 return; |
| 229 } | 229 } |
| 230 | 230 |
| 231 std::vector<string16> v(values); | 231 std::vector<string16> v(values); |
| 232 std::vector<string16> l(labels); | 232 std::vector<string16> l(labels); |
| 233 std::vector<string16> i(icons); | 233 std::vector<string16> i(icons); |
| 234 std::vector<int> ids(unique_ids); | 234 std::vector<int> ids(unique_ids); |
| 235 int separator_index = -1; | 235 int separator_index = -1; |
| 236 | 236 |
| 237 if (ids[0] < 0 && ids.size() > 1) { | 237 if (!autofill_query_element_.isNull() && |
| 238 !autofill_query_element_.autoComplete()) { |
| 239 // If autofill is disabled and we had suggestions, show a warning instead. |
| 240 v.assign(1, l10n_util::GetStringUTF16(IDS_AUTOFILL_WARNING_FORM_DISABLED)); |
| 241 l.assign(1, string16()); |
| 242 i.assign(1, string16()); |
| 243 ids.assign(1, -1); |
| 244 } else if (ids[0] < 0 && ids.size() > 1) { |
| 238 // If we received a warning instead of suggestions from autofill but regular | 245 // If we received a warning instead of suggestions from autofill but regular |
| 239 // suggestions from autocomplete, don't show the autofill warning. | 246 // suggestions from autocomplete, don't show the autofill warning. |
| 240 v.erase(v.begin()); | 247 v.erase(v.begin()); |
| 241 l.erase(l.begin()); | 248 l.erase(l.begin()); |
| 242 i.erase(i.begin()); | 249 i.erase(i.begin()); |
| 243 ids.erase(ids.begin()); | 250 ids.erase(ids.begin()); |
| 244 } | 251 } |
| 245 | 252 |
| 246 // If we were about to show a warning and we shouldn't, don't. | 253 // If we were about to show a warning and we shouldn't, don't. |
| 247 if (ids[0] < 0 && !display_warning_if_disabled_) | 254 if (ids[0] < 0 && !display_warning_if_disabled_) |
| 248 return; | 255 return; |
| 249 | 256 |
| 250 // Only include "Autofill Options" special menu item if we have Autofill | 257 // Only include "Autofill Options" special menu item if we have Autofill |
| 251 // items, identified by |unique_ids| having at least one valid value. | 258 // items, identified by |unique_ids| having at least one valid value. |
| 252 bool has_autofill_item = false; | 259 bool has_autofill_item = false; |
| 253 for (size_t i = 0; i < ids.size(); ++i) { | 260 for (size_t i = 0; i < ids.size(); ++i) { |
| 254 if (ids[i] > 0) { | 261 if (ids[i] > 0) { |
| 255 has_autofill_item = true; | 262 has_autofill_item = true; |
| 256 break; | 263 break; |
| 257 } | 264 } |
| 258 } | 265 } |
| 259 | 266 |
| 260 // The form has been auto-filled, so give the user the chance to clear the | 267 // The form has been auto-filled, so give the user the chance to clear the |
| 261 // form. Append the 'Clear form' menu item. | 268 // form. Append the 'Clear form' menu item. |
| 262 if (has_autofill_item && | 269 if (has_autofill_item && |
| 263 form_manager_.FormWithNodeIsAutofilled(autofill_query_node_)) { | 270 form_manager_.FormWithNodeIsAutofilled(autofill_query_element_)) { |
| 264 v.push_back(l10n_util::GetStringUTF16(IDS_AUTOFILL_CLEAR_FORM_MENU_ITEM)); | 271 v.push_back(l10n_util::GetStringUTF16(IDS_AUTOFILL_CLEAR_FORM_MENU_ITEM)); |
| 265 l.push_back(string16()); | 272 l.push_back(string16()); |
| 266 i.push_back(string16()); | 273 i.push_back(string16()); |
| 267 ids.push_back(0); | 274 ids.push_back(0); |
| 268 suggestions_clear_index_ = v.size() - 1; | 275 suggestions_clear_index_ = v.size() - 1; |
| 269 separator_index = v.size() - 1; | 276 separator_index = v.size() - 1; |
| 270 } | 277 } |
| 271 | 278 |
| 272 if (has_autofill_item) { | 279 if (has_autofill_item) { |
| 273 // Append the 'Chrome Autofill options' menu item; | 280 // Append the 'Chrome Autofill options' menu item; |
| 274 v.push_back(l10n_util::GetStringFUTF16(IDS_AUTOFILL_OPTIONS_POPUP, | 281 v.push_back(l10n_util::GetStringFUTF16(IDS_AUTOFILL_OPTIONS_POPUP, |
| 275 WideToUTF16(chrome::kBrowserAppName))); | 282 WideToUTF16(chrome::kBrowserAppName))); |
| 276 l.push_back(string16()); | 283 l.push_back(string16()); |
| 277 i.push_back(string16()); | 284 i.push_back(string16()); |
| 278 ids.push_back(0); | 285 ids.push_back(0); |
| 279 suggestions_options_index_ = v.size() - 1; | 286 suggestions_options_index_ = v.size() - 1; |
| 280 separator_index = values.size(); | 287 separator_index = values.size(); |
| 281 } | 288 } |
| 282 | 289 |
| 283 // Send to WebKit for display. | 290 // Send to WebKit for display. |
| 284 if (!v.empty() && !autofill_query_node_.isNull() && | 291 if (!v.empty() && !autofill_query_element_.isNull() && |
| 285 autofill_query_node_.isFocusable()) { | 292 autofill_query_element_.isFocusable()) { |
| 286 web_view->applyAutofillSuggestions( | 293 web_view->applyAutofillSuggestions( |
| 287 autofill_query_node_, v, l, i, ids, separator_index); | 294 autofill_query_element_, v, l, i, ids, separator_index); |
| 288 } | 295 } |
| 289 | 296 |
| 290 Send(new AutofillHostMsg_DidShowAutofillSuggestions(routing_id())); | 297 Send(new AutofillHostMsg_DidShowAutofillSuggestions(routing_id())); |
| 291 } | 298 } |
| 292 | 299 |
| 293 void AutofillAgent::OnFormDataFilled(int query_id, | 300 void AutofillAgent::OnFormDataFilled(int query_id, |
| 294 const webkit_glue::FormData& form) { | 301 const webkit_glue::FormData& form) { |
| 295 if (!render_view()->webview() || query_id != autofill_query_id_) | 302 if (!render_view()->webview() || query_id != autofill_query_id_) |
| 296 return; | 303 return; |
| 297 | 304 |
| 298 switch (autofill_action_) { | 305 switch (autofill_action_) { |
| 299 case AUTOFILL_FILL: | 306 case AUTOFILL_FILL: |
| 300 form_manager_.FillForm(form, autofill_query_node_); | 307 form_manager_.FillForm(form, autofill_query_element_); |
| 301 break; | 308 break; |
| 302 case AUTOFILL_PREVIEW: | 309 case AUTOFILL_PREVIEW: |
| 303 form_manager_.PreviewForm(form, autofill_query_node_); | 310 form_manager_.PreviewForm(form, autofill_query_element_); |
| 304 break; | 311 break; |
| 305 default: | 312 default: |
| 306 NOTREACHED(); | 313 NOTREACHED(); |
| 307 } | 314 } |
| 308 autofill_action_ = AUTOFILL_NONE; | 315 autofill_action_ = AUTOFILL_NONE; |
| 309 Send(new AutofillHostMsg_DidFillAutofillFormData(routing_id())); | 316 Send(new AutofillHostMsg_DidFillAutofillFormData(routing_id())); |
| 310 } | 317 } |
| 311 | 318 |
| 312 void AutofillAgent::OnFieldTypePredictionsAvailable( | 319 void AutofillAgent::OnFieldTypePredictionsAvailable( |
| 313 const std::vector<FormDataPredictions>& forms) { | 320 const std::vector<FormDataPredictions>& forms) { |
| 314 for (size_t i = 0; i < forms.size(); ++i) { | 321 for (size_t i = 0; i < forms.size(); ++i) { |
| 315 form_manager_.ShowPredictions(forms[i]); | 322 form_manager_.ShowPredictions(forms[i]); |
| 316 } | 323 } |
| 317 } | 324 } |
| 318 | 325 |
| 319 void AutofillAgent::ShowSuggestions(const WebInputElement& element, | 326 void AutofillAgent::ShowSuggestions(const WebInputElement& element, |
| 320 bool autofill_on_empty_values, | 327 bool autofill_on_empty_values, |
| 321 bool requires_caret_at_end, | 328 bool requires_caret_at_end, |
| 322 bool display_warning_if_disabled) { | 329 bool display_warning_if_disabled) { |
| 323 if (!element.isEnabled() || element.isReadOnly() || !element.autoComplete() || | 330 // If autocomplete is disabled at the form level, then we might want to show |
| 331 // a warning in place of suggestions. However, if autocomplete is disabled |
| 332 // specifically for this field, we never want to show a warning. Otherwise, |
| 333 // we might interfere with custom popups (e.g. search suggestions) used by |
| 334 // the website. |
| 335 const WebFormElement form = element.form(); |
| 336 if (!element.isEnabled() || element.isReadOnly() || |
| 337 (!element.autoComplete() && form.autoComplete()) || |
| 324 !element.isTextField() || element.isPasswordField() || | 338 !element.isTextField() || element.isPasswordField() || |
| 325 !element.suggestedValue().isEmpty()) | 339 !element.suggestedValue().isEmpty()) |
| 326 return; | 340 return; |
| 327 | 341 |
| 328 // If the field has no name, then we won't have values. | 342 // If the field has no name, then we won't have values. |
| 329 if (element.nameForAutofill().isEmpty()) | 343 if (element.nameForAutofill().isEmpty()) |
| 330 return; | 344 return; |
| 331 | 345 |
| 332 // Don't attempt to autofill with values that are too large. | 346 // Don't attempt to autofill with values that are too large. |
| 333 WebString value = element.value(); | 347 WebString value = element.value(); |
| 334 if (value.length() > kMaximumTextSizeForAutofill) | 348 if (value.length() > kMaximumTextSizeForAutofill) |
| 335 return; | 349 return; |
| 336 | 350 |
| 337 if (!autofill_on_empty_values && value.isEmpty()) | 351 if (!autofill_on_empty_values && value.isEmpty()) |
| 338 return; | 352 return; |
| 339 | 353 |
| 340 if (requires_caret_at_end && | 354 if (requires_caret_at_end && |
| 341 (element.selectionStart() != element.selectionEnd() || | 355 (element.selectionStart() != element.selectionEnd() || |
| 342 element.selectionEnd() != static_cast<int>(value.length()))) | 356 element.selectionEnd() != static_cast<int>(value.length()))) |
| 343 return; | 357 return; |
| 344 | 358 |
| 345 QueryAutofillSuggestions(element, display_warning_if_disabled); | 359 QueryAutofillSuggestions(element, display_warning_if_disabled); |
| 346 } | 360 } |
| 347 | 361 |
| 348 void AutofillAgent::QueryAutofillSuggestions(const WebNode& node, | 362 void AutofillAgent::QueryAutofillSuggestions(const WebInputElement& element, |
| 349 bool display_warning_if_disabled) { | 363 bool display_warning_if_disabled) { |
| 350 static int query_counter = 0; | 364 static int query_counter = 0; |
| 351 autofill_query_id_ = query_counter++; | 365 autofill_query_id_ = query_counter++; |
| 352 autofill_query_node_ = node; | 366 autofill_query_element_ = element; |
| 353 display_warning_if_disabled_ = display_warning_if_disabled; | 367 display_warning_if_disabled_ = display_warning_if_disabled; |
| 354 | 368 |
| 355 webkit_glue::FormData form; | 369 webkit_glue::FormData form; |
| 356 webkit_glue::FormField field; | 370 webkit_glue::FormField field; |
| 357 if (!FindFormAndFieldForNode(node, &form, &field)) { | 371 if (!FindFormAndFieldForNode(element, &form, &field)) { |
| 358 // If we didn't find the cached form, at least let autocomplete have a shot | 372 // If we didn't find the cached form, at least let autocomplete have a shot |
| 359 // at providing suggestions. | 373 // at providing suggestions. |
| 360 FormManager::WebFormControlElementToFormField( | 374 FormManager::WebFormControlElementToFormField(element, |
| 361 node.toConst<WebFormControlElement>(), FormManager::EXTRACT_VALUE, | 375 FormManager::EXTRACT_VALUE, |
| 362 &field); | 376 &field); |
| 363 } | 377 } |
| 364 | 378 |
| 365 Send(new AutofillHostMsg_QueryFormFieldAutofill( | 379 Send(new AutofillHostMsg_QueryFormFieldAutofill( |
| 366 routing_id(), autofill_query_id_, form, field)); | 380 routing_id(), autofill_query_id_, form, field)); |
| 367 } | 381 } |
| 368 | 382 |
| 369 void AutofillAgent::FillAutofillFormData(const WebNode& node, | 383 void AutofillAgent::FillAutofillFormData(const WebNode& node, |
| 370 int unique_id, | 384 int unique_id, |
| 371 AutofillAction action) { | 385 AutofillAction action) { |
| 372 static int query_counter = 0; | 386 static int query_counter = 0; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 397 // WebFormControlElementToFormField does not scrape the DOM for the field | 411 // WebFormControlElementToFormField does not scrape the DOM for the field |
| 398 // label, so find the label here. | 412 // label, so find the label here. |
| 399 // TODO(isherman): Add form and field identities so we can use the cached form | 413 // TODO(isherman): Add form and field identities so we can use the cached form |
| 400 // data in FormManager. | 414 // data in FormManager. |
| 401 field->label = FormManager::LabelForElement(element); | 415 field->label = FormManager::LabelForElement(element); |
| 402 | 416 |
| 403 return true; | 417 return true; |
| 404 } | 418 } |
| 405 | 419 |
| 406 } // namespace autofill | 420 } // namespace autofill |
| OLD | NEW |