Commit cb858941 authored by Maria Kazinova's avatar Maria Kazinova Committed by Commit Bot

[iOS] Fixing password generation outside the form tag.

Previously it was possible to generate a password on a password field
outside the form tag but it was not filled, since formless fields
were ignored in this flow. This CL fixes that.

Bug: 1146005
Change-Id: I5bf6347c9666b6b7e4f1d796418597f27d5e8f86
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2527144Reviewed-by: default avatarJan Wilken Dörrie <jdoerrie@chromium.org>
Commit-Queue: Maria Kazinova <kazinova@google.com>
Cr-Commit-Position: refs/heads/master@{#825799}
parent 21460dbe
...@@ -23,6 +23,16 @@ using autofill::FieldRendererId; ...@@ -23,6 +23,16 @@ using autofill::FieldRendererId;
using autofill::kNotSetRendererID; using autofill::kNotSetRendererID;
using base::SysNSStringToUTF8; using base::SysNSStringToUTF8;
// Converts FormRendererId to int value that can be used in Javascript methods.
int FormRendererIdToJsParameter(FormRendererId formID) {
return formID ? formID.value() : kNotSetRendererID;
}
// Converts FieldRendererId to int value that can be used in Javascript methods.
int FieldRendererIdToJsParameter(FieldRendererId fieldID) {
return fieldID ? fieldID.value() : kNotSetRendererID;
}
namespace password_manager { namespace password_manager {
std::unique_ptr<base::Value> SerializeFillData( std::unique_ptr<base::Value> SerializeFillData(
...@@ -34,14 +44,14 @@ std::unique_ptr<base::Value> SerializeFillData( ...@@ -34,14 +44,14 @@ std::unique_ptr<base::Value> SerializeFillData(
const base::string16& password_value) { const base::string16& password_value) {
auto rootDict = std::make_unique<base::DictionaryValue>(); auto rootDict = std::make_unique<base::DictionaryValue>();
rootDict->SetString("origin", origin.spec()); rootDict->SetString("origin", origin.spec());
rootDict->SetInteger("unique_renderer_id", form_renderer_id.value()); rootDict->SetInteger("unique_renderer_id",
FormRendererIdToJsParameter(form_renderer_id));
auto fieldList = std::make_unique<base::ListValue>(); auto fieldList = std::make_unique<base::ListValue>();
auto usernameField = std::make_unique<base::DictionaryValue>(); auto usernameField = std::make_unique<base::DictionaryValue>();
usernameField->SetInteger("unique_renderer_id", username_element usernameField->SetInteger("unique_renderer_id",
? username_element.value() FieldRendererIdToJsParameter(username_element));
: kNotSetRendererID);
usernameField->SetString("value", username_value); usernameField->SetString("value", username_value);
fieldList->Append(std::move(usernameField)); fieldList->Append(std::move(usernameField));
...@@ -119,9 +129,10 @@ std::unique_ptr<base::Value> SerializeFillData( ...@@ -119,9 +129,10 @@ std::unique_ptr<base::Value> SerializeFillData(
completionHandler:(void (^)(BOOL))completionHandler { completionHandler:(void (^)(BOOL))completionHandler {
DCHECK(completionHandler); DCHECK(completionHandler);
std::vector<base::Value> parameters; std::vector<base::Value> parameters;
parameters.emplace_back(static_cast<int>(formIdentifier.value())); parameters.emplace_back(FormRendererIdToJsParameter(formIdentifier));
parameters.emplace_back(static_cast<int>(newPasswordIdentifier.value())); parameters.emplace_back(FieldRendererIdToJsParameter(newPasswordIdentifier));
parameters.emplace_back(static_cast<int>(confirmPasswordIdentifier.value())); parameters.emplace_back(
FieldRendererIdToJsParameter(confirmPasswordIdentifier));
parameters.push_back(base::Value(SysNSStringToUTF8(generatedPassword))); parameters.push_back(base::Value(SysNSStringToUTF8(generatedPassword)));
autofill::ExecuteJavaScriptFunction( autofill::ExecuteJavaScriptFunction(
"passwords.fillPasswordFormWithGeneratedPassword", parameters, frame, "passwords.fillPasswordFormWithGeneratedPassword", parameters, frame,
......
...@@ -225,11 +225,15 @@ __gCrWeb.passwords['fillPasswordForm'] = function( ...@@ -225,11 +225,15 @@ __gCrWeb.passwords['fillPasswordForm'] = function(
__gCrWeb.passwords['fillPasswordFormWithGeneratedPassword'] = function( __gCrWeb.passwords['fillPasswordFormWithGeneratedPassword'] = function(
formIdentifier, newPasswordIdentifier, confirmPasswordIdentifier, formIdentifier, newPasswordIdentifier, confirmPasswordIdentifier,
password) { password) {
const hasFormTag =
formIdentifier.toString() !== __gCrWeb.fill.RENDERER_ID_NOT_SET;
const form = __gCrWeb.form.getFormElementFromUniqueFormId(formIdentifier); const form = __gCrWeb.form.getFormElementFromUniqueFormId(formIdentifier);
if (!form) { if (!form && hasFormTag) {
return false; return false;
} }
const inputs = getFormInputElements(form); const inputs = hasFormTag ?
getFormInputElements(form) :
__gCrWeb.fill.getUnownedAutofillableFormFieldElements(document.all, []);
const newPasswordField = const newPasswordField =
findInputByUniqueFieldId(inputs, newPasswordIdentifier); findInputByUniqueFieldId(inputs, newPasswordIdentifier);
if (!newPasswordField) { if (!newPasswordField) {
......
...@@ -643,6 +643,39 @@ TEST_F( ...@@ -643,6 +643,39 @@ TEST_F(
@"document.getElementById('user').value == '%@'", password)); @"document.getElementById('user').value == '%@'", password));
} }
// Check that a matching and complete password form is successfully filled
// with the generated password.
TEST_F(PasswordControllerJsTest,
FillPasswordFormWithGeneratedPassword_SucceedsOutsideFormTag) {
LoadHtmlAndInject(@"<html>"
" <body>"
" <input type=\"text\" id=\"user\" name=\"user\">"
" <input type=\"password\" id=\"ps1\" name=\"ps1\">"
" <input type=\"password\" id=\"ps2\" name=\"ps2\">"
" <input type=\"submit\" name=\"go\">"
" </body>"
"</html>");
SetUpUniqueIDs();
NSString* const password = @"abc";
uint32_t const newPasswordIdentifier = 1;
uint32_t const confirmPasswordIdentifier = 2;
EXPECT_NSEQ(@YES,
ExecuteJavaScriptWithFormat(
@"__gCrWeb.passwords."
@"fillPasswordFormWithGeneratedPassword(-1, %u, %u, '%@')",
newPasswordIdentifier, confirmPasswordIdentifier, password));
EXPECT_NSEQ(@YES,
ExecuteJavaScriptWithFormat(
@"document.getElementById('ps1').value == '%@'", password));
EXPECT_NSEQ(@YES,
ExecuteJavaScriptWithFormat(
@"document.getElementById('ps2').value == '%@'", password));
EXPECT_NSEQ(@NO,
ExecuteJavaScriptWithFormat(
@"document.getElementById('user').value == '%@'", password));
}
// Check that a form with only password field (i.e. w/o username) is filled. // Check that a form with only password field (i.e. w/o username) is filled.
TEST_F(PasswordControllerJsTest, FillOnlyPasswordField) { TEST_F(PasswordControllerJsTest, FillOnlyPasswordField) {
LoadHtmlAndInject( LoadHtmlAndInject(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment