Index: components/password_manager/core/browser/psl_matching_helper_unittest.cc |
diff --git a/components/password_manager/core/browser/psl_matching_helper_unittest.cc b/components/password_manager/core/browser/psl_matching_helper_unittest.cc |
index 66c798df366b9877620e8a973b5f2c3981952550..3f6a25b041d3a15a4c7081da5065e67c7ea88dcd 100644 |
--- a/components/password_manager/core/browser/psl_matching_helper_unittest.cc |
+++ b/components/password_manager/core/browser/psl_matching_helper_unittest.cc |
@@ -5,10 +5,15 @@ |
#include "components/password_manager/core/browser/psl_matching_helper.h" |
#include <stddef.h> |
+#include <cctype> |
#include "base/macros.h" |
+#include "base/stl_util.h" |
+#include "base/strings/string_util.h" |
+#include "base/strings/stringprintf.h" |
#include "components/autofill/core/common/password_form.h" |
#include "testing/gtest/include/gtest/gtest.h" |
+#include "url/gurl.h" |
namespace password_manager { |
@@ -387,6 +392,102 @@ TEST(PSLMatchingUtilsTest, IsFederatedPSLMatch) { |
} |
} |
+TEST(PSLMatchingUtilsTest, GetOrganizationIdentifyingName) { |
+ static constexpr const struct { |
+ const char* url; |
+ const char* expected_organization_name; |
+ } kTestCases[] = { |
+ {"http://example.com/login", "example"}, |
+ {"https://example.com", "example"}, |
+ {"ftp://example.com/ftp_realm", "example"}, |
+ |
+ {"http://foo.bar.example.com", "example"}, |
+ {"http://example.co.uk", "example"}, |
+ {"http://bar.example.appspot.com", "example"}, |
+ {"http://foo.bar", "foo"}, |
+ {"https://user:pass@www.example.com:80/path?query#ref", "example"}, |
+ |
+ {"http://www.foo+bar.com", "foo+bar"}, |
+ {"http://www.foo-bar.com", "foo-bar"}, |
+ {"https://foo_bar.com", "foo_bar"}, |
+ {"http://www.foo%2Bbar.com", "foo+bar"}, |
+ {"http://www.foo%2Dbar.com", "foo-bar"}, |
+ {"https://foo%5Fbar.com", "foo_bar"}, |
+ {"http://www.foo%2Ebar.com", "bar"}, |
+ |
+ // Internationalized Domain Names: each dot-separated label of the domain |
+ // name is individually Punycode-encoded, so the organization-identifying |
+ // name is still well-defined and can be determined as normal. |
+ // , , |
+ // szotar = sz\xc3\xb3t\xc3\xa1r (UTF-8) = xn--sztr-7na0i (IDN) |
+ // | | |
+ // U+00E1 U+00F3 |
+ {"https://www.sz\xc3\xb3t\xc3\xa1r.appspot.com", "xn--sztr-7na0i"}, |
+ |
+ {"http://www.foo!bar.com", "foo%21bar"}, |
+ {"http://www.foo%21bar.com", "foo%21bar"}, |
+ {"http://www.foo$bar.com", "foo%24bar"}, |
+ {"http://www.foo&bar.com", "foo%26bar"}, |
+ {"http://www.foo\'bar.com", "foo%27bar"}, |
+ {"http://www.foo(bar.com", "foo%28bar"}, |
+ {"http://www.foo)bar.com", "foo%29bar"}, |
+ {"http://www.foo*bar.com", "foo%2Abar"}, |
+ {"http://www.foo,bar.com", "foo%2Cbar"}, |
+ {"http://www.foo=bar.com", "foo%3Dbar"}, |
+ |
+ // URLs without host portions, hosts without registry controlled domains |
+ // should, or hosts consisting of a registry yield the empty string. |
+ {"http://localhost", ""}, |
+ {"http://co.uk", ""}, |
+ {"http://google", ""}, |
+ {"http://127.0.0.1", ""}, |
+ {"file:///usr/bin/stuff", ""}, |
+ {"federation://example.com/google.com", ""}, |
+ {"android://hash@com.example/", ""}, |
+ {"http://[1080:0:0:0:8:800:200C:417A]/", ""}, |
+ {"http://[3ffe:2a00:100:7031::1]", ""}, |
+ {"http://[::192.9.5.5]/", ""}, |
+ |
+ // Invalid URLs should yield the empty string. |
+ {"", ""}, |
+ {"http://", ""}, |
+ {"bad url", ""}, |
+ {"http://www.example.com/%00", ""}, |
+ {"http://www.foo;bar.com", ""}, |
+ {"http://www.foo~bar.com", ""}, |
+ }; |
+ |
+ for (const auto& test_case : kTestCases) { |
+ SCOPED_TRACE(test_case.url); |
+ GURL url(test_case.url); |
+ EXPECT_EQ(test_case.expected_organization_name, |
+ GetOrganizationIdentifyingName(url)); |
+ } |
+} |
+ |
+// Apart from alphanumeric characters and '.', only |kExpectedUnescapedChars| |
+// are expected to appear without percent-encoding in the domain of a valid, |
+// canonicalized URL. |
+// |
+// The purpose of this test is to ensure that the test cases around unescaped |
+// special characters in `GetOrganizationIdentifyingName` are exhaustive. |
+TEST(PSLMatchingUtilsTest, |
+ GetOrganizationIdentifyingName_UnescapedSpecialChars) { |
+ static constexpr const char kExpectedNonAlnumChars[] = {'+', '-', '_', '.'}; |
+ for (int chr = 0; chr <= 255; ++chr) { |
+ const auto percent_encoded = base::StringPrintf("http://a%%%02Xb.hu/", chr); |
+ const GURL url(percent_encoded); |
+ if (isalnum(chr) || base::ContainsValue(kExpectedNonAlnumChars, chr)) { |
+ ASSERT_TRUE(url.is_valid()); |
+ const auto percent_decoded = base::StringPrintf( |
+ "http://a%cb.hu/", base::ToLowerASCII(static_cast<char>(chr))); |
+ EXPECT_EQ(percent_decoded, url.spec()); |
+ } else if (url.is_valid()) { |
+ EXPECT_EQ(percent_encoded, url.spec()); |
+ } |
+ } |
+} |
+ |
} // namespace |
} // namespace password_manager |