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

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

Issue 2650623002: Use explicit WebString conversions in autofill (Closed)
Patch Set: . Created 3 years, 11 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
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_form_conversion_utils.h" 5 #include "components/autofill/content/renderer/password_form_conversion_utils.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <string> 10 #include <string>
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 web_control_elements.end()); 139 web_control_elements.end());
140 synthetic_form->action = web_form.action(); 140 synthetic_form->action = web_form.action();
141 synthetic_form->document = web_form.document(); 141 synthetic_form->document = web_form.document();
142 } 142 }
143 143
144 // Helper function that removes |username_element.value()| from the vector 144 // Helper function that removes |username_element.value()| from the vector
145 // |other_possible_usernames|, if the value presents in the vector. 145 // |other_possible_usernames|, if the value presents in the vector.
146 void ExcludeUsernameFromOtherUsernamesList( 146 void ExcludeUsernameFromOtherUsernamesList(
147 const WebInputElement& username_element, 147 const WebInputElement& username_element,
148 std::vector<base::string16>* other_possible_usernames) { 148 std::vector<base::string16>* other_possible_usernames) {
149 other_possible_usernames->erase( 149 other_possible_usernames->erase(std::remove(other_possible_usernames->begin(),
150 std::remove(other_possible_usernames->begin(), 150 other_possible_usernames->end(),
151 other_possible_usernames->end(), 151 username_element.value().utf16()),
152 username_element.value()), 152 other_possible_usernames->end());
153 other_possible_usernames->end());
154 } 153 }
155 154
156 // Helper to determine which password is the main (current) one, and which is 155 // Helper to determine which password is the main (current) one, and which is
157 // the new password (e.g., on a sign-up or change password form), if any. If the 156 // the new password (e.g., on a sign-up or change password form), if any. If the
158 // new password is found and there is another password field with the same user 157 // new password is found and there is another password field with the same user
159 // input, the function also sets |confirmation_password| to this field. 158 // input, the function also sets |confirmation_password| to this field.
160 bool LocateSpecificPasswords(std::vector<WebInputElement> passwords, 159 bool LocateSpecificPasswords(std::vector<WebInputElement> passwords,
161 WebInputElement* current_password, 160 WebInputElement* current_password,
162 WebInputElement* new_password, 161 WebInputElement* new_password,
163 WebInputElement* confirmation_password) { 162 WebInputElement* confirmation_password) {
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
281 return; 280 return;
282 281
283 std::vector<blink::WebFormControlElement> autofillable_elements = 282 std::vector<blink::WebFormControlElement> autofillable_elements =
284 form_util::ExtractAutofillableElementsFromSet(form.control_elements); 283 form_util::ExtractAutofillableElementsFromSet(form.control_elements);
285 const PasswordFormFieldPredictionMap& field_predictions = 284 const PasswordFormFieldPredictionMap& field_predictions =
286 predictions_it->second; 285 predictions_it->second;
287 for (const auto& prediction : field_predictions) { 286 for (const auto& prediction : field_predictions) {
288 const FormFieldData& target_field = prediction.first; 287 const FormFieldData& target_field = prediction.first;
289 const PasswordFormFieldPredictionType& type = prediction.second; 288 const PasswordFormFieldPredictionType& type = prediction.second;
290 for (const auto& control_element : autofillable_elements) { 289 for (const auto& control_element : autofillable_elements) {
291 if (control_element.nameForAutofill() == target_field.name) { 290 if (control_element.nameForAutofill().utf16() == target_field.name) {
292 const WebInputElement* input_element = 291 const WebInputElement* input_element =
293 toWebInputElement(&control_element); 292 toWebInputElement(&control_element);
294 293
295 // TODO(sebsg): Investigate why this guard is necessary, see 294 // TODO(sebsg): Investigate why this guard is necessary, see
296 // https://crbug.com/517490 for more details. 295 // https://crbug.com/517490 for more details.
297 if (input_element) { 296 if (input_element) {
298 (*predicted_elements)[*input_element] = type; 297 (*predicted_elements)[*input_element] = type;
299 } 298 }
300 break; 299 break;
301 } 300 }
(...skipping 12 matching lines...) Expand all
314 return CreateMatcher(instance, kPasswordSiteUrlRegex); 313 return CreateMatcher(instance, kPasswordSiteUrlRegex);
315 } 314 }
316 }; 315 };
317 316
318 base::LazyInstance<re2::RE2, PasswordSiteUrlLazyInstanceTraits> 317 base::LazyInstance<re2::RE2, PasswordSiteUrlLazyInstanceTraits>
319 g_password_site_matcher = LAZY_INSTANCE_INITIALIZER; 318 g_password_site_matcher = LAZY_INSTANCE_INITIALIZER;
320 319
321 // Returns the |input_field| name if its non-empty; otherwise a |dummy_name|. 320 // Returns the |input_field| name if its non-empty; otherwise a |dummy_name|.
322 base::string16 FieldName(const WebInputElement& input_field, 321 base::string16 FieldName(const WebInputElement& input_field,
323 const char dummy_name[]) { 322 const char dummy_name[]) {
324 base::string16 field_name = input_field.nameForAutofill(); 323 base::string16 field_name = input_field.nameForAutofill().utf16();
325 return field_name.empty() ? base::ASCIIToUTF16(dummy_name) : field_name; 324 return field_name.empty() ? base::ASCIIToUTF16(dummy_name) : field_name;
326 } 325 }
327 326
328 bool FieldHasNonscriptModifiedValue( 327 bool FieldHasNonscriptModifiedValue(
329 const FieldValueAndPropertiesMaskMap* field_map, 328 const FieldValueAndPropertiesMaskMap* field_map,
330 const blink::WebFormControlElement& element) { 329 const blink::WebFormControlElement& element) {
331 if (!field_map) 330 if (!field_map)
332 return false; 331 return false;
333 FieldValueAndPropertiesMaskMap::const_iterator it = field_map->find(element); 332 FieldValueAndPropertiesMaskMap::const_iterator it = field_map->find(element);
334 return it != field_map->end() && it->second.first.get(); 333 return it != field_map->end() && it->second.first.get();
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
476 if (password_form->username_marked_by_site) { 475 if (password_form->username_marked_by_site) {
477 // A second or subsequent element marked with autocomplete='username'. 476 // A second or subsequent element marked with autocomplete='username'.
478 // This makes us less confident that we have understood the form. We 477 // This makes us less confident that we have understood the form. We
479 // will stick to our choice that the first such element was the real 478 // will stick to our choice that the first such element was the real
480 // username, but will start collecting other_possible_usernames from 479 // username, but will start collecting other_possible_usernames from
481 // the extra elements marked with autocomplete='username'. Note that 480 // the extra elements marked with autocomplete='username'. Note that
482 // unlike username_element, other_possible_usernames is used only for 481 // unlike username_element, other_possible_usernames is used only for
483 // autofill, not for form identification, and blank autofill entries 482 // autofill, not for form identification, and blank autofill entries
484 // are not useful, so we do not collect empty strings. 483 // are not useful, so we do not collect empty strings.
485 if (!input_element->value().isEmpty()) 484 if (!input_element->value().isEmpty())
486 other_possible_usernames.push_back(input_element->value()); 485 other_possible_usernames.push_back(input_element->value().utf16());
487 } else { 486 } else {
488 // The first element marked with autocomplete='username'. Take the 487 // The first element marked with autocomplete='username'. Take the
489 // hint and treat it as the username (overruling the tentative choice 488 // hint and treat it as the username (overruling the tentative choice
490 // we might have made before). Furthermore, drop all other possible 489 // we might have made before). Furthermore, drop all other possible
491 // usernames we have accrued so far: they come from fields not marked 490 // usernames we have accrued so far: they come from fields not marked
492 // with the autocomplete attribute, making them unlikely alternatives. 491 // with the autocomplete attribute, making them unlikely alternatives.
493 username_element = *input_element; 492 username_element = *input_element;
494 password_form->username_marked_by_site = true; 493 password_form->username_marked_by_site = true;
495 other_possible_usernames.clear(); 494 other_possible_usernames.clear();
496 } 495 }
497 } else { 496 } else {
498 if (password_form->username_marked_by_site) { 497 if (password_form->username_marked_by_site) {
499 // Having seen elements with autocomplete='username', elements without 498 // Having seen elements with autocomplete='username', elements without
500 // this attribute are no longer interesting. No-op. 499 // this attribute are no longer interesting. No-op.
501 } else { 500 } else {
502 // No elements marked with autocomplete='username' so far whatsoever. 501 // No elements marked with autocomplete='username' so far whatsoever.
503 // If we have not yet selected a username element even provisionally, 502 // If we have not yet selected a username element even provisionally,
504 // then remember this element for the case when the next field turns 503 // then remember this element for the case when the next field turns
505 // out to be a password. Save a non-empty username as a possible 504 // out to be a password. Save a non-empty username as a possible
506 // alternative, at least for now. 505 // alternative, at least for now.
507 if (username_element.isNull()) 506 if (username_element.isNull())
508 latest_input_element = *input_element; 507 latest_input_element = *input_element;
509 if (!input_element->value().isEmpty()) 508 if (!input_element->value().isEmpty())
510 other_possible_usernames.push_back(input_element->value()); 509 other_possible_usernames.push_back(input_element->value().utf16());
511 } 510 }
512 } 511 }
513 } 512 }
514 } 513 }
515 514
516 WebInputElement password; 515 WebInputElement password;
517 WebInputElement new_password; 516 WebInputElement new_password;
518 WebInputElement confirmation_password; 517 WebInputElement confirmation_password;
519 if (!LocateSpecificPasswords(passwords, &password, &new_password, 518 if (!LocateSpecificPasswords(passwords, &password, &new_password,
520 &confirmation_password)) 519 &confirmation_password))
(...skipping 18 matching lines...) Expand all
539 538
540 // Let server predictions override the selection of the username field. This 539 // Let server predictions override the selection of the username field. This
541 // allows instant adjusting without changing Chromium code. 540 // allows instant adjusting without changing Chromium code.
542 auto username_element_iterator = predicted_elements.find(username_element); 541 auto username_element_iterator = predicted_elements.find(username_element);
543 if (map_has_username_prediction && 542 if (map_has_username_prediction &&
544 (username_element_iterator == predicted_elements.end() || 543 (username_element_iterator == predicted_elements.end() ||
545 username_element_iterator->second != PREDICTION_USERNAME)) { 544 username_element_iterator->second != PREDICTION_USERNAME)) {
546 ExcludeUsernameFromOtherUsernamesList(predicted_username_element, 545 ExcludeUsernameFromOtherUsernamesList(predicted_username_element,
547 &other_possible_usernames); 546 &other_possible_usernames);
548 if (!username_element.isNull()) { 547 if (!username_element.isNull()) {
549 other_possible_usernames.push_back(username_element.value()); 548 other_possible_usernames.push_back(username_element.value().utf16());
550 } 549 }
551 username_element = predicted_username_element; 550 username_element = predicted_username_element;
552 password_form->was_parsed_using_autofill_predictions = true; 551 password_form->was_parsed_using_autofill_predictions = true;
553 } 552 }
554 553
555 if (!username_element.isNull()) { 554 if (!username_element.isNull()) {
556 password_form->username_element = 555 password_form->username_element =
557 FieldName(username_element, "anonymous_username"); 556 FieldName(username_element, "anonymous_username");
558 base::string16 username_value = username_element.value(); 557 base::string16 username_value = username_element.value().utf16();
559 if (FieldHasNonscriptModifiedValue(field_value_and_properties_map, 558 if (FieldHasNonscriptModifiedValue(field_value_and_properties_map,
560 username_element)) { 559 username_element)) {
561 base::string16 typed_username_value = 560 base::string16 typed_username_value =
562 *field_value_and_properties_map->at(username_element).first; 561 *field_value_and_properties_map->at(username_element).first;
563 if (!base::StartsWith(base::i18n::ToLower(username_value), 562 if (!base::StartsWith(base::i18n::ToLower(username_value),
564 base::i18n::ToLower(typed_username_value), 563 base::i18n::ToLower(typed_username_value),
565 base::CompareCase::SENSITIVE)) { 564 base::CompareCase::SENSITIVE)) {
566 // We check that |username_value| was not obtained by autofilling 565 // We check that |username_value| was not obtained by autofilling
567 // |typed_username_value|. In case when it was, |typed_username_value| 566 // |typed_username_value|. In case when it was, |typed_username_value|
568 // is incomplete, so we should leave autofilled value. 567 // is incomplete, so we should leave autofilled value.
569 username_value = typed_username_value; 568 username_value = typed_username_value;
570 } 569 }
571 } 570 }
572 password_form->username_value = username_value; 571 password_form->username_value = username_value;
573 } 572 }
574 573
575 password_form->origin = 574 password_form->origin =
576 form_util::GetCanonicalOriginForDocument(form.document); 575 form_util::GetCanonicalOriginForDocument(form.document);
577 GURL::Replacements rep; 576 GURL::Replacements rep;
578 rep.SetPathStr(""); 577 rep.SetPathStr("");
579 password_form->signon_realm = 578 password_form->signon_realm =
580 password_form->origin.ReplaceComponents(rep).spec(); 579 password_form->origin.ReplaceComponents(rep).spec();
581 password_form->other_possible_usernames.swap(other_possible_usernames); 580 password_form->other_possible_usernames.swap(other_possible_usernames);
582 581
583 if (!password.isNull()) { 582 if (!password.isNull()) {
584 password_form->password_element = FieldName(password, "anonymous_password"); 583 password_form->password_element = FieldName(password, "anonymous_password");
585 blink::WebString password_value = password.value(); 584 blink::WebString password_value = password.value();
586 if (FieldHasNonscriptModifiedValue(field_value_and_properties_map, 585 if (FieldHasNonscriptModifiedValue(field_value_and_properties_map,
587 password)) 586 password))
588 password_value = *field_value_and_properties_map->at(password).first; 587 password_value = blink::WebString::fromUTF16(
589 password_form->password_value = password_value; 588 *field_value_and_properties_map->at(password).first);
589 password_form->password_value = password_value.utf16();
590 } 590 }
591 if (!new_password.isNull()) { 591 if (!new_password.isNull()) {
592 password_form->new_password_element = 592 password_form->new_password_element =
593 FieldName(new_password, "anonymous_new_password"); 593 FieldName(new_password, "anonymous_new_password");
594 password_form->new_password_value = new_password.value(); 594 password_form->new_password_value = new_password.value().utf16();
595 password_form->new_password_value_is_default = 595 password_form->new_password_value_is_default =
596 new_password.getAttribute("value") == new_password.value(); 596 new_password.getAttribute("value") == new_password.value();
597 if (HasAutocompleteAttributeValue(new_password, kAutocompleteNewPassword)) 597 if (HasAutocompleteAttributeValue(new_password, kAutocompleteNewPassword))
598 password_form->new_password_marked_by_site = true; 598 password_form->new_password_marked_by_site = true;
599 if (!confirmation_password.isNull()) { 599 if (!confirmation_password.isNull()) {
600 password_form->confirmation_password_element = 600 password_form->confirmation_password_element =
601 FieldName(confirmation_password, "anonymous_confirmation_password"); 601 FieldName(confirmation_password, "anonymous_confirmation_password");
602 } 602 }
603 } 603 }
604 604
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
714 return std::unique_ptr<PasswordForm>(); 714 return std::unique_ptr<PasswordForm>();
715 715
716 // No actual action on the form, so use the the origin as the action. 716 // No actual action on the form, so use the the origin as the action.
717 password_form->action = password_form->origin; 717 password_form->action = password_form->origin;
718 718
719 return password_form; 719 return password_form;
720 } 720 }
721 721
722 bool HasAutocompleteAttributeValue(const blink::WebInputElement& element, 722 bool HasAutocompleteAttributeValue(const blink::WebInputElement& element,
723 const char* value_in_lowercase) { 723 const char* value_in_lowercase) {
724 base::string16 autocomplete_attribute(element.getAttribute("autocomplete")); 724 base::string16 autocomplete_attribute(
725 element.getAttribute("autocomplete").utf16());
725 std::vector<std::string> tokens = LowercaseAndTokenizeAttributeString( 726 std::vector<std::string> tokens = LowercaseAndTokenizeAttributeString(
726 base::UTF16ToUTF8(autocomplete_attribute)); 727 base::UTF16ToUTF8(autocomplete_attribute));
727 728
728 return base::ContainsValue(tokens, value_in_lowercase); 729 return base::ContainsValue(tokens, value_in_lowercase);
729 } 730 }
730 731
731 } // namespace autofill 732 } // namespace autofill
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698