[Password Generation] Use signatures for form matching

At this time, the form matching is based on form name and action. Action should have canonical form and be non-empty. We missed to prepare actions in some cases. So, even if we classified a field as suitable for password generation, we didn't show generation popup, because form matching failed. It should be fixed.

Since the server sends signatures of form and fields, it is more error-prone to match forms based on what server works with.

BUG=582434

Review-Url: https://codereview.chromium.org/2318533002
Cr-Commit-Position: refs/heads/master@{#420043}
diff --git a/chrome/renderer/autofill/password_generation_test_utils.cc b/chrome/renderer/autofill/password_generation_test_utils.cc
index d510daf9..455dd6c 100644
--- a/chrome/renderer/autofill/password_generation_test_utils.cc
+++ b/chrome/renderer/autofill/password_generation_test_utils.cc
@@ -10,6 +10,7 @@
 #include "components/autofill/content/renderer/form_autofill_util.h"
 #include "components/autofill/content/renderer/test_password_generation_agent.h"
 #include "components/autofill/core/common/password_form_generation_data.h"
+#include "components/autofill/core/common/signatures_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/WebKit/public/web/WebDocument.h"
 #include "third_party/WebKit/public/web/WebFormElement.h"
@@ -41,8 +42,8 @@
 
   std::vector<autofill::PasswordFormGenerationData> forms;
   forms.push_back(autofill::PasswordFormGenerationData{
-      form_data.name, form_util::StripAuthAndParams(form_data.action),
-      form_data.fields[field_index]});
+      CalculateFormSignature(form_data),
+      CalculateFieldSignatureForField(form_data.fields[field_index])});
   generation_agent->FoundFormsEligibleForGeneration(forms);
 }
 
diff --git a/components/autofill/content/public/cpp/autofill_types_struct_traits.cc b/components/autofill/content/public/cpp/autofill_types_struct_traits.cc
index 3ea26e92..4b02077 100644
--- a/components/autofill/content/public/cpp/autofill_types_struct_traits.cc
+++ b/components/autofill/content/public/cpp/autofill_types_struct_traits.cc
@@ -513,10 +513,8 @@
                   PasswordFormGenerationData>::
     Read(mojom::PasswordFormGenerationDataDataView data,
          PasswordFormGenerationData* out) {
-  if (!data.ReadName(&out->name) || !data.ReadAction(&out->action) ||
-      !data.ReadGenerationField(&out->generation_field))
-    return false;
-
+  out->form_signature = data.form_signature();
+  out->field_signature = data.field_signature();
   return true;
 }
 
diff --git a/components/autofill/content/public/cpp/autofill_types_struct_traits.h b/components/autofill/content/public/cpp/autofill_types_struct_traits.h
index e68b93a..e22085f 100644
--- a/components/autofill/content/public/cpp/autofill_types_struct_traits.h
+++ b/components/autofill/content/public/cpp/autofill_types_struct_traits.h
@@ -365,18 +365,14 @@
 template <>
 struct StructTraits<autofill::mojom::PasswordFormGenerationDataDataView,
                     autofill::PasswordFormGenerationData> {
-  static const base::string16& name(
+  static uint64_t form_signature(
       const autofill::PasswordFormGenerationData& r) {
-    return r.name;
+    return r.form_signature;
   }
 
-  static const GURL& action(const autofill::PasswordFormGenerationData& r) {
-    return r.action;
-  }
-
-  static const autofill::FormFieldData& generation_field(
+  static uint32_t field_signature(
       const autofill::PasswordFormGenerationData& r) {
-    return r.generation_field;
+    return r.field_signature;
   }
 
   static bool Read(autofill::mojom::PasswordFormGenerationDataDataView data,
diff --git a/components/autofill/content/public/cpp/autofill_types_struct_traits_unittest.cc b/components/autofill/content/public/cpp/autofill_types_struct_traits_unittest.cc
index 82f8383..7013668 100644
--- a/components/autofill/content/public/cpp/autofill_types_struct_traits_unittest.cc
+++ b/components/autofill/content/public/cpp/autofill_types_struct_traits_unittest.cc
@@ -9,6 +9,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/signatures_util.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -197,9 +198,8 @@
 void CheckEqualPasswordFormGenerationData(
     const PasswordFormGenerationData& expected,
     const PasswordFormGenerationData& actual) {
-  EXPECT_EQ(expected.name, actual.name);
-  EXPECT_EQ(expected.action, actual.action);
-  EXPECT_EQ(expected.generation_field, actual.generation_field);
+  EXPECT_EQ(expected.form_signature, actual.form_signature);
+  EXPECT_EQ(expected.field_signature, actual.field_signature);
 }
 
 }  // namespace
@@ -403,7 +403,10 @@
 TEST_F(AutofillTypeTraitsTestImpl, PassPasswordFormGenerationData) {
   FormData form;
   test::CreateTestAddressFormData(&form);
-  PasswordFormGenerationData input{form.name, form.action, form.fields[0]};
+  FormSignature form_signature = CalculateFormSignature(form);
+  FieldSignature field_signature =
+      CalculateFieldSignatureForField(form.fields[0]);
+  PasswordFormGenerationData input{form_signature, field_signature};
 
   base::RunLoop loop;
   mojom::TypeTraitsTestPtr proxy = GetTypeTraitsTestProxy();
diff --git a/components/autofill/content/public/interfaces/autofill_types.mojom b/components/autofill/content/public/interfaces/autofill_types.mojom
index 2433d8e..91905f2 100644
--- a/components/autofill/content/public/interfaces/autofill_types.mojom
+++ b/components/autofill/content/public/interfaces/autofill_types.mojom
@@ -150,9 +150,8 @@
 
 // autofill::PasswordFormGenerationData
 struct PasswordFormGenerationData {
-  string name;
-  url.mojom.Url action;
-  FormFieldData generation_field;
+  uint64 form_signature;
+  uint32 field_signature;
 };
 
 // autofill::PasswordForm
diff --git a/components/autofill/content/renderer/password_generation_agent.cc b/components/autofill/content/renderer/password_generation_agent.cc
index 74a6113..bc36e3d 100644
--- a/components/autofill/content/renderer/password_generation_agent.cc
+++ b/components/autofill/content/renderer/password_generation_agent.cc
@@ -18,6 +18,7 @@
 #include "components/autofill/core/common/password_form.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/signatures_util.h"
 #include "content/public/renderer/render_frame.h"
 #include "content/public/renderer/render_view.h"
 #include "google_apis/gaia/gaia_urls.h"
@@ -55,39 +56,39 @@
   return std::find(urls.begin(), urls.end(), url) != urls.end();
 }
 
-// Finds a form in |forms| that has the same action and name as |form|.
+// Calculates the signature of |form| and searches it in |forms|.
 const PasswordFormGenerationData* FindFormGenerationData(
     const std::vector<PasswordFormGenerationData>& forms,
     const PasswordForm& form) {
+  FormSignature form_signature = CalculateFormSignature(form.form_data);
   for (const auto& form_it : forms) {
-    if (form_it.name == form.form_data.name && form_it.action == form.action)
+    if (form_it.form_signature == form_signature)
       return &form_it;
   }
   return nullptr;
 }
 
 // This function returns a vector of password fields into which Chrome should
-// fill the generated password. It assumes that |field_data| describes the field
-// where Chrome shows the password generation prompt. It returns no more
+// fill the generated password. It assumes that |field_signature| describes the
+// field where Chrome shows the password generation prompt. It returns no more
 // than 2 elements.
 std::vector<blink::WebInputElement> FindPasswordElementsForGeneration(
     const std::vector<blink::WebInputElement>& all_password_elements,
-    const base::string16& field_name) {
-  auto iter =
-      std::find_if(all_password_elements.begin(), all_password_elements.end(),
-                   [&field_name](const blink::WebInputElement& input) {
-                     // Make explicit conversion before comparing with string16.
-                     base::string16 input_name = input.nameForAutofill();
-                     return input_name == field_name;
-                   });
+    const FieldSignature field_signature) {
+  auto iter = std::find_if(
+      all_password_elements.begin(), all_password_elements.end(),
+      [&field_signature](const blink::WebInputElement& input) {
+        FieldSignature signature = CalculateFieldSignatureByNameAndType(
+            input.nameForAutofill(), input.formControlType().utf8());
+        return signature == field_signature;
+      });
   std::vector<blink::WebInputElement> passwords;
 
   // We copy not more than 2 fields because occasionally there are forms where
   // the security question answers are put in password fields and we don't want
   // to fill those.
-  for (; iter != all_password_elements.end() && passwords.size() < 2; ++iter) {
+  for (; iter != all_password_elements.end() && passwords.size() < 2; ++iter)
     passwords.push_back(*iter);
-  }
   return passwords;
 }
 
@@ -403,7 +404,7 @@
     std::vector<blink::WebInputElement> password_elements =
         generation_data ? FindPasswordElementsForGeneration(
                               possible_form_data.password_elements,
-                              generation_data->generation_field.name)
+                              generation_data->field_signature)
                         : possible_form_data.password_elements;
     if (password_elements.empty()) {
       // It might be if JavaScript changes field names.
@@ -565,7 +566,10 @@
   std::vector<blink::WebInputElement> password_elements;
   GetAccountCreationPasswordFields(control_elements, &password_elements);
   password_elements = FindPasswordElementsForGeneration(
-      password_elements, last_focused_password_element_.nameForAutofill());
+      password_elements,
+      CalculateFieldSignatureByNameAndType(
+          last_focused_password_element_.nameForAutofill(),
+          last_focused_password_element_.formControlType().utf8()));
   generation_form_data_.reset(new AccountCreationFormData(
       make_linked_ptr(password_form.release()), password_elements));
   is_manually_triggered_ = true;
diff --git a/components/autofill/core/browser/autofill_download_manager.cc b/components/autofill/core/browser/autofill_download_manager.cc
index 86c4886..021a850 100644
--- a/components/autofill/core/browser/autofill_download_manager.cc
+++ b/components/autofill/core/browser/autofill_download_manager.cc
@@ -215,7 +215,7 @@
   }
 
   FormRequestData request_data;
-  request_data.form_signatures.push_back(form.FormSignature());
+  request_data.form_signatures.push_back(form.FormSignatureAsStr());
   request_data.request_type = AutofillDownloadManager::REQUEST_UPLOAD;
   request_data.payload = payload;
 
diff --git a/components/autofill/core/browser/autofill_download_manager_unittest.cc b/components/autofill/core/browser/autofill_download_manager_unittest.cc
index 1a359d0..e9bfcb3 100644
--- a/components/autofill/core/browser/autofill_download_manager_unittest.cc
+++ b/components/autofill/core/browser/autofill_download_manager_unittest.cc
@@ -277,7 +277,7 @@
   EXPECT_EQ(AutofillDownloadManagerTest::REQUEST_UPLOAD_FAILED,
             responses_.front().type_of_response);
   EXPECT_EQ(net::HTTP_NOT_FOUND, responses_.front().error);
-  EXPECT_EQ(form_structures[1]->FormSignature(),
+  EXPECT_EQ(form_structures[1]->FormSignatureAsStr(),
             responses_.front().signature);
   // Expected response on non-query request is an empty string.
   EXPECT_EQ(std::string(), responses_.front().response);
@@ -426,7 +426,7 @@
   EXPECT_EQ(AutofillDownloadManagerTest::REQUEST_UPLOAD_FAILED,
             responses_.front().type_of_response);
   EXPECT_EQ(net::HTTP_NOT_FOUND, responses_.front().error);
-  EXPECT_EQ(form_structure->FormSignature(), responses_.front().signature);
+  EXPECT_EQ(form_structure->FormSignatureAsStr(), responses_.front().signature);
   // Expected response on non-query request is an empty string.
   EXPECT_EQ(std::string(), responses_.front().response);
   responses_.pop_front();
diff --git a/components/autofill/core/browser/autofill_field.cc b/components/autofill/core/browser/autofill_field.cc
index 403be36..bf57cae 100644
--- a/components/autofill/core/browser/autofill_field.cc
+++ b/components/autofill/core/browser/autofill_field.cc
@@ -11,7 +11,6 @@
 #include "base/i18n/string_search.h"
 #include "base/logging.h"
 #include "base/metrics/field_trial.h"
-#include "base/sha1.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
@@ -527,17 +526,6 @@
   return true;
 }
 
-std::string Hash32Bit(const std::string& str) {
-  std::string hash_bin = base::SHA1HashString(str);
-  DCHECK_EQ(base::kSHA1Length, hash_bin.length());
-
-  uint32_t hash32 = ((hash_bin[0] & 0xFF) << 24) |
-                    ((hash_bin[1] & 0xFF) << 16) | ((hash_bin[2] & 0xFF) << 8) |
-                    (hash_bin[3] & 0xFF);
-
-  return base::UintToString(hash32);
-}
-
 base::string16 RemoveWhitespace(const base::string16& value) {
   base::string16 stripped_value;
   base::RemoveChars(value, base::kWhitespaceUTF16, &stripped_value);
@@ -643,10 +631,12 @@
   return value.empty();
 }
 
-std::string AutofillField::FieldSignature() const {
-  std::string field_name = base::UTF16ToUTF8(name);
-  std::string field_string = field_name + "&" + form_control_type;
-  return Hash32Bit(field_string);
+FieldSignature AutofillField::GetFieldSignature() const {
+  return CalculateFieldSignatureByNameAndType(name, form_control_type);
+}
+
+std::string AutofillField::FieldSignatureAsStr() const {
+  return base::UintToString(GetFieldSignature());
 }
 
 bool AutofillField::IsFieldFillable() const {
diff --git a/components/autofill/core/browser/autofill_field.h b/components/autofill/core/browser/autofill_field.h
index 52137e1a..ed74fdf 100644
--- a/components/autofill/core/browser/autofill_field.h
+++ b/components/autofill/core/browser/autofill_field.h
@@ -14,6 +14,7 @@
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/proto/server.pb.h"
 #include "components/autofill/core/common/form_field_data.h"
+#include "components/autofill/core/common/signatures_util.h"
 
 namespace autofill {
 
@@ -67,7 +68,10 @@
 
   // The unique signature of this field, composed of the field name and the html
   // input type in a 32-bit hash.
-  std::string FieldSignature() const;
+  FieldSignature GetFieldSignature() const;
+
+  // Returns the field signature as string.
+  std::string FieldSignatureAsStr() const;
 
   // Returns true if the field type has been determined (without the text in the
   // field).
diff --git a/components/autofill/core/browser/autofill_field_unittest.cc b/components/autofill/core/browser/autofill_field_unittest.cc
index aa88edc..ef4c047 100644
--- a/components/autofill/core/browser/autofill_field_unittest.cc
+++ b/components/autofill/core/browser/autofill_field_unittest.cc
@@ -198,29 +198,29 @@
   EXPECT_FALSE(field.IsEmpty());
 }
 
-TEST_F(AutofillFieldTest, FieldSignature) {
+TEST_F(AutofillFieldTest, FieldSignatureAsStr) {
   AutofillField field;
   ASSERT_EQ(base::string16(), field.name);
   ASSERT_EQ(std::string(), field.form_control_type);
 
   // Signature is empty.
-  EXPECT_EQ("2085434232", field.FieldSignature());
+  EXPECT_EQ("2085434232", field.FieldSignatureAsStr());
 
   // Field name is set.
   field.name = ASCIIToUTF16("Name");
-  EXPECT_EQ("1606968241", field.FieldSignature());
+  EXPECT_EQ("1606968241", field.FieldSignatureAsStr());
 
   // Field form control type is set.
   field.form_control_type = "text";
-  EXPECT_EQ("502192749", field.FieldSignature());
+  EXPECT_EQ("502192749", field.FieldSignatureAsStr());
 
   // Heuristic type does not affect FieldSignature.
   field.set_heuristic_type(NAME_FIRST);
-  EXPECT_EQ("502192749", field.FieldSignature());
+  EXPECT_EQ("502192749", field.FieldSignatureAsStr());
 
   // Server type does not affect FieldSignature.
   field.set_server_type(NAME_LAST);
-  EXPECT_EQ("502192749", field.FieldSignature());
+  EXPECT_EQ("502192749", field.FieldSignatureAsStr());
 }
 
 TEST_F(AutofillFieldTest, IsFieldFillable) {
diff --git a/components/autofill/core/browser/autofill_manager.cc b/components/autofill/core/browser/autofill_manager.cc
index adca0fa..5fbc050 100644
--- a/components/autofill/core/browser/autofill_manager.cc
+++ b/components/autofill/core/browser/autofill_manager.cc
@@ -906,7 +906,7 @@
   std::vector<FormStructure*> queried_forms;
   for (const std::string& signature : base::Reversed(form_signatures)) {
     for (FormStructure* cur_form : base::Reversed(form_structures_)) {
-      if (cur_form->FormSignature() == signature) {
+      if (cur_form->FormSignatureAsStr() == signature) {
         queried_forms.push_back(cur_form);
         break;
       }
@@ -1272,7 +1272,7 @@
 
   // Check if the form is among the forms that were recently auto-filled.
   bool was_autofilled = false;
-  std::string form_signature = submitted_form.FormSignature();
+  std::string form_signature = submitted_form.FormSignatureAsStr();
   for (const std::string& cur_sig : autofilled_form_signatures_) {
     if (cur_sig == form_signature) {
       was_autofilled = true;
@@ -1539,7 +1539,7 @@
     }
   }
 
-  autofilled_form_signatures_.push_front(form_structure->FormSignature());
+  autofilled_form_signatures_.push_front(form_structure->FormSignatureAsStr());
   // Only remember the last few forms that we've seen, both to avoid false
   // positives and to avoid wasting memory.
   if (autofilled_form_signatures_.size() > kMaxRecentFormSignaturesToRemember)
diff --git a/components/autofill/core/browser/autofill_manager_unittest.cc b/components/autofill/core/browser/autofill_manager_unittest.cc
index 9333062..6d2c976 100644
--- a/components/autofill/core/browser/autofill_manager_unittest.cc
+++ b/components/autofill/core/browser/autofill_manager_unittest.cc
@@ -574,7 +574,7 @@
 
   void UploadFormData(const FormStructure& submitted_form,
                       bool observed_submission) override {
-    submitted_form_signature_ = submitted_form.FormSignature();
+    submitted_form_signature_ = submitted_form.FormSignatureAsStr();
   }
 
   const std::string GetSubmittedFormSignature() {
@@ -3249,8 +3249,8 @@
   ASSERT_TRUE(response.SerializeToString(&response_string));
 
   std::vector<std::string> signatures;
-  signatures.push_back(form_structure->FormSignature());
-  signatures.push_back(form_structure2->FormSignature());
+  signatures.push_back(form_structure->FormSignatureAsStr());
+  signatures.push_back(form_structure2->FormSignatureAsStr());
 
   base::HistogramTester histogram_tester;
   autofill_manager_->OnLoadedServerPredictions(response_string, signatures);
@@ -3299,7 +3299,7 @@
   ASSERT_TRUE(response.SerializeToString(&response_string));
 
   std::vector<std::string> signatures;
-  signatures.push_back(form_structure->FormSignature());
+  signatures.push_back(form_structure->FormSignatureAsStr());
 
   // Reset the manager (such as during a navigation).
   autofill_manager_->Reset();
@@ -3401,7 +3401,7 @@
   FormsSeen(forms);
 
   // Cache the expected form signature.
-  std::string signature = FormStructure(form).FormSignature();
+  std::string signature = FormStructure(form).FormSignatureAsStr();
 
   // Change the structure of the form prior to submission.
   // Websites would typically invoke JavaScript either on page load or on form
diff --git a/components/autofill/core/browser/autofill_metrics_unittest.cc b/components/autofill/core/browser/autofill_metrics_unittest.cc
index e5695a0..6ebf24c0 100644
--- a/components/autofill/core/browser/autofill_metrics_unittest.cc
+++ b/components/autofill/core/browser/autofill_metrics_unittest.cc
@@ -755,7 +755,7 @@
   ASSERT_TRUE(response.SerializeToString(&response_string));
 
   std::vector<std::string> signatures;
-  signatures.push_back(form_structure->FormSignature());
+  signatures.push_back(form_structure->FormSignatureAsStr());
 
   base::HistogramTester histogram_tester;
   autofill_manager_->OnLoadedServerPredictions(response_string, signatures);
diff --git a/components/autofill/core/browser/form_field.cc b/components/autofill/core/browser/form_field.cc
index a63634c..3d31c0b 100644
--- a/components/autofill/core/browser/form_field.cc
+++ b/components/autofill/core/browser/form_field.cc
@@ -24,6 +24,7 @@
 #include "components/autofill/core/browser/name_field.h"
 #include "components/autofill/core/browser/phone_field.h"
 #include "components/autofill/core/common/autofill_regexes.h"
+#include "components/autofill/core/common/autofill_util.h"
 
 namespace autofill {
 namespace {
diff --git a/components/autofill/core/browser/form_structure.cc b/components/autofill/core/browser/form_structure.cc
index 5d6815f..fb0c495 100644
--- a/components/autofill/core/browser/form_structure.cc
+++ b/components/autofill/core/browser/form_structure.cc
@@ -27,13 +27,14 @@
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/form_field.h"
 #include "components/autofill/core/common/autofill_constants.h"
+#include "components/autofill/core/common/autofill_util.h"
 #include "components/autofill/core/common/form_data.h"
 #include "components/autofill/core/common/form_data_predictions.h"
 #include "components/autofill/core/common/form_field_data.h"
 #include "components/autofill/core/common/form_field_data_predictions.h"
+#include "components/autofill/core/common/signatures_util.h"
 #include "components/rappor/rappor_service.h"
 #include "components/rappor/rappor_utils.h"
-#include "third_party/re2/src/re2/re2.h"
 
 namespace autofill {
 namespace {
@@ -42,9 +43,6 @@
 const char kBillingMode[] = "billing";
 const char kShippingMode[] = "shipping";
 
-// Strip away >= 5 consecutive digits.
-const char kIgnorePatternInFieldName[] = "\\d{5,}";
-
 // A form is considered to have a high prediction mismatch rate if the number of
 // mismatches exceeds this threshold.
 const int kNumberOfMismatchesThreshold = 3;
@@ -272,14 +270,6 @@
   return HTML_TYPE_UNRECOGNIZED;
 }
 
-std::string StripDigitsIfRequired(const base::string16& input) {
-  std::string return_string = base::UTF16ToUTF8(input);
-
-  re2::RE2::GlobalReplace(&return_string, re2::RE2(kIgnorePatternInFieldName),
-                          std::string());
-  return return_string;
-}
-
 std::ostream& operator<<(
     std::ostream& out,
     const autofill::AutofillQueryResponseContents& response) {
@@ -317,14 +307,8 @@
   // Copy the form fields.
   std::map<base::string16, size_t> unique_names;
   for (const FormFieldData& field : form.fields) {
-    if (!ShouldSkipField(field)) {
-      // Add all supported form fields (including with empty names) to the
-      // signature.  This is a requirement for Autofill servers.
-      form_signature_field_names_.append("&");
-      form_signature_field_names_.append(StripDigitsIfRequired(field.name));
-
+    if (!ShouldSkipField(field))
       ++active_field_count_;
-    }
 
     if (field.form_control_type == "password")
       has_password_field_ = true;
@@ -340,6 +324,7 @@
     fields_.push_back(new AutofillField(field, unique_name));
   }
 
+  form_signature_ = autofill::CalculateFormSignature(form);
   // Do further processing on the fields, as needed.
   ProcessExtractedFields();
 }
@@ -403,12 +388,12 @@
 
   upload->set_submission(observed_submission);
   upload->set_client_version(kClientVersion);
-  upload->set_form_signature(FormSignature64Bit());
+  upload->set_form_signature(form_signature());
   upload->set_autofill_used(form_was_autofilled);
   upload->set_data_present(EncodeFieldTypes(available_field_types));
 
   if (IsAutofillFieldMetadataEnabled()) {
-    upload->set_action_signature(Hash64Bit(target_url_.host()));
+    upload->set_action_signature(StrToHash64Bit(target_url_.host()));
     if (!form_name().empty())
       upload->set_form_name(base::UTF16ToUTF8(form_name()));
   }
@@ -441,7 +426,7 @@
   // one form as returned data would be the same for all the repeated forms.
   std::set<std::string> processed_forms;
   for (const auto* form : forms) {
-    std::string signature(form->FormSignature());
+    std::string signature(form->FormSignatureAsStr());
     if (processed_forms.find(signature) != processed_forms.end())
       continue;
     processed_forms.insert(signature);
@@ -545,13 +530,13 @@
     form.data.origin = form_structure->source_url_;
     form.data.action = form_structure->target_url_;
     form.data.is_form_tag = form_structure->is_form_tag_;
-    form.signature = form_structure->FormSignature();
+    form.signature = form_structure->FormSignatureAsStr();
 
     for (const AutofillField* field : form_structure->fields_) {
       form.data.fields.push_back(FormFieldData(*field));
 
       FormFieldDataPredictions annotated_field;
-      annotated_field.signature = field->FieldSignature();
+      annotated_field.signature = field->FieldSignatureAsStr();
       annotated_field.heuristic_type =
           AutofillType(field->heuristic_type()).ToString();
       annotated_field.server_type =
@@ -574,8 +559,8 @@
   return base::StartsWith(group_name, "Enabled", base::CompareCase::SENSITIVE);
 }
 
-std::string FormStructure::FormSignature() const {
-  return base::Uint64ToString(FormSignature64Bit());
+std::string FormStructure::FormSignatureAsStr() const {
+  return base::Uint64ToString(form_signature());
 }
 
 bool FormStructure::IsAutofillable() const {
@@ -642,12 +627,12 @@
   std::map<std::string, const AutofillField*> cached_fields;
   for (size_t i = 0; i < cached_form.field_count(); ++i) {
     const AutofillField* field = cached_form.field(i);
-    cached_fields[field->FieldSignature()] = field;
+    cached_fields[field->FieldSignatureAsStr()] = field;
   }
 
   for (AutofillField* field : *this) {
-    std::map<std::string, const AutofillField*>::const_iterator
-        cached_field = cached_fields.find(field->FieldSignature());
+    std::map<std::string, const AutofillField*>::const_iterator cached_field =
+        cached_fields.find(field->FieldSignatureAsStr());
     if (cached_field != cached_fields.end()) {
       if (field->form_control_type != "select-one" &&
           field->value == cached_field->second->value) {
@@ -678,7 +663,7 @@
   DCHECK_EQ(cached_form.form_name_, form_name_);
   DCHECK_EQ(cached_form.source_url_, source_url_);
   DCHECK_EQ(cached_form.target_url_, target_url_);
-  form_signature_field_names_ = cached_form.form_signature_field_names_;
+  form_signature_ = cached_form.form_signature_;
 }
 
 void FormStructure::LogQualityMetrics(const base::TimeTicks& load_time,
@@ -1128,19 +1113,14 @@
     AutofillQueryContents::Form* query_form) const {
   DCHECK(!IsMalformed());
 
-  query_form->set_signature(FormSignature64Bit());
+  query_form->set_signature(form_signature());
   for (const AutofillField* field : fields_) {
     if (ShouldSkipField(*field))
       continue;
 
     AutofillQueryContents::Form::Field* added_field = query_form->add_field();
-    unsigned sig = 0;
 
-    // The signature is a required field. If it can't be parsed, the proto would
-    // not serialize.
-    if (!base::StringToUint(field->FieldSignature(), &sig))
-      continue;
-    added_field->set_signature(sig);
+    added_field->set_signature(field->GetFieldSignature());
 
     if (IsAutofillFieldMetadataEnabled()) {
       added_field->set_type(field->form_control_type);
@@ -1176,12 +1156,7 @@
             field->form_classifier_outcome());
       }
 
-      unsigned sig = 0;
-      // The signature is a required field. If it can't be parsed, the proto
-      // would not serialize.
-      if (!base::StringToUint(field->FieldSignature(), &sig))
-        continue;
-      added_field->set_signature(sig);
+      added_field->set_signature(field->GetFieldSignature());
 
       if (IsAutofillFieldMetadataEnabled()) {
         added_field->set_type(field->form_control_type);
@@ -1202,40 +1177,6 @@
   }
 }
 
-uint64_t FormStructure::Hash64Bit(const std::string& str) {
-  std::string hash_bin = base::SHA1HashString(str);
-  DCHECK_EQ(base::kSHA1Length, hash_bin.length());
-
-  uint64_t hash64 = (((static_cast<uint64_t>(hash_bin[0])) & 0xFF) << 56) |
-                    (((static_cast<uint64_t>(hash_bin[1])) & 0xFF) << 48) |
-                    (((static_cast<uint64_t>(hash_bin[2])) & 0xFF) << 40) |
-                    (((static_cast<uint64_t>(hash_bin[3])) & 0xFF) << 32) |
-                    (((static_cast<uint64_t>(hash_bin[4])) & 0xFF) << 24) |
-                    (((static_cast<uint64_t>(hash_bin[5])) & 0xFF) << 16) |
-                    (((static_cast<uint64_t>(hash_bin[6])) & 0xFF) << 8) |
-                    ((static_cast<uint64_t>(hash_bin[7])) & 0xFF);
-
-  return hash64;
-}
-
-uint64_t FormStructure::FormSignature64Bit() const {
-  std::string scheme(target_url_.scheme());
-  std::string host(target_url_.host());
-
-  // If target host or scheme is empty, set scheme and host of source url.
-  // This is done to match the Toolbar's behavior.
-  if (scheme.empty() || host.empty()) {
-    scheme = source_url_.scheme();
-    host = source_url_.host();
-  }
-
-  std::string form_string = scheme + "://" + host + "&" +
-                            base::UTF16ToUTF8(form_name_) +
-                            form_signature_field_names_;
-
-  return Hash64Bit(form_string);
-}
-
 bool FormStructure::IsMalformed() const {
   if (!field_count())  // Nothing to add.
     return true;
diff --git a/components/autofill/core/browser/form_structure.h b/components/autofill/core/browser/form_structure.h
index 074c229..e359a8f 100644
--- a/components/autofill/core/browser/form_structure.h
+++ b/components/autofill/core/browser/form_structure.h
@@ -91,9 +91,8 @@
   // Returns whether sending autofill field metadata to the server is enabled.
   static bool IsAutofillFieldMetadataEnabled();
 
-  // The unique signature for this form, composed of the target url domain,
-  // the form name, and the form field names in a 64-bit hash.
-  std::string FormSignature() const;
+  // Return the form signature as string.
+  std::string FormSignatureAsStr() const;
 
   // Runs a quick heuristic to rule out forms that are obviously not
   // auto-fillable, like google/yahoo/msn search, etc.
@@ -221,6 +220,8 @@
 
   bool all_fields_are_passwords() const { return all_fields_are_passwords_; }
 
+  FormSignature form_signature() const { return form_signature_; }
+
   // Returns a FormData containing the data this form structure knows about.
   FormData ToFormData() const;
 
@@ -240,11 +241,6 @@
   // Encodes information about this form and its fields into |upload|.
   void EncodeFormForUpload(autofill::AutofillUploadContents* upload) const;
 
-  // 64-bit hash of the string - used in FormSignature and unit-tests.
-  static uint64_t Hash64Bit(const std::string& str);
-
-  uint64_t FormSignature64Bit() const;
-
   // Returns true if the form has no fields, or too many.
   bool IsMalformed() const;
 
@@ -290,11 +286,6 @@
   // included in queries to the Autofill server.
   size_t active_field_count_;
 
-  // The names of the form input elements, that are part of the form signature.
-  // The string starts with "&" and the names are also separated by the "&"
-  // character. E.g.: "&form_input1_name&form_input2_name&...&form_inputN_name"
-  std::string form_signature_field_names_;
-
   // Whether the server expects us to always upload, never upload, or default
   // to the stored upload rates.
   UploadRequired upload_required_;
@@ -324,6 +315,10 @@
   // True if all form fields are password fields.
   bool all_fields_are_passwords_;
 
+  // The unique signature for this form, composed of the target url domain,
+  // the form name, and the form field names in a 64-bit hash.
+  FormSignature form_signature_;
+
   DISALLOW_COPY_AND_ASSIGN(FormStructure);
 };
 
diff --git a/components/autofill/core/browser/form_structure_unittest.cc b/components/autofill/core/browser/form_structure_unittest.cc
index 8d7f647..bd5194624 100644
--- a/components/autofill/core/browser/form_structure_unittest.cc
+++ b/components/autofill/core/browser/form_structure_unittest.cc
@@ -17,6 +17,7 @@
 #include "components/autofill/core/common/autofill_switches.h"
 #include "components/autofill/core/common/form_data.h"
 #include "components/autofill/core/common/form_field_data.h"
+#include "components/autofill/core/common/signatures_util.h"
 #include "components/variations/entropy_provider.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
@@ -50,7 +51,7 @@
 class FormStructureTest : public testing::Test {
  public:
   static std::string Hash64Bit(const std::string& str) {
-    return base::Uint64ToString(FormStructure::Hash64Bit(str));
+    return base::Uint64ToString(StrToHash64Bit(str));
   }
 
   void SetUp() override {
@@ -3308,27 +3309,26 @@
 
   form_structure.reset(new FormStructure(form));
 
-  EXPECT_EQ(FormStructureTest::Hash64Bit(
-      std::string("://&&email&first")),
-      form_structure->FormSignature());
+  EXPECT_EQ(FormStructureTest::Hash64Bit(std::string("://&&email&first")),
+            form_structure->FormSignatureAsStr());
 
   form.origin = GURL(std::string("http://www.facebook.com"));
   form_structure.reset(new FormStructure(form));
   EXPECT_EQ(FormStructureTest::Hash64Bit(
-      std::string("http://www.facebook.com&&email&first")),
-      form_structure->FormSignature());
+                std::string("http://www.facebook.com&&email&first")),
+            form_structure->FormSignatureAsStr());
 
   form.action = GURL(std::string("https://login.facebook.com/path"));
   form_structure.reset(new FormStructure(form));
   EXPECT_EQ(FormStructureTest::Hash64Bit(
-      std::string("https://login.facebook.com&&email&first")),
-      form_structure->FormSignature());
+                std::string("https://login.facebook.com&&email&first")),
+            form_structure->FormSignatureAsStr());
 
   form.name = ASCIIToUTF16("login_form");
   form_structure.reset(new FormStructure(form));
-  EXPECT_EQ(FormStructureTest::Hash64Bit(
-      std::string("https://login.facebook.com&login_form&email&first")),
-      form_structure->FormSignature());
+  EXPECT_EQ(FormStructureTest::Hash64Bit(std::string(
+                "https://login.facebook.com&login_form&email&first")),
+            form_structure->FormSignatureAsStr());
 
   field.check_status = FormFieldData::NOT_CHECKABLE;
   field.label = ASCIIToUTF16("Random Field label");
@@ -3346,9 +3346,9 @@
   form.fields.push_back(field);
   form_structure.reset(new FormStructure(form));
   EXPECT_EQ(FormStructureTest::Hash64Bit(
-      std::string("https://login.facebook.com&login_form&email&first&"
-                  "random1234&random&1random&random")),
-      form_structure->FormSignature());
+                std::string("https://login.facebook.com&login_form&email&first&"
+                            "random1234&random&1random&random")),
+            form_structure->FormSignatureAsStr());
 }
 
 TEST_F(FormStructureTest, ToFormData) {
diff --git a/components/autofill/core/common/BUILD.gn b/components/autofill/core/common/BUILD.gn
index a462078..d01d18e 100644
--- a/components/autofill/core/common/BUILD.gn
+++ b/components/autofill/core/common/BUILD.gn
@@ -36,11 +36,14 @@
     "password_generation_util.h",
     "save_password_progress_logger.cc",
     "save_password_progress_logger.h",
+    "signatures_util.cc",
+    "signatures_util.h",
   ]
 
   deps = [
     "//base",
     "//base:i18n",
+    "//third_party/re2",
     "//url",
   ]
 
diff --git a/components/autofill/core/common/DEPS b/components/autofill/core/common/DEPS
new file mode 100644
index 0000000..0de07bb
--- /dev/null
+++ b/components/autofill/core/common/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+third_party/re2",
+]
diff --git a/components/autofill/core/common/autofill_util.cc b/components/autofill/core/common/autofill_util.cc
index 28fc6c5..faf019e 100644
--- a/components/autofill/core/common/autofill_util.cc
+++ b/components/autofill/core/common/autofill_util.cc
@@ -105,4 +105,31 @@
 #endif
 }
 
+bool ShouldSkipField(const FormFieldData& field) {
+  return IsCheckable(field.check_status);
+}
+
+bool IsCheckable(const FormFieldData::CheckStatus& check_status) {
+  return check_status != FormFieldData::CheckStatus::NOT_CHECKABLE;
+}
+
+bool IsChecked(const FormFieldData::CheckStatus& check_status) {
+  return check_status == FormFieldData::CheckStatus::CHECKED;
+}
+
+void SetCheckStatus(FormFieldData* form_field_data,
+                    bool isCheckable,
+                    bool isChecked) {
+  if (isChecked) {
+    form_field_data->check_status = FormFieldData::CheckStatus::CHECKED;
+  } else {
+    if (isCheckable) {
+      form_field_data->check_status =
+          FormFieldData::CheckStatus::CHECKABLE_BUT_UNCHECKED;
+    } else {
+      form_field_data->check_status = FormFieldData::CheckStatus::NOT_CHECKABLE;
+    }
+  }
+}
+
 }  // namespace autofill
diff --git a/components/autofill/core/common/autofill_util.h b/components/autofill/core/common/autofill_util.h
index 34a2b022..519b3cbe 100644
--- a/components/autofill/core/common/autofill_util.h
+++ b/components/autofill/core/common/autofill_util.h
@@ -8,6 +8,7 @@
 #include <stddef.h>
 
 #include "base/strings/string16.h"
+#include "components/autofill/core/common/form_field_data.h"
 
 namespace autofill {
 
@@ -42,6 +43,14 @@
 // Android or iOS is considered desktop.
 bool IsDesktopPlatform();
 
+bool ShouldSkipField(const FormFieldData& field);
+
+bool IsCheckable(const FormFieldData::CheckStatus& check_status);
+bool IsChecked(const FormFieldData::CheckStatus& check_status);
+void SetCheckStatus(FormFieldData* form_field_data,
+                    bool isCheckable,
+                    bool isChecked);
+
 }  // namespace autofill
 
 #endif  // COMPONENTS_AUTOFILL_CORE_COMMON_AUTOFILL_UTIL_H_
diff --git a/components/autofill/core/common/form_field_data.cc b/components/autofill/core/common/form_field_data.cc
index 49447aba..6e19116 100644
--- a/components/autofill/core/common/form_field_data.cc
+++ b/components/autofill/core/common/form_field_data.cc
@@ -7,6 +7,7 @@
 #include "base/pickle.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "components/autofill/core/common/autofill_util.h"
 
 namespace autofill {
 
@@ -350,27 +351,4 @@
             << field.properties_mask;
 }
 
-bool IsCheckable(const FormFieldData::CheckStatus& check_status) {
-  return check_status != FormFieldData::CheckStatus::NOT_CHECKABLE;
-}
-
-bool IsChecked(const FormFieldData::CheckStatus& check_status) {
-  return check_status == FormFieldData::CheckStatus::CHECKED;
-}
-
-void SetCheckStatus(FormFieldData* form_field_data,
-                    bool isCheckable,
-                    bool isChecked) {
-  if (isChecked) {
-    form_field_data->check_status = FormFieldData::CheckStatus::CHECKED;
-  } else {
-    if (isCheckable) {
-      form_field_data->check_status =
-          FormFieldData::CheckStatus::CHECKABLE_BUT_UNCHECKED;
-    } else {
-      form_field_data->check_status = FormFieldData::CheckStatus::NOT_CHECKABLE;
-    }
-  }
-}
-
 }  // namespace autofill
diff --git a/components/autofill/core/common/form_field_data.h b/components/autofill/core/common/form_field_data.h
index 451249c..dbcb3ea 100644
--- a/components/autofill/core/common/form_field_data.h
+++ b/components/autofill/core/common/form_field_data.h
@@ -103,12 +103,6 @@
 // So we can compare FormFieldDatas with EXPECT_EQ().
 std::ostream& operator<<(std::ostream& os, const FormFieldData& field);
 
-bool IsCheckable(const FormFieldData::CheckStatus& check_status);
-bool IsChecked(const FormFieldData::CheckStatus& check_status);
-void SetCheckStatus(FormFieldData* form_field_data,
-                    bool isCheckable,
-                    bool isChecked);
-
 // Prefer to use this macro in place of |EXPECT_EQ()| for comparing
 // |FormFieldData|s in test code.
 #define EXPECT_FORM_FIELD_DATA_EQUALS(expected, actual)                        \
diff --git a/components/autofill/core/common/form_field_data_unittest.cc b/components/autofill/core/common/form_field_data_unittest.cc
index 79ae717..cae49ec 100644
--- a/components/autofill/core/common/form_field_data_unittest.cc
+++ b/components/autofill/core/common/form_field_data_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/i18n/rtl.h"
 #include "base/pickle.h"
 #include "base/strings/utf_string_conversions.h"
+#include "components/autofill/core/common/autofill_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace autofill {
diff --git a/components/autofill/core/common/password_form_generation_data.h b/components/autofill/core/common/password_form_generation_data.h
index 38910c9..d010d9a 100644
--- a/components/autofill/core/common/password_form_generation_data.h
+++ b/components/autofill/core/common/password_form_generation_data.h
@@ -5,8 +5,11 @@
 #ifndef COMPONENTS_AUTOFILL_CORE_COMMON_PASSWORD_FORM_GENERATION_DATA_H_
 #define COMPONENTS_AUTOFILL_CORE_COMMON_PASSWORD_FORM_GENERATION_DATA_H_
 
+#include <stdint.h>
+
 #include "base/strings/string16.h"
 #include "components/autofill/core/common/form_field_data.h"
+#include "components/autofill/core/common/signatures_util.h"
 #include "url/gurl.h"
 
 namespace autofill {
@@ -14,15 +17,13 @@
 // Structure used for sending information from browser to renderer about on
 // which fields password should be generated.
 struct PasswordFormGenerationData {
-  // The name of the form.
-  base::string16 name;
+  // The unique signature of form where password should be generated
+  // (see components/autofill/core/browser/form_structure.h).
+  FormSignature form_signature;
 
-  // The action target of the form; this URL consists of the scheme, host, port
-  // and path; the rest is stripped.
-  GURL action;
-
-  // Field in which password should be generated.
-  FormFieldData generation_field;
+  // The unique signature of field where password should be generated
+  // (see components/autofill/core/browser/autofill_field.h).
+  FieldSignature field_signature;
 };
 
 }  // namespace autofill
diff --git a/components/autofill/core/common/signatures_util.cc b/components/autofill/core/common/signatures_util.cc
new file mode 100644
index 0000000..8e7695e
--- /dev/null
+++ b/components/autofill/core/common/signatures_util.cc
@@ -0,0 +1,107 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/core/common/signatures_util.h"
+
+#include "base/sha1.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/utf_string_conversions.h"
+#include "components/autofill/core/common/autofill_util.h"
+#include "components/autofill/core/common/form_data.h"
+#include "components/autofill/core/common/form_field_data.h"
+#include "third_party/re2/src/re2/re2.h"
+#include "third_party/re2/src/re2/stringpiece.h"
+#include "url/gurl.h"
+
+namespace autofill {
+
+namespace {
+
+// Strip away >= 5 consecutive digits.
+const char kIgnorePatternInFieldName[] = "\\d{5,}";
+
+// Returns a copy of |input| without all occurrences of
+// |kIgnorePatternInFieldName|
+std::string StripDigitsIfRequired(const base::string16& input) {
+  std::string return_string = base::UTF16ToUTF8(input);
+  re2::RE2::GlobalReplace(&return_string, re2::RE2(kIgnorePatternInFieldName),
+                          re2::StringPiece());
+  return return_string;
+}
+
+}  // namespace
+
+FormSignature CalculateFormSignature(const FormData& form_data) {
+  const GURL& target_url = form_data.action;
+  const GURL& source_url = form_data.origin;
+  std::string scheme(target_url.scheme());
+  std::string host(target_url.host());
+
+  // If target host or scheme is empty, set scheme and host of source url.
+  // This is done to match the Toolbar's behavior.
+  if (scheme.empty() || host.empty()) {
+    scheme = source_url.scheme();
+    host = source_url.host();
+  }
+
+  std::string form_signature_field_names;
+
+  for (const FormFieldData& field : form_data.fields) {
+    if (!ShouldSkipField(field)) {
+      // Add all supported form fields (including with empty names) to the
+      // signature.  This is a requirement for Autofill servers.
+      form_signature_field_names.append("&");
+      form_signature_field_names.append(StripDigitsIfRequired(field.name));
+    }
+  }
+
+  std::string form_string = scheme + "://" + host + "&" +
+                            base::UTF16ToUTF8(form_data.name) +
+                            form_signature_field_names;
+
+  return StrToHash64Bit(form_string);
+}
+
+FieldSignature CalculateFieldSignatureByNameAndType(
+    const base::string16& field_name,
+    const std::string& field_type) {
+  std::string name = base::UTF16ToUTF8(field_name);
+  std::string field_string = name + "&" + field_type;
+  return StrToHash32Bit(field_string);
+}
+
+FieldSignature CalculateFieldSignatureForField(
+    const FormFieldData& field_data) {
+  return CalculateFieldSignatureByNameAndType(field_data.name,
+                                              field_data.form_control_type);
+}
+
+uint64_t StrToHash64Bit(const std::string& str) {
+  std::string hash_bin = base::SHA1HashString(str);
+  DCHECK_EQ(base::kSHA1Length, hash_bin.length());
+
+  uint64_t hash64 = (((static_cast<uint64_t>(hash_bin[0])) & 0xFF) << 56) |
+                    (((static_cast<uint64_t>(hash_bin[1])) & 0xFF) << 48) |
+                    (((static_cast<uint64_t>(hash_bin[2])) & 0xFF) << 40) |
+                    (((static_cast<uint64_t>(hash_bin[3])) & 0xFF) << 32) |
+                    (((static_cast<uint64_t>(hash_bin[4])) & 0xFF) << 24) |
+                    (((static_cast<uint64_t>(hash_bin[5])) & 0xFF) << 16) |
+                    (((static_cast<uint64_t>(hash_bin[6])) & 0xFF) << 8) |
+                    ((static_cast<uint64_t>(hash_bin[7])) & 0xFF);
+
+  return hash64;
+}
+
+uint32_t StrToHash32Bit(const std::string& str) {
+  std::string hash_bin = base::SHA1HashString(str);
+  DCHECK_EQ(base::kSHA1Length, hash_bin.length());
+
+  uint32_t hash32 = ((hash_bin[0] & 0xFF) << 24) |
+                    ((hash_bin[1] & 0xFF) << 16) | ((hash_bin[2] & 0xFF) << 8) |
+                    (hash_bin[3] & 0xFF);
+
+  return hash32;
+}
+
+}  // namespace autofill
diff --git a/components/autofill/core/common/signatures_util.h b/components/autofill/core/common/signatures_util.h
new file mode 100644
index 0000000..15be6ae
--- /dev/null
+++ b/components/autofill/core/common/signatures_util.h
@@ -0,0 +1,43 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CORE_COMMON_SIGNATURES_UTIL_H_
+#define COMPONENTS_AUTOFILL_CORE_COMMON_SIGNATURES_UTIL_H_
+
+#include <stddef.h>
+
+#include <stdint.h>
+#include <string>
+
+#include "base/strings/string16.h"
+
+namespace autofill {
+
+struct FormData;
+struct FormFieldData;
+
+using FormSignature = uint64_t;
+using FieldSignature = uint32_t;
+
+// Calculates form signature based on |form_data|.
+FormSignature CalculateFormSignature(const FormData& form_data);
+
+// Calculates field signature based on |field_name| and |field_type|.
+FieldSignature CalculateFieldSignatureByNameAndType(
+    const base::string16& field_name,
+    const std::string& field_type);
+
+// Calculates field signature based on |field_data|. This function is a proxy to
+// |CalculateFieldSignatureByNameAndType|.
+FieldSignature CalculateFieldSignatureForField(const FormFieldData& field_data);
+
+// Returns 64-bit hash of the string.
+uint64_t StrToHash64Bit(const std::string& str);
+
+// Returns 32-bit hash of the string.
+uint32_t StrToHash32Bit(const std::string& str);
+
+}
+
+#endif  // COMPONENTS_AUTOFILL_CORE_COMMON_SIGNATURES_UTIL_H_
diff --git a/components/password_manager/core/browser/browser_save_password_progress_logger.cc b/components/password_manager/core/browser/browser_save_password_progress_logger.cc
index a7d01dc..c15455e 100644
--- a/components/password_manager/core/browser/browser_save_password_progress_logger.cc
+++ b/components/password_manager/core/browser/browser_save_password_progress_logger.cc
@@ -37,7 +37,7 @@
   autofill::FormStructure form_structure(form.form_data);
   std::string message = GetStringFromID(label) + ": {\n";
   message += GetStringFromID(STRING_FORM_SIGNATURE) + ": " +
-             ScrubNonDigit(form_structure.FormSignature()) + "\n";
+             ScrubNonDigit(form_structure.FormSignatureAsStr()) + "\n";
   message += GetStringFromID(STRING_SIGNON_REALM) + ": " +
              ScrubURL(GURL(form.signon_realm)) + "\n";
   message +=
@@ -50,8 +50,8 @@
 
   for (const autofill::AutofillField* field : form_structure) {
     std::string field_info = ScrubElementID(field->name) + ": " +
-                             ScrubNonDigit(field->FieldSignature()) + ", " +
-                             ScrubElementID(field->form_control_type);
+                             ScrubNonDigit(field->FieldSignatureAsStr()) +
+                             ", " + ScrubElementID(field->form_control_type);
     if (!field->autocomplete_attribute.empty())
       field_info += ", " + ScrubElementID(field->autocomplete_attribute);
     message += field_info + "\n";
diff --git a/components/password_manager/core/browser/password_form_manager.cc b/components/password_manager/core/browser/password_form_manager.cc
index a87ad07..59d9c0a 100644
--- a/components/password_manager/core/browser/password_form_manager.cc
+++ b/components/password_manager/core/browser/password_form_manager.cc
@@ -368,7 +368,7 @@
   if (observed_form_.IsPossibleChangePasswordForm()) {
     FormStructure form_structure(credentials_to_update.form_data);
     UploadChangePasswordForm(autofill::NEW_PASSWORD,
-                             form_structure.FormSignature());
+                             form_structure.FormSignatureAsStr());
   }
   base::string16 password_to_save = pending_credentials_.password_value;
   bool skip_zero_click = pending_credentials_.skip_zero_click;
@@ -715,7 +715,8 @@
   // to PasswordForm. Even without this check, these FormStructure's won't
   // be uploaded, but it makes it hard to see if we are encountering
   // unexpected errors.
-  if (pending_structure.FormSignature() != observed_structure.FormSignature()) {
+  if (pending_structure.FormSignatureAsStr() !=
+      observed_structure.FormSignatureAsStr()) {
     // Only upload if this is the first time the password has been used.
     // Otherwise the credentials have been used on the same field before so
     // they aren't from an account creation form.
@@ -725,7 +726,7 @@
     if (pending->times_used == 1 && selected_username_.empty()) {
       if (UploadPasswordForm(pending->form_data, pending->username_element,
                              autofill::ACCOUNT_CREATION_PASSWORD,
-                             observed_structure.FormSignature())) {
+                             observed_structure.FormSignatureAsStr())) {
         pending->generation_upload_status =
             autofill::PasswordForm::POSITIVE_SIGNAL_SENT;
       }
diff --git a/components/password_manager/core/browser/password_form_manager_unittest.cc b/components/password_manager/core/browser/password_form_manager_unittest.cc
index e32d976..df0a437 100644
--- a/components/password_manager/core/browser/password_form_manager_unittest.cc
+++ b/components/password_manager/core/browser/password_form_manager_unittest.cc
@@ -119,7 +119,7 @@
            form_signature,
            expected_types,
            "Unexpected autofill types or form signature") {
-  if (form_signature != arg.FormSignature()) {
+  if (form_signature != arg.FormSignatureAsStr()) {
     // An unexpected form is uploaded.
     return false;
   }
@@ -156,10 +156,10 @@
            form_signature,
            expected_generation_types,
            "Unexpected generation types or form signature") {
-  if (form_signature != arg.FormSignature()) {
+  if (form_signature != arg.FormSignatureAsStr()) {
     // Unexpected form's signature.
     ADD_FAILURE() << "Expected form signature is " << form_signature
-                  << ", but found " << arg.FormSignature();
+                  << ", but found " << arg.FormSignatureAsStr();
     return false;
   }
   for (const autofill::AutofillField* field : arg) {
@@ -499,10 +499,10 @@
     std::string expected_login_signature;
     autofill::FormStructure observed_structure(observed_form_data);
     autofill::FormStructure pending_structure(saved_match()->form_data);
-    if (observed_structure.FormSignature() !=
-            pending_structure.FormSignature() &&
+    if (observed_structure.FormSignatureAsStr() !=
+            pending_structure.FormSignatureAsStr() &&
         times_used == 0) {
-      expected_login_signature = observed_structure.FormSignature();
+      expected_login_signature = observed_structure.FormSignatureAsStr();
     }
     autofill::ServerFieldTypeSet expected_available_field_types;
     expected_available_field_types.insert(autofill::USERNAME);
@@ -522,11 +522,11 @@
 
     if (field_type) {
       EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
-                  StartUploadRequest(
-                      CheckUploadedAutofillTypesAndSignature(
-                          pending_structure.FormSignature(), expected_types),
-                      false, expected_available_field_types,
-                      expected_login_signature, true));
+                  StartUploadRequest(CheckUploadedAutofillTypesAndSignature(
+                                         pending_structure.FormSignatureAsStr(),
+                                         expected_types),
+                                     false, expected_available_field_types,
+                                     expected_login_signature, true));
     } else {
       EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
                   StartUploadRequest(_, _, _, _, _))
@@ -592,12 +592,13 @@
     expected_available_field_types.insert(field_type);
 
     std::string observed_form_signature =
-        autofill::FormStructure(observed_form()->form_data).FormSignature();
+        autofill::FormStructure(observed_form()->form_data)
+            .FormSignatureAsStr();
 
     std::string expected_login_signature;
     if (field_type == autofill::NEW_PASSWORD) {
       autofill::FormStructure pending_structure(saved_match()->form_data);
-      expected_login_signature = pending_structure.FormSignature();
+      expected_login_signature = pending_structure.FormSignatureAsStr();
     }
     EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
                 StartUploadRequest(CheckUploadedAutofillTypesAndSignature(
@@ -715,7 +716,7 @@
         *client()->mock_driver()->mock_autofill_download_manager(),
         StartUploadRequest(
             CheckUploadedGenerationTypesAndSignature(
-                form_structure.FormSignature(), expected_generation_types),
+                form_structure.FormSignatureAsStr(), expected_generation_types),
             false, expected_available_field_types, std::string(), true));
 
     form_manager.ProvisionallySave(
@@ -2766,10 +2767,10 @@
   expected_available_field_types.insert(autofill::NEW_PASSWORD);
 
   std::string observed_form_signature =
-      autofill::FormStructure(observed_form()->form_data).FormSignature();
+      autofill::FormStructure(observed_form()->form_data).FormSignatureAsStr();
 
   std::string expected_login_signature =
-      autofill::FormStructure(saved_match()->form_data).FormSignature();
+      autofill::FormStructure(saved_match()->form_data).FormSignatureAsStr();
 
   EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
               StartUploadRequest(CheckUploadedAutofillTypesAndSignature(
@@ -2988,7 +2989,7 @@
   EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
               StartUploadRequest(
                   CheckUploadedAutofillTypesAndSignature(
-                      pending_structure.FormSignature(), expected_types),
+                      pending_structure.FormSignatureAsStr(), expected_types),
                   false, expected_available_field_types, std::string(), true));
 
   form_manager.ProvisionallySave(
diff --git a/components/password_manager/core/browser/password_generation_manager.cc b/components/password_manager/core/browser/password_generation_manager.cc
index 607a7adc..d334255 100644
--- a/components/password_manager/core/browser/password_generation_manager.cc
+++ b/components/password_manager/core/browser/password_generation_manager.cc
@@ -14,24 +14,6 @@
 
 namespace password_manager {
 
-namespace {
-
-// Helper function that returns canonical action based on |target_url| and
-// |source_url|.
-GURL GetCanonicalAction(const GURL& source_url, const GURL& target_url) {
-  GURL action = target_url;
-  if (action.is_empty())
-    action = source_url;
-  GURL::Replacements rep;
-  rep.ClearUsername();
-  rep.ClearPassword();
-  rep.ClearQuery();
-  rep.ClearRef();
-  return action.ReplaceComponents(rep);
-}
-
-}  // namespace
-
 PasswordGenerationManager::PasswordGenerationManager(
     PasswordManagerClient* client,
     PasswordManagerDriver* driver)
@@ -59,10 +41,8 @@
       if (field->server_type() == autofill::ACCOUNT_CREATION_PASSWORD ||
           field->server_type() == autofill::NEW_PASSWORD) {
         forms_eligible_for_generation.push_back(
-            autofill::PasswordFormGenerationData{
-                form->form_name(),
-                GetCanonicalAction(form->source_url(), form->target_url()),
-                *field});
+            autofill::PasswordFormGenerationData{form->form_signature(),
+                                                 field->GetFieldSignature()});
         break;
       }
     }
diff --git a/components/password_manager/core/browser/password_generation_manager_unittest.cc b/components/password_manager/core/browser/password_generation_manager_unittest.cc
index 5a3aedc..ef4725d2 100644
--- a/components/password_manager/core/browser/password_generation_manager_unittest.cc
+++ b/components/password_manager/core/browser/password_generation_manager_unittest.cc
@@ -17,6 +17,7 @@
 #include "components/autofill/core/common/form_data.h"
 #include "components/autofill/core/common/form_field_data.h"
 #include "components/autofill/core/common/password_form_generation_data.h"
+#include "components/autofill/core/common/signatures_util.h"
 #include "components/password_manager/core/browser/password_autofill_manager.h"
 #include "components/password_manager/core/browser/password_manager.h"
 #include "components/password_manager/core/browser/stub_password_manager_client.h"
@@ -31,6 +32,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
+using autofill::FormStructure;
 using base::ASCIIToUTF16;
 using testing::_;
 
@@ -189,6 +191,7 @@
   autofill::FormStructure form1(login_form);
   std::vector<autofill::FormStructure*> forms;
   forms.push_back(&form1);
+
   autofill::FormData account_creation_form;
   account_creation_form.origin = GURL("http://accounts.yahoo.com/");
   account_creation_form.action = GURL("http://accounts.yahoo.com/signup");
@@ -200,8 +203,13 @@
   confirm_password.name = ASCIIToUTF16("password");
   confirm_password.form_control_type = "password";
   account_creation_form.fields.push_back(confirm_password);
+  autofill::FormSignature account_creation_form_signature =
+      autofill::CalculateFormSignature(account_creation_form);
+  autofill::FieldSignature account_creation_field_signature =
+      autofill::CalculateFieldSignatureForField(password);
   autofill::FormStructure form2(account_creation_form);
   forms.push_back(&form2);
+
   autofill::FormData change_password_form;
   change_password_form.origin = GURL("http://accounts.yahoo.com/");
   change_password_form.action = GURL("http://accounts.yahoo.com/change");
@@ -210,6 +218,10 @@
   change_password_form.fields[0].name = ASCIIToUTF16("new_password");
   change_password_form.fields.push_back(confirm_password);
   autofill::FormStructure form3(change_password_form);
+  autofill::FormSignature change_password_form_signature =
+      autofill::CalculateFormSignature(change_password_form);
+  autofill::FieldSignature change_password_field_signature =
+      autofill::CalculateFieldSignatureForField(change_password_form.fields[0]);
   forms.push_back(&form3);
 
   // Simulate the server response to set the field types.
@@ -233,21 +245,19 @@
 
   DetectFormsEligibleForGeneration(forms);
   EXPECT_EQ(2u, GetTestDriver()->GetFoundEligibleForGenerationForms().size());
-  EXPECT_EQ(GURL("http://accounts.yahoo.com/signup"),
-            GetTestDriver()->GetFoundEligibleForGenerationForms()[0].action);
-  EXPECT_EQ(account_creation_form.name,
-            GetTestDriver()->GetFoundEligibleForGenerationForms()[0].name);
-  EXPECT_EQ(password.name, GetTestDriver()
-                               ->GetFoundEligibleForGenerationForms()[0]
-                               .generation_field.name);
-  EXPECT_EQ(GURL("http://accounts.yahoo.com/change"),
-            GetTestDriver()->GetFoundEligibleForGenerationForms()[1].action);
-  EXPECT_EQ(ASCIIToUTF16("new_password"),
-            GetTestDriver()
-                ->GetFoundEligibleForGenerationForms()[1]
-                .generation_field.name);
-  EXPECT_EQ(change_password_form.name,
-            GetTestDriver()->GetFoundEligibleForGenerationForms()[1].name);
+  EXPECT_EQ(
+      account_creation_form_signature,
+      GetTestDriver()->GetFoundEligibleForGenerationForms()[0].form_signature);
+  EXPECT_EQ(
+      account_creation_field_signature,
+      GetTestDriver()->GetFoundEligibleForGenerationForms()[0].field_signature);
+
+  EXPECT_EQ(
+      change_password_form_signature,
+      GetTestDriver()->GetFoundEligibleForGenerationForms()[1].form_signature);
+  EXPECT_EQ(
+      change_password_field_signature,
+      GetTestDriver()->GetFoundEligibleForGenerationForms()[1].field_signature);
 }
 
 TEST_F(PasswordGenerationManagerTest, UpdatePasswordSyncStateIncognito) {