xref: /aosp_15_r20/external/cronet/url/mojom/url_gurl_mojom_traits_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2016 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <utility>
6 
7 #include "base/test/task_environment.h"
8 #include "mojo/public/cpp/bindings/pending_receiver.h"
9 #include "mojo/public/cpp/bindings/receiver.h"
10 #include "mojo/public/cpp/bindings/remote.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "url/mojom/url_test.mojom.h"
13 
14 namespace url {
15 
16 class UrlTestImpl : public mojom::UrlTest {
17  public:
UrlTestImpl(mojo::PendingReceiver<mojom::UrlTest> receiver)18   explicit UrlTestImpl(mojo::PendingReceiver<mojom::UrlTest> receiver)
19       : receiver_(this, std::move(receiver)) {}
20 
21   // UrlTest:
BounceUrl(const GURL & in,BounceUrlCallback callback)22   void BounceUrl(const GURL& in, BounceUrlCallback callback) override {
23     std::move(callback).Run(in);
24   }
25 
BounceOrigin(const Origin & in,BounceOriginCallback callback)26   void BounceOrigin(const Origin& in, BounceOriginCallback callback) override {
27     std::move(callback).Run(in);
28   }
29 
30  private:
31   mojo::Receiver<UrlTest> receiver_;
32 };
33 
34 class MojoGURLStructTraitsTest : public ::testing::Test {
35  public:
MojoGURLStructTraitsTest()36   MojoGURLStructTraitsTest()
37       : url_test_impl_(url_test_remote_.BindNewPipeAndPassReceiver()) {}
38 
BounceUrl(const GURL & input)39   GURL BounceUrl(const GURL& input) {
40     GURL output;
41     EXPECT_TRUE(url_test_remote_->BounceUrl(input, &output));
42     return output;
43   }
44 
ExpectSerializationRoundtrips(const GURL & input)45   void ExpectSerializationRoundtrips(const GURL& input) {
46     SCOPED_TRACE(testing::Message()
47                  << "Input GURL: " << input.possibly_invalid_spec());
48     GURL output = BounceUrl(input);
49 
50     // We want to test each component individually to make sure its range was
51     // correctly serialized and deserialized, not just the spec.
52     EXPECT_EQ(input.possibly_invalid_spec(), output.possibly_invalid_spec());
53     EXPECT_EQ(input.is_valid(), output.is_valid());
54     EXPECT_EQ(input.scheme(), output.scheme());
55     EXPECT_EQ(input.username(), output.username());
56     EXPECT_EQ(input.password(), output.password());
57     EXPECT_EQ(input.host(), output.host());
58     EXPECT_EQ(input.port(), output.port());
59     EXPECT_EQ(input.path(), output.path());
60     EXPECT_EQ(input.query(), output.query());
61     EXPECT_EQ(input.ref(), output.ref());
62   }
63 
BounceOrigin(const Origin & input)64   Origin BounceOrigin(const Origin& input) {
65     Origin output;
66     EXPECT_TRUE(url_test_remote_->BounceOrigin(input, &output));
67     return output;
68   }
69 
70  private:
71   base::test::SingleThreadTaskEnvironment task_environment;
72   mojo::Remote<mojom::UrlTest> url_test_remote_;
73   UrlTestImpl url_test_impl_;
74 };
75 
76 // Mojo version of chrome IPC test in url/ipc/url_param_traits_unittest.cc.
TEST_F(MojoGURLStructTraitsTest,Basic)77 TEST_F(MojoGURLStructTraitsTest, Basic) {
78   const char* serialize_cases[] = {
79       "http://www.google.com/",
80       "http://user:[email protected]:888/foo;bar?baz#nop",
81   };
82 
83   for (const char* test_input : serialize_cases) {
84     SCOPED_TRACE(testing::Message() << "Test input: " << test_input);
85     GURL input(test_input);
86     ExpectSerializationRoundtrips(input);
87   }
88 }
89 
90 // Test of an excessively long GURL.
TEST_F(MojoGURLStructTraitsTest,ExcessivelyLongUrl)91 TEST_F(MojoGURLStructTraitsTest, ExcessivelyLongUrl) {
92   const std::string url =
93       std::string("http://example.org/").append(kMaxURLChars + 1, 'a');
94   GURL input(url.c_str());
95   GURL output = BounceUrl(input);
96   EXPECT_TRUE(output.is_empty());
97 }
98 
99 // Test for the GURL testcase based on https://crbug.com/1214098 (which in turn
100 // was based on ContentSecurityPolicyBrowserTest.FileURLs).
TEST_F(MojoGURLStructTraitsTest,WindowsDriveInPathReplacement)101 TEST_F(MojoGURLStructTraitsTest, WindowsDriveInPathReplacement) {
102   {
103     // #1: Try creating a file URL with a non-empty hostname.
104     GURL url_without_windows_drive_letter("file://hostname/");
105     EXPECT_EQ("/", url_without_windows_drive_letter.path());
106     EXPECT_EQ("hostname", url_without_windows_drive_letter.host());
107     ExpectSerializationRoundtrips(url_without_windows_drive_letter);
108   }
109 
110   {
111     // #2: Use GURL::Replacement to create a GURL with 1) a path that starts
112     // with a Windows drive letter and 2) has a non-empty hostname (inherited
113     // from `url_without_windows_drive_letter` above). This used to not go
114     // through the DoParseUNC path that normally strips the hostname (for more
115     // details, see https://crbug.com/1214098#c4).
116     GURL::Replacements repl;
117     const std::string kNewPath = "/C:/dir/file.txt";
118     repl.SetPathStr(kNewPath);
119     GURL url_made_with_replace_components =
120         GURL("file://hostname/").ReplaceComponents(repl);
121 
122     EXPECT_EQ(kNewPath, url_made_with_replace_components.path());
123     EXPECT_EQ("hostname", url_made_with_replace_components.host());
124     EXPECT_EQ("file://hostname/C:/dir/file.txt",
125               url_made_with_replace_components.spec());
126     // This is the MAIN VERIFICATION in this test. This used to fail on Windows,
127     // see https://crbug.com/1214098.
128     ExpectSerializationRoundtrips(url_made_with_replace_components);
129   }
130 
131   {
132     // #3: Try to create a URL with a Windows drive letter and a non-empty
133     // hostname directly.
134     GURL url_created_directly("file://hostname/C:/dir/file.txt");
135     EXPECT_EQ("/C:/dir/file.txt", url_created_directly.path());
136     EXPECT_EQ("hostname", url_created_directly.host());
137     EXPECT_EQ("file://hostname/C:/dir/file.txt", url_created_directly.spec());
138     ExpectSerializationRoundtrips(url_created_directly);
139 
140     // The URL created directly and the URL created through ReplaceComponents
141     // should be the same.
142     GURL::Replacements repl;
143     const std::string kNewPath = "/C:/dir/file.txt";
144     repl.SetPathStr(kNewPath);
145     GURL url_made_with_replace_components =
146         GURL("file://hostname/").ReplaceComponents(repl);
147     EXPECT_EQ(url_created_directly.spec(),
148               url_made_with_replace_components.spec());
149   }
150 
151   {
152     // #4: Try to create a URL with a Windows drive letter and "localhost" as
153     // hostname directly.
154     GURL url_created_directly("file://localhost/C:/dir/file.txt");
155     EXPECT_EQ("/C:/dir/file.txt", url_created_directly.path());
156     EXPECT_EQ("", url_created_directly.host());
157     EXPECT_EQ("file:///C:/dir/file.txt", url_created_directly.spec());
158     ExpectSerializationRoundtrips(url_created_directly);
159 
160     // The URL created directly and the URL created through ReplaceComponents
161     // should be the same.
162     GURL::Replacements repl;
163     const std::string kNewPath = "/C:/dir/file.txt";
164     repl.SetPathStr(kNewPath);
165     GURL url_made_with_replace_components =
166         GURL("file://localhost/").ReplaceComponents(repl);
167     EXPECT_EQ(url_created_directly.spec(),
168               url_made_with_replace_components.spec());
169   }
170 }
171 
172 // Test of basic Origin serialization.
TEST_F(MojoGURLStructTraitsTest,OriginSerialization)173 TEST_F(MojoGURLStructTraitsTest, OriginSerialization) {
174   Origin non_unique = Origin::UnsafelyCreateTupleOriginWithoutNormalization(
175                           "http", "www.google.com", 80)
176                           .value();
177   Origin output = BounceOrigin(non_unique);
178   EXPECT_EQ(non_unique, output);
179   EXPECT_FALSE(output.opaque());
180 
181   Origin unique1;
182   Origin unique2 = non_unique.DeriveNewOpaqueOrigin();
183   EXPECT_NE(unique1, unique2);
184   EXPECT_NE(unique2, unique1);
185   EXPECT_NE(unique2, non_unique);
186   output = BounceOrigin(unique1);
187   EXPECT_TRUE(output.opaque());
188   EXPECT_EQ(unique1, output);
189   Origin output2 = BounceOrigin(unique2);
190   EXPECT_EQ(unique2, output2);
191   EXPECT_NE(unique2, output);
192   EXPECT_NE(unique1, output2);
193 
194   Origin normalized =
195       Origin::CreateFromNormalizedTuple("http", "www.google.com", 80);
196   EXPECT_EQ(normalized, non_unique);
197   output = BounceOrigin(normalized);
198   EXPECT_EQ(normalized, output);
199   EXPECT_EQ(non_unique, output);
200   EXPECT_FALSE(output.opaque());
201 }
202 
203 // Test that the "kMaxURLChars" values are the same in url.mojom and
204 // url_constants.cc.
TEST_F(MojoGURLStructTraitsTest,TestMaxURLChars)205 TEST_F(MojoGURLStructTraitsTest, TestMaxURLChars) {
206   EXPECT_EQ(kMaxURLChars, mojom::kMaxURLChars);
207 }
208 
209 }  // namespace url
210