origin_abstract_tests.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527
  1. // Copyright 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef URL_ORIGIN_ABSTRACT_TESTS_H_
  5. #define URL_ORIGIN_ABSTRACT_TESTS_H_
  6. #include <string>
  7. #include <type_traits>
  8. #include "base/containers/contains.h"
  9. #include "base/strings/string_piece.h"
  10. #include "testing/gtest/include/gtest/gtest.h"
  11. #include "url/gurl.h"
  12. #include "url/origin.h"
  13. #include "url/scheme_host_port.h"
  14. #include "url/url_util.h"
  15. namespace url {
  16. void ExpectParsedUrlsEqual(const GURL& a, const GURL& b);
  17. // AbstractOriginTest below abstracts away differences between url::Origin and
  18. // blink::SecurityOrigin by parametrizing the tests with a class that has to
  19. // expose the same public members as UrlOriginTestTraits below.
  20. class UrlOriginTestTraits {
  21. public:
  22. using OriginType = Origin;
  23. // Constructing an origin.
  24. static OriginType CreateOriginFromString(base::StringPiece s);
  25. static OriginType CreateUniqueOpaqueOrigin();
  26. static OriginType CreateWithReferenceOrigin(
  27. base::StringPiece url,
  28. const OriginType& reference_origin);
  29. static OriginType DeriveNewOpaqueOrigin(const OriginType& reference_origin);
  30. // Accessors for origin properties.
  31. static bool IsOpaque(const OriginType& origin);
  32. static std::string GetScheme(const OriginType& origin);
  33. static std::string GetHost(const OriginType& origin);
  34. static uint16_t GetPort(const OriginType& origin);
  35. static SchemeHostPort GetTupleOrPrecursorTupleIfOpaque(
  36. const OriginType& origin);
  37. // Wrappers for other instance methods of OriginType.
  38. static bool IsSameOrigin(const OriginType& a, const OriginType& b);
  39. static std::string Serialize(const OriginType& origin);
  40. // "Accessors" of URL properties.
  41. //
  42. // TODO(lukasza): Consider merging together OriginTraitsBase here and
  43. // UrlTraitsBase in //url/gurl_abstract_tests.h.
  44. static bool IsValidUrl(base::StringPiece str);
  45. // Only static members = no constructors are needed.
  46. UrlOriginTestTraits() = delete;
  47. };
  48. // Test suite for tests that cover both url::Origin and blink::SecurityOrigin.
  49. template <typename TOriginTraits>
  50. class AbstractOriginTest : public testing::Test {
  51. public:
  52. void SetUp() override {
  53. const char* kSchemesToRegister[] = {
  54. "noaccess",
  55. "std-with-host",
  56. "noaccess-std-with-host",
  57. "local",
  58. "local-noaccess",
  59. "local-std-with-host",
  60. "local-noaccess-std-with-host",
  61. "also-local",
  62. "sec",
  63. "sec-std-with-host",
  64. "sec-noaccess",
  65. };
  66. for (const char* kScheme : kSchemesToRegister) {
  67. std::string scheme(kScheme);
  68. if (base::Contains(scheme, "noaccess"))
  69. AddNoAccessScheme(kScheme);
  70. if (base::Contains(scheme, "std-with-host"))
  71. AddStandardScheme(kScheme, SchemeType::SCHEME_WITH_HOST);
  72. if (base::Contains(scheme, "local"))
  73. AddLocalScheme(kScheme);
  74. if (base::Contains(scheme, "sec"))
  75. AddSecureScheme(kScheme);
  76. }
  77. }
  78. protected:
  79. // Wrappers that help ellide away TOriginTraits.
  80. //
  81. // Note that calling the wrappers needs to be prefixed with `this->...` to
  82. // avoid hitting: explicit qualification required to use member 'IsOpaque'
  83. // from dependent base class.
  84. using OriginType = typename TOriginTraits::OriginType;
  85. OriginType CreateOriginFromString(base::StringPiece s) {
  86. return TOriginTraits::CreateOriginFromString(s);
  87. }
  88. OriginType CreateUniqueOpaqueOrigin() {
  89. return TOriginTraits::CreateUniqueOpaqueOrigin();
  90. }
  91. OriginType CreateWithReferenceOrigin(base::StringPiece url,
  92. const OriginType& reference_origin) {
  93. return TOriginTraits::CreateWithReferenceOrigin(url, reference_origin);
  94. }
  95. OriginType DeriveNewOpaqueOrigin(const OriginType& reference_origin) {
  96. return TOriginTraits::DeriveNewOpaqueOrigin(reference_origin);
  97. }
  98. bool IsOpaque(const OriginType& origin) {
  99. return TOriginTraits::IsOpaque(origin);
  100. }
  101. std::string GetScheme(const OriginType& origin) {
  102. return TOriginTraits::GetScheme(origin);
  103. }
  104. std::string GetHost(const OriginType& origin) {
  105. return TOriginTraits::GetHost(origin);
  106. }
  107. uint16_t GetPort(const OriginType& origin) {
  108. return TOriginTraits::GetPort(origin);
  109. }
  110. SchemeHostPort GetTupleOrPrecursorTupleIfOpaque(const OriginType& origin) {
  111. return TOriginTraits::GetTupleOrPrecursorTupleIfOpaque(origin);
  112. }
  113. bool IsSameOrigin(const OriginType& a, const OriginType& b) {
  114. bool is_a_same_with_b = TOriginTraits::IsSameOrigin(a, b);
  115. bool is_b_same_with_a = TOriginTraits::IsSameOrigin(b, a);
  116. EXPECT_EQ(is_a_same_with_b, is_b_same_with_a);
  117. return is_a_same_with_b;
  118. }
  119. std::string Serialize(const OriginType& origin) {
  120. return TOriginTraits::Serialize(origin);
  121. }
  122. bool IsValidUrl(base::StringPiece str) {
  123. return TOriginTraits::IsValidUrl(str);
  124. }
  125. #define EXPECT_SAME_ORIGIN(a, b) \
  126. EXPECT_TRUE(this->IsSameOrigin((a), (b))) \
  127. << "When checking if \"" << this->Serialize(a) << "\" is " \
  128. << "same-origin with \"" << this->Serialize(b) << "\""
  129. #define EXPECT_CROSS_ORIGIN(a, b) \
  130. EXPECT_FALSE(this->IsSameOrigin((a), (b))) \
  131. << "When checking if \"" << this->Serialize(a) << "\" is " \
  132. << "cross-origin from \"" << this->Serialize(b) << "\""
  133. void VerifyOriginInvariants(const OriginType& origin) {
  134. // An origin is always same-origin with itself.
  135. EXPECT_SAME_ORIGIN(origin, origin);
  136. // A copy of |origin| should be same-origin as well.
  137. auto origin_copy = origin;
  138. EXPECT_EQ(this->GetScheme(origin), this->GetScheme(origin_copy));
  139. EXPECT_EQ(this->GetHost(origin), this->GetHost(origin_copy));
  140. EXPECT_EQ(this->GetPort(origin), this->GetPort(origin_copy));
  141. EXPECT_EQ(this->IsOpaque(origin), this->IsOpaque(origin_copy));
  142. EXPECT_SAME_ORIGIN(origin, origin_copy);
  143. // An origin is always cross-origin from another, unique, opaque origin.
  144. EXPECT_CROSS_ORIGIN(origin, this->CreateUniqueOpaqueOrigin());
  145. // An origin is always cross-origin from another tuple origin.
  146. auto different_tuple_origin =
  147. this->CreateOriginFromString("https://not-in-the-list.test/");
  148. EXPECT_CROSS_ORIGIN(origin, different_tuple_origin);
  149. // Deriving an origin for "about:blank".
  150. auto about_blank_origin1 =
  151. this->CreateWithReferenceOrigin("about:blank", origin);
  152. auto about_blank_origin2 =
  153. this->CreateWithReferenceOrigin("about:blank?bar#foo", origin);
  154. EXPECT_SAME_ORIGIN(origin, about_blank_origin1);
  155. EXPECT_SAME_ORIGIN(origin, about_blank_origin2);
  156. // Derived opaque origins.
  157. std::vector<OriginType> derived_origins = {
  158. this->DeriveNewOpaqueOrigin(origin),
  159. this->CreateWithReferenceOrigin("data:text/html,baz", origin),
  160. this->DeriveNewOpaqueOrigin(about_blank_origin1),
  161. };
  162. for (size_t i = 0; i < derived_origins.size(); i++) {
  163. SCOPED_TRACE(testing::Message() << "Derived origin #" << i);
  164. const OriginType& derived_origin = derived_origins[i];
  165. EXPECT_TRUE(this->IsOpaque(derived_origin));
  166. EXPECT_SAME_ORIGIN(derived_origin, derived_origin);
  167. EXPECT_CROSS_ORIGIN(origin, derived_origin);
  168. EXPECT_EQ(this->GetTupleOrPrecursorTupleIfOpaque(origin),
  169. this->GetTupleOrPrecursorTupleIfOpaque(derived_origin));
  170. }
  171. }
  172. void VerifyUniqueOpaqueOriginInvariants(const OriginType& origin) {
  173. if (!this->IsOpaque(origin)) {
  174. ADD_FAILURE() << "Got unexpectedly non-opaque origin: "
  175. << this->Serialize(origin);
  176. return; // Skip other test assertions.
  177. }
  178. // Opaque origins should have an "empty" scheme, host and port.
  179. EXPECT_EQ("", this->GetScheme(origin));
  180. EXPECT_EQ("", this->GetHost(origin));
  181. EXPECT_EQ(0, this->GetPort(origin));
  182. // Unique opaque origins should have an empty precursor tuple.
  183. EXPECT_EQ(SchemeHostPort(), this->GetTupleOrPrecursorTupleIfOpaque(origin));
  184. // Serialization test.
  185. EXPECT_EQ("null", this->Serialize(origin));
  186. // Invariants that should hold for any origin.
  187. VerifyOriginInvariants(origin);
  188. }
  189. void TestUniqueOpaqueOrigin(base::StringPiece test_input) {
  190. auto origin = this->CreateOriginFromString(test_input);
  191. this->VerifyUniqueOpaqueOriginInvariants(origin);
  192. // Re-creating from the URL should be cross-origin.
  193. auto origin_recreated_from_same_input =
  194. this->CreateOriginFromString(test_input);
  195. EXPECT_CROSS_ORIGIN(origin, origin_recreated_from_same_input);
  196. }
  197. void VerifyTupleOriginInvariants(const OriginType& origin,
  198. const SchemeHostPort& expected_tuple) {
  199. if (this->IsOpaque(origin)) {
  200. ADD_FAILURE() << "Got unexpectedly opaque origin";
  201. return; // Skip other test assertions.
  202. }
  203. SCOPED_TRACE(testing::Message()
  204. << "Actual origin: " << this->Serialize(origin));
  205. // Compare `origin` against the `expected_tuple`.
  206. EXPECT_EQ(expected_tuple.scheme(), this->GetScheme(origin));
  207. EXPECT_EQ(expected_tuple.host(), this->GetHost(origin));
  208. EXPECT_EQ(expected_tuple.port(), this->GetPort(origin));
  209. EXPECT_EQ(expected_tuple, this->GetTupleOrPrecursorTupleIfOpaque(origin));
  210. // Serialization test.
  211. //
  212. // TODO(lukasza): Consider preserving the hostname when serializing file:
  213. // URLs. Dropping the hostname seems incompatible with section 6 of
  214. // rfc6454. Even though section 4 says that "the implementation MAY
  215. // return an implementation-defined value", it seems that Chromium
  216. // implementation *does* include the hostname in the origin SchemeHostPort
  217. // tuple.
  218. if (expected_tuple.scheme() != kFileScheme || expected_tuple.host() == "") {
  219. EXPECT_SAME_ORIGIN(origin,
  220. this->CreateOriginFromString(this->Serialize(origin)));
  221. }
  222. // Invariants that should hold for any origin.
  223. VerifyOriginInvariants(origin);
  224. }
  225. private:
  226. ScopedSchemeRegistryForTests scoped_scheme_registry_;
  227. };
  228. TYPED_TEST_SUITE_P(AbstractOriginTest);
  229. TYPED_TEST_P(AbstractOriginTest, NonStandardSchemeWithAndroidWebViewHack) {
  230. EnableNonStandardSchemesForAndroidWebView();
  231. // Regression test for https://crbug.com/896059.
  232. auto origin = this->CreateOriginFromString("unknown-scheme://");
  233. EXPECT_FALSE(this->IsOpaque(origin));
  234. EXPECT_EQ("unknown-scheme", this->GetScheme(origin));
  235. EXPECT_EQ("", this->GetHost(origin));
  236. EXPECT_EQ(0, this->GetPort(origin));
  237. // about:blank translates into an opaque origin, even in presence of
  238. // EnableNonStandardSchemesForAndroidWebView.
  239. origin = this->CreateOriginFromString("about:blank");
  240. EXPECT_TRUE(this->IsOpaque(origin));
  241. }
  242. TYPED_TEST_P(AbstractOriginTest, OpaqueOriginsFromValidUrls) {
  243. const char* kTestCases[] = {
  244. // Built-in noaccess schemes.
  245. "data:text/html,Hello!",
  246. "javascript:alert(1)",
  247. "about:blank",
  248. // Opaque blob URLs.
  249. "blob:null/foo", // blob:null (actually a valid URL)
  250. "blob:data:foo", // blob + data (which is nonstandard)
  251. "blob:about://blank/", // blob + about (which is nonstandard)
  252. "blob:about:blank/", // blob + about (which is nonstandard)
  253. "blob:blob:http://www.example.com/guid-goes-here",
  254. "blob:filesystem:ws:b/.",
  255. "blob:filesystem:ftp://a/b",
  256. "blob:blob:file://localhost/foo/bar",
  257. };
  258. for (const char* test_input : kTestCases) {
  259. SCOPED_TRACE(testing::Message() << "Test input: " << test_input);
  260. // Verify that `origin` is opaque not just because `test_input` results is
  261. // an invalid URL (because of a typo in the scheme name, or because of a
  262. // technicality like having no host in a noaccess-std-with-host: scheme).
  263. EXPECT_TRUE(this->IsValidUrl(test_input));
  264. this->TestUniqueOpaqueOrigin(test_input);
  265. }
  266. }
  267. TYPED_TEST_P(AbstractOriginTest, OpaqueOriginsFromInvalidUrls) {
  268. // TODO(lukasza): Consider moving those to GURL/KURL tests that verify what
  269. // inputs are parsed as an invalid URL.
  270. const char* kTestCases[] = {
  271. // Invalid file: URLs.
  272. "file://example.com:443/etc/passwd", // No port expected.
  273. // Invalid HTTP URLs.
  274. "http",
  275. "http:",
  276. "http:/",
  277. "http://",
  278. "http://:",
  279. "http://:1",
  280. "http::///invalid.example.com/",
  281. "http://example.com:65536/", // Port out of range.
  282. "http://example.com:-1/", // Port out of range.
  283. "http://example.com:18446744073709551616/", // Port = 2^64.
  284. "http://example.com:18446744073709551616999/", // Lots of port digits.
  285. // Invalid filesystem URLs.
  286. "filesystem:http://example.com/", // Missing /type/.
  287. "filesystem:local:baz./type/",
  288. "filesystem:local://hostname/type/",
  289. "filesystem:unknown-scheme://hostname/type/",
  290. "filesystem:filesystem:http://example.org:88/foo/bar",
  291. // Invalid IP addresses
  292. "http://[]/",
  293. "http://[2001:0db8:0000:0000:0000:0000:0000:0000:0001]/", // 9 groups.
  294. // Unknown scheme without a colon character (":") gives an invalid URL.
  295. "unknown-scheme",
  296. // Standard schemes require a hostname (and result in an opaque origin if
  297. // the hostname is missing).
  298. "local-std-with-host:",
  299. "noaccess-std-with-host:",
  300. };
  301. for (const char* test_input : kTestCases) {
  302. SCOPED_TRACE(testing::Message() << "Test input: " << test_input);
  303. // All testcases here are expected to represent invalid URLs.
  304. // an invalid URL (because of a type in scheme name, or because of a
  305. // technicality like having no host in a noaccess-std-with-host: scheme).
  306. EXPECT_FALSE(this->IsValidUrl(test_input));
  307. // Invalid URLs should always result in an opaque origin.
  308. this->TestUniqueOpaqueOrigin(test_input);
  309. }
  310. }
  311. TYPED_TEST_P(AbstractOriginTest, TupleOrigins) {
  312. struct TestCase {
  313. const char* input;
  314. SchemeHostPort expected_tuple;
  315. } kTestCases[] = {
  316. // file: URLs
  317. {"file:///etc/passwd", {"file", "", 0}},
  318. {"file://example.com/etc/passwd", {"file", "example.com", 0}},
  319. {"file:///", {"file", "", 0}},
  320. {"file://hostname/C:/dir/file.txt", {"file", "hostname", 0}},
  321. // HTTP URLs
  322. {"http://example.com/", {"http", "example.com", 80}},
  323. {"http://example.com:80/", {"http", "example.com", 80}},
  324. {"http://example.com:123/", {"http", "example.com", 123}},
  325. {"http://example.com:0/", {"http", "example.com", 0}},
  326. {"http://example.com:65535/", {"http", "example.com", 65535}},
  327. {"https://example.com/", {"https", "example.com", 443}},
  328. {"https://example.com:443/", {"https", "example.com", 443}},
  329. {"https://example.com:123/", {"https", "example.com", 123}},
  330. {"https://example.com:0/", {"https", "example.com", 0}},
  331. {"https://example.com:65535/", {"https", "example.com", 65535}},
  332. {"http://user:pass@example.com/", {"http", "example.com", 80}},
  333. {"http://example.com:123/?query", {"http", "example.com", 123}},
  334. {"https://example.com/#1234", {"https", "example.com", 443}},
  335. {"https://u:p@example.com:123/?query#1234",
  336. {"https", "example.com", 123}},
  337. {"http://example/", {"http", "example", 80}},
  338. // Blob URLs.
  339. {"blob:http://example.com/guid-goes-here", {"http", "example.com", 80}},
  340. {"blob:http://example.com:123/guid-goes-here",
  341. {"http", "example.com", 123}},
  342. {"blob:https://example.com/guid-goes-here",
  343. {"https", "example.com", 443}},
  344. {"blob:http://u:p@example.com/guid-goes-here",
  345. {"http", "example.com", 80}},
  346. // Filesystem URLs.
  347. {"filesystem:http://example.com/type/", {"http", "example.com", 80}},
  348. {"filesystem:http://example.com:123/type/", {"http", "example.com", 123}},
  349. {"filesystem:https://example.com/type/", {"https", "example.com", 443}},
  350. {"filesystem:https://example.com:123/type/",
  351. {"https", "example.com", 123}},
  352. {"filesystem:local-std-with-host:baz./type/",
  353. {"local-std-with-host", "baz.", 0}},
  354. // IP Addresses
  355. {"http://192.168.9.1/", {"http", "192.168.9.1", 80}},
  356. {"http://[2001:db8::1]/", {"http", "[2001:db8::1]", 80}},
  357. {"http://[2001:0db8:0000:0000:0000:0000:0000:0001]/",
  358. {"http", "[2001:db8::1]", 80}},
  359. {"http://1/", {"http", "0.0.0.1", 80}},
  360. {"http://1:1/", {"http", "0.0.0.1", 1}},
  361. {"http://3232237825/", {"http", "192.168.9.1", 80}},
  362. // Punycode
  363. {"http://☃.net/", {"http", "xn--n3h.net", 80}},
  364. {"blob:http://☃.net/", {"http", "xn--n3h.net", 80}},
  365. {"local-std-with-host:↑↑↓↓←→←→ba.↑↑↓↓←→←→ba.0.bg",
  366. {"local-std-with-host", "xn--ba-rzuadaibfa.xn--ba-rzuadaibfa.0.bg", 0}},
  367. // Registered URLs
  368. {"ftp://example.com/", {"ftp", "example.com", 21}},
  369. {"ws://example.com/", {"ws", "example.com", 80}},
  370. {"wss://example.com/", {"wss", "example.com", 443}},
  371. {"wss://user:pass@example.com/", {"wss", "example.com", 443}},
  372. };
  373. for (const TestCase& test : kTestCases) {
  374. SCOPED_TRACE(testing::Message() << "Test input: " << test.input);
  375. // Only valid URLs should translate into valid, non-opaque origins.
  376. EXPECT_TRUE(this->IsValidUrl(test.input));
  377. auto origin = this->CreateOriginFromString(test.input);
  378. this->VerifyTupleOriginInvariants(origin, test.expected_tuple);
  379. }
  380. }
  381. TYPED_TEST_P(AbstractOriginTest, CustomSchemes_OpaqueOrigins) {
  382. const char* kTestCases[] = {
  383. // Unknown scheme
  384. "unknown-scheme:foo",
  385. "unknown-scheme://bar",
  386. // Unknown scheme that is a prefix or suffix of a registered scheme.
  387. "loca:foo",
  388. "ocal:foo",
  389. "local-suffix:foo",
  390. "prefix-local:foo",
  391. // Custom no-access schemes translate into an opaque origin (just like the
  392. // built-in no-access schemes such as about:blank or data:).
  393. "noaccess-std-with-host:foo",
  394. "noaccess-std-with-host://bar",
  395. "noaccess://host",
  396. "local-noaccess://host",
  397. "local-noaccess-std-with-host://host",
  398. };
  399. for (const char* test_input : kTestCases) {
  400. SCOPED_TRACE(testing::Message() << "Test input: " << test_input);
  401. // Verify that `origin` is opaque not just because `test_input` results is
  402. // an invalid URL (because of a typo in the scheme name, or because of a
  403. // technicality like having no host in a noaccess-std-with-host: scheme).
  404. EXPECT_TRUE(this->IsValidUrl(test_input));
  405. this->TestUniqueOpaqueOrigin(test_input);
  406. }
  407. }
  408. TYPED_TEST_P(AbstractOriginTest, CustomSchemes_TupleOrigins) {
  409. struct TestCase {
  410. const char* input;
  411. SchemeHostPort expected_tuple;
  412. } kTestCases[] = {
  413. // Scheme (registered in SetUp()) that's both local and standard.
  414. // TODO: Is it really appropriate to do network-host canonicalization of
  415. // schemes without ports?
  416. {"local-std-with-host:20", {"local-std-with-host", "0.0.0.20", 0}},
  417. {"local-std-with-host:20.", {"local-std-with-host", "0.0.0.20", 0}},
  418. {"local-std-with-host:foo", {"local-std-with-host", "foo", 0}},
  419. {"local-std-with-host://bar:20", {"local-std-with-host", "bar", 0}},
  420. {"local-std-with-host:baz.", {"local-std-with-host", "baz.", 0}},
  421. {"local-std-with-host:baz..", {"local-std-with-host", "baz..", 0}},
  422. {"local-std-with-host:baz..bar", {"local-std-with-host", "baz..bar", 0}},
  423. {"local-std-with-host:baz...", {"local-std-with-host", "baz...", 0}},
  424. // Scheme (registered in SetUp()) that's local but nonstandard. These
  425. // always have empty hostnames, but are allowed to be url::Origins.
  426. {"local:", {"local", "", 0}},
  427. {"local:foo", {"local", "", 0}},
  428. {"local://bar", {"local", "", 0}},
  429. {"also-local://bar", {"also-local", "", 0}},
  430. {"std-with-host://host", {"std-with-host", "host", 0}},
  431. {"local://host", {"local", "", 0}},
  432. {"local-std-with-host://host", {"local-std-with-host", "host", 0}},
  433. };
  434. for (const TestCase& test : kTestCases) {
  435. SCOPED_TRACE(testing::Message() << "Test input: " << test.input);
  436. // Only valid URLs should translate into valid, non-opaque origins.
  437. EXPECT_TRUE(this->IsValidUrl(test.input));
  438. auto origin = this->CreateOriginFromString(test.input);
  439. this->VerifyTupleOriginInvariants(origin, test.expected_tuple);
  440. }
  441. }
  442. REGISTER_TYPED_TEST_SUITE_P(AbstractOriginTest,
  443. NonStandardSchemeWithAndroidWebViewHack,
  444. OpaqueOriginsFromValidUrls,
  445. OpaqueOriginsFromInvalidUrls,
  446. TupleOrigins,
  447. CustomSchemes_OpaqueOrigins,
  448. CustomSchemes_TupleOrigins);
  449. } // namespace url
  450. #endif // URL_ORIGIN_ABSTRACT_TESTS_H_