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

Side by Side Diff: components/autofill/content/renderer/password_autofill_agent.cc

Issue 1918823005: Extend logging for password manager internals page (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Remove a full-stop from the message string Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | components/autofill/core/common/save_password_progress_logger.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 <stddef.h> 7 #include <stddef.h>
8 8
9 #include <memory> 9 #include <memory>
10 #include <string>
10 #include <utility> 11 #include <utility>
11 12
12 #include "base/bind.h" 13 #include "base/bind.h"
13 #include "base/command_line.h" 14 #include "base/command_line.h"
14 #include "base/i18n/case_conversion.h" 15 #include "base/i18n/case_conversion.h"
15 #include "base/memory/linked_ptr.h" 16 #include "base/memory/linked_ptr.h"
16 #include "base/message_loop/message_loop.h" 17 #include "base/message_loop/message_loop.h"
17 #include "base/metrics/field_trial.h" 18 #include "base/metrics/field_trial.h"
18 #include "base/metrics/histogram_macros.h" 19 #include "base/metrics/histogram_macros.h"
19 #include "base/strings/utf_string_conversions.h" 20 #include "base/strings/utf_string_conversions.h"
(...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after
426 // value through |registration_callback|. If a match is found, return true and 427 // value through |registration_callback|. If a match is found, return true and
427 // |nonscript_modified_values| will be modified with the autofilled credentials. 428 // |nonscript_modified_values| will be modified with the autofilled credentials.
428 bool FillUserNameAndPassword( 429 bool FillUserNameAndPassword(
429 blink::WebInputElement* username_element, 430 blink::WebInputElement* username_element,
430 blink::WebInputElement* password_element, 431 blink::WebInputElement* password_element,
431 const PasswordFormFillData& fill_data, 432 const PasswordFormFillData& fill_data,
432 bool exact_username_match, 433 bool exact_username_match,
433 bool set_selection, 434 bool set_selection,
434 std::map<const blink::WebInputElement, blink::WebString>* 435 std::map<const blink::WebInputElement, blink::WebString>*
435 nonscript_modified_values, 436 nonscript_modified_values,
436 base::Callback<void(blink::WebInputElement*)> registration_callback) { 437 base::Callback<void(blink::WebInputElement*)> registration_callback,
438 RendererSavePasswordProgressLogger* logger) {
439 if (logger)
440 logger->LogMessage(Logger::STRING_FILL_USERNAME_AND_PASSWORD_METHOD);
441
437 // Don't fill username if password can't be set. 442 // Don't fill username if password can't be set.
438 if (!IsElementAutocompletable(*password_element)) 443 if (!IsElementAutocompletable(*password_element))
439 return false; 444 return false;
440 445
441 base::string16 current_username; 446 base::string16 current_username;
442 if (!username_element->isNull()) { 447 if (!username_element->isNull()) {
443 current_username = username_element->value(); 448 current_username = username_element->value();
444 } 449 }
445 450
446 // username and password will contain the match found if any. 451 // username and password will contain the match found if any.
447 base::string16 username; 452 base::string16 username;
448 base::string16 password; 453 base::string16 password;
449 454
450 // Look for any suitable matches to current field text. 455 // Look for any suitable matches to current field text.
451 if (DoUsernamesMatch(fill_data.username_field.value, current_username, 456 if (DoUsernamesMatch(fill_data.username_field.value, current_username,
452 exact_username_match)) { 457 exact_username_match)) {
453 username = fill_data.username_field.value; 458 username = fill_data.username_field.value;
454 password = fill_data.password_field.value; 459 password = fill_data.password_field.value;
460 if (logger)
461 logger->LogMessage(Logger::STRING_USERNAMES_MATCH);
455 } else { 462 } else {
456 // Scan additional logins for a match. 463 // Scan additional logins for a match.
457 for (const auto& it : fill_data.additional_logins) { 464 for (const auto& it : fill_data.additional_logins) {
458 if (DoUsernamesMatch(it.first, current_username, exact_username_match)) { 465 if (DoUsernamesMatch(it.first, current_username, exact_username_match)) {
459 username = it.first; 466 username = it.first;
460 password = it.second.password; 467 password = it.second.password;
461 break; 468 break;
462 } 469 }
463 } 470 }
471 if (logger) {
472 logger->LogBoolean(Logger::STRING_MATCH_IN_ADDITIONAL,
473 !(username.empty() && password.empty()));
474 }
464 475
465 // Check possible usernames. 476 // Check possible usernames.
466 if (username.empty() && password.empty()) { 477 if (username.empty() && password.empty()) {
467 for (const auto& it : fill_data.other_possible_usernames) { 478 for (const auto& it : fill_data.other_possible_usernames) {
468 for (size_t i = 0; i < it.second.size(); ++i) { 479 for (size_t i = 0; i < it.second.size(); ++i) {
469 if (DoUsernamesMatch( 480 if (DoUsernamesMatch(
470 it.second[i], current_username, exact_username_match)) { 481 it.second[i], current_username, exact_username_match)) {
471 username = it.second[i]; 482 username = it.second[i];
472 password = it.first.password; 483 password = it.first.password;
473 break; 484 break;
474 } 485 }
475 } 486 }
476 if (!username.empty() && !password.empty()) 487 if (!username.empty() && !password.empty())
477 break; 488 break;
478 } 489 }
479 } 490 }
480 } 491 }
481 if (password.empty()) 492 if (password.empty())
482 return false; 493 return false;
483 494
484 // TODO(tkent): Check maxlength and pattern for both username and password 495 // TODO(tkent): Check maxlength and pattern for both username and password
485 // fields. 496 // fields.
486 497
487 // Input matches the username, fill in required values. 498 // Input matches the username, fill in required values.
488 if (!username_element->isNull() && 499 if (!username_element->isNull() &&
489 IsElementAutocompletable(*username_element)) { 500 IsElementAutocompletable(*username_element)) {
490 // TODO(vabr): Why not setSuggestedValue? http://crbug.com/507714 501 // TODO(crbug.com/507714): Why not setSuggestedValue?
491 username_element->setValue(username, true); 502 username_element->setValue(username, true);
492 (*nonscript_modified_values)[*username_element] = username; 503 (*nonscript_modified_values)[*username_element] = username;
493 username_element->setAutofilled(true); 504 username_element->setAutofilled(true);
505 if (logger)
506 logger->LogMessage(Logger::STRING_USERNAME_FILLED);
dvadym 2016/04/26 14:47:34 It seems that it would be helpful to log also name
vabr (Chromium) 2016/04/26 16:55:41 While I agree, this would need some more changes t
494 if (set_selection) { 507 if (set_selection) {
495 form_util::PreviewSuggestion(username, current_username, 508 form_util::PreviewSuggestion(username, current_username,
496 username_element); 509 username_element);
497 } 510 }
498 } else if (current_username != username) { 511 } else if (current_username != username) {
499 // If the username can't be filled and it doesn't match a saved password 512 // If the username can't be filled and it doesn't match a saved password
500 // as is, don't autofill a password. 513 // as is, don't autofill a password.
501 return false; 514 return false;
502 } 515 }
503 516
504 // Wait to fill in the password until a user gesture occurs. This is to make 517 // Wait to fill in the password until a user gesture occurs. This is to make
505 // sure that we do not fill in the DOM with a password until we believe the 518 // sure that we do not fill in the DOM with a password until we believe the
506 // user is intentionally interacting with the page. 519 // user is intentionally interacting with the page.
507 password_element->setSuggestedValue(password); 520 password_element->setSuggestedValue(password);
508 (*nonscript_modified_values)[*password_element] = password; 521 (*nonscript_modified_values)[*password_element] = password;
509 registration_callback.Run(password_element); 522 registration_callback.Run(password_element);
510 523
511 password_element->setAutofilled(true); 524 password_element->setAutofilled(true);
525 if (logger)
526 logger->LogMessage(Logger::STRING_PASSWORD_FILLED);
dvadym 2016/04/26 14:47:34 It seems that it would be helpful to log also name
vabr (Chromium) 2016/04/26 16:55:41 Ditto.
512 return true; 527 return true;
513 } 528 }
514 529
515 // Attempts to fill |username_element| and |password_element| with the 530 // Attempts to fill |username_element| and |password_element| with the
516 // |fill_data|. Will use the data corresponding to the preferred username, 531 // |fill_data|. Will use the data corresponding to the preferred username,
517 // unless the |username_element| already has a value set. In that case, 532 // unless the |username_element| already has a value set. In that case,
518 // attempts to fill the password matching the already filled username, if 533 // attempts to fill the password matching the already filled username, if
519 // such a password exists. The |password_element| will have the 534 // such a password exists. The |password_element| will have the
520 // |suggestedValue| set, and |suggestedValue| will be registered for copying to 535 // |suggestedValue| set, and |suggestedValue| will be registered for copying to
521 // the real value through |registration_callback|. Returns true if the password 536 // the real value through |registration_callback|. Returns true if the password
522 // is filled. 537 // is filled.
523 bool FillFormOnPasswordReceived( 538 bool FillFormOnPasswordReceived(
524 const PasswordFormFillData& fill_data, 539 const PasswordFormFillData& fill_data,
525 blink::WebInputElement username_element, 540 blink::WebInputElement username_element,
526 blink::WebInputElement password_element, 541 blink::WebInputElement password_element,
527 std::map<const blink::WebInputElement, blink::WebString>* 542 std::map<const blink::WebInputElement, blink::WebString>*
528 nonscript_modified_values, 543 nonscript_modified_values,
529 base::Callback<void(blink::WebInputElement*)> registration_callback) { 544 base::Callback<void(blink::WebInputElement*)> registration_callback,
545 RendererSavePasswordProgressLogger* logger) {
530 // Do not fill if the password field is in a chain of iframes not having 546 // Do not fill if the password field is in a chain of iframes not having
531 // identical origin. 547 // identical origin.
532 blink::WebFrame* cur_frame = password_element.document().frame(); 548 blink::WebFrame* cur_frame = password_element.document().frame();
533 blink::WebString bottom_frame_origin = 549 blink::WebString bottom_frame_origin =
534 cur_frame->getSecurityOrigin().toString(); 550 cur_frame->getSecurityOrigin().toString();
535 551
536 DCHECK(cur_frame); 552 DCHECK(cur_frame);
537 553
538 while (cur_frame->parent()) { 554 while (cur_frame->parent()) {
539 cur_frame = cur_frame->parent(); 555 cur_frame = cur_frame->parent();
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
587 return false; 603 return false;
588 } 604 }
589 605
590 if (form_has_fillable_username && username_element.value().isEmpty()) { 606 if (form_has_fillable_username && username_element.value().isEmpty()) {
591 // TODO(tkent): Check maxlength and pattern. 607 // TODO(tkent): Check maxlength and pattern.
592 username_element.setValue(fill_data.username_field.value, true); 608 username_element.setValue(fill_data.username_field.value, true);
593 } 609 }
594 610
595 // Fill if we have an exact match for the username. Note that this sets 611 // Fill if we have an exact match for the username. Note that this sets
596 // username to autofilled. 612 // username to autofilled.
597 return FillUserNameAndPassword(&username_element, 613 return FillUserNameAndPassword(
598 &password_element, 614 &username_element, &password_element, fill_data,
599 fill_data, 615 true /* exact_username_match */, false /* set_selection */,
600 true /* exact_username_match */, 616 nonscript_modified_values, registration_callback, logger);
601 false /* set_selection */,
602 nonscript_modified_values,
603 registration_callback);
604 } 617 }
605 618
606 // Takes a |map| with pointers as keys and linked_ptr as values, and returns 619 // Takes a |map| with pointers as keys and linked_ptr as values, and returns
607 // true if |key| is not NULL and |map| contains a non-NULL entry for |key|. 620 // true if |key| is not NULL and |map| contains a non-NULL entry for |key|.
608 // Makes sure not to create an entry as a side effect of using the operator []. 621 // Makes sure not to create an entry as a side effect of using the operator [].
609 template <class Key, class Value> 622 template <class Key, class Value>
610 bool ContainsNonNullEntryForNonNullKey( 623 bool ContainsNonNullEntryForNonNullKey(
611 const std::map<Key*, linked_ptr<Value>>& map, 624 const std::map<Key*, linked_ptr<Value>>& map,
612 Key* key) { 625 Key* key) {
613 if (!key) 626 if (!key)
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
687 return false; 700 return false;
688 701
689 blink::WebInputElement password = password_info.password_field; 702 blink::WebInputElement password = password_info.password_field;
690 if (!IsElementEditable(password)) 703 if (!IsElementEditable(password))
691 return false; 704 return false;
692 705
693 blink::WebInputElement username = element; // We need a non-const. 706 blink::WebInputElement username = element; // We need a non-const.
694 707
695 // Do not set selection when ending an editing session, otherwise it can 708 // Do not set selection when ending an editing session, otherwise it can
696 // mess with focus. 709 // mess with focus.
697 FillUserNameAndPassword( 710 FillUserNameAndPassword(&username, &password, fill_data, true, false,
698 &username, &password, fill_data, true, false, 711 &nonscript_modified_values_,
699 &nonscript_modified_values_, 712 base::Bind(&PasswordValueGatekeeper::RegisterElement,
700 base::Bind(&PasswordValueGatekeeper::RegisterElement, 713 base::Unretained(&gatekeeper_)),
701 base::Unretained(&gatekeeper_))); 714 nullptr);
702 return true; 715 return true;
703 } 716 }
704 717
705 bool PasswordAutofillAgent::TextDidChangeInTextField( 718 bool PasswordAutofillAgent::TextDidChangeInTextField(
706 const blink::WebInputElement& element) { 719 const blink::WebInputElement& element) {
707 // TODO(vabr): Get a mutable argument instead. http://crbug.com/397083 720 // TODO(vabr): Get a mutable argument instead. http://crbug.com/397083
708 blink::WebInputElement mutable_element = element; // We need a non-const. 721 blink::WebInputElement mutable_element = element; // We need a non-const.
709 mutable_element.setAutofilled(false); 722 mutable_element.setAutofilled(false);
710 723
711 WebInputToPasswordInfoMap::iterator iter = 724 WebInputToPasswordInfoMap::iterator iter =
(...skipping 592 matching lines...) Expand 10 before | Expand all | Expand 10 after
1304 } 1317 }
1305 1318
1306 // This is a new navigation, so require a new user gesture before filling in 1319 // This is a new navigation, so require a new user gesture before filling in
1307 // passwords. 1320 // passwords.
1308 gatekeeper_.Reset(); 1321 gatekeeper_.Reset();
1309 } 1322 }
1310 1323
1311 void PasswordAutofillAgent::OnFillPasswordForm( 1324 void PasswordAutofillAgent::OnFillPasswordForm(
1312 int key, 1325 int key,
1313 const PasswordFormFillData& form_data) { 1326 const PasswordFormFillData& form_data) {
1327 std::unique_ptr<RendererSavePasswordProgressLogger> logger;
1328 if (logging_state_active_) {
1329 logger.reset(new RendererSavePasswordProgressLogger(this, routing_id()));
1330 logger->LogMessage(Logger::STRING_ON_FILL_PASSWORD_FORM_METHOD);
1331 }
1332
1314 bool ambiguous_or_empty_names = 1333 bool ambiguous_or_empty_names =
1315 DoesFormContainAmbiguousOrEmptyNames(form_data); 1334 DoesFormContainAmbiguousOrEmptyNames(form_data);
1316 FormElementsList forms; 1335 FormElementsList forms;
1317 FindFormElements(render_frame(), form_data, ambiguous_or_empty_names, &forms); 1336 FindFormElements(render_frame(), form_data, ambiguous_or_empty_names, &forms);
1337 if (logger) {
1338 logger->LogBoolean(Logger::STRING_AMBIGUOUS_OR_EMPTY_NAMES,
1339 ambiguous_or_empty_names);
1340 logger->LogNumber(Logger::STRING_NUMBER_OF_POTENTIAL_FORMS_TO_FILL,
1341 forms.size());
1342 logger->LogBoolean(Logger::STRING_FORM_DATA_WAIT,
1343 form_data.wait_for_username);
1344 }
1318 for (const auto& form : forms) { 1345 for (const auto& form : forms) {
1319 base::string16 username_field_name; 1346 base::string16 username_field_name;
1320 base::string16 password_field_name = 1347 base::string16 password_field_name =
1321 FieldName(form_data.password_field, ambiguous_or_empty_names); 1348 FieldName(form_data.password_field, ambiguous_or_empty_names);
1322 bool form_contains_fillable_username_field = 1349 bool form_contains_fillable_username_field =
1323 FillDataContainsFillableUsername(form_data); 1350 FillDataContainsFillableUsername(form_data);
1324 if (form_contains_fillable_username_field) { 1351 if (form_contains_fillable_username_field) {
1325 username_field_name = 1352 username_field_name =
1326 FieldName(form_data.username_field, ambiguous_or_empty_names); 1353 FieldName(form_data.username_field, ambiguous_or_empty_names);
1327 } 1354 }
1355 if (logger) {
1356 logger->LogBoolean(Logger::STRING_CONTAINS_FILLABLE_USERNAME_FIELD,
1357 form_contains_fillable_username_field);
1358 logger->LogBoolean(Logger::STRING_USERNAME_FIELD_NAME_EMPTY,
1359 username_field_name.empty());
1360 logger->LogBoolean(Logger::STRING_PASSWORD_FIELD_NAME_EMPTY,
1361 password_field_name.empty());
1362 }
1328 1363
1329 // Attach autocomplete listener to enable selecting alternate logins. 1364 // Attach autocomplete listener to enable selecting alternate logins.
1330 blink::WebInputElement username_element; 1365 blink::WebInputElement username_element;
1331 blink::WebInputElement password_element; 1366 blink::WebInputElement password_element;
1332 1367
1333 // Check whether the password form has a username input field. 1368 // Check whether the password form has a username input field.
1334 if (!username_field_name.empty()) { 1369 if (!username_field_name.empty()) {
1335 const auto it = form.find(username_field_name); 1370 const auto it = form.find(username_field_name);
1336 DCHECK(it != form.end()); 1371 DCHECK(it != form.end());
1337 username_element = it->second; 1372 username_element = it->second;
(...skipping 17 matching lines...) Expand all
1355 // We might have already filled this form if there are two <form> elements 1390 // We might have already filled this form if there are two <form> elements
1356 // with identical markup. 1391 // with identical markup.
1357 if (web_input_to_password_info_.find(main_element) != 1392 if (web_input_to_password_info_.find(main_element) !=
1358 web_input_to_password_info_.end()) 1393 web_input_to_password_info_.end())
1359 continue; 1394 continue;
1360 1395
1361 // If wait_for_username is true, we don't want to initially fill the form 1396 // If wait_for_username is true, we don't want to initially fill the form
1362 // until the user types in a valid username. 1397 // until the user types in a valid username.
1363 if (!form_data.wait_for_username) { 1398 if (!form_data.wait_for_username) {
1364 FillFormOnPasswordReceived( 1399 FillFormOnPasswordReceived(
1365 form_data, 1400 form_data, username_element, password_element,
1366 username_element,
1367 password_element,
1368 &nonscript_modified_values_, 1401 &nonscript_modified_values_,
1369 base::Bind(&PasswordValueGatekeeper::RegisterElement, 1402 base::Bind(&PasswordValueGatekeeper::RegisterElement,
1370 base::Unretained(&gatekeeper_))); 1403 base::Unretained(&gatekeeper_)),
1404 logger.get());
1371 } 1405 }
1372 1406
1373 PasswordInfo password_info; 1407 PasswordInfo password_info;
1374 password_info.fill_data = form_data; 1408 password_info.fill_data = form_data;
1375 password_info.key = key; 1409 password_info.key = key;
1376 password_info.password_field = password_element; 1410 password_info.password_field = password_element;
1377 web_input_to_password_info_[main_element] = password_info; 1411 web_input_to_password_info_[main_element] = password_info;
1378 if (!main_element.isPasswordField()) 1412 if (!main_element.isPasswordField())
1379 password_to_username_[password_element] = username_element; 1413 password_to_username_[password_element] = username_element;
1380 } 1414 }
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
1501 } 1535 }
1502 1536
1503 bool PasswordAutofillAgent::ProvisionallySavedPasswordIsValid() { 1537 bool PasswordAutofillAgent::ProvisionallySavedPasswordIsValid() {
1504 return provisionally_saved_form_ && 1538 return provisionally_saved_form_ &&
1505 !provisionally_saved_form_->username_value.empty() && 1539 !provisionally_saved_form_->username_value.empty() &&
1506 !(provisionally_saved_form_->password_value.empty() && 1540 !(provisionally_saved_form_->password_value.empty() &&
1507 provisionally_saved_form_->new_password_value.empty()); 1541 provisionally_saved_form_->new_password_value.empty());
1508 } 1542 }
1509 1543
1510 } // namespace autofill 1544 } // namespace autofill
OLDNEW
« no previous file with comments | « no previous file | components/autofill/core/common/save_password_progress_logger.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698