diff options
Diffstat (limited to 'chromium/components/autofill/content/common')
9 files changed, 233 insertions, 39 deletions
diff --git a/chromium/components/autofill/content/common/BUILD.gn b/chromium/components/autofill/content/common/BUILD.gn index 1b2628c71b0..04379f467a7 100644 --- a/chromium/components/autofill/content/common/BUILD.gn +++ b/chromium/components/autofill/content/common/BUILD.gn @@ -25,6 +25,7 @@ mojom("mojo_types") { public_deps = [ "//mojo/public/mojom/base", + "//ui/gfx/geometry/mojo", "//url/mojom:url_mojom_gurl", "//url/mojom:url_mojom_origin", ] diff --git a/chromium/components/autofill/content/common/autofill_agent.mojom b/chromium/components/autofill/content/common/autofill_agent.mojom index 66a2f598b61..891f2b86ea0 100644 --- a/chromium/components/autofill/content/common/autofill_agent.mojom +++ b/chromium/components/autofill/content/common/autofill_agent.mojom @@ -84,6 +84,10 @@ interface PasswordAutofillAgent { // ShowPasswordSuggestions messages to the browser. FillPasswordForm(int32 key, PasswordFormFillData form_data); + // Fills the given |credential| into the last focused text input. + FillIntoFocusedField(bool is_password, mojo_base.mojom.String16 credential) + => (FillingStatus status); + // Notification to start (|active| == true) or stop (|active| == false) // logging the decisions made about saving the password. SetLoggingState(bool active); @@ -97,10 +101,6 @@ interface PasswordAutofillAgent { // Renderer is expected to return the found password form. If no password form // is focused, the response will contain an empty |autofill::PasswordForm|. FindFocusedPasswordForm() => (PasswordForm form); - - // Notifies PasswordAutofillAgent that the matching blacklisted form was - // found. - BlacklistedFormFound(); }; // There is one instance of this interface per render frame in the render @@ -115,10 +115,6 @@ interface PasswordGenerationAgent { // browser with the message |ShowPasswordGenerationPopup|. UserTriggeredGeneratePassword(); - // Tells the renderer to populate the correct password fields with this - // generated password. - UserSelectedManualGenerationOption(); - // Tells the renderer that this password form is not blacklisted. A form can // be blacklisted if a user chooses "never save passwords for this site". FormNotBlacklisted(PasswordForm form); diff --git a/chromium/components/autofill/content/common/autofill_driver.mojom b/chromium/components/autofill/content/common/autofill_driver.mojom index c15cb9fa67a..34be2a1e28e 100644 --- a/chromium/components/autofill/content/common/autofill_driver.mojom +++ b/chromium/components/autofill/content/common/autofill_driver.mojom @@ -50,7 +50,8 @@ interface AutofillDriver { QueryFormFieldAutofill(int32 id, FormData form, FormFieldData field, - gfx.mojom.RectF bounding_box); + gfx.mojom.RectF bounding_box, + bool autoselect_first_suggestion); // Instructs the browser to hide the Autofill popup if it is open. HidePopup(); @@ -123,19 +124,6 @@ interface PasswordManagerDriver { mojo_base.mojom.String16 typed_username, int32 options, gfx.mojom.RectF bounds); - // Instructs the browser to show a suggestion, which will redirect the user to - // the list of all saved passwords. The popup will use |text_direction| for - // displaying text. - ShowManualFallbackSuggestion(mojo_base.mojom.TextDirection text_direction, - gfx.mojom.RectF bounds); - - // Instructs the browser to presave the form with generated password. - PresaveGeneratedPassword(PasswordForm password_form); - - // Instructs the browser that form no longer contains a generated password and - // the presaved form should be removed. - PasswordNoLongerGenerated(PasswordForm password_form); - // Sends the outcome of HTML parsing based form classifier that detects the // forms where password generation should be available. SaveGenerationFieldDetectedByClassifier( @@ -145,6 +133,10 @@ interface PasswordManagerDriver { // username/password field is on. CheckSafeBrowsingReputation( url.mojom.Url form_action, url.mojom.Url frame_url); + + // The focus changed to a different input in the same frame (e.g. tabbed from + // email to password field). + FocusedInputChanged(bool is_fillable, bool is_password_field); }; // There is one instance of this interface per web contents in the browser @@ -154,24 +146,33 @@ interface PasswordManagerClient { // form. This is used for UMA stats. GenerationAvailableForForm(PasswordForm password_form); - // Instructs the browser to show the password generation popup at the - // specified location. This location should be specified in the renderers - // coordinate system. Form is the form associated with the password field. - // The popup will be anchored at |bounds|. The generated password - // will be no longer than |max_length|. |generation_element| should contain a - // name of a password field at which generation popup is attached. - // |is_manually_triggered| informs whether it is automatically or manually - // triggered generation. - ShowPasswordGenerationPopup( - gfx.mojom.RectF bounds, int32 max_length, - mojo_base.mojom.String16 generation_element, bool is_manually_triggered, - PasswordForm password_form); + // Notifies the browser when automatic generation becomes available or + // unavailable and provides data needed by the UI. + AutomaticGenerationStatusChanged( + bool available, PasswordGenerationUIData? password_generation_ui_data); + + // Instructs the browser to show the password generation popup for manual + // generation and provides the data necessary to display it. + // TODO(crbug.com/845458): Replace this with a method called from the browser + // when user triggers generation manually which returns a boolean signaling + // whether the state for generation could be saved or not. + ShowManualPasswordGenerationPopup( + PasswordGenerationUIData password_generation_ui_data); // Instructs the browser to show the popup for editing a generated password. // The location should be specified in the renderers coordinate system. Form // is the form associated with the password field. ShowPasswordEditingPopup(gfx.mojom.RectF bounds, PasswordForm password_form); - // Instructs the browser to hide any password generation popups. - HidePasswordGenerationPopup(); + // Informs the browser that the password generation option was rejected + // by the user typing more characters than the maximum offer size into the + // password field. + PasswordGenerationRejectedByTyping(); + + // Instructs the browser to presave the form with generated password. + PresaveGeneratedPassword(PasswordForm password_form); + + // Instructs the browser that form no longer contains a generated password and + // the presaved form should be removed. + PasswordNoLongerGenerated(PasswordForm password_form); }; diff --git a/chromium/components/autofill/content/common/autofill_types.mojom b/chromium/components/autofill/content/common/autofill_types.mojom index bbda37d00a4..c9ecc5760f8 100644 --- a/chromium/components/autofill/content/common/autofill_types.mojom +++ b/chromium/components/autofill/content/common/autofill_types.mojom @@ -7,6 +7,7 @@ module autofill.mojom; import "mojo/public/mojom/base/text_direction.mojom"; import "mojo/public/mojom/base/time.mojom"; import "mojo/public/mojom/base/string16.mojom"; +import "ui/gfx/geometry/mojo/geometry.mojom"; import "url/mojom/origin.mojom"; import "url/mojom/url.mojom"; @@ -99,6 +100,13 @@ enum LabelSource { VALUE, }; +// autofill::FillingStatus +enum FillingStatus { + SUCCESS, + ERROR_NO_VALID_FIELD, + ERROR_NOT_ALLOWED, +}; + // autofill::FormFieldData struct FormFieldData { mojo_base.mojom.String16 label; @@ -142,6 +150,7 @@ struct FormData { bool is_formless_checkout; uint32 unique_renderer_id; array<FormFieldData> fields; + array<uint32> username_predictions; }; // autofill::FormFieldDataPredictions @@ -170,15 +179,18 @@ struct PasswordAndRealm { // autofill::PasswordFormFillData struct PasswordFormFillData { + uint32 form_renderer_id; mojo_base.mojom.String16 name; url.mojom.Url origin; url.mojom.Url action; FormFieldData username_field; FormFieldData password_field; + bool username_may_use_prefilled_placeholder; string preferred_realm; map<mojo_base.mojom.String16, PasswordAndRealm> additional_logins; bool wait_for_username; bool is_possible_change_password_form; + bool has_renderer_ids; }; // autofill::PasswordFormGenerationData @@ -189,6 +201,15 @@ struct PasswordFormGenerationData { uint32 confirmation_field_signature; }; +// autofill::password_generation::PasswordGenerationUIData +struct PasswordGenerationUIData { + gfx.mojom.RectF bounds; + int32 max_length; + mojo_base.mojom.String16 generation_element; + mojo_base.mojom.TextDirection text_direction; + PasswordForm password_form; +}; + // autofill::ValueElementPair struct ValueElementPair { mojo_base.mojom.String16 value; diff --git a/chromium/components/autofill/content/common/autofill_types.typemap b/chromium/components/autofill/content/common/autofill_types.typemap index 44e88ba309a..1f9b633589c 100644 --- a/chromium/components/autofill/content/common/autofill_types.typemap +++ b/chromium/components/autofill/content/common/autofill_types.typemap @@ -4,6 +4,7 @@ mojom = "//components/autofill/content/common/autofill_types.mojom" public_headers = [ + "//components/autofill/core/common/filling_status.h", "//components/autofill/core/common/form_data.h", "//components/autofill/core/common/form_data_predictions.h", "//components/autofill/core/common/form_field_data.h", @@ -12,6 +13,7 @@ public_headers = [ "//components/autofill/core/common/password_form_field_prediction_map.h", "//components/autofill/core/common/password_form_fill_data.h", "//components/autofill/core/common/password_form_generation_data.h", + "//components/autofill/core/common/password_generation_util.h", "//components/autofill/core/common/submission_source.h", ] traits_headers = @@ -23,10 +25,12 @@ deps = [ "//base", "//base:i18n", "//components/autofill/core/common", + "//ui/gfx/geometry/mojo:struct_traits", ] type_mappings = [ "autofill.mojom.CheckStatus=autofill::FormFieldData::CheckStatus", + "autofill.mojom.FillingStatus=autofill::FillingStatus", "autofill.mojom.FormData=autofill::FormData", "autofill.mojom.FormDataPredictions=autofill::FormDataPredictions", "autofill.mojom.FormFieldData=autofill::FormFieldData", @@ -41,9 +45,10 @@ type_mappings = [ "autofill.mojom.PasswordFormGenerationData=autofill::PasswordFormGenerationData", "autofill.mojom.PasswordFormLayout=autofill::PasswordForm::Layout", "autofill.mojom.PasswordFormScheme=autofill::PasswordForm::Scheme", + "autofill.mojom.PasswordFormSubmissionIndicatorEvent=autofill::PasswordForm::SubmissionIndicatorEvent", "autofill.mojom.PasswordFormType=autofill::PasswordForm::Type", + "autofill.mojom.PasswordGenerationUIData=autofill::password_generation::PasswordGenerationUIData", "autofill.mojom.RoleAttribute=autofill::FormFieldData::RoleAttribute", - "autofill.mojom.ValueElementPair=autofill::ValueElementPair", - "autofill.mojom.PasswordFormSubmissionIndicatorEvent=autofill::PasswordForm::SubmissionIndicatorEvent", "autofill.mojom.SubmissionSource=autofill::SubmissionSource", + "autofill.mojom.ValueElementPair=autofill::ValueElementPair", ] diff --git a/chromium/components/autofill/content/common/autofill_types_struct_traits.cc b/chromium/components/autofill/content/common/autofill_types_struct_traits.cc index d4552fd7520..fad95dddd5c 100644 --- a/chromium/components/autofill/content/common/autofill_types_struct_traits.cc +++ b/chromium/components/autofill/content/common/autofill_types_struct_traits.cc @@ -6,8 +6,8 @@ #include "base/i18n/rtl.h" #include "mojo/public/cpp/base/string16_mojom_traits.h" -#include "mojo/public/cpp/base/text_direction_mojom_traits.h" #include "mojo/public/cpp/base/time_mojom_traits.h" +#include "ui/gfx/geometry/mojo/geometry_struct_traits.h" #include "url/mojom/origin_mojom_traits.h" #include "url/mojom/url_gurl_mojom_traits.h" @@ -533,6 +533,41 @@ bool EnumTraits<autofill::mojom::LabelSource, } // static +autofill::mojom::FillingStatus +EnumTraits<autofill::mojom::FillingStatus, autofill::FillingStatus>::ToMojom( + autofill::FillingStatus input) { + switch (input) { + case autofill::FillingStatus::SUCCESS: + return autofill::mojom::FillingStatus::SUCCESS; + case autofill::FillingStatus::ERROR_NO_VALID_FIELD: + return autofill::mojom::FillingStatus::ERROR_NO_VALID_FIELD; + case autofill::FillingStatus::ERROR_NOT_ALLOWED: + return autofill::mojom::FillingStatus::ERROR_NOT_ALLOWED; + } + NOTREACHED(); + return autofill::mojom::FillingStatus::SUCCESS; +} + +// static +bool EnumTraits<autofill::mojom::FillingStatus, autofill::FillingStatus>:: + FromMojom(autofill::mojom::FillingStatus input, + autofill::FillingStatus* output) { + switch (input) { + case autofill::mojom::FillingStatus::SUCCESS: + *output = autofill::FillingStatus::SUCCESS; + return true; + case autofill::mojom::FillingStatus::ERROR_NO_VALID_FIELD: + *output = autofill::FillingStatus::ERROR_NO_VALID_FIELD; + return true; + case autofill::mojom::FillingStatus::ERROR_NOT_ALLOWED: + *output = autofill::FillingStatus::ERROR_NOT_ALLOWED; + return true; + } + NOTREACHED(); + return false; +} + +// static bool StructTraits< autofill::mojom::FormFieldDataDataView, autofill::FormFieldData>::Read(autofill::mojom::FormFieldDataDataView data, @@ -614,6 +649,9 @@ bool StructTraits<autofill::mojom::FormDataDataView, autofill::FormData>::Read( if (!data.ReadFields(&out->fields)) return false; + if (!data.ReadUsernamePredictions(&out->username_predictions)) + return false; + return true; } @@ -681,9 +719,13 @@ bool StructTraits<autofill::mojom::PasswordFormFillDataDataView, !data.ReadAdditionalLogins(&out->additional_logins)) return false; + out->form_renderer_id = data.form_renderer_id(); out->wait_for_username = data.wait_for_username(); out->is_possible_change_password_form = data.is_possible_change_password_form(); + out->has_renderer_ids = data.has_renderer_ids(); + out->username_may_use_prefilled_placeholder = + data.username_may_use_prefilled_placeholder(); return true; } @@ -705,6 +747,24 @@ bool StructTraits<autofill::mojom::PasswordFormGenerationDataDataView, } // static +bool StructTraits<autofill::mojom::PasswordGenerationUIDataDataView, + autofill::password_generation::PasswordGenerationUIData>:: + Read(autofill::mojom::PasswordGenerationUIDataDataView data, + autofill::password_generation::PasswordGenerationUIData* out) { + if (!data.ReadBounds(&out->bounds)) + return false; + + out->max_length = data.max_length(); + + if (!data.ReadGenerationElement(&out->generation_element) || + !data.ReadTextDirection(&out->text_direction) || + !data.ReadPasswordForm(&out->password_form)) + return false; + + return true; +} + +// static bool StructTraits< autofill::mojom::PasswordFormDataView, autofill::PasswordForm>::Read(autofill::mojom::PasswordFormDataView data, diff --git a/chromium/components/autofill/content/common/autofill_types_struct_traits.h b/chromium/components/autofill/content/common/autofill_types_struct_traits.h index 4c42d624ac8..68d03e0ec10 100644 --- a/chromium/components/autofill/content/common/autofill_types_struct_traits.h +++ b/chromium/components/autofill/content/common/autofill_types_struct_traits.h @@ -21,8 +21,11 @@ #include "components/autofill/core/common/password_form_field_prediction_map.h" #include "components/autofill/core/common/password_form_fill_data.h" #include "components/autofill/core/common/password_form_generation_data.h" +#include "components/autofill/core/common/password_generation_util.h" #include "components/autofill/core/common/submission_source.h" +#include "mojo/public/cpp/base/text_direction_mojom_traits.h" #include "mojo/public/cpp/bindings/struct_traits.h" +#include "ui/gfx/geometry/rect_f.h" #include "url/origin.h" namespace mojo { @@ -119,6 +122,13 @@ struct EnumTraits<autofill::mojom::LabelSource, }; template <> +struct EnumTraits<autofill::mojom::FillingStatus, autofill::FillingStatus> { + static autofill::mojom::FillingStatus ToMojom(autofill::FillingStatus input); + static bool FromMojom(autofill::mojom::FillingStatus input, + autofill::FillingStatus* output); +}; + +template <> struct StructTraits<autofill::mojom::FormFieldDataDataView, autofill::FormFieldData> { static const base::string16& label(const autofill::FormFieldData& r) { @@ -262,6 +272,11 @@ struct StructTraits<autofill::mojom::FormDataDataView, autofill::FormData> { return r.fields; } + static const std::vector<uint32_t>& username_predictions( + const autofill::FormData& r) { + return r.username_predictions; + } + static bool Read(autofill::mojom::FormDataDataView data, autofill::FormData* out); }; @@ -347,6 +362,9 @@ struct StructTraits<autofill::mojom::PasswordAndRealmDataView, template <> struct StructTraits<autofill::mojom::PasswordFormFillDataDataView, autofill::PasswordFormFillData> { + static uint32_t form_renderer_id(const autofill::PasswordFormFillData& r) { + return r.form_renderer_id; + } static const base::string16& name(const autofill::PasswordFormFillData& r) { return r.name; @@ -370,6 +388,11 @@ struct StructTraits<autofill::mojom::PasswordFormFillDataDataView, return r.password_field; } + static bool username_may_use_prefilled_placeholder( + const autofill::PasswordFormFillData& r) { + return r.username_may_use_prefilled_placeholder; + } + static const std::string& preferred_realm( const autofill::PasswordFormFillData& r) { return r.preferred_realm; @@ -389,6 +412,10 @@ struct StructTraits<autofill::mojom::PasswordFormFillDataDataView, return r.is_possible_change_password_form; } + static bool has_renderer_ids(const autofill::PasswordFormFillData& r) { + return r.has_renderer_ids; + } + static bool Read(autofill::mojom::PasswordFormFillDataDataView data, autofill::PasswordFormFillData* out); }; @@ -421,6 +448,39 @@ struct StructTraits<autofill::mojom::PasswordFormGenerationDataDataView, }; template <> +struct StructTraits<autofill::mojom::PasswordGenerationUIDataDataView, + autofill::password_generation::PasswordGenerationUIData> { + static const gfx::RectF& bounds( + const autofill::password_generation::PasswordGenerationUIData& r) { + return r.bounds; + } + + static int max_length( + const autofill::password_generation::PasswordGenerationUIData& r) { + return r.max_length; + } + + static const base::string16& generation_element( + const autofill::password_generation::PasswordGenerationUIData& r) { + return r.generation_element; + } + + static base::i18n::TextDirection text_direction( + const autofill::password_generation::PasswordGenerationUIData& r) { + return r.text_direction; + } + + static const autofill::PasswordForm& password_form( + const autofill::password_generation::PasswordGenerationUIData& r) { + return r.password_form; + } + + static bool Read( + autofill::mojom::PasswordGenerationUIDataDataView data, + autofill::password_generation::PasswordGenerationUIData* out); +}; + +template <> struct StructTraits<autofill::mojom::PasswordFormDataView, autofill::PasswordForm> { static autofill::PasswordForm::Scheme scheme( diff --git a/chromium/components/autofill/content/common/autofill_types_struct_traits_unittest.cc b/chromium/components/autofill/content/common/autofill_types_struct_traits_unittest.cc index 6c0b146e472..f0f8abfdea2 100644 --- a/chromium/components/autofill/content/common/autofill_types_struct_traits_unittest.cc +++ b/chromium/components/autofill/content/common/autofill_types_struct_traits_unittest.cc @@ -11,6 +11,7 @@ #include "components/autofill/core/browser/autofill_test_utils.h" #include "components/autofill/core/common/form_data.h" #include "components/autofill/core/common/form_field_data.h" +#include "components/autofill/core/common/password_generation_util.h" #include "components/autofill/core/common/signatures_util.h" #include "mojo/public/cpp/bindings/binding_set.h" #include "mojo/public/cpp/bindings/interface_request.h" @@ -35,6 +36,7 @@ void CreateTestFieldDataPredictions(const std::string& signature, } void CreateTestPasswordFormFillData(PasswordFormFillData* fill_data) { + fill_data->form_renderer_id = 1234; fill_data->name = base::ASCIIToUTF16("TestName"); fill_data->origin = GURL("https://foo.com/"); fill_data->action = GURL("https://foo.com/login"); @@ -143,8 +145,18 @@ void CreateTestFormsPredictionsMap(FormsPredictionsMap* predictions) { PasswordFormFieldPredictionType::PREDICTION_CURRENT_PASSWORD; } +void CreatePasswordGenerationUIData( + password_generation::PasswordGenerationUIData* data) { + data->bounds = gfx::RectF(1, 1, 200, 100); + data->max_length = 20; + data->generation_element = base::ASCIIToUTF16("generation_element"); + data->text_direction = base::i18n::RIGHT_TO_LEFT; + CreateTestPasswordForm(&data->password_form); +} + void CheckEqualPasswordFormFillData(const PasswordFormFillData& expected, const PasswordFormFillData& actual) { + EXPECT_EQ(expected.form_renderer_id, actual.form_renderer_id); EXPECT_EQ(expected.name, actual.name); EXPECT_EQ(expected.origin, actual.origin); EXPECT_EQ(expected.action, actual.action); @@ -184,6 +196,16 @@ void CheckEqualPasswordFormGenerationData( actual.confirmation_field_signature.value()); } +void CheckEqualPassPasswordGenerationUIData( + const password_generation::PasswordGenerationUIData& expected, + const password_generation::PasswordGenerationUIData& actual) { + EXPECT_EQ(expected.bounds, actual.bounds); + EXPECT_EQ(expected.max_length, actual.max_length); + EXPECT_EQ(expected.generation_element, actual.generation_element); + EXPECT_EQ(expected.text_direction, actual.text_direction); + EXPECT_EQ(expected.password_form, actual.password_form); +} + } // namespace class AutofillTypeTraitsTestImpl : public testing::Test, @@ -231,6 +253,12 @@ class AutofillTypeTraitsTestImpl : public testing::Test, std::move(callback).Run(s); } + void PassPasswordGenerationUIData( + const password_generation::PasswordGenerationUIData& s, + PassPasswordGenerationUIDataCallback callback) override { + std::move(callback).Run(s); + } + void PassPasswordForm(const PasswordForm& s, PassPasswordFormCallback callback) override { std::move(callback).Run(s); @@ -291,6 +319,14 @@ void ExpectPasswordFormGenerationData( closure.Run(); } +void ExpectPasswordGenerationUIData( + const password_generation::PasswordGenerationUIData& expected, + base::OnceClosure closure, + const password_generation::PasswordGenerationUIData& passed) { + CheckEqualPassPasswordGenerationUIData(expected, passed); + std::move(closure).Run(); +} + void ExpectPasswordForm(const PasswordForm& expected, const base::Closure& closure, const PasswordForm& passed) { @@ -332,6 +368,7 @@ TEST_F(AutofillTypeTraitsTestImpl, PassFormFieldData) { TEST_F(AutofillTypeTraitsTestImpl, PassFormData) { FormData input; test::CreateTestAddressFormData(&input); + input.username_predictions = {1, 13, 2}; base::RunLoop loop; mojom::TypeTraitsTestPtr proxy = GetTypeTraitsTestProxy(); @@ -402,6 +439,18 @@ TEST_F(AutofillTypeTraitsTestImpl, PassPasswordFormGenerationData) { loop.Run(); } +TEST_F(AutofillTypeTraitsTestImpl, PassPasswordGenerationUIData) { + password_generation::PasswordGenerationUIData input; + CreatePasswordGenerationUIData(&input); + + base::RunLoop loop; + mojom::TypeTraitsTestPtr proxy = GetTypeTraitsTestProxy(); + proxy->PassPasswordGenerationUIData( + input, base::BindOnce(&ExpectPasswordGenerationUIData, input, + loop.QuitClosure())); + loop.Run(); +} + TEST_F(AutofillTypeTraitsTestImpl, PassPasswordForm) { PasswordForm input; CreateTestPasswordForm(&input); diff --git a/chromium/components/autofill/content/common/test_autofill_types.mojom b/chromium/components/autofill/content/common/test_autofill_types.mojom index b578eb47ada..a0a0234d217 100644 --- a/chromium/components/autofill/content/common/test_autofill_types.mojom +++ b/chromium/components/autofill/content/common/test_autofill_types.mojom @@ -15,4 +15,5 @@ interface TypeTraitsTest { PassPasswordFormFillData(PasswordFormFillData s) => (PasswordFormFillData passed); PassFormsPredictionsMap(FormsPredictionsMap s) => (FormsPredictionsMap passed); PassPasswordFormGenerationData(PasswordFormGenerationData s) => (PasswordFormGenerationData passed); + PassPasswordGenerationUIData(PasswordGenerationUIData s) => (PasswordGenerationUIData passed); }; |