OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "components/autofill/content/renderer/password_autofill_agent.h" | 5 #include "components/autofill/content/renderer/password_autofill_agent.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/memory/scoped_ptr.h" | 8 #include "base/memory/scoped_ptr.h" |
9 #include "base/message_loop/message_loop.h" | 9 #include "base/message_loop/message_loop.h" |
10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
239 PasswordAutofillAgent::~PasswordAutofillAgent() { | 239 PasswordAutofillAgent::~PasswordAutofillAgent() { |
240 } | 240 } |
241 | 241 |
242 PasswordAutofillAgent::PasswordValueGatekeeper::PasswordValueGatekeeper() | 242 PasswordAutofillAgent::PasswordValueGatekeeper::PasswordValueGatekeeper() |
243 : was_user_gesture_seen_(false) { | 243 : was_user_gesture_seen_(false) { |
244 } | 244 } |
245 | 245 |
246 PasswordAutofillAgent::PasswordValueGatekeeper::~PasswordValueGatekeeper() { | 246 PasswordAutofillAgent::PasswordValueGatekeeper::~PasswordValueGatekeeper() { |
247 } | 247 } |
248 | 248 |
249 void PasswordAutofillAgent::PasswordValueGatekeeper::RegisterElement( | 249 void PasswordAutofillAgent::PasswordValueGatekeeper::RegisterElementInfo( |
250 blink::WebInputElement* element) { | 250 PasswordInfo* element_info) { |
251 if (was_user_gesture_seen_) | 251 DCHECK(element_info); |
252 ShowValue(element); | 252 if (was_user_gesture_seen_) { |
253 else | 253 ShowValue(&element_info->password_field); |
254 elements_.push_back(*element); | 254 } else { |
255 elements_info_.insert(element_info); | |
256 } | |
257 } | |
258 | |
259 void PasswordAutofillAgent::PasswordValueGatekeeper::UnregisterElementInfo( | |
260 PasswordInfo* element_info) { | |
261 elements_info_.erase(element_info); | |
255 } | 262 } |
256 | 263 |
257 void PasswordAutofillAgent::PasswordValueGatekeeper::OnUserGesture() { | 264 void PasswordAutofillAgent::PasswordValueGatekeeper::OnUserGesture() { |
258 was_user_gesture_seen_ = true; | 265 was_user_gesture_seen_ = true; |
259 | 266 |
260 for (std::vector<blink::WebInputElement>::iterator it = elements_.begin(); | 267 for (std::set<PasswordInfo*>::iterator it = elements_info_.begin(); |
261 it != elements_.end(); | 268 it != elements_info_.end(); |
262 ++it) { | 269 ++it) { |
263 ShowValue(&(*it)); | 270 if (!(*it)->wait_for_username_change) |
engedy
2014/07/31 17:14:46
I would suggest keeping this logic out of Password
vabr (Chromium)
2014/08/04 15:10:07
I agree. I also realised that the callers, which n
| |
271 ShowValue(&(*it)->password_field); | |
264 } | 272 } |
265 | 273 |
266 elements_.clear(); | 274 elements_info_.clear(); |
267 } | 275 } |
268 | 276 |
269 void PasswordAutofillAgent::PasswordValueGatekeeper::Reset() { | 277 void PasswordAutofillAgent::PasswordValueGatekeeper::Reset() { |
270 was_user_gesture_seen_ = false; | 278 was_user_gesture_seen_ = false; |
271 elements_.clear(); | 279 elements_info_.clear(); |
272 } | 280 } |
273 | 281 |
274 void PasswordAutofillAgent::PasswordValueGatekeeper::ShowValue( | 282 void PasswordAutofillAgent::PasswordValueGatekeeper::ShowValue( |
275 blink::WebInputElement* element) { | 283 blink::WebInputElement* element) { |
276 if (!element->isNull() && !element->suggestedValue().isNull()) | 284 if (!element->isNull() && !element->suggestedValue().isEmpty()) |
277 element->setValue(element->suggestedValue(), true); | 285 element->setValue(element->suggestedValue(), true); |
278 } | 286 } |
279 | 287 |
280 bool PasswordAutofillAgent::TextFieldDidEndEditing( | 288 bool PasswordAutofillAgent::TextFieldDidEndEditing( |
281 const blink::WebInputElement& element) { | 289 const blink::WebInputElement& element) { |
282 LoginToPasswordInfoMap::const_iterator iter = | 290 LoginToPasswordInfoMap::const_iterator iter = |
283 login_to_password_info_.find(element); | 291 login_to_password_info_.find(element); |
284 if (iter == login_to_password_info_.end()) | 292 if (iter == login_to_password_info_.end()) |
engedy
2014/07/31 17:14:46
nit: I would personally add an alias here and in T
vabr (Chromium)
2014/08/04 15:10:07
Done.
| |
285 return false; | 293 return false; |
286 | 294 |
287 const PasswordFormFillData& fill_data = iter->second.fill_data; | 295 // Don't let autofill overwrite an explicit change made by the user. |
296 if (iter->second->wait_for_username_change) | |
297 return false; | |
288 | 298 |
289 // If wait_for_username is false, we should have filled when the text changed. | 299 // If wait_for_username is false, we should have filled when the text changed. |
290 if (!fill_data.wait_for_username) | 300 if (!iter->second->fill_data.wait_for_username) |
291 return false; | 301 return false; |
292 | 302 |
293 blink::WebInputElement password = iter->second.password_field; | 303 if (!IsElementEditable(iter->second->password_field)) |
294 if (!IsElementEditable(password)) | |
295 return false; | 304 return false; |
296 | 305 |
297 blink::WebInputElement username = element; // We need a non-const. | 306 blink::WebInputElement username = element; // We need a non-const. |
298 | 307 |
299 // Do not set selection when ending an editing session, otherwise it can | 308 // Do not set selection when ending an editing session, otherwise it can |
300 // mess with focus. | 309 // mess with focus. |
301 FillUserNameAndPassword(&username, | 310 FillUserNameAndPassword(&username, |
302 &password, | 311 iter->second, |
303 fill_data, | |
304 true /* exact_username_match */, | 312 true /* exact_username_match */, |
305 false /* set_selection */); | 313 false /* set_selection */); |
306 return true; | 314 return true; |
307 } | 315 } |
308 | 316 |
309 bool PasswordAutofillAgent::TextDidChangeInTextField( | 317 bool PasswordAutofillAgent::TextDidChangeInTextField( |
310 const blink::WebInputElement& element) { | 318 const blink::WebInputElement& element) { |
319 // TODO(vabr): Get a mutable argument instead. http://crbug.com/397083 | |
320 blink::WebInputElement mutable_element = element; // We need a non-const. | |
321 | |
311 if (element.isPasswordField()) { | 322 if (element.isPasswordField()) { |
312 // Some login forms have event handlers that put a hash of the password into | 323 // Some login forms have event handlers that put a hash of the password into |
313 // a hidden field and then clear the password (http://crbug.com/28910, | 324 // a hidden field and then clear the password (http://crbug.com/28910, |
314 // http://crbug.com/391693). This method gets called before any of those | 325 // http://crbug.com/391693). This method gets called before any of those |
315 // handlers run, so save away a copy of the password in case it gets lost. | 326 // handlers run, so save away a copy of the password in case it gets lost. |
316 // To honor the user having explicitly cleared the password, even an empty | 327 // To honor the user having explicitly cleared the password, even an empty |
317 // password will be saved here. | 328 // password will be saved here. |
318 ProvisionallySavePassword( | 329 ProvisionallySavePassword( |
319 element.document().frame(), element.form(), RESTRICTION_NONE); | 330 element.document().frame(), element.form(), RESTRICTION_NONE); |
331 | |
332 PasswordToLoginMap::iterator iter = password_to_username_.find(element); | |
333 if (iter != password_to_username_.end()) { | |
334 // The user changed the password after it was autofilled. Flipping the | |
335 // flag below to true makes sure it is not overwritten by autofill | |
336 // re-firing for the same username. | |
337 login_to_password_info_[iter->second]->wait_for_username_change = true; | |
engedy
2014/07/31 17:14:46
Perhaps this would be caught by tests, but we shou
vabr (Chromium)
2014/08/04 15:10:06
I'm reasonably certain that TextDidChangeInTextFie
| |
338 mutable_element.setAutofilled(false); | |
339 } | |
320 return false; | 340 return false; |
321 } | 341 } |
322 | 342 |
323 LoginToPasswordInfoMap::const_iterator iter = | 343 LoginToPasswordInfoMap::const_iterator iter = |
324 login_to_password_info_.find(element); | 344 login_to_password_info_.find(element); |
325 if (iter == login_to_password_info_.end()) | 345 if (iter == login_to_password_info_.end()) |
326 return false; | 346 return false; |
327 | 347 |
328 // The input text is being changed, so any autofilled password is now | 348 // The input text is being changed, so any autofilled password is now |
329 // outdated. | 349 // outdated. |
330 blink::WebInputElement username = element; // We need a non-const. | 350 mutable_element.setAutofilled(false); |
331 username.setAutofilled(false); | 351 iter->second->wait_for_username_change = false; |
engedy
2014/07/31 17:14:46
Hmm, let us discuss this logic tomorrow in person,
vabr (Chromium)
2014/08/04 15:10:07
Acknowledged.
| |
332 | 352 |
333 blink::WebInputElement password = iter->second.password_field; | 353 blink::WebInputElement password = iter->second->password_field; |
334 if (password.isAutofilled()) { | 354 if (password.isAutofilled()) { |
335 password.setValue(base::string16(), true); | 355 password.setValue(base::string16(), true); |
336 password.setAutofilled(false); | 356 password.setAutofilled(false); |
337 } | 357 } |
338 | 358 |
339 // If wait_for_username is true we will fill when the username loses focus. | 359 // If wait_for_username is true we will fill when the username loses focus. |
340 if (iter->second.fill_data.wait_for_username) | 360 if (iter->second->fill_data.wait_for_username) |
341 return false; | 361 return false; |
342 | 362 |
343 if (!element.isText() || !IsElementAutocompletable(element) || | 363 if (!element.isText() || !IsElementAutocompletable(element) || |
344 !IsElementAutocompletable(password)) { | 364 !IsElementAutocompletable(password)) { |
345 return false; | 365 return false; |
346 } | 366 } |
347 | 367 |
348 // Don't inline autocomplete if the user is deleting, that would be confusing. | 368 // Don't inline autocomplete if the user is deleting, that would be confusing. |
349 // But refresh the popup. Note, since this is ours, return true to signal | 369 // But refresh the popup. Note, since this is ours, return true to signal |
350 // no further processing is required. | 370 // no further processing is required. |
351 if (iter->second.backspace_pressed_last) { | 371 if (iter->second->backspace_pressed_last) { |
352 ShowSuggestionPopup(iter->second.fill_data, username, false); | 372 ShowSuggestionPopup(iter->second->fill_data, element, false); |
353 return true; | 373 return true; |
354 } | 374 } |
355 | 375 |
356 blink::WebString name = element.nameForAutofill(); | 376 blink::WebString name = element.nameForAutofill(); |
357 if (name.isEmpty()) | 377 if (name.isEmpty()) |
358 return false; // If the field has no name, then we won't have values. | 378 return false; // If the field has no name, then we won't have values. |
359 | 379 |
360 // Don't attempt to autofill with values that are too large. | 380 // Don't attempt to autofill with values that are too large. |
361 if (element.value().length() > kMaximumTextSizeForAutocomplete) | 381 if (element.value().length() > kMaximumTextSizeForAutocomplete) |
362 return false; | 382 return false; |
363 | 383 |
364 // The caret position should have already been updated. | 384 // The caret position should have already been updated. |
365 PerformInlineAutocomplete(element, password, iter->second.fill_data); | 385 PerformInlineAutocomplete(&mutable_element, iter->second); |
366 return true; | 386 return true; |
367 } | 387 } |
368 | 388 |
369 bool PasswordAutofillAgent::TextFieldHandlingKeyDown( | 389 bool PasswordAutofillAgent::TextFieldHandlingKeyDown( |
370 const blink::WebInputElement& element, | 390 const blink::WebInputElement& element, |
371 const blink::WebKeyboardEvent& event) { | 391 const blink::WebKeyboardEvent& event) { |
372 // If using the new Autofill UI that lives in the browser, it will handle | 392 // If using the new Autofill UI that lives in the browser, it will handle |
373 // keypresses before this function. This is not currently an issue but if | 393 // keypresses before this function. This is not currently an issue but if |
374 // the keys handled there or here change, this issue may appear. | 394 // the keys handled there or here change, this issue may appear. |
375 | 395 |
376 LoginToPasswordInfoMap::iterator iter = login_to_password_info_.find(element); | 396 LoginToPasswordInfoMap::iterator iter = login_to_password_info_.find(element); |
377 if (iter == login_to_password_info_.end()) | 397 if (iter == login_to_password_info_.end()) |
378 return false; | 398 return false; |
379 | 399 |
380 int win_key_code = event.windowsKeyCode; | 400 int win_key_code = event.windowsKeyCode; |
381 iter->second.backspace_pressed_last = | 401 iter->second->backspace_pressed_last = |
382 (win_key_code == ui::VKEY_BACK || win_key_code == ui::VKEY_DELETE); | 402 (win_key_code == ui::VKEY_BACK || win_key_code == ui::VKEY_DELETE); |
383 return true; | 403 return true; |
384 } | 404 } |
385 | 405 |
386 bool PasswordAutofillAgent::FillSuggestion( | 406 bool PasswordAutofillAgent::FillSuggestion( |
387 const blink::WebNode& node, | 407 const blink::WebNode& node, |
388 const blink::WebString& username, | 408 const blink::WebString& username, |
389 const blink::WebString& password) { | 409 const blink::WebString& password) { |
390 blink::WebInputElement username_element; | 410 blink::WebInputElement username_element; |
391 PasswordInfo password_info; | 411 PasswordInfo* password_info; |
392 | 412 |
393 if (!FindLoginInfo(node, &username_element, &password_info) || | 413 if (!FindLoginInfo(node, &username_element, &password_info) || |
394 !IsElementAutocompletable(username_element) || | 414 !IsElementAutocompletable(username_element) || |
395 !IsElementAutocompletable(password_info.password_field)) { | 415 !IsElementAutocompletable(password_info->password_field)) { |
396 return false; | 416 return false; |
397 } | 417 } |
398 | 418 |
399 base::string16 current_username = username_element.value(); | 419 if (username_element.value() != username_element.value()) |
420 password_info->wait_for_username_change = false; | |
400 username_element.setValue(username, true); | 421 username_element.setValue(username, true); |
401 username_element.setAutofilled(true); | 422 username_element.setAutofilled(true); |
402 username_element.setSelectionRange(username.length(), username.length()); | 423 username_element.setSelectionRange(username.length(), username.length()); |
403 | 424 |
404 password_info.password_field.setValue(password, true); | 425 password_info->password_field.setValue(password, true); |
405 password_info.password_field.setAutofilled(true); | 426 password_info->password_field.setAutofilled(true); |
406 | 427 |
407 return true; | 428 return true; |
408 } | 429 } |
409 | 430 |
410 bool PasswordAutofillAgent::PreviewSuggestion( | 431 bool PasswordAutofillAgent::PreviewSuggestion( |
411 const blink::WebNode& node, | 432 const blink::WebNode& node, |
412 const blink::WebString& username, | 433 const blink::WebString& username, |
413 const blink::WebString& password) { | 434 const blink::WebString& password) { |
414 blink::WebInputElement username_element; | 435 blink::WebInputElement username_element; |
415 PasswordInfo password_info; | 436 PasswordInfo* password_info; |
416 | 437 |
417 if (!FindLoginInfo(node, &username_element, &password_info) || | 438 if (!FindLoginInfo(node, &username_element, &password_info) || |
418 !IsElementAutocompletable(username_element) || | 439 !IsElementAutocompletable(username_element) || |
419 !IsElementAutocompletable(password_info.password_field)) { | 440 !IsElementAutocompletable(password_info->password_field)) { |
420 return false; | 441 return false; |
421 } | 442 } |
422 | 443 |
423 was_username_autofilled_ = username_element.isAutofilled(); | 444 was_username_autofilled_ = username_element.isAutofilled(); |
424 username_selection_start_ = username_element.selectionStart(); | 445 username_selection_start_ = username_element.selectionStart(); |
425 username_element.setSuggestedValue(username); | 446 username_element.setSuggestedValue(username); |
426 username_element.setAutofilled(true); | 447 username_element.setAutofilled(true); |
427 username_element.setSelectionRange( | 448 username_element.setSelectionRange( |
428 username_selection_start_, | 449 username_selection_start_, |
429 username_element.suggestedValue().length()); | 450 username_element.suggestedValue().length()); |
430 | 451 |
431 was_password_autofilled_ = password_info.password_field.isAutofilled(); | 452 was_password_autofilled_ = password_info->password_field.isAutofilled(); |
432 password_info.password_field.setSuggestedValue(password); | 453 password_info->password_field.setSuggestedValue(password); |
433 password_info.password_field.setAutofilled(true); | 454 password_info->password_field.setAutofilled(true); |
434 | 455 |
435 return true; | 456 return true; |
436 } | 457 } |
437 | 458 |
438 bool PasswordAutofillAgent::DidClearAutofillSelection( | 459 bool PasswordAutofillAgent::DidClearAutofillSelection( |
439 const blink::WebNode& node) { | 460 const blink::WebNode& node) { |
440 blink::WebInputElement username_element; | 461 blink::WebInputElement username_element; |
441 PasswordInfo password_info; | 462 PasswordInfo* password_info; |
442 if (!FindLoginInfo(node, &username_element, &password_info)) | 463 if (!FindLoginInfo(node, &username_element, &password_info)) |
443 return false; | 464 return false; |
444 | 465 |
445 ClearPreview(&username_element, &password_info.password_field); | 466 ClearPreview(&username_element, &password_info->password_field); |
446 return true; | 467 return true; |
447 } | 468 } |
448 | 469 |
449 bool PasswordAutofillAgent::ShowSuggestions( | 470 bool PasswordAutofillAgent::ShowSuggestions( |
450 const blink::WebInputElement& element, | 471 const blink::WebInputElement& element, |
451 bool show_all) { | 472 bool show_all) { |
452 LoginToPasswordInfoMap::const_iterator iter = | 473 LoginToPasswordInfoMap::const_iterator iter = |
453 login_to_password_info_.find(element); | 474 login_to_password_info_.find(element); |
454 if (iter == login_to_password_info_.end()) | 475 if (iter == login_to_password_info_.end()) |
455 return false; | 476 return false; |
456 | 477 |
457 // If autocomplete='off' is set on the form elements, no suggestion dialog | 478 // If autocomplete='off' is set on the form elements, no suggestion dialog |
458 // should be shown. However, return |true| to indicate that this is a known | 479 // should be shown. However, return |true| to indicate that this is a known |
459 // password form and that the request to show suggestions has been handled (as | 480 // password form and that the request to show suggestions has been handled (as |
460 // a no-op). | 481 // a no-op). |
461 if (!IsElementAutocompletable(element) || | 482 if (!IsElementAutocompletable(element) || |
462 !IsElementAutocompletable(iter->second.password_field)) | 483 !IsElementAutocompletable(iter->second->password_field)) |
463 return true; | 484 return true; |
464 | 485 |
465 return ShowSuggestionPopup(iter->second.fill_data, element, show_all); | 486 return ShowSuggestionPopup(iter->second->fill_data, element, show_all); |
466 } | 487 } |
467 | 488 |
468 bool PasswordAutofillAgent::OriginCanAccessPasswordManager( | 489 bool PasswordAutofillAgent::OriginCanAccessPasswordManager( |
469 const blink::WebSecurityOrigin& origin) { | 490 const blink::WebSecurityOrigin& origin) { |
470 return origin.canAccessPasswordManager(); | 491 return origin.canAccessPasswordManager(); |
471 } | 492 } |
472 | 493 |
473 void PasswordAutofillAgent::OnDynamicFormsSeen(blink::WebFrame* frame) { | 494 void PasswordAutofillAgent::OnDynamicFormsSeen(blink::WebFrame* frame) { |
474 SendPasswordForms(frame, false /* only_visible */); | 495 SendPasswordForms(frame, false /* only_visible */); |
475 } | 496 } |
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
789 // Attach autocomplete listener to enable selecting alternate logins. | 810 // Attach autocomplete listener to enable selecting alternate logins. |
790 // First, get pointers to username element. | 811 // First, get pointers to username element. |
791 blink::WebInputElement username_element = | 812 blink::WebInputElement username_element = |
792 form_elements->input_elements[form_data.basic_data.fields[0].name]; | 813 form_elements->input_elements[form_data.basic_data.fields[0].name]; |
793 | 814 |
794 // Get pointer to password element. (We currently only support single | 815 // Get pointer to password element. (We currently only support single |
795 // password forms). | 816 // password forms). |
796 blink::WebInputElement password_element = | 817 blink::WebInputElement password_element = |
797 form_elements->input_elements[form_data.basic_data.fields[1].name]; | 818 form_elements->input_elements[form_data.basic_data.fields[1].name]; |
798 | 819 |
799 // If wait_for_username is true, we don't want to initially fill the form | |
800 // until the user types in a valid username. | |
801 if (!form_data.wait_for_username) | |
802 FillFormOnPasswordRecieved(form_data, username_element, password_element); | |
803 | |
804 // We might have already filled this form if there are two <form> elements | 820 // We might have already filled this form if there are two <form> elements |
805 // with identical markup. | 821 // with identical markup. |
806 if (login_to_password_info_.find(username_element) != | 822 if (login_to_password_info_.find(username_element) != |
807 login_to_password_info_.end()) | 823 login_to_password_info_.end()) |
808 continue; | 824 continue; |
809 | 825 |
810 PasswordInfo password_info; | 826 scoped_ptr<PasswordInfo> password_info(new PasswordInfo); |
811 password_info.fill_data = form_data; | 827 password_info->fill_data = form_data; |
812 password_info.password_field = password_element; | 828 password_info->password_field = password_element; |
813 login_to_password_info_[username_element] = password_info; | 829 login_to_password_info_[username_element] = password_info.get(); |
830 password_to_username_[password_element] = username_element; | |
831 // If wait_for_username is true, we don't want to initially fill the form | |
832 // until the user types in a valid username. | |
833 if (!form_data.wait_for_username) | |
834 FillFormOnPasswordRecieved(&username_element, password_info.get()); | |
835 password_infos_[username_element.document().frame()].push_back( | |
836 make_linked_ptr(password_info.release())); | |
814 | 837 |
815 FormData form; | 838 FormData form; |
816 FormFieldData field; | 839 FormFieldData field; |
817 FindFormAndFieldForFormControlElement( | 840 FindFormAndFieldForFormControlElement( |
818 username_element, &form, &field, REQUIRE_NONE); | 841 username_element, &form, &field, REQUIRE_NONE); |
819 Send(new AutofillHostMsg_AddPasswordFormMapping( | 842 Send(new AutofillHostMsg_AddPasswordFormMapping( |
820 routing_id(), field, form_data)); | 843 routing_id(), field, form_data)); |
821 } | 844 } |
822 } | 845 } |
823 | 846 |
824 void PasswordAutofillAgent::OnSetLoggingState(bool active) { | 847 void PasswordAutofillAgent::OnSetLoggingState(bool active) { |
825 logging_state_active_ = active; | 848 logging_state_active_ = active; |
826 } | 849 } |
827 | 850 |
828 //////////////////////////////////////////////////////////////////////////////// | 851 //////////////////////////////////////////////////////////////////////////////// |
829 // PasswordAutofillAgent, private: | 852 // PasswordAutofillAgent, private: |
830 | 853 |
854 PasswordAutofillAgent::PasswordInfo::PasswordInfo() | |
855 : backspace_pressed_last(false), wait_for_username_change(false) { | |
856 } | |
857 | |
831 void PasswordAutofillAgent::GetSuggestions( | 858 void PasswordAutofillAgent::GetSuggestions( |
832 const PasswordFormFillData& fill_data, | 859 const PasswordFormFillData& fill_data, |
833 const base::string16& input, | 860 const base::string16& input, |
834 std::vector<base::string16>* suggestions, | 861 std::vector<base::string16>* suggestions, |
835 std::vector<base::string16>* realms, | 862 std::vector<base::string16>* realms, |
836 bool show_all) { | 863 bool show_all) { |
837 if (show_all || | 864 if (show_all || |
838 StartsWith(fill_data.basic_data.fields[0].value, input, false)) { | 865 StartsWith(fill_data.basic_data.fields[0].value, input, false)) { |
839 suggestions->push_back(fill_data.basic_data.fields[0].value); | 866 suggestions->push_back(fill_data.basic_data.fields[0].value); |
840 realms->push_back(base::UTF8ToUTF16(fill_data.preferred_realm)); | 867 realms->push_back(base::UTF8ToUTF16(fill_data.preferred_realm)); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
894 gfx::RectF bounding_box_scaled(bounding_box.x() * scale, | 921 gfx::RectF bounding_box_scaled(bounding_box.x() * scale, |
895 bounding_box.y() * scale, | 922 bounding_box.y() * scale, |
896 bounding_box.width() * scale, | 923 bounding_box.width() * scale, |
897 bounding_box.height() * scale); | 924 bounding_box.height() * scale); |
898 Send(new AutofillHostMsg_ShowPasswordSuggestions( | 925 Send(new AutofillHostMsg_ShowPasswordSuggestions( |
899 routing_id(), field, bounding_box_scaled, suggestions, realms)); | 926 routing_id(), field, bounding_box_scaled, suggestions, realms)); |
900 return !suggestions.empty(); | 927 return !suggestions.empty(); |
901 } | 928 } |
902 | 929 |
903 void PasswordAutofillAgent::FillFormOnPasswordRecieved( | 930 void PasswordAutofillAgent::FillFormOnPasswordRecieved( |
904 const PasswordFormFillData& fill_data, | 931 blink::WebInputElement* username_element, |
905 blink::WebInputElement username_element, | 932 PasswordInfo* password_info) { |
906 blink::WebInputElement password_element) { | 933 blink::WebInputElement* password_element = &password_info->password_field; |
907 // Do not fill if the password field is in an iframe. | 934 // Do not fill if the password field is in an iframe. |
908 DCHECK(password_element.document().frame()); | 935 DCHECK(password_element->document().frame()); |
909 if (password_element.document().frame()->parent()) | 936 if (password_element->document().frame()->parent()) |
910 return; | 937 return; |
911 | 938 |
912 if (!ShouldIgnoreAutocompleteOffForPasswordFields() && | 939 if (!ShouldIgnoreAutocompleteOffForPasswordFields() && |
913 !username_element.form().autoComplete()) | 940 !username_element->form().autoComplete()) |
914 return; | 941 return; |
915 | 942 |
916 // If we can't modify the password, don't try to set the username | 943 // If we can't modify the password, don't try to set the username |
917 if (!IsElementAutocompletable(password_element)) | 944 if (!IsElementAutocompletable(*password_element)) |
918 return; | 945 return; |
919 | 946 |
920 // Try to set the username to the preferred name, but only if the field | 947 // Try to set the username to the preferred name, but only if the field |
921 // can be set and isn't prefilled. | 948 // can be set and isn't prefilled. |
922 if (IsElementAutocompletable(username_element) && | 949 if (IsElementAutocompletable(*username_element) && |
923 username_element.value().isEmpty()) { | 950 username_element->value().isEmpty()) { |
924 // TODO(tkent): Check maxlength and pattern. | 951 // TODO(tkent): Check maxlength and pattern. |
925 username_element.setValue(fill_data.basic_data.fields[0].value, true); | 952 username_element->setValue( |
953 password_info->fill_data.basic_data.fields[0].value, true); | |
926 } | 954 } |
927 | 955 |
928 // Fill if we have an exact match for the username. Note that this sets | 956 // Fill if we have an exact match for the username. Note that this sets |
929 // username to autofilled. | 957 // username to autofilled. |
930 FillUserNameAndPassword(&username_element, | 958 FillUserNameAndPassword(username_element, |
931 &password_element, | 959 password_info, |
932 fill_data, | |
933 true /* exact_username_match */, | 960 true /* exact_username_match */, |
934 false /* set_selection */); | 961 false /* set_selection */); |
935 } | 962 } |
936 | 963 |
937 bool PasswordAutofillAgent::FillUserNameAndPassword( | 964 bool PasswordAutofillAgent::FillUserNameAndPassword( |
938 blink::WebInputElement* username_element, | 965 blink::WebInputElement* username_element, |
939 blink::WebInputElement* password_element, | 966 PasswordInfo* password_info, |
940 const PasswordFormFillData& fill_data, | |
941 bool exact_username_match, | 967 bool exact_username_match, |
942 bool set_selection) { | 968 bool set_selection) { |
969 blink::WebInputElement password_element = password_info->password_field; | |
970 const PasswordFormFillData& fill_data = password_info->fill_data; | |
943 base::string16 current_username = username_element->value(); | 971 base::string16 current_username = username_element->value(); |
944 // username and password will contain the match found if any. | 972 // username and password will contain the match found if any. |
945 base::string16 username; | 973 base::string16 username; |
946 base::string16 password; | 974 base::string16 password; |
947 | 975 |
948 // Look for any suitable matches to current field text. | 976 // Look for any suitable matches to current field text. |
949 if (DoUsernamesMatch(fill_data.basic_data.fields[0].value, | 977 if (DoUsernamesMatch(fill_data.basic_data.fields[0].value, |
950 current_username, | 978 current_username, |
951 exact_username_match)) { | 979 exact_username_match)) { |
952 username = fill_data.basic_data.fields[0].value; | 980 username = fill_data.basic_data.fields[0].value; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
985 } | 1013 } |
986 } | 1014 } |
987 } | 1015 } |
988 if (password.empty()) | 1016 if (password.empty()) |
989 return false; // No match was found. | 1017 return false; // No match was found. |
990 | 1018 |
991 // TODO(tkent): Check maxlength and pattern for both username and password | 1019 // TODO(tkent): Check maxlength and pattern for both username and password |
992 // fields. | 1020 // fields. |
993 | 1021 |
994 // Don't fill username if password can't be set. | 1022 // Don't fill username if password can't be set. |
995 if (!IsElementAutocompletable(*password_element)) { | 1023 if (!IsElementAutocompletable(password_element)) { |
996 return false; | 1024 return false; |
997 } | 1025 } |
998 | 1026 |
999 // Input matches the username, fill in required values. | 1027 // Input matches the username, fill in required values. |
1000 if (IsElementAutocompletable(*username_element)) { | 1028 if (IsElementAutocompletable(*username_element)) { |
1001 username_element->setValue(username, true); | 1029 username_element->setValue(username, true); |
1002 username_element->setAutofilled(true); | 1030 username_element->setAutofilled(true); |
1003 | 1031 |
1004 if (set_selection) { | 1032 if (set_selection) { |
1005 username_element->setSelectionRange(current_username.length(), | 1033 username_element->setSelectionRange(current_username.length(), |
1006 username.length()); | 1034 username.length()); |
1007 } | 1035 } |
1008 } else if (current_username != username) { | 1036 } else if (current_username != username) { |
1009 // If the username can't be filled and it doesn't match a saved password | 1037 // If the username can't be filled and it doesn't match a saved password |
1010 // as is, don't autofill a password. | 1038 // as is, don't autofill a password. |
1011 return false; | 1039 return false; |
1012 } | 1040 } |
1013 | 1041 |
1014 // Wait to fill in the password until a user gesture occurs. This is to make | 1042 // Wait to fill in the password until a user gesture occurs. This is to make |
1015 // sure that we do not fill in the DOM with a password until we believe the | 1043 // sure that we do not fill in the DOM with a password until we believe the |
1016 // user is intentionally interacting with the page. | 1044 // user is intentionally interacting with the page. |
1017 password_element->setSuggestedValue(password); | 1045 password_element.setSuggestedValue(password); |
1018 gatekeeper_.RegisterElement(password_element); | 1046 gatekeeper_.RegisterElementInfo(password_info); |
1019 | 1047 |
1020 password_element->setAutofilled(true); | 1048 password_element.setAutofilled(true); |
1021 return true; | 1049 return true; |
1022 } | 1050 } |
1023 | 1051 |
1024 void PasswordAutofillAgent::PerformInlineAutocomplete( | 1052 void PasswordAutofillAgent::PerformInlineAutocomplete( |
1025 const blink::WebInputElement& username_input, | 1053 blink::WebInputElement* username, |
1026 const blink::WebInputElement& password_input, | 1054 PasswordInfo* password_info) { |
1027 const PasswordFormFillData& fill_data) { | 1055 DCHECK(!password_info->fill_data.wait_for_username); |
1028 DCHECK(!fill_data.wait_for_username); | |
1029 | 1056 |
1030 // We need non-const versions of the username and password inputs. | 1057 blink::WebInputElement password = password_info->password_field; |
1031 blink::WebInputElement username = username_input; | |
1032 blink::WebInputElement password = password_input; | |
1033 | 1058 |
1034 // Don't inline autocomplete if the caret is not at the end. | 1059 // Don't inline autocomplete if the caret is not at the end. |
1035 // TODO(jcivelli): is there a better way to test the caret location? | 1060 // TODO(jcivelli): is there a better way to test the caret location? |
1036 if (username.selectionStart() != username.selectionEnd() || | 1061 if (username->selectionStart() != username->selectionEnd() || |
1037 username.selectionEnd() != static_cast<int>(username.value().length())) { | 1062 username->selectionEnd() != |
1063 static_cast<int>(username->value().length())) { | |
1038 return; | 1064 return; |
1039 } | 1065 } |
1040 | 1066 |
1041 // Show the popup with the list of available usernames. | 1067 // Show the popup with the list of available usernames. |
1042 ShowSuggestionPopup(fill_data, username, false); | 1068 ShowSuggestionPopup(password_info->fill_data, *username, false); |
1043 | 1069 |
1044 #if !defined(OS_ANDROID) | 1070 #if !defined(OS_ANDROID) |
1045 // Fill the user and password field with the most relevant match. Android | 1071 // Fill the user and password field with the most relevant match. Android |
1046 // only fills in the fields after the user clicks on the suggestion popup. | 1072 // only fills in the fields after the user clicks on the suggestion popup. |
1047 FillUserNameAndPassword(&username, | 1073 FillUserNameAndPassword(username, |
1048 &password, | 1074 password_info, |
1049 fill_data, | |
1050 false /* exact_username_match */, | 1075 false /* exact_username_match */, |
1051 true /* set_selection */); | 1076 true /* set_selection */); |
1052 #endif | 1077 #endif |
1053 } | 1078 } |
1054 | 1079 |
1055 void PasswordAutofillAgent::FrameClosing(const blink::WebFrame* frame) { | 1080 void PasswordAutofillAgent::FrameClosing(const blink::WebFrame* frame) { |
1056 for (LoginToPasswordInfoMap::iterator iter = login_to_password_info_.begin(); | 1081 for (LoginToPasswordInfoMap::iterator iter = login_to_password_info_.begin(); |
1057 iter != login_to_password_info_.end();) { | 1082 iter != login_to_password_info_.end();) { |
1058 if (iter->first.document().frame() == frame) | 1083 if (iter->first.document().frame() == frame) { |
1084 password_to_username_.erase(iter->second->password_field); | |
1085 gatekeeper_.UnregisterElementInfo(iter->second); | |
1059 login_to_password_info_.erase(iter++); | 1086 login_to_password_info_.erase(iter++); |
1060 else | 1087 } else { |
1061 ++iter; | 1088 ++iter; |
1089 } | |
1062 } | 1090 } |
1091 password_infos_.erase(frame); | |
1063 for (FrameToPasswordFormMap::iterator iter = | 1092 for (FrameToPasswordFormMap::iterator iter = |
1064 provisionally_saved_forms_.begin(); | 1093 provisionally_saved_forms_.begin(); |
1065 iter != provisionally_saved_forms_.end();) { | 1094 iter != provisionally_saved_forms_.end();) { |
1066 if (iter->first == frame) | 1095 if (iter->first == frame) |
1067 provisionally_saved_forms_.erase(iter++); | 1096 provisionally_saved_forms_.erase(iter++); |
1068 else | 1097 else |
1069 ++iter; | 1098 ++iter; |
1070 } | 1099 } |
1071 } | 1100 } |
1072 | 1101 |
1073 bool PasswordAutofillAgent::FindLoginInfo(const blink::WebNode& node, | 1102 bool PasswordAutofillAgent::FindLoginInfo(const blink::WebNode& node, |
1074 blink::WebInputElement* found_input, | 1103 blink::WebInputElement* found_input, |
1075 PasswordInfo* found_password) { | 1104 PasswordInfo** found_password) { |
1076 if (!node.isElementNode()) | 1105 if (!node.isElementNode()) |
1077 return false; | 1106 return false; |
1078 | 1107 |
1079 blink::WebElement element = node.toConst<blink::WebElement>(); | 1108 blink::WebElement element = node.toConst<blink::WebElement>(); |
1080 if (!element.hasHTMLTagName("input")) | 1109 if (!element.hasHTMLTagName("input")) |
1081 return false; | 1110 return false; |
1082 | 1111 |
1083 blink::WebInputElement input = element.to<blink::WebInputElement>(); | 1112 blink::WebInputElement input = element.to<blink::WebInputElement>(); |
1084 LoginToPasswordInfoMap::iterator iter = login_to_password_info_.find(input); | 1113 LoginToPasswordInfoMap::iterator iter = login_to_password_info_.find(input); |
1085 if (iter == login_to_password_info_.end()) | 1114 if (iter == login_to_password_info_.end()) |
(...skipping 26 matching lines...) Expand all Loading... | |
1112 scoped_ptr<PasswordForm> password_form(CreatePasswordForm(form)); | 1141 scoped_ptr<PasswordForm> password_form(CreatePasswordForm(form)); |
1113 if (!password_form || (restriction == RESTRICTION_NON_EMPTY_PASSWORD && | 1142 if (!password_form || (restriction == RESTRICTION_NON_EMPTY_PASSWORD && |
1114 password_form->password_value.empty() && | 1143 password_form->password_value.empty() && |
1115 password_form->new_password_value.empty())) { | 1144 password_form->new_password_value.empty())) { |
1116 return; | 1145 return; |
1117 } | 1146 } |
1118 provisionally_saved_forms_[frame].reset(password_form.release()); | 1147 provisionally_saved_forms_[frame].reset(password_form.release()); |
1119 } | 1148 } |
1120 | 1149 |
1121 } // namespace autofill | 1150 } // namespace autofill |
OLD | NEW |