xref: /aosp_15_r20/external/cronet/url/ipc/url_param_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 <string>
6 
7 #include "ipc/ipc_message.h"
8 #include "ipc/ipc_message_utils.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10 #include "url/gurl.h"
11 #include "url/ipc/url_param_traits.h"
12 
13 namespace {
14 
BounceUrl(const GURL & input)15 GURL BounceUrl(const GURL& input) {
16   IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL);
17   IPC::ParamTraits<GURL>::Write(&msg, input);
18 
19   GURL output;
20   base::PickleIterator iter(msg);
21   EXPECT_TRUE(IPC::ParamTraits<GURL>::Read(&msg, &iter, &output));
22 
23   return output;
24 }
25 
ExpectSerializationRoundtrips(const GURL & input)26 void ExpectSerializationRoundtrips(const GURL& input) {
27   SCOPED_TRACE(testing::Message()
28                << "Input GURL: " << input.possibly_invalid_spec());
29   GURL output = BounceUrl(input);
30 
31   // We want to test each component individually to make sure its range was
32   // correctly serialized and deserialized, not just the spec.
33   EXPECT_EQ(input.possibly_invalid_spec(), output.possibly_invalid_spec());
34   EXPECT_EQ(input.is_valid(), output.is_valid());
35   EXPECT_EQ(input.scheme(), output.scheme());
36   EXPECT_EQ(input.username(), output.username());
37   EXPECT_EQ(input.password(), output.password());
38   EXPECT_EQ(input.host(), output.host());
39   EXPECT_EQ(input.port(), output.port());
40   EXPECT_EQ(input.path(), output.path());
41   EXPECT_EQ(input.query(), output.query());
42   EXPECT_EQ(input.ref(), output.ref());
43 }
44 
45 }  // namespace
46 
47 // Tests that serialize/deserialize correctly understand each other.
TEST(IPCMessageTest,SerializeGurl_Basic)48 TEST(IPCMessageTest, SerializeGurl_Basic) {
49   const char* serialize_cases[] = {
50     "http://www.google.com/",
51     "http://user:[email protected]:888/foo;bar?baz#nop",
52   };
53 
54   for (const char* test_input : serialize_cases) {
55     SCOPED_TRACE(testing::Message() << "Test input: " << test_input);
56     GURL input(test_input);
57     ExpectSerializationRoundtrips(input);
58   }
59 }
60 
61 // Test of an excessively long GURL.
TEST(IPCMessageTest,SerializeGurl_ExcessivelyLong)62 TEST(IPCMessageTest, SerializeGurl_ExcessivelyLong) {
63   const std::string url =
64       std::string("http://example.org/").append(url::kMaxURLChars + 1, 'a');
65   GURL input(url.c_str());
66   GURL output = BounceUrl(input);
67   EXPECT_TRUE(output.is_empty());
68 }
69 
70 // Test of an invalid GURL.
TEST(IPCMessageTest,SerializeGurl_InvalidUrl)71 TEST(IPCMessageTest, SerializeGurl_InvalidUrl) {
72   IPC::Message msg;
73   msg.WriteString("#inva://idurl/");
74   GURL output;
75   base::PickleIterator iter(msg);
76   EXPECT_FALSE(IPC::ParamTraits<GURL>::Read(&msg, &iter, &output));
77 }
78 
79 // Test of a corrupt deserialization input.
TEST(IPCMessageTest,SerializeGurl_CorruptPayload)80 TEST(IPCMessageTest, SerializeGurl_CorruptPayload) {
81   IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL);
82   msg.WriteInt(99);
83   GURL output;
84   base::PickleIterator iter(msg);
85   EXPECT_FALSE(IPC::ParamTraits<GURL>::Read(&msg, &iter, &output));
86 }
87 
88 // Test for the GURL testcase based on https://crbug.com/1214098 (which in turn
89 // was based on ContentSecurityPolicyBrowserTest.FileURLs).
TEST(IPCMessageTest,SerializeGurl_WindowsDriveInPathReplacement)90 TEST(IPCMessageTest, SerializeGurl_WindowsDriveInPathReplacement) {
91   {
92     // #1: Try creating a file URL with a non-empty hostname.
93     GURL url_without_windows_drive_letter("file://hostname/");
94     EXPECT_EQ("/", url_without_windows_drive_letter.path());
95     EXPECT_EQ("hostname", url_without_windows_drive_letter.host());
96     ExpectSerializationRoundtrips(url_without_windows_drive_letter);
97   }
98 
99   {
100     // #2: Use GURL::Replacement to create a GURL with 1) a path that starts
101     // with a Windows drive letter and 2) has a non-empty hostname (inherited
102     // from `url_without_windows_drive_letter` above). This used to not go
103     // through the DoParseUNC path that normally strips the hostname (for more
104     // details, see https://crbug.com/1214098#c4).
105     GURL::Replacements repl;
106     const std::string kNewPath = "/C:/dir/file.txt";
107     repl.SetPathStr(kNewPath);
108     GURL url_made_with_replace_components =
109         GURL("file://hostname/").ReplaceComponents(repl);
110 
111     EXPECT_EQ(kNewPath, url_made_with_replace_components.path());
112     EXPECT_EQ("hostname", url_made_with_replace_components.host());
113     EXPECT_EQ("file://hostname/C:/dir/file.txt",
114               url_made_with_replace_components.spec());
115     // This is the MAIN VERIFICATION in this test. This used to fail on Windows,
116     // see https://crbug.com/1214098.
117     ExpectSerializationRoundtrips(url_made_with_replace_components);
118   }
119 
120   {
121     // #3: Try to create a URL with a Windows drive letter and a non-empty
122     // hostname directly.
123     GURL url_created_directly("file://hostname/C:/dir/file.txt");
124     EXPECT_EQ("/C:/dir/file.txt", url_created_directly.path());
125     EXPECT_EQ("hostname", url_created_directly.host());
126     EXPECT_EQ("file://hostname/C:/dir/file.txt", url_created_directly.spec());
127     ExpectSerializationRoundtrips(url_created_directly);
128 
129     // The URL created directly and the URL created through ReplaceComponents
130     // should be the same.
131     GURL::Replacements repl;
132     const std::string kNewPath = "/C:/dir/file.txt";
133     repl.SetPathStr(kNewPath);
134     GURL url_made_with_replace_components =
135         GURL("file://hostname/").ReplaceComponents(repl);
136     EXPECT_EQ(url_created_directly.spec(),
137               url_made_with_replace_components.spec());
138   }
139 
140   {
141     // #4: Try to create a URL with a Windows drive letter and "localhost" as
142     // hostname directly.
143     GURL url_created_directly("file://localhost/C:/dir/file.txt");
144     EXPECT_EQ("/C:/dir/file.txt", url_created_directly.path());
145     EXPECT_EQ("", url_created_directly.host());
146     EXPECT_EQ("file:///C:/dir/file.txt", url_created_directly.spec());
147     ExpectSerializationRoundtrips(url_created_directly);
148 
149     // The URL created directly and the URL created through ReplaceComponents
150     // should be the same.
151     GURL::Replacements repl;
152     const std::string kNewPath = "/C:/dir/file.txt";
153     repl.SetPathStr(kNewPath);
154     GURL url_made_with_replace_components =
155         GURL("file://localhost/").ReplaceComponents(repl);
156     EXPECT_EQ(url_created_directly.spec(),
157               url_made_with_replace_components.spec());
158   }
159 }
160