Sort password details before exporting the passwords

This CL sorts the password details based on name, url, username,
passowrd and note before exporting it to a file

Bug: 1516467
Change-Id: Ifa3a137439bb72830986469340fc887174b96d04
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5198232
Commit-Queue: Viktor Semeniuk <vsemeniuk@google.com>
Reviewed-by: Viktor Semeniuk <vsemeniuk@google.com>
Reviewed-by: Vasilii Sukhanov <vasilii@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1251968}
diff --git a/components/password_manager/core/browser/export/password_csv_writer.cc b/components/password_manager/core/browser/export/password_csv_writer.cc
index 54520d23..487481b7 100644
--- a/components/password_manager/core/browser/export/password_csv_writer.cc
+++ b/components/password_manager/core/browser/export/password_csv_writer.cc
@@ -63,6 +63,16 @@
     }
   }
 
+  std::sort(records.begin(), records.end(), [&header](
+    const std::map<std::string, std::string>& lhs,
+    const std::map<std::string, std::string>& rhs) {
+      for (const std::string& headerVal : header) {
+        if (lhs.at(headerVal) < rhs.at(headerVal)) return true;
+        if (lhs.at(headerVal) > rhs.at(headerVal)) return false;
+      }
+      return false;
+  });
+
   std::string result;
   WriteCSV(header, records, &result);
   return result;
diff --git a/components/password_manager/core/browser/export/password_csv_writer_unittest.cc b/components/password_manager/core/browser/export/password_csv_writer_unittest.cc
index 365c6e76..656a98e8 100644
--- a/components/password_manager/core/browser/export/password_csv_writer_unittest.cc
+++ b/components/password_manager/core/browser/export/password_csv_writer_unittest.cc
@@ -148,17 +148,55 @@
   std::string expected =
       base::FeatureList::IsEnabled(syncer::kPasswordNotesWithBackup)
           ? "name,url,username,password,note" + kLineEnding +
-                "example.com,https://example.com/,a,b," + kLineEnding +
                 "Netflix,android://Jzj5T2E45Hb33D-lk-"
                 "EHZVCrb7a064dEicTwrTYQYGXO99JqE2YERhbMP1qLogwJiy87OsB"
                 "zC09Gk094Z-U_hg==@com.netflix.mediaclient,a,b," +
-                kLineEnding
+                kLineEnding +
+                "example.com,https://example.com/,a,b," + kLineEnding
           : "name,url,username,password" + kLineEnding +
-                "example.com,https://example.com/,a,b" + kLineEnding +
                 "Netflix,android://Jzj5T2E45Hb33D-lk-"
                 "EHZVCrb7a064dEicTwrTYQYGXO99JqE2YERhbMP1qLogwJiy87OsB"
                 "zC09Gk094Z-U_hg==@com.netflix.mediaclient,a,b" +
-                kLineEnding;
+                kLineEnding +
+                "example.com,https://example.com/,a,b" + kLineEnding;
+  EXPECT_EQ(expected, PasswordCSVWriter::SerializePasswords(credentials));
+}
+
+TEST_P(PasswordCSVWriterTest, SerializePasswordsIsSorted) {
+  std::vector<CredentialUIEntry> credentials;
+  PasswordForm form;
+  form.signon_realm = "https://example.com/";
+  form.url = GURL("https://example.com");
+  form.username_value = u"a";
+  form.password_value = u"b";
+  credentials.emplace_back(form);
+  form.signon_realm = "https://other.org/";
+  form.url = GURL("https://other.org");
+  form.username_value = u"a";
+  form.password_value = u"b";
+  credentials.emplace_back(form);
+  form.signon_realm = "https://example.com/";
+  form.url = GURL("https://example.com");
+  form.username_value = u"someone";
+  form.password_value = u"secret";
+  credentials.emplace_back(form);
+  form.signon_realm = "https://example.org/";
+  form.url = GURL("https://example.org");
+  form.username_value = u"a";
+  form.password_value = u"b";
+  credentials.emplace_back(form);
+  std::string expected =
+      base::FeatureList::IsEnabled(syncer::kPasswordNotesWithBackup)
+          ? "name,url,username,password,note" + kLineEnding +
+                "example.com,https://example.com/,a,b," + kLineEnding +
+                "example.com,https://example.com/,someone,secret," + kLineEnding +
+                "example.org,https://example.org/,a,b," + kLineEnding +
+                "other.org,https://other.org/,a,b," + kLineEnding
+          : "name,url,username,password" + kLineEnding +
+                "example.com,https://example.com/,a,b" + kLineEnding +
+                "example.com,https://example.com/,someone,secret" + kLineEnding +
+                "example.org,https://example.org/,a,b" + kLineEnding +
+                "other.org,https://other.org/,a,b" + kLineEnding;
   EXPECT_EQ(expected, PasswordCSVWriter::SerializePasswords(credentials));
 }