xref: /aosp_15_r20/external/cronet/url/origin_abstract_tests.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2020 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #ifndef URL_ORIGIN_ABSTRACT_TESTS_H_
6*6777b538SAndroid Build Coastguard Worker #define URL_ORIGIN_ABSTRACT_TESTS_H_
7*6777b538SAndroid Build Coastguard Worker 
8*6777b538SAndroid Build Coastguard Worker #include <initializer_list>
9*6777b538SAndroid Build Coastguard Worker #include <string>
10*6777b538SAndroid Build Coastguard Worker #include <string_view>
11*6777b538SAndroid Build Coastguard Worker #include <type_traits>
12*6777b538SAndroid Build Coastguard Worker 
13*6777b538SAndroid Build Coastguard Worker #include "base/containers/contains.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/test/scoped_feature_list.h"
15*6777b538SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
16*6777b538SAndroid Build Coastguard Worker #include "url/gurl.h"
17*6777b538SAndroid Build Coastguard Worker #include "url/origin.h"
18*6777b538SAndroid Build Coastguard Worker #include "url/scheme_host_port.h"
19*6777b538SAndroid Build Coastguard Worker #include "url/url_features.h"
20*6777b538SAndroid Build Coastguard Worker #include "url/url_util.h"
21*6777b538SAndroid Build Coastguard Worker 
22*6777b538SAndroid Build Coastguard Worker namespace url {
23*6777b538SAndroid Build Coastguard Worker 
24*6777b538SAndroid Build Coastguard Worker void ExpectParsedUrlsEqual(const GURL& a, const GURL& b);
25*6777b538SAndroid Build Coastguard Worker 
26*6777b538SAndroid Build Coastguard Worker // AbstractOriginTest below abstracts away differences between url::Origin and
27*6777b538SAndroid Build Coastguard Worker // blink::SecurityOrigin by parametrizing the tests with a class that has to
28*6777b538SAndroid Build Coastguard Worker // expose the same public members as UrlOriginTestTraits below.
29*6777b538SAndroid Build Coastguard Worker class UrlOriginTestTraits {
30*6777b538SAndroid Build Coastguard Worker  public:
31*6777b538SAndroid Build Coastguard Worker   using OriginType = Origin;
32*6777b538SAndroid Build Coastguard Worker 
33*6777b538SAndroid Build Coastguard Worker   // Constructing an origin.
34*6777b538SAndroid Build Coastguard Worker   static OriginType CreateOriginFromString(std::string_view s);
35*6777b538SAndroid Build Coastguard Worker   static OriginType CreateUniqueOpaqueOrigin();
36*6777b538SAndroid Build Coastguard Worker   static OriginType CreateWithReferenceOrigin(
37*6777b538SAndroid Build Coastguard Worker       std::string_view url,
38*6777b538SAndroid Build Coastguard Worker       const OriginType& reference_origin);
39*6777b538SAndroid Build Coastguard Worker   static OriginType DeriveNewOpaqueOrigin(const OriginType& reference_origin);
40*6777b538SAndroid Build Coastguard Worker 
41*6777b538SAndroid Build Coastguard Worker   // Accessors for origin properties.
42*6777b538SAndroid Build Coastguard Worker   static bool IsOpaque(const OriginType& origin);
43*6777b538SAndroid Build Coastguard Worker   static std::string GetScheme(const OriginType& origin);
44*6777b538SAndroid Build Coastguard Worker   static std::string GetHost(const OriginType& origin);
45*6777b538SAndroid Build Coastguard Worker   static uint16_t GetPort(const OriginType& origin);
46*6777b538SAndroid Build Coastguard Worker   static SchemeHostPort GetTupleOrPrecursorTupleIfOpaque(
47*6777b538SAndroid Build Coastguard Worker       const OriginType& origin);
48*6777b538SAndroid Build Coastguard Worker 
49*6777b538SAndroid Build Coastguard Worker   // Wrappers for other instance methods of OriginType.
50*6777b538SAndroid Build Coastguard Worker   static bool IsSameOrigin(const OriginType& a, const OriginType& b);
51*6777b538SAndroid Build Coastguard Worker   static std::string Serialize(const OriginType& origin);
52*6777b538SAndroid Build Coastguard Worker 
53*6777b538SAndroid Build Coastguard Worker   // "Accessors" of URL properties.
54*6777b538SAndroid Build Coastguard Worker   //
55*6777b538SAndroid Build Coastguard Worker   // TODO(lukasza): Consider merging together OriginTraitsBase here and
56*6777b538SAndroid Build Coastguard Worker   // UrlTraitsBase in //url/gurl_abstract_tests.h.
57*6777b538SAndroid Build Coastguard Worker   static bool IsValidUrl(std::string_view str);
58*6777b538SAndroid Build Coastguard Worker 
59*6777b538SAndroid Build Coastguard Worker   // Only static members = no constructors are needed.
60*6777b538SAndroid Build Coastguard Worker   UrlOriginTestTraits() = delete;
61*6777b538SAndroid Build Coastguard Worker };
62*6777b538SAndroid Build Coastguard Worker 
63*6777b538SAndroid Build Coastguard Worker // Test suite for tests that cover both url::Origin and blink::SecurityOrigin.
64*6777b538SAndroid Build Coastguard Worker template <typename TOriginTraits>
65*6777b538SAndroid Build Coastguard Worker class AbstractOriginTest : public testing::Test {
66*6777b538SAndroid Build Coastguard Worker  public:
SetUp()67*6777b538SAndroid Build Coastguard Worker   void SetUp() override {
68*6777b538SAndroid Build Coastguard Worker     const char* kSchemesToRegister[] = {
69*6777b538SAndroid Build Coastguard Worker         "noaccess",
70*6777b538SAndroid Build Coastguard Worker         "std-with-host",
71*6777b538SAndroid Build Coastguard Worker         "noaccess-std-with-host",
72*6777b538SAndroid Build Coastguard Worker         "local",
73*6777b538SAndroid Build Coastguard Worker         "local-noaccess",
74*6777b538SAndroid Build Coastguard Worker         "local-std-with-host",
75*6777b538SAndroid Build Coastguard Worker         "local-noaccess-std-with-host",
76*6777b538SAndroid Build Coastguard Worker         "also-local",
77*6777b538SAndroid Build Coastguard Worker         "sec",
78*6777b538SAndroid Build Coastguard Worker         "sec-std-with-host",
79*6777b538SAndroid Build Coastguard Worker         "sec-noaccess",
80*6777b538SAndroid Build Coastguard Worker     };
81*6777b538SAndroid Build Coastguard Worker     for (const char* kScheme : kSchemesToRegister) {
82*6777b538SAndroid Build Coastguard Worker       std::string scheme(kScheme);
83*6777b538SAndroid Build Coastguard Worker       if (base::Contains(scheme, "noaccess"))
84*6777b538SAndroid Build Coastguard Worker         AddNoAccessScheme(kScheme);
85*6777b538SAndroid Build Coastguard Worker       if (base::Contains(scheme, "std-with-host"))
86*6777b538SAndroid Build Coastguard Worker         AddStandardScheme(kScheme, SchemeType::SCHEME_WITH_HOST);
87*6777b538SAndroid Build Coastguard Worker       if (base::Contains(scheme, "local"))
88*6777b538SAndroid Build Coastguard Worker         AddLocalScheme(kScheme);
89*6777b538SAndroid Build Coastguard Worker       if (base::Contains(scheme, "sec"))
90*6777b538SAndroid Build Coastguard Worker         AddSecureScheme(kScheme);
91*6777b538SAndroid Build Coastguard Worker     }
92*6777b538SAndroid Build Coastguard Worker   }
93*6777b538SAndroid Build Coastguard Worker 
94*6777b538SAndroid Build Coastguard Worker  protected:
95*6777b538SAndroid Build Coastguard Worker   // Wrappers that help ellide away TOriginTraits.
96*6777b538SAndroid Build Coastguard Worker   //
97*6777b538SAndroid Build Coastguard Worker   // Note that calling the wrappers needs to be prefixed with `this->...` to
98*6777b538SAndroid Build Coastguard Worker   // avoid hitting: explicit qualification required to use member 'IsOpaque'
99*6777b538SAndroid Build Coastguard Worker   // from dependent base class.
100*6777b538SAndroid Build Coastguard Worker   using OriginType = typename TOriginTraits::OriginType;
CreateOriginFromString(std::string_view s)101*6777b538SAndroid Build Coastguard Worker   OriginType CreateOriginFromString(std::string_view s) {
102*6777b538SAndroid Build Coastguard Worker     return TOriginTraits::CreateOriginFromString(s);
103*6777b538SAndroid Build Coastguard Worker   }
CreateUniqueOpaqueOrigin()104*6777b538SAndroid Build Coastguard Worker   OriginType CreateUniqueOpaqueOrigin() {
105*6777b538SAndroid Build Coastguard Worker     return TOriginTraits::CreateUniqueOpaqueOrigin();
106*6777b538SAndroid Build Coastguard Worker   }
CreateWithReferenceOrigin(std::string_view url,const OriginType & reference_origin)107*6777b538SAndroid Build Coastguard Worker   OriginType CreateWithReferenceOrigin(std::string_view url,
108*6777b538SAndroid Build Coastguard Worker                                        const OriginType& reference_origin) {
109*6777b538SAndroid Build Coastguard Worker     return TOriginTraits::CreateWithReferenceOrigin(url, reference_origin);
110*6777b538SAndroid Build Coastguard Worker   }
DeriveNewOpaqueOrigin(const OriginType & reference_origin)111*6777b538SAndroid Build Coastguard Worker   OriginType DeriveNewOpaqueOrigin(const OriginType& reference_origin) {
112*6777b538SAndroid Build Coastguard Worker     return TOriginTraits::DeriveNewOpaqueOrigin(reference_origin);
113*6777b538SAndroid Build Coastguard Worker   }
IsOpaque(const OriginType & origin)114*6777b538SAndroid Build Coastguard Worker   bool IsOpaque(const OriginType& origin) {
115*6777b538SAndroid Build Coastguard Worker     return TOriginTraits::IsOpaque(origin);
116*6777b538SAndroid Build Coastguard Worker   }
GetScheme(const OriginType & origin)117*6777b538SAndroid Build Coastguard Worker   std::string GetScheme(const OriginType& origin) {
118*6777b538SAndroid Build Coastguard Worker     return TOriginTraits::GetScheme(origin);
119*6777b538SAndroid Build Coastguard Worker   }
GetHost(const OriginType & origin)120*6777b538SAndroid Build Coastguard Worker   std::string GetHost(const OriginType& origin) {
121*6777b538SAndroid Build Coastguard Worker     return TOriginTraits::GetHost(origin);
122*6777b538SAndroid Build Coastguard Worker   }
GetPort(const OriginType & origin)123*6777b538SAndroid Build Coastguard Worker   uint16_t GetPort(const OriginType& origin) {
124*6777b538SAndroid Build Coastguard Worker     return TOriginTraits::GetPort(origin);
125*6777b538SAndroid Build Coastguard Worker   }
GetTupleOrPrecursorTupleIfOpaque(const OriginType & origin)126*6777b538SAndroid Build Coastguard Worker   SchemeHostPort GetTupleOrPrecursorTupleIfOpaque(const OriginType& origin) {
127*6777b538SAndroid Build Coastguard Worker     return TOriginTraits::GetTupleOrPrecursorTupleIfOpaque(origin);
128*6777b538SAndroid Build Coastguard Worker   }
IsSameOrigin(const OriginType & a,const OriginType & b)129*6777b538SAndroid Build Coastguard Worker   bool IsSameOrigin(const OriginType& a, const OriginType& b) {
130*6777b538SAndroid Build Coastguard Worker     bool is_a_same_with_b = TOriginTraits::IsSameOrigin(a, b);
131*6777b538SAndroid Build Coastguard Worker     bool is_b_same_with_a = TOriginTraits::IsSameOrigin(b, a);
132*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(is_a_same_with_b, is_b_same_with_a);
133*6777b538SAndroid Build Coastguard Worker     return is_a_same_with_b;
134*6777b538SAndroid Build Coastguard Worker   }
Serialize(const OriginType & origin)135*6777b538SAndroid Build Coastguard Worker   std::string Serialize(const OriginType& origin) {
136*6777b538SAndroid Build Coastguard Worker     return TOriginTraits::Serialize(origin);
137*6777b538SAndroid Build Coastguard Worker   }
IsValidUrl(std::string_view str)138*6777b538SAndroid Build Coastguard Worker   bool IsValidUrl(std::string_view str) {
139*6777b538SAndroid Build Coastguard Worker     return TOriginTraits::IsValidUrl(str);
140*6777b538SAndroid Build Coastguard Worker   }
141*6777b538SAndroid Build Coastguard Worker 
142*6777b538SAndroid Build Coastguard Worker #define EXPECT_SAME_ORIGIN(a, b)                                 \
143*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(this->IsSameOrigin((a), (b)))                      \
144*6777b538SAndroid Build Coastguard Worker       << "When checking if \"" << this->Serialize(a) << "\" is " \
145*6777b538SAndroid Build Coastguard Worker       << "same-origin with \"" << this->Serialize(b) << "\""
146*6777b538SAndroid Build Coastguard Worker 
147*6777b538SAndroid Build Coastguard Worker #define EXPECT_CROSS_ORIGIN(a, b)                                \
148*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(this->IsSameOrigin((a), (b)))                     \
149*6777b538SAndroid Build Coastguard Worker       << "When checking if \"" << this->Serialize(a) << "\" is " \
150*6777b538SAndroid Build Coastguard Worker       << "cross-origin from \"" << this->Serialize(b) << "\""
151*6777b538SAndroid Build Coastguard Worker 
VerifyOriginInvariants(const OriginType & origin)152*6777b538SAndroid Build Coastguard Worker   void VerifyOriginInvariants(const OriginType& origin) {
153*6777b538SAndroid Build Coastguard Worker     // An origin is always same-origin with itself.
154*6777b538SAndroid Build Coastguard Worker     EXPECT_SAME_ORIGIN(origin, origin);
155*6777b538SAndroid Build Coastguard Worker 
156*6777b538SAndroid Build Coastguard Worker     // A copy of |origin| should be same-origin as well.
157*6777b538SAndroid Build Coastguard Worker     auto origin_copy = origin;
158*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(this->GetScheme(origin), this->GetScheme(origin_copy));
159*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(this->GetHost(origin), this->GetHost(origin_copy));
160*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(this->GetPort(origin), this->GetPort(origin_copy));
161*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(this->IsOpaque(origin), this->IsOpaque(origin_copy));
162*6777b538SAndroid Build Coastguard Worker     EXPECT_SAME_ORIGIN(origin, origin_copy);
163*6777b538SAndroid Build Coastguard Worker 
164*6777b538SAndroid Build Coastguard Worker     // An origin is always cross-origin from another, unique, opaque origin.
165*6777b538SAndroid Build Coastguard Worker     EXPECT_CROSS_ORIGIN(origin, this->CreateUniqueOpaqueOrigin());
166*6777b538SAndroid Build Coastguard Worker 
167*6777b538SAndroid Build Coastguard Worker     // An origin is always cross-origin from another tuple origin.
168*6777b538SAndroid Build Coastguard Worker     auto different_tuple_origin =
169*6777b538SAndroid Build Coastguard Worker         this->CreateOriginFromString("https://not-in-the-list.test/");
170*6777b538SAndroid Build Coastguard Worker     EXPECT_CROSS_ORIGIN(origin, different_tuple_origin);
171*6777b538SAndroid Build Coastguard Worker 
172*6777b538SAndroid Build Coastguard Worker     // Deriving an origin for "about:blank".
173*6777b538SAndroid Build Coastguard Worker     auto about_blank_origin1 =
174*6777b538SAndroid Build Coastguard Worker         this->CreateWithReferenceOrigin("about:blank", origin);
175*6777b538SAndroid Build Coastguard Worker     auto about_blank_origin2 =
176*6777b538SAndroid Build Coastguard Worker         this->CreateWithReferenceOrigin("about:blank?bar#foo", origin);
177*6777b538SAndroid Build Coastguard Worker     EXPECT_SAME_ORIGIN(origin, about_blank_origin1);
178*6777b538SAndroid Build Coastguard Worker     EXPECT_SAME_ORIGIN(origin, about_blank_origin2);
179*6777b538SAndroid Build Coastguard Worker 
180*6777b538SAndroid Build Coastguard Worker     // Derived opaque origins.
181*6777b538SAndroid Build Coastguard Worker     std::vector<OriginType> derived_origins = {
182*6777b538SAndroid Build Coastguard Worker         this->DeriveNewOpaqueOrigin(origin),
183*6777b538SAndroid Build Coastguard Worker         this->CreateWithReferenceOrigin("data:text/html,baz", origin),
184*6777b538SAndroid Build Coastguard Worker         this->DeriveNewOpaqueOrigin(about_blank_origin1),
185*6777b538SAndroid Build Coastguard Worker     };
186*6777b538SAndroid Build Coastguard Worker     for (size_t i = 0; i < derived_origins.size(); i++) {
187*6777b538SAndroid Build Coastguard Worker       SCOPED_TRACE(testing::Message() << "Derived origin #" << i);
188*6777b538SAndroid Build Coastguard Worker       const OriginType& derived_origin = derived_origins[i];
189*6777b538SAndroid Build Coastguard Worker       EXPECT_TRUE(this->IsOpaque(derived_origin));
190*6777b538SAndroid Build Coastguard Worker       EXPECT_SAME_ORIGIN(derived_origin, derived_origin);
191*6777b538SAndroid Build Coastguard Worker       EXPECT_CROSS_ORIGIN(origin, derived_origin);
192*6777b538SAndroid Build Coastguard Worker       EXPECT_EQ(this->GetTupleOrPrecursorTupleIfOpaque(origin),
193*6777b538SAndroid Build Coastguard Worker                 this->GetTupleOrPrecursorTupleIfOpaque(derived_origin));
194*6777b538SAndroid Build Coastguard Worker     }
195*6777b538SAndroid Build Coastguard Worker   }
196*6777b538SAndroid Build Coastguard Worker 
VerifyUniqueOpaqueOriginInvariants(const OriginType & origin)197*6777b538SAndroid Build Coastguard Worker   void VerifyUniqueOpaqueOriginInvariants(const OriginType& origin) {
198*6777b538SAndroid Build Coastguard Worker     if (!this->IsOpaque(origin)) {
199*6777b538SAndroid Build Coastguard Worker       ADD_FAILURE() << "Got unexpectedly non-opaque origin: "
200*6777b538SAndroid Build Coastguard Worker                     << this->Serialize(origin);
201*6777b538SAndroid Build Coastguard Worker       return;  // Skip other test assertions.
202*6777b538SAndroid Build Coastguard Worker     }
203*6777b538SAndroid Build Coastguard Worker 
204*6777b538SAndroid Build Coastguard Worker     // Opaque origins should have an "empty" scheme, host and port.
205*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ("", this->GetScheme(origin));
206*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ("", this->GetHost(origin));
207*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(0, this->GetPort(origin));
208*6777b538SAndroid Build Coastguard Worker 
209*6777b538SAndroid Build Coastguard Worker     // Unique opaque origins should have an empty precursor tuple.
210*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(SchemeHostPort(), this->GetTupleOrPrecursorTupleIfOpaque(origin));
211*6777b538SAndroid Build Coastguard Worker 
212*6777b538SAndroid Build Coastguard Worker     // Serialization test.
213*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ("null", this->Serialize(origin));
214*6777b538SAndroid Build Coastguard Worker 
215*6777b538SAndroid Build Coastguard Worker     // Invariants that should hold for any origin.
216*6777b538SAndroid Build Coastguard Worker     VerifyOriginInvariants(origin);
217*6777b538SAndroid Build Coastguard Worker   }
218*6777b538SAndroid Build Coastguard Worker 
TestUniqueOpaqueOrigin(std::string_view test_input)219*6777b538SAndroid Build Coastguard Worker   void TestUniqueOpaqueOrigin(std::string_view test_input) {
220*6777b538SAndroid Build Coastguard Worker     auto origin = this->CreateOriginFromString(test_input);
221*6777b538SAndroid Build Coastguard Worker     this->VerifyUniqueOpaqueOriginInvariants(origin);
222*6777b538SAndroid Build Coastguard Worker 
223*6777b538SAndroid Build Coastguard Worker     // Re-creating from the URL should be cross-origin.
224*6777b538SAndroid Build Coastguard Worker     auto origin_recreated_from_same_input =
225*6777b538SAndroid Build Coastguard Worker         this->CreateOriginFromString(test_input);
226*6777b538SAndroid Build Coastguard Worker     EXPECT_CROSS_ORIGIN(origin, origin_recreated_from_same_input);
227*6777b538SAndroid Build Coastguard Worker   }
228*6777b538SAndroid Build Coastguard Worker 
VerifyTupleOriginInvariants(const OriginType & origin,const SchemeHostPort & expected_tuple)229*6777b538SAndroid Build Coastguard Worker   void VerifyTupleOriginInvariants(const OriginType& origin,
230*6777b538SAndroid Build Coastguard Worker                                    const SchemeHostPort& expected_tuple) {
231*6777b538SAndroid Build Coastguard Worker     if (this->IsOpaque(origin)) {
232*6777b538SAndroid Build Coastguard Worker       ADD_FAILURE() << "Got unexpectedly opaque origin";
233*6777b538SAndroid Build Coastguard Worker       return;  // Skip other test assertions.
234*6777b538SAndroid Build Coastguard Worker     }
235*6777b538SAndroid Build Coastguard Worker     SCOPED_TRACE(testing::Message()
236*6777b538SAndroid Build Coastguard Worker                  << "Actual origin: " << this->Serialize(origin));
237*6777b538SAndroid Build Coastguard Worker 
238*6777b538SAndroid Build Coastguard Worker     // Compare `origin` against the `expected_tuple`.
239*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(expected_tuple.scheme(), this->GetScheme(origin));
240*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(expected_tuple.host(), this->GetHost(origin));
241*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(expected_tuple.port(), this->GetPort(origin));
242*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(expected_tuple, this->GetTupleOrPrecursorTupleIfOpaque(origin));
243*6777b538SAndroid Build Coastguard Worker 
244*6777b538SAndroid Build Coastguard Worker     // Serialization test.
245*6777b538SAndroid Build Coastguard Worker     //
246*6777b538SAndroid Build Coastguard Worker     // TODO(lukasza): Consider preserving the hostname when serializing file:
247*6777b538SAndroid Build Coastguard Worker     // URLs.  Dropping the hostname seems incompatible with section 6 of
248*6777b538SAndroid Build Coastguard Worker     // rfc6454.  Even though section 4 says that "the implementation MAY
249*6777b538SAndroid Build Coastguard Worker     // return an implementation-defined value", it seems that Chromium
250*6777b538SAndroid Build Coastguard Worker     // implementation *does* include the hostname in the origin SchemeHostPort
251*6777b538SAndroid Build Coastguard Worker     // tuple.
252*6777b538SAndroid Build Coastguard Worker     if (expected_tuple.scheme() != kFileScheme || expected_tuple.host() == "") {
253*6777b538SAndroid Build Coastguard Worker       EXPECT_SAME_ORIGIN(origin,
254*6777b538SAndroid Build Coastguard Worker                          this->CreateOriginFromString(this->Serialize(origin)));
255*6777b538SAndroid Build Coastguard Worker     }
256*6777b538SAndroid Build Coastguard Worker 
257*6777b538SAndroid Build Coastguard Worker     // Invariants that should hold for any origin.
258*6777b538SAndroid Build Coastguard Worker     VerifyOriginInvariants(origin);
259*6777b538SAndroid Build Coastguard Worker   }
260*6777b538SAndroid Build Coastguard Worker 
261*6777b538SAndroid Build Coastguard Worker  private:
262*6777b538SAndroid Build Coastguard Worker   ScopedSchemeRegistryForTests scoped_scheme_registry_;
263*6777b538SAndroid Build Coastguard Worker };
264*6777b538SAndroid Build Coastguard Worker 
265*6777b538SAndroid Build Coastguard Worker TYPED_TEST_SUITE_P(AbstractOriginTest);
266*6777b538SAndroid Build Coastguard Worker 
TYPED_TEST_P(AbstractOriginTest,NonStandardSchemeWithAndroidWebViewHack)267*6777b538SAndroid Build Coastguard Worker TYPED_TEST_P(AbstractOriginTest, NonStandardSchemeWithAndroidWebViewHack) {
268*6777b538SAndroid Build Coastguard Worker   EnableNonStandardSchemesForAndroidWebView();
269*6777b538SAndroid Build Coastguard Worker 
270*6777b538SAndroid Build Coastguard Worker   // Regression test for https://crbug.com/896059.
271*6777b538SAndroid Build Coastguard Worker   auto origin = this->CreateOriginFromString("unknown-scheme://");
272*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(this->IsOpaque(origin));
273*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("unknown-scheme", this->GetScheme(origin));
274*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("", this->GetHost(origin));
275*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(0, this->GetPort(origin));
276*6777b538SAndroid Build Coastguard Worker 
277*6777b538SAndroid Build Coastguard Worker   // about:blank translates into an opaque origin, even in presence of
278*6777b538SAndroid Build Coastguard Worker   // EnableNonStandardSchemesForAndroidWebView.
279*6777b538SAndroid Build Coastguard Worker   origin = this->CreateOriginFromString("about:blank");
280*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(this->IsOpaque(origin));
281*6777b538SAndroid Build Coastguard Worker }
282*6777b538SAndroid Build Coastguard Worker 
TYPED_TEST_P(AbstractOriginTest,AndroidWebViewHackWithStandardCompliantNonSpecialSchemeURLParsing)283*6777b538SAndroid Build Coastguard Worker TYPED_TEST_P(
284*6777b538SAndroid Build Coastguard Worker     AbstractOriginTest,
285*6777b538SAndroid Build Coastguard Worker     AndroidWebViewHackWithStandardCompliantNonSpecialSchemeURLParsing) {
286*6777b538SAndroid Build Coastguard Worker   EnableNonStandardSchemesForAndroidWebView();
287*6777b538SAndroid Build Coastguard Worker 
288*6777b538SAndroid Build Coastguard Worker   // Manual flag-dependent tests to ensure that the behavior doesn't change
289*6777b538SAndroid Build Coastguard Worker   // whether the flag is enabled or not.
290*6777b538SAndroid Build Coastguard Worker   for (bool flag : {false, true}) {
291*6777b538SAndroid Build Coastguard Worker     base::test::ScopedFeatureList scoped_feature_list;
292*6777b538SAndroid Build Coastguard Worker     if (flag) {
293*6777b538SAndroid Build Coastguard Worker       scoped_feature_list.InitAndEnableFeature(
294*6777b538SAndroid Build Coastguard Worker           kStandardCompliantNonSpecialSchemeURLParsing);
295*6777b538SAndroid Build Coastguard Worker     } else {
296*6777b538SAndroid Build Coastguard Worker       scoped_feature_list.InitAndDisableFeature(
297*6777b538SAndroid Build Coastguard Worker           kStandardCompliantNonSpecialSchemeURLParsing);
298*6777b538SAndroid Build Coastguard Worker     }
299*6777b538SAndroid Build Coastguard Worker 
300*6777b538SAndroid Build Coastguard Worker     // Non-Standard scheme cases.
301*6777b538SAndroid Build Coastguard Worker     {
302*6777b538SAndroid Build Coastguard Worker       auto origin_a = this->CreateOriginFromString("non-standard://a.com:80");
303*6777b538SAndroid Build Coastguard Worker       // Ensure that a host and a port are discarded.
304*6777b538SAndroid Build Coastguard Worker       EXPECT_EQ(this->GetHost(origin_a), "");
305*6777b538SAndroid Build Coastguard Worker       EXPECT_EQ(this->GetPort(origin_a), 0);
306*6777b538SAndroid Build Coastguard Worker       EXPECT_EQ(this->Serialize(origin_a), "non-standard://");
307*6777b538SAndroid Build Coastguard Worker       EXPECT_FALSE(this->IsOpaque(origin_a));
308*6777b538SAndroid Build Coastguard Worker 
309*6777b538SAndroid Build Coastguard Worker       // URLs are considered same-origin if their schemes match, even if
310*6777b538SAndroid Build Coastguard Worker       // their host and port are different.
311*6777b538SAndroid Build Coastguard Worker       auto origin_b = this->CreateOriginFromString("non-standard://b.com:90");
312*6777b538SAndroid Build Coastguard Worker       EXPECT_TRUE(this->IsSameOrigin(origin_a, origin_b));
313*6777b538SAndroid Build Coastguard Worker 
314*6777b538SAndroid Build Coastguard Worker       // URLs are not considered same-origin if their schemes don't match,
315*6777b538SAndroid Build Coastguard Worker       // even if their host and port are same.
316*6777b538SAndroid Build Coastguard Worker       auto another_origin_a =
317*6777b538SAndroid Build Coastguard Worker           this->CreateOriginFromString("another-non-standard://a.com:80");
318*6777b538SAndroid Build Coastguard Worker       EXPECT_FALSE(this->IsSameOrigin(origin_a, another_origin_a));
319*6777b538SAndroid Build Coastguard Worker     }
320*6777b538SAndroid Build Coastguard Worker 
321*6777b538SAndroid Build Coastguard Worker     // Standard scheme cases.
322*6777b538SAndroid Build Coastguard Worker     {
323*6777b538SAndroid Build Coastguard Worker       // Ensure that the behavior of a standard URL is preserved.
324*6777b538SAndroid Build Coastguard Worker       auto origin_a = this->CreateOriginFromString("https://a.com:80");
325*6777b538SAndroid Build Coastguard Worker       EXPECT_EQ(this->GetHost(origin_a), "a.com");
326*6777b538SAndroid Build Coastguard Worker       EXPECT_EQ(this->GetPort(origin_a), 80);
327*6777b538SAndroid Build Coastguard Worker       EXPECT_EQ(this->Serialize(origin_a), "https://a.com:80");
328*6777b538SAndroid Build Coastguard Worker       EXPECT_FALSE(this->IsOpaque(origin_a));
329*6777b538SAndroid Build Coastguard Worker 
330*6777b538SAndroid Build Coastguard Worker       auto origin_b = this->CreateOriginFromString("https://b.com:80");
331*6777b538SAndroid Build Coastguard Worker       EXPECT_FALSE(this->IsSameOrigin(origin_a, origin_b));
332*6777b538SAndroid Build Coastguard Worker     }
333*6777b538SAndroid Build Coastguard Worker   }
334*6777b538SAndroid Build Coastguard Worker }
335*6777b538SAndroid Build Coastguard Worker 
TYPED_TEST_P(AbstractOriginTest,OpaqueOriginsFromValidUrls)336*6777b538SAndroid Build Coastguard Worker TYPED_TEST_P(AbstractOriginTest, OpaqueOriginsFromValidUrls) {
337*6777b538SAndroid Build Coastguard Worker   const char* kTestCases[] = {
338*6777b538SAndroid Build Coastguard Worker       // Built-in noaccess schemes.
339*6777b538SAndroid Build Coastguard Worker       "data:text/html,Hello!",
340*6777b538SAndroid Build Coastguard Worker       "javascript:alert(1)",
341*6777b538SAndroid Build Coastguard Worker       "about:blank",
342*6777b538SAndroid Build Coastguard Worker 
343*6777b538SAndroid Build Coastguard Worker       // Opaque blob URLs.
344*6777b538SAndroid Build Coastguard Worker       "blob:null/foo",        // blob:null (actually a valid URL)
345*6777b538SAndroid Build Coastguard Worker       "blob:data:foo",        // blob + data (which is nonstandard)
346*6777b538SAndroid Build Coastguard Worker       "blob:about://blank/",  // blob + about (which is nonstandard)
347*6777b538SAndroid Build Coastguard Worker       "blob:about:blank/",    // blob + about (which is nonstandard)
348*6777b538SAndroid Build Coastguard Worker       "blob:blob:http://www.example.com/guid-goes-here",
349*6777b538SAndroid Build Coastguard Worker       "blob:filesystem:ws:b/.",
350*6777b538SAndroid Build Coastguard Worker       "blob:filesystem:ftp://a/b",
351*6777b538SAndroid Build Coastguard Worker       "blob:blob:file://localhost/foo/bar",
352*6777b538SAndroid Build Coastguard Worker   };
353*6777b538SAndroid Build Coastguard Worker 
354*6777b538SAndroid Build Coastguard Worker   for (const char* test_input : kTestCases) {
355*6777b538SAndroid Build Coastguard Worker     SCOPED_TRACE(testing::Message() << "Test input: " << test_input);
356*6777b538SAndroid Build Coastguard Worker 
357*6777b538SAndroid Build Coastguard Worker     // Verify that `origin` is opaque not just because `test_input` results is
358*6777b538SAndroid Build Coastguard Worker     // an invalid URL (because of a typo in the scheme name, or because of a
359*6777b538SAndroid Build Coastguard Worker     // technicality like having no host in a noaccess-std-with-host: scheme).
360*6777b538SAndroid Build Coastguard Worker     EXPECT_TRUE(this->IsValidUrl(test_input));
361*6777b538SAndroid Build Coastguard Worker 
362*6777b538SAndroid Build Coastguard Worker     this->TestUniqueOpaqueOrigin(test_input);
363*6777b538SAndroid Build Coastguard Worker   }
364*6777b538SAndroid Build Coastguard Worker }
365*6777b538SAndroid Build Coastguard Worker 
TYPED_TEST_P(AbstractOriginTest,OpaqueOriginsFromInvalidUrls)366*6777b538SAndroid Build Coastguard Worker TYPED_TEST_P(AbstractOriginTest, OpaqueOriginsFromInvalidUrls) {
367*6777b538SAndroid Build Coastguard Worker   // TODO(lukasza): Consider moving those to GURL/KURL tests that verify what
368*6777b538SAndroid Build Coastguard Worker   // inputs are parsed as an invalid URL.
369*6777b538SAndroid Build Coastguard Worker 
370*6777b538SAndroid Build Coastguard Worker   const char* kTestCases[] = {
371*6777b538SAndroid Build Coastguard Worker       // Invalid file: URLs.
372*6777b538SAndroid Build Coastguard Worker       "file://example.com:443/etc/passwd",  // No port expected.
373*6777b538SAndroid Build Coastguard Worker 
374*6777b538SAndroid Build Coastguard Worker       // Invalid HTTP URLs.
375*6777b538SAndroid Build Coastguard Worker       "http",
376*6777b538SAndroid Build Coastguard Worker       "http:",
377*6777b538SAndroid Build Coastguard Worker       "http:/",
378*6777b538SAndroid Build Coastguard Worker       "http://",
379*6777b538SAndroid Build Coastguard Worker       "http://:",
380*6777b538SAndroid Build Coastguard Worker       "http://:1",
381*6777b538SAndroid Build Coastguard Worker       "http::///invalid.example.com/",
382*6777b538SAndroid Build Coastguard Worker       "http://example.com:65536/",                    // Port out of range.
383*6777b538SAndroid Build Coastguard Worker       "http://example.com:-1/",                       // Port out of range.
384*6777b538SAndroid Build Coastguard Worker       "http://example.com:18446744073709551616/",     // Port = 2^64.
385*6777b538SAndroid Build Coastguard Worker       "http://example.com:18446744073709551616999/",  // Lots of port digits.
386*6777b538SAndroid Build Coastguard Worker 
387*6777b538SAndroid Build Coastguard Worker       // Invalid filesystem URLs.
388*6777b538SAndroid Build Coastguard Worker       "filesystem:http://example.com/",  // Missing /type/.
389*6777b538SAndroid Build Coastguard Worker       "filesystem:local:baz./type/",
390*6777b538SAndroid Build Coastguard Worker       "filesystem:local://hostname/type/",
391*6777b538SAndroid Build Coastguard Worker       "filesystem:unknown-scheme://hostname/type/",
392*6777b538SAndroid Build Coastguard Worker       "filesystem:filesystem:http://example.org:88/foo/bar",
393*6777b538SAndroid Build Coastguard Worker 
394*6777b538SAndroid Build Coastguard Worker       // Invalid IP addresses
395*6777b538SAndroid Build Coastguard Worker       "http://[]/",
396*6777b538SAndroid Build Coastguard Worker       "http://[2001:0db8:0000:0000:0000:0000:0000:0000:0001]/",  // 9 groups.
397*6777b538SAndroid Build Coastguard Worker 
398*6777b538SAndroid Build Coastguard Worker       // Unknown scheme without a colon character (":") gives an invalid URL.
399*6777b538SAndroid Build Coastguard Worker       "unknown-scheme",
400*6777b538SAndroid Build Coastguard Worker 
401*6777b538SAndroid Build Coastguard Worker       // Standard schemes require a hostname (and result in an opaque origin if
402*6777b538SAndroid Build Coastguard Worker       // the hostname is missing).
403*6777b538SAndroid Build Coastguard Worker       "local-std-with-host:",
404*6777b538SAndroid Build Coastguard Worker       "noaccess-std-with-host:",
405*6777b538SAndroid Build Coastguard Worker   };
406*6777b538SAndroid Build Coastguard Worker 
407*6777b538SAndroid Build Coastguard Worker   for (const char* test_input : kTestCases) {
408*6777b538SAndroid Build Coastguard Worker     SCOPED_TRACE(testing::Message() << "Test input: " << test_input);
409*6777b538SAndroid Build Coastguard Worker 
410*6777b538SAndroid Build Coastguard Worker     // All testcases here are expected to represent invalid URLs.
411*6777b538SAndroid Build Coastguard Worker     // an invalid URL (because of a type in scheme name, or because of a
412*6777b538SAndroid Build Coastguard Worker     // technicality like having no host in a noaccess-std-with-host: scheme).
413*6777b538SAndroid Build Coastguard Worker     EXPECT_FALSE(this->IsValidUrl(test_input));
414*6777b538SAndroid Build Coastguard Worker 
415*6777b538SAndroid Build Coastguard Worker     // Invalid URLs should always result in an opaque origin.
416*6777b538SAndroid Build Coastguard Worker     this->TestUniqueOpaqueOrigin(test_input);
417*6777b538SAndroid Build Coastguard Worker   }
418*6777b538SAndroid Build Coastguard Worker }
419*6777b538SAndroid Build Coastguard Worker 
TYPED_TEST_P(AbstractOriginTest,TupleOrigins)420*6777b538SAndroid Build Coastguard Worker TYPED_TEST_P(AbstractOriginTest, TupleOrigins) {
421*6777b538SAndroid Build Coastguard Worker   struct TestCase {
422*6777b538SAndroid Build Coastguard Worker     const char* input;
423*6777b538SAndroid Build Coastguard Worker     SchemeHostPort expected_tuple;
424*6777b538SAndroid Build Coastguard Worker   } kTestCases[] = {
425*6777b538SAndroid Build Coastguard Worker       // file: URLs
426*6777b538SAndroid Build Coastguard Worker       {"file:///etc/passwd", {"file", "", 0}},
427*6777b538SAndroid Build Coastguard Worker       {"file://example.com/etc/passwd", {"file", "example.com", 0}},
428*6777b538SAndroid Build Coastguard Worker       {"file:///", {"file", "", 0}},
429*6777b538SAndroid Build Coastguard Worker       {"file://hostname/C:/dir/file.txt", {"file", "hostname", 0}},
430*6777b538SAndroid Build Coastguard Worker 
431*6777b538SAndroid Build Coastguard Worker       // HTTP URLs
432*6777b538SAndroid Build Coastguard Worker       {"http://example.com/", {"http", "example.com", 80}},
433*6777b538SAndroid Build Coastguard Worker       {"http://example.com:80/", {"http", "example.com", 80}},
434*6777b538SAndroid Build Coastguard Worker       {"http://example.com:123/", {"http", "example.com", 123}},
435*6777b538SAndroid Build Coastguard Worker       {"http://example.com:0/", {"http", "example.com", 0}},
436*6777b538SAndroid Build Coastguard Worker       {"http://example.com:65535/", {"http", "example.com", 65535}},
437*6777b538SAndroid Build Coastguard Worker       {"https://example.com/", {"https", "example.com", 443}},
438*6777b538SAndroid Build Coastguard Worker       {"https://example.com:443/", {"https", "example.com", 443}},
439*6777b538SAndroid Build Coastguard Worker       {"https://example.com:123/", {"https", "example.com", 123}},
440*6777b538SAndroid Build Coastguard Worker       {"https://example.com:0/", {"https", "example.com", 0}},
441*6777b538SAndroid Build Coastguard Worker       {"https://example.com:65535/", {"https", "example.com", 65535}},
442*6777b538SAndroid Build Coastguard Worker       {"http://user:[email protected]/", {"http", "example.com", 80}},
443*6777b538SAndroid Build Coastguard Worker       {"http://example.com:123/?query", {"http", "example.com", 123}},
444*6777b538SAndroid Build Coastguard Worker       {"https://example.com/#1234", {"https", "example.com", 443}},
445*6777b538SAndroid Build Coastguard Worker       {"https://u:[email protected]:123/?query#1234",
446*6777b538SAndroid Build Coastguard Worker        {"https", "example.com", 123}},
447*6777b538SAndroid Build Coastguard Worker       {"http://example/", {"http", "example", 80}},
448*6777b538SAndroid Build Coastguard Worker 
449*6777b538SAndroid Build Coastguard Worker       // Blob URLs.
450*6777b538SAndroid Build Coastguard Worker       {"blob:http://example.com/guid-goes-here", {"http", "example.com", 80}},
451*6777b538SAndroid Build Coastguard Worker       {"blob:http://example.com:123/guid-goes-here",
452*6777b538SAndroid Build Coastguard Worker        {"http", "example.com", 123}},
453*6777b538SAndroid Build Coastguard Worker       {"blob:https://example.com/guid-goes-here",
454*6777b538SAndroid Build Coastguard Worker        {"https", "example.com", 443}},
455*6777b538SAndroid Build Coastguard Worker       {"blob:http://u:[email protected]/guid-goes-here",
456*6777b538SAndroid Build Coastguard Worker        {"http", "example.com", 80}},
457*6777b538SAndroid Build Coastguard Worker 
458*6777b538SAndroid Build Coastguard Worker       // Filesystem URLs.
459*6777b538SAndroid Build Coastguard Worker       {"filesystem:http://example.com/type/", {"http", "example.com", 80}},
460*6777b538SAndroid Build Coastguard Worker       {"filesystem:http://example.com:123/type/", {"http", "example.com", 123}},
461*6777b538SAndroid Build Coastguard Worker       {"filesystem:https://example.com/type/", {"https", "example.com", 443}},
462*6777b538SAndroid Build Coastguard Worker       {"filesystem:https://example.com:123/type/",
463*6777b538SAndroid Build Coastguard Worker        {"https", "example.com", 123}},
464*6777b538SAndroid Build Coastguard Worker       {"filesystem:local-std-with-host:baz./type/",
465*6777b538SAndroid Build Coastguard Worker        {"local-std-with-host", "baz.", 0}},
466*6777b538SAndroid Build Coastguard Worker 
467*6777b538SAndroid Build Coastguard Worker       // IP Addresses
468*6777b538SAndroid Build Coastguard Worker       {"http://192.168.9.1/", {"http", "192.168.9.1", 80}},
469*6777b538SAndroid Build Coastguard Worker       {"http://[2001:db8::1]/", {"http", "[2001:db8::1]", 80}},
470*6777b538SAndroid Build Coastguard Worker       {"http://[2001:0db8:0000:0000:0000:0000:0000:0001]/",
471*6777b538SAndroid Build Coastguard Worker        {"http", "[2001:db8::1]", 80}},
472*6777b538SAndroid Build Coastguard Worker       {"http://1/", {"http", "0.0.0.1", 80}},
473*6777b538SAndroid Build Coastguard Worker       {"http://1:1/", {"http", "0.0.0.1", 1}},
474*6777b538SAndroid Build Coastguard Worker       {"http://3232237825/", {"http", "192.168.9.1", 80}},
475*6777b538SAndroid Build Coastguard Worker 
476*6777b538SAndroid Build Coastguard Worker       // Punycode
477*6777b538SAndroid Build Coastguard Worker       {"http://☃.net/", {"http", "xn--n3h.net", 80}},
478*6777b538SAndroid Build Coastguard Worker       {"blob:http://☃.net/", {"http", "xn--n3h.net", 80}},
479*6777b538SAndroid Build Coastguard Worker       {"local-std-with-host:↑↑↓↓←→←→ba.↑↑↓↓←→←→ba.0.bg",
480*6777b538SAndroid Build Coastguard Worker        {"local-std-with-host", "xn--ba-rzuadaibfa.xn--ba-rzuadaibfa.0.bg", 0}},
481*6777b538SAndroid Build Coastguard Worker 
482*6777b538SAndroid Build Coastguard Worker       // Registered URLs
483*6777b538SAndroid Build Coastguard Worker       {"ftp://example.com/", {"ftp", "example.com", 21}},
484*6777b538SAndroid Build Coastguard Worker       {"ws://example.com/", {"ws", "example.com", 80}},
485*6777b538SAndroid Build Coastguard Worker       {"wss://example.com/", {"wss", "example.com", 443}},
486*6777b538SAndroid Build Coastguard Worker       {"wss://user:[email protected]/", {"wss", "example.com", 443}},
487*6777b538SAndroid Build Coastguard Worker   };
488*6777b538SAndroid Build Coastguard Worker 
489*6777b538SAndroid Build Coastguard Worker   for (const TestCase& test : kTestCases) {
490*6777b538SAndroid Build Coastguard Worker     SCOPED_TRACE(testing::Message() << "Test input: " << test.input);
491*6777b538SAndroid Build Coastguard Worker 
492*6777b538SAndroid Build Coastguard Worker     // Only valid URLs should translate into valid, non-opaque origins.
493*6777b538SAndroid Build Coastguard Worker     EXPECT_TRUE(this->IsValidUrl(test.input));
494*6777b538SAndroid Build Coastguard Worker 
495*6777b538SAndroid Build Coastguard Worker     auto origin = this->CreateOriginFromString(test.input);
496*6777b538SAndroid Build Coastguard Worker     this->VerifyTupleOriginInvariants(origin, test.expected_tuple);
497*6777b538SAndroid Build Coastguard Worker   }
498*6777b538SAndroid Build Coastguard Worker }
499*6777b538SAndroid Build Coastguard Worker 
TYPED_TEST_P(AbstractOriginTest,CustomSchemes_OpaqueOrigins)500*6777b538SAndroid Build Coastguard Worker TYPED_TEST_P(AbstractOriginTest, CustomSchemes_OpaqueOrigins) {
501*6777b538SAndroid Build Coastguard Worker   const char* kTestCases[] = {
502*6777b538SAndroid Build Coastguard Worker       // Unknown scheme
503*6777b538SAndroid Build Coastguard Worker       "unknown-scheme:foo",
504*6777b538SAndroid Build Coastguard Worker       "unknown-scheme://bar",
505*6777b538SAndroid Build Coastguard Worker 
506*6777b538SAndroid Build Coastguard Worker       // Unknown scheme that is a prefix or suffix of a registered scheme.
507*6777b538SAndroid Build Coastguard Worker       "loca:foo",
508*6777b538SAndroid Build Coastguard Worker       "ocal:foo",
509*6777b538SAndroid Build Coastguard Worker       "local-suffix:foo",
510*6777b538SAndroid Build Coastguard Worker       "prefix-local:foo",
511*6777b538SAndroid Build Coastguard Worker 
512*6777b538SAndroid Build Coastguard Worker       // Custom no-access schemes translate into an opaque origin (just like the
513*6777b538SAndroid Build Coastguard Worker       // built-in no-access schemes such as about:blank or data:).
514*6777b538SAndroid Build Coastguard Worker       "noaccess-std-with-host:foo",
515*6777b538SAndroid Build Coastguard Worker       "noaccess-std-with-host://bar",
516*6777b538SAndroid Build Coastguard Worker       "noaccess://host",
517*6777b538SAndroid Build Coastguard Worker       "local-noaccess://host",
518*6777b538SAndroid Build Coastguard Worker       "local-noaccess-std-with-host://host",
519*6777b538SAndroid Build Coastguard Worker   };
520*6777b538SAndroid Build Coastguard Worker 
521*6777b538SAndroid Build Coastguard Worker   for (const char* test_input : kTestCases) {
522*6777b538SAndroid Build Coastguard Worker     SCOPED_TRACE(testing::Message() << "Test input: " << test_input);
523*6777b538SAndroid Build Coastguard Worker 
524*6777b538SAndroid Build Coastguard Worker     // Verify that `origin` is opaque not just because `test_input` results is
525*6777b538SAndroid Build Coastguard Worker     // an invalid URL (because of a typo in the scheme name, or because of a
526*6777b538SAndroid Build Coastguard Worker     // technicality like having no host in a noaccess-std-with-host: scheme).
527*6777b538SAndroid Build Coastguard Worker     EXPECT_TRUE(this->IsValidUrl(test_input));
528*6777b538SAndroid Build Coastguard Worker 
529*6777b538SAndroid Build Coastguard Worker     this->TestUniqueOpaqueOrigin(test_input);
530*6777b538SAndroid Build Coastguard Worker   }
531*6777b538SAndroid Build Coastguard Worker }
532*6777b538SAndroid Build Coastguard Worker 
TYPED_TEST_P(AbstractOriginTest,CustomSchemes_TupleOrigins)533*6777b538SAndroid Build Coastguard Worker TYPED_TEST_P(AbstractOriginTest, CustomSchemes_TupleOrigins) {
534*6777b538SAndroid Build Coastguard Worker   struct TestCase {
535*6777b538SAndroid Build Coastguard Worker     const char* input;
536*6777b538SAndroid Build Coastguard Worker     SchemeHostPort expected_tuple;
537*6777b538SAndroid Build Coastguard Worker   } kTestCases[] = {
538*6777b538SAndroid Build Coastguard Worker       // Scheme (registered in SetUp()) that's both local and standard.
539*6777b538SAndroid Build Coastguard Worker       // TODO: Is it really appropriate to do network-host canonicalization of
540*6777b538SAndroid Build Coastguard Worker       // schemes without ports?
541*6777b538SAndroid Build Coastguard Worker       {"local-std-with-host:20", {"local-std-with-host", "0.0.0.20", 0}},
542*6777b538SAndroid Build Coastguard Worker       {"local-std-with-host:20.", {"local-std-with-host", "0.0.0.20", 0}},
543*6777b538SAndroid Build Coastguard Worker       {"local-std-with-host:foo", {"local-std-with-host", "foo", 0}},
544*6777b538SAndroid Build Coastguard Worker       {"local-std-with-host://bar:20", {"local-std-with-host", "bar", 0}},
545*6777b538SAndroid Build Coastguard Worker       {"local-std-with-host:baz.", {"local-std-with-host", "baz.", 0}},
546*6777b538SAndroid Build Coastguard Worker       {"local-std-with-host:baz..", {"local-std-with-host", "baz..", 0}},
547*6777b538SAndroid Build Coastguard Worker       {"local-std-with-host:baz..bar", {"local-std-with-host", "baz..bar", 0}},
548*6777b538SAndroid Build Coastguard Worker       {"local-std-with-host:baz...", {"local-std-with-host", "baz...", 0}},
549*6777b538SAndroid Build Coastguard Worker 
550*6777b538SAndroid Build Coastguard Worker       // Scheme (registered in SetUp()) that's local but nonstandard. These
551*6777b538SAndroid Build Coastguard Worker       // always have empty hostnames, but are allowed to be url::Origins.
552*6777b538SAndroid Build Coastguard Worker       {"local:", {"local", "", 0}},
553*6777b538SAndroid Build Coastguard Worker       {"local:foo", {"local", "", 0}},
554*6777b538SAndroid Build Coastguard Worker 
555*6777b538SAndroid Build Coastguard Worker       {"std-with-host://host", {"std-with-host", "host", 0}},
556*6777b538SAndroid Build Coastguard Worker       {"local-std-with-host://host", {"local-std-with-host", "host", 0}},
557*6777b538SAndroid Build Coastguard Worker   };
558*6777b538SAndroid Build Coastguard Worker 
559*6777b538SAndroid Build Coastguard Worker   for (const TestCase& test : kTestCases) {
560*6777b538SAndroid Build Coastguard Worker     SCOPED_TRACE(testing::Message() << "Test input: " << test.input);
561*6777b538SAndroid Build Coastguard Worker 
562*6777b538SAndroid Build Coastguard Worker     // Only valid URLs should translate into valid, non-opaque origins.
563*6777b538SAndroid Build Coastguard Worker     EXPECT_TRUE(this->IsValidUrl(test.input));
564*6777b538SAndroid Build Coastguard Worker 
565*6777b538SAndroid Build Coastguard Worker     auto origin = this->CreateOriginFromString(test.input);
566*6777b538SAndroid Build Coastguard Worker     this->VerifyTupleOriginInvariants(origin, test.expected_tuple);
567*6777b538SAndroid Build Coastguard Worker   }
568*6777b538SAndroid Build Coastguard Worker }
569*6777b538SAndroid Build Coastguard Worker 
TYPED_TEST_P(AbstractOriginTest,CustomSchemes_TupleOrigins_StandardCompliantNonSpecialSchemeFlag)570*6777b538SAndroid Build Coastguard Worker TYPED_TEST_P(AbstractOriginTest,
571*6777b538SAndroid Build Coastguard Worker              CustomSchemes_TupleOrigins_StandardCompliantNonSpecialSchemeFlag) {
572*6777b538SAndroid Build Coastguard Worker   // Manual flag-dependent tests.
573*6777b538SAndroid Build Coastguard Worker   //
574*6777b538SAndroid Build Coastguard Worker   // See AbstractOriginTest/CustomSchemes_TupleOrigins, which covers common
575*6777b538SAndroid Build Coastguard Worker   // test cases.
576*6777b538SAndroid Build Coastguard Worker   for (bool flag : {false, true}) {
577*6777b538SAndroid Build Coastguard Worker     // Note: The feature must be set before we construct test cases because
578*6777b538SAndroid Build Coastguard Worker     // SchemeHostPort's constructor changes its behavior.
579*6777b538SAndroid Build Coastguard Worker     base::test::ScopedFeatureList scoped_feature_list;
580*6777b538SAndroid Build Coastguard Worker     if (flag) {
581*6777b538SAndroid Build Coastguard Worker       scoped_feature_list.InitAndEnableFeature(
582*6777b538SAndroid Build Coastguard Worker           kStandardCompliantNonSpecialSchemeURLParsing);
583*6777b538SAndroid Build Coastguard Worker     } else {
584*6777b538SAndroid Build Coastguard Worker       scoped_feature_list.InitAndDisableFeature(
585*6777b538SAndroid Build Coastguard Worker           kStandardCompliantNonSpecialSchemeURLParsing);
586*6777b538SAndroid Build Coastguard Worker     }
587*6777b538SAndroid Build Coastguard Worker 
588*6777b538SAndroid Build Coastguard Worker     struct TestCase {
589*6777b538SAndroid Build Coastguard Worker       std::string_view input;
590*6777b538SAndroid Build Coastguard Worker       SchemeHostPort expected_tuple_when_standard_compliant_flag_off;
591*6777b538SAndroid Build Coastguard Worker       SchemeHostPort expected_tuple_when_standard_compliant_flag_on;
592*6777b538SAndroid Build Coastguard Worker     } test_cases[] = {
593*6777b538SAndroid Build Coastguard Worker         {"local://bar", {"local", "", 0}, {"local", "bar", 0}},
594*6777b538SAndroid Build Coastguard Worker         {"also-local://bar", {"also-local", "", 0}, {"also-local", "bar", 0}},
595*6777b538SAndroid Build Coastguard Worker     };
596*6777b538SAndroid Build Coastguard Worker     for (const TestCase& test : test_cases) {
597*6777b538SAndroid Build Coastguard Worker       SCOPED_TRACE(testing::Message() << "Test input: " << test.input);
598*6777b538SAndroid Build Coastguard Worker       EXPECT_TRUE(this->IsValidUrl(test.input));
599*6777b538SAndroid Build Coastguard Worker       auto origin = this->CreateOriginFromString(test.input);
600*6777b538SAndroid Build Coastguard Worker       this->VerifyTupleOriginInvariants(
601*6777b538SAndroid Build Coastguard Worker           origin, flag ? test.expected_tuple_when_standard_compliant_flag_on
602*6777b538SAndroid Build Coastguard Worker                        : test.expected_tuple_when_standard_compliant_flag_off);
603*6777b538SAndroid Build Coastguard Worker     }
604*6777b538SAndroid Build Coastguard Worker   }
605*6777b538SAndroid Build Coastguard Worker }
606*6777b538SAndroid Build Coastguard Worker 
607*6777b538SAndroid Build Coastguard Worker REGISTER_TYPED_TEST_SUITE_P(
608*6777b538SAndroid Build Coastguard Worker     AbstractOriginTest,
609*6777b538SAndroid Build Coastguard Worker     NonStandardSchemeWithAndroidWebViewHack,
610*6777b538SAndroid Build Coastguard Worker     AndroidWebViewHackWithStandardCompliantNonSpecialSchemeURLParsing,
611*6777b538SAndroid Build Coastguard Worker     OpaqueOriginsFromValidUrls,
612*6777b538SAndroid Build Coastguard Worker     OpaqueOriginsFromInvalidUrls,
613*6777b538SAndroid Build Coastguard Worker     TupleOrigins,
614*6777b538SAndroid Build Coastguard Worker     CustomSchemes_OpaqueOrigins,
615*6777b538SAndroid Build Coastguard Worker     CustomSchemes_TupleOrigins,
616*6777b538SAndroid Build Coastguard Worker     CustomSchemes_TupleOrigins_StandardCompliantNonSpecialSchemeFlag);
617*6777b538SAndroid Build Coastguard Worker 
618*6777b538SAndroid Build Coastguard Worker }  // namespace url
619*6777b538SAndroid Build Coastguard Worker 
620*6777b538SAndroid Build Coastguard Worker #endif  // URL_ORIGIN_ABSTRACT_TESTS_H_
621