OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "headless/public/util/generic_url_request_job.h" | 5 #include "headless/public/util/generic_url_request_job.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 #include <string> | 8 #include <string> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
11 #include "base/json/json_reader.h" | 11 #include "base/json/json_reader.h" |
12 #include "base/json/json_writer.h" | 12 #include "base/json/json_writer.h" |
13 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" |
14 #include "base/run_loop.h" | 14 #include "base/run_loop.h" |
15 #include "base/single_thread_task_runner.h" | 15 #include "base/single_thread_task_runner.h" |
16 #include "base/strings/stringprintf.h" | 16 #include "base/strings/stringprintf.h" |
17 #include "base/values.h" | 17 #include "base/values.h" |
18 #include "headless/public/util/expedited_dispatcher.h" | 18 #include "headless/public/util/expedited_dispatcher.h" |
19 #include "headless/public/util/testing/generic_url_request_mocks.h" | 19 #include "headless/public/util/testing/generic_url_request_mocks.h" |
20 #include "headless/public/util/url_fetcher.h" | 20 #include "headless/public/util/url_fetcher.h" |
| 21 #include "net/base/elements_upload_data_stream.h" |
| 22 #include "net/base/upload_bytes_element_reader.h" |
21 #include "net/http/http_response_headers.h" | 23 #include "net/http/http_response_headers.h" |
22 #include "net/url_request/url_request_job_factory_impl.h" | 24 #include "net/url_request/url_request_job_factory_impl.h" |
23 #include "testing/gmock/include/gmock/gmock.h" | 25 #include "testing/gmock/include/gmock/gmock.h" |
24 #include "testing/gtest/include/gtest/gtest.h" | 26 #include "testing/gtest/include/gtest/gtest.h" |
25 | 27 |
| 28 using testing::_; |
| 29 |
26 std::ostream& operator<<(std::ostream& os, const base::Value& value) { | 30 std::ostream& operator<<(std::ostream& os, const base::Value& value) { |
27 std::string json; | 31 std::string json; |
28 base::JSONWriter::WriteWithOptions( | 32 base::JSONWriter::WriteWithOptions( |
29 value, base::JSONWriter::OPTIONS_PRETTY_PRINT, &json); | 33 value, base::JSONWriter::OPTIONS_PRETTY_PRINT, &json); |
30 os << json; | 34 os << json; |
31 return os; | 35 return os; |
32 } | 36 } |
33 | 37 |
34 MATCHER_P(MatchesJson, json, json.c_str()) { | 38 MATCHER_P(MatchesJson, json, json.c_str()) { |
35 std::unique_ptr<base::Value> expected( | 39 std::unique_ptr<base::Value> expected( |
36 base::JSONReader::Read(json, base::JSON_PARSE_RFC)); | 40 base::JSONReader::Read(json, base::JSON_PARSE_RFC)); |
37 return arg.Equals(expected.get()); | 41 return arg.Equals(expected.get()); |
38 } | 42 } |
39 | 43 |
40 namespace headless { | 44 namespace headless { |
41 | 45 |
42 namespace { | 46 namespace { |
43 | 47 |
| 48 class MockDelegate : public MockGenericURLRequestJobDelegate { |
| 49 public: |
| 50 MOCK_METHOD2(OnResourceLoadFailed, |
| 51 void(const Request* request, net::Error error)); |
| 52 }; |
| 53 |
44 class MockFetcher : public URLFetcher { | 54 class MockFetcher : public URLFetcher { |
45 public: | 55 public: |
46 MockFetcher(base::DictionaryValue* fetch_request, | 56 MockFetcher(base::DictionaryValue* fetch_request, |
47 const std::string& json_reply) | 57 std::map<std::string, std::string>* json_fetch_reply_map) |
48 : fetch_reply_(base::JSONReader::Read(json_reply, base::JSON_PARSE_RFC)), | 58 : json_fetch_reply_map_(json_fetch_reply_map), |
49 fetch_request_(fetch_request) { | 59 fetch_request_(fetch_request) {} |
50 CHECK(fetch_reply_) << "Invalid json: " << json_reply; | |
51 } | |
52 | 60 |
53 ~MockFetcher() override {} | 61 ~MockFetcher() override {} |
54 | 62 |
55 void StartFetch(const GURL& url, | 63 void StartFetch(const GURL& url, |
56 const std::string& method, | 64 const std::string& method, |
| 65 const std::string& post_data, |
57 const net::HttpRequestHeaders& request_headers, | 66 const net::HttpRequestHeaders& request_headers, |
58 const std::string& devtools_request_id, | |
59 ResultListener* result_listener) override { | 67 ResultListener* result_listener) override { |
60 // Record the request. | 68 // Record the request. |
61 fetch_request_->SetString("url", url.spec()); | 69 fetch_request_->SetString("url", url.spec()); |
62 fetch_request_->SetString("method", method); | 70 fetch_request_->SetString("method", method); |
63 std::unique_ptr<base::DictionaryValue> headers(new base::DictionaryValue); | 71 std::unique_ptr<base::DictionaryValue> headers(new base::DictionaryValue); |
64 for (net::HttpRequestHeaders::Iterator it(request_headers); it.GetNext();) { | 72 for (net::HttpRequestHeaders::Iterator it(request_headers); it.GetNext();) { |
65 headers->SetString(it.name(), it.value()); | 73 headers->SetString(it.name(), it.value()); |
66 } | 74 } |
67 fetch_request_->Set("headers", std::move(headers)); | 75 fetch_request_->Set("headers", std::move(headers)); |
| 76 if (!post_data.empty()) |
| 77 fetch_request_->SetString("post_data", post_data); |
| 78 |
| 79 const auto find_it = json_fetch_reply_map_->find(url.spec()); |
| 80 if (find_it == json_fetch_reply_map_->end()) { |
| 81 result_listener->OnFetchStartError(net::ERR_ADDRESS_UNREACHABLE); |
| 82 return; |
| 83 } |
68 | 84 |
69 // Return the canned response. | 85 // Return the canned response. |
| 86 std::unique_ptr<base::Value> fetch_reply( |
| 87 base::JSONReader::Read(find_it->second, base::JSON_PARSE_RFC)); |
| 88 CHECK(fetch_reply) << "Invalid json: " << find_it->second; |
| 89 |
70 base::DictionaryValue* reply_dictionary; | 90 base::DictionaryValue* reply_dictionary; |
71 ASSERT_TRUE(fetch_reply_->GetAsDictionary(&reply_dictionary)); | 91 ASSERT_TRUE(fetch_reply->GetAsDictionary(&reply_dictionary)); |
72 std::string final_url; | 92 std::string final_url; |
73 ASSERT_TRUE(reply_dictionary->GetString("url", &final_url)); | 93 ASSERT_TRUE(reply_dictionary->GetString("url", &final_url)); |
74 int http_response_code; | 94 int http_response_code; |
75 ASSERT_TRUE(reply_dictionary->GetInteger("http_response_code", | 95 ASSERT_TRUE(reply_dictionary->GetInteger("http_response_code", |
76 &http_response_code)); | 96 &http_response_code)); |
77 ASSERT_TRUE(reply_dictionary->GetString("data", &response_data_)); | 97 ASSERT_TRUE(reply_dictionary->GetString("data", &response_data_)); |
78 base::DictionaryValue* reply_headers_dictionary; | 98 base::DictionaryValue* reply_headers_dictionary; |
79 ASSERT_TRUE( | 99 ASSERT_TRUE( |
80 reply_dictionary->GetDictionary("headers", &reply_headers_dictionary)); | 100 reply_dictionary->GetDictionary("headers", &reply_headers_dictionary)); |
81 scoped_refptr<net::HttpResponseHeaders> response_headers( | 101 scoped_refptr<net::HttpResponseHeaders> response_headers( |
82 new net::HttpResponseHeaders("")); | 102 new net::HttpResponseHeaders("")); |
83 for (base::DictionaryValue::Iterator it(*reply_headers_dictionary); | 103 for (base::DictionaryValue::Iterator it(*reply_headers_dictionary); |
84 !it.IsAtEnd(); it.Advance()) { | 104 !it.IsAtEnd(); it.Advance()) { |
85 std::string value; | 105 std::string value; |
86 ASSERT_TRUE(it.value().GetAsString(&value)); | 106 ASSERT_TRUE(it.value().GetAsString(&value)); |
87 response_headers->AddHeader( | 107 response_headers->AddHeader( |
88 base::StringPrintf("%s: %s", it.key().c_str(), value.c_str())); | 108 base::StringPrintf("%s: %s", it.key().c_str(), value.c_str())); |
89 } | 109 } |
90 | 110 |
91 result_listener->OnFetchComplete( | 111 result_listener->OnFetchComplete( |
92 GURL(final_url), http_response_code, std::move(response_headers), | 112 GURL(final_url), http_response_code, std::move(response_headers), |
93 response_data_.c_str(), response_data_.size()); | 113 response_data_.c_str(), response_data_.size()); |
94 } | 114 } |
95 | 115 |
96 private: | 116 private: |
97 std::unique_ptr<base::Value> fetch_reply_; | 117 std::map<std::string, std::string>* json_fetch_reply_map_; // NOT OWNED |
98 base::DictionaryValue* fetch_request_; // NOT OWNED | 118 base::DictionaryValue* fetch_request_; // NOT OWNED |
99 std::string response_data_; // Here to ensure the required lifetime. | 119 std::string response_data_; // Here to ensure the required lifetime. |
100 }; | 120 }; |
101 | 121 |
102 class MockProtocolHandler : public net::URLRequestJobFactory::ProtocolHandler { | 122 class MockProtocolHandler : public net::URLRequestJobFactory::ProtocolHandler { |
103 public: | 123 public: |
104 // Details of the fetch will be stored in |fetch_request|. | 124 // Details of the fetch will be stored in |fetch_request|. |
105 // The fetch response will be created from parsing |json_fetch_reply_|. | 125 // The fetch response will be created from parsing |json_fetch_reply_map|. |
106 MockProtocolHandler(base::DictionaryValue* fetch_request, | 126 MockProtocolHandler(base::DictionaryValue* fetch_request, |
107 std::string* json_fetch_reply, | 127 std::map<std::string, std::string>* json_fetch_reply_map, |
108 URLRequestDispatcher* dispatcher, | 128 URLRequestDispatcher* dispatcher, |
109 GenericURLRequestJob::Delegate* job_delegate) | 129 GenericURLRequestJob::Delegate* job_delegate) |
110 : fetch_request_(fetch_request), | 130 : fetch_request_(fetch_request), |
111 json_fetch_reply_(json_fetch_reply), | 131 json_fetch_reply_map_(json_fetch_reply_map), |
112 job_delegate_(job_delegate), | 132 job_delegate_(job_delegate), |
113 dispatcher_(dispatcher) {} | 133 dispatcher_(dispatcher) {} |
114 | 134 |
115 // net::URLRequestJobFactory::ProtocolHandler override. | 135 // net::URLRequestJobFactory::ProtocolHandler override. |
116 net::URLRequestJob* MaybeCreateJob( | 136 net::URLRequestJob* MaybeCreateJob( |
117 net::URLRequest* request, | 137 net::URLRequest* request, |
118 net::NetworkDelegate* network_delegate) const override { | 138 net::NetworkDelegate* network_delegate) const override { |
119 return new GenericURLRequestJob( | 139 return new GenericURLRequestJob( |
120 request, network_delegate, dispatcher_, | 140 request, network_delegate, dispatcher_, |
121 base::MakeUnique<MockFetcher>(fetch_request_, *json_fetch_reply_), | 141 base::MakeUnique<MockFetcher>(fetch_request_, json_fetch_reply_map_), |
122 job_delegate_); | 142 job_delegate_); |
123 } | 143 } |
124 | 144 |
125 private: | 145 private: |
126 base::DictionaryValue* fetch_request_; // NOT OWNED | 146 base::DictionaryValue* fetch_request_; // NOT OWNED |
127 std::string* json_fetch_reply_; // NOT OWNED | 147 std::map<std::string, std::string>* json_fetch_reply_map_; // NOT OWNED |
128 GenericURLRequestJob::Delegate* job_delegate_; // NOT OWNED | 148 GenericURLRequestJob::Delegate* job_delegate_; // NOT OWNED |
129 URLRequestDispatcher* dispatcher_; // NOT OWNED | 149 URLRequestDispatcher* dispatcher_; // NOT OWNED |
130 }; | 150 }; |
131 | 151 |
132 } // namespace | 152 } // namespace |
133 | 153 |
134 class GenericURLRequestJobTest : public testing::Test { | 154 class GenericURLRequestJobTest : public testing::Test { |
135 public: | 155 public: |
136 GenericURLRequestJobTest() : dispatcher_(message_loop_.task_runner()) { | 156 GenericURLRequestJobTest() : dispatcher_(message_loop_.task_runner()) { |
137 url_request_job_factory_.SetProtocolHandler( | 157 url_request_job_factory_.SetProtocolHandler( |
138 "https", base::WrapUnique(new MockProtocolHandler( | 158 "https", base::WrapUnique(new MockProtocolHandler( |
139 &fetch_request_, &json_fetch_reply_, &dispatcher_, | 159 &fetch_request_, &json_fetch_reply_map_, &dispatcher_, |
140 &job_delegate_))); | 160 &job_delegate_))); |
141 url_request_context_.set_job_factory(&url_request_job_factory_); | 161 url_request_context_.set_job_factory(&url_request_job_factory_); |
142 url_request_context_.set_cookie_store(&cookie_store_); | 162 url_request_context_.set_cookie_store(&cookie_store_); |
143 } | 163 } |
144 | 164 |
145 std::unique_ptr<net::URLRequest> CreateAndCompleteJob( | 165 std::unique_ptr<net::URLRequest> CreateAndCompleteGetJob( |
146 const GURL& url, | 166 const GURL& url, |
147 const std::string& json_reply) { | 167 const std::string& json_reply) { |
148 json_fetch_reply_ = json_reply; | 168 json_fetch_reply_map_[url.spec()] = json_reply; |
149 | 169 |
150 std::unique_ptr<net::URLRequest> request(url_request_context_.CreateRequest( | 170 std::unique_ptr<net::URLRequest> request(url_request_context_.CreateRequest( |
151 url, net::DEFAULT_PRIORITY, &request_delegate_)); | 171 url, net::DEFAULT_PRIORITY, &request_delegate_)); |
152 request->Start(); | 172 request->Start(); |
153 base::RunLoop().RunUntilIdle(); | 173 base::RunLoop().RunUntilIdle(); |
154 return request; | 174 return request; |
155 } | 175 } |
156 | 176 |
157 protected: | 177 protected: |
158 base::MessageLoop message_loop_; | 178 base::MessageLoop message_loop_; |
159 ExpeditedDispatcher dispatcher_; | 179 ExpeditedDispatcher dispatcher_; |
160 | 180 |
161 net::URLRequestJobFactoryImpl url_request_job_factory_; | 181 net::URLRequestJobFactoryImpl url_request_job_factory_; |
162 net::URLRequestContext url_request_context_; | 182 net::URLRequestContext url_request_context_; |
163 MockCookieStore cookie_store_; | 183 MockCookieStore cookie_store_; |
164 | 184 |
165 MockURLRequestDelegate request_delegate_; | 185 MockURLRequestDelegate request_delegate_; |
166 base::DictionaryValue fetch_request_; // The request sent to MockFetcher. | 186 base::DictionaryValue fetch_request_; // The request sent to MockFetcher. |
167 std::string json_fetch_reply_; // The reply to be sent by MockFetcher. | 187 std::map<std::string, std::string> |
168 MockGenericURLRequestJobDelegate job_delegate_; | 188 json_fetch_reply_map_; // Replies to be sent by MockFetcher. |
| 189 MockDelegate job_delegate_; |
169 }; | 190 }; |
170 | 191 |
171 TEST_F(GenericURLRequestJobTest, BasicRequestParams) { | 192 TEST_F(GenericURLRequestJobTest, BasicGetRequestParams) { |
172 // TODO(alexclarke): Lobby for raw string literals and use them here! | 193 json_fetch_reply_map_["https://example.com/"] = R"( |
173 json_fetch_reply_ = | 194 { |
174 "{\"url\":\"https://example.com\"," | 195 "url": "https://example.com", |
175 " \"http_response_code\":200," | 196 "http_response_code": 200, |
176 " \"data\":\"Reply\"," | 197 "data": "Reply", |
177 " \"headers\":{\"Content-Type\":\"text/plain\"}}"; | 198 "headers": { |
| 199 "Content-Type": "text/html; charset=UTF-8" |
| 200 } |
| 201 })"; |
178 | 202 |
179 std::unique_ptr<net::URLRequest> request(url_request_context_.CreateRequest( | 203 std::unique_ptr<net::URLRequest> request(url_request_context_.CreateRequest( |
180 GURL("https://example.com"), net::DEFAULT_PRIORITY, &request_delegate_)); | 204 GURL("https://example.com"), net::DEFAULT_PRIORITY, &request_delegate_)); |
| 205 request->SetReferrer("https://referrer.example.com"); |
| 206 request->SetExtraRequestHeaderByName("Extra-Header", "Value", true); |
| 207 request->SetExtraRequestHeaderByName("User-Agent", "TestBrowser", true); |
| 208 request->SetExtraRequestHeaderByName("Accept", "text/plain", true); |
| 209 request->Start(); |
| 210 base::RunLoop().RunUntilIdle(); |
| 211 |
| 212 std::string expected_request_json = R"( |
| 213 { |
| 214 "url": "https://example.com/", |
| 215 "method": "GET", |
| 216 "headers": { |
| 217 "Accept": "text/plain", |
| 218 "Cookie": "", |
| 219 "Extra-Header": "Value", |
| 220 "Referer": "https://referrer.example.com/", |
| 221 "User-Agent": "TestBrowser" |
| 222 } |
| 223 })"; |
| 224 |
| 225 EXPECT_THAT(fetch_request_, MatchesJson(expected_request_json)); |
| 226 } |
| 227 |
| 228 TEST_F(GenericURLRequestJobTest, BasicPostRequestParams) { |
| 229 json_fetch_reply_map_["https://example.com/"] = R"( |
| 230 { |
| 231 "url": "https://example.com", |
| 232 "http_response_code": 200, |
| 233 "data": "Reply", |
| 234 "headers": { |
| 235 "Content-Type": "text/html; charset=UTF-8" |
| 236 } |
| 237 })"; |
| 238 |
| 239 std::unique_ptr<net::URLRequest> request(url_request_context_.CreateRequest( |
| 240 GURL("https://example.com"), net::DEFAULT_PRIORITY, &request_delegate_)); |
181 request->SetReferrer("https://referrer.example.com"); | 241 request->SetReferrer("https://referrer.example.com"); |
182 request->SetExtraRequestHeaderByName("Extra-Header", "Value", true); | 242 request->SetExtraRequestHeaderByName("Extra-Header", "Value", true); |
183 request->SetExtraRequestHeaderByName("User-Agent", "TestBrowser", true); | 243 request->SetExtraRequestHeaderByName("User-Agent", "TestBrowser", true); |
184 request->SetExtraRequestHeaderByName("Accept", "text/plain", true); | 244 request->SetExtraRequestHeaderByName("Accept", "text/plain", true); |
| 245 request->set_method("POST"); |
| 246 |
| 247 std::string post_data = "lorem ipsom"; |
| 248 request->set_upload(net::ElementsUploadDataStream::CreateWithReader( |
| 249 base::MakeUnique<net::UploadBytesElementReader>(post_data.data(), |
| 250 post_data.size()), |
| 251 0)); |
185 request->Start(); | 252 request->Start(); |
186 base::RunLoop().RunUntilIdle(); | 253 base::RunLoop().RunUntilIdle(); |
187 | 254 |
188 std::string expected_request_json = | 255 std::string expected_request_json = R"( |
189 "{\"url\": \"https://example.com/\"," | 256 { |
190 " \"method\": \"GET\"," | 257 "url": "https://example.com/", |
191 " \"headers\": {" | 258 "method": "POST", |
192 " \"Accept\": \"text/plain\"," | 259 "post_data": "lorem ipsom", |
193 " \"Cookie\": \"\"," | 260 "headers": { |
194 " \"Extra-Header\": \"Value\"," | 261 "Accept": "text/plain", |
195 " \"Referer\": \"https://referrer.example.com/\"," | 262 "Cookie": "", |
196 " \"User-Agent\": \"TestBrowser\"" | 263 "Extra-Header": "Value", |
197 " }" | 264 "Referer": "https://referrer.example.com/", |
198 "}"; | 265 "User-Agent": "TestBrowser" |
| 266 } |
| 267 })"; |
199 | 268 |
200 EXPECT_THAT(fetch_request_, MatchesJson(expected_request_json)); | 269 EXPECT_THAT(fetch_request_, MatchesJson(expected_request_json)); |
201 } | 270 } |
202 | 271 |
203 TEST_F(GenericURLRequestJobTest, BasicRequestProperties) { | 272 TEST_F(GenericURLRequestJobTest, BasicRequestProperties) { |
204 std::string reply = | 273 std::string reply = R"( |
205 "{\"url\":\"https://example.com\"," | 274 { |
206 " \"http_response_code\":200," | 275 "url": "https://example.com", |
207 " \"data\":\"Reply\"," | 276 "http_response_code": 200, |
208 " \"headers\":{\"Content-Type\":\"text/html; charset=UTF-8\"}}"; | 277 "data": "Reply", |
| 278 "headers": { |
| 279 "Content-Type": "text/html; charset=UTF-8" |
| 280 } |
| 281 })"; |
209 | 282 |
210 std::unique_ptr<net::URLRequest> request( | 283 std::unique_ptr<net::URLRequest> request( |
211 CreateAndCompleteJob(GURL("https://example.com"), reply)); | 284 CreateAndCompleteGetJob(GURL("https://example.com"), reply)); |
212 | 285 |
213 EXPECT_EQ(200, request->GetResponseCode()); | 286 EXPECT_EQ(200, request->GetResponseCode()); |
214 | 287 |
215 std::string mime_type; | 288 std::string mime_type; |
216 request->GetMimeType(&mime_type); | 289 request->GetMimeType(&mime_type); |
217 EXPECT_EQ("text/html", mime_type); | 290 EXPECT_EQ("text/html", mime_type); |
218 | 291 |
219 std::string charset; | 292 std::string charset; |
220 request->GetCharset(&charset); | 293 request->GetCharset(&charset); |
221 EXPECT_EQ("utf-8", charset); | 294 EXPECT_EQ("utf-8", charset); |
222 | 295 |
223 std::string content_type; | 296 std::string content_type; |
224 EXPECT_TRUE(request->response_info().headers->GetNormalizedHeader( | 297 EXPECT_TRUE(request->response_info().headers->GetNormalizedHeader( |
225 "Content-Type", &content_type)); | 298 "Content-Type", &content_type)); |
226 EXPECT_EQ("text/html; charset=UTF-8", content_type); | 299 EXPECT_EQ("text/html; charset=UTF-8", content_type); |
227 } | 300 } |
228 | 301 |
229 TEST_F(GenericURLRequestJobTest, BasicRequestContents) { | 302 TEST_F(GenericURLRequestJobTest, BasicRequestContents) { |
230 std::string reply = | 303 std::string reply = R"( |
231 "{\"url\":\"https://example.com\"," | 304 { |
232 " \"http_response_code\":200," | 305 "url": "https://example.com", |
233 " \"data\":\"Reply\"," | 306 "http_response_code": 200, |
234 " \"headers\":{\"Content-Type\":\"text/html; charset=UTF-8\"}}"; | 307 "data": "Reply", |
| 308 "headers": { |
| 309 "Content-Type": "text/html; charset=UTF-8" |
| 310 } |
| 311 })"; |
235 | 312 |
236 std::unique_ptr<net::URLRequest> request( | 313 std::unique_ptr<net::URLRequest> request( |
237 CreateAndCompleteJob(GURL("https://example.com"), reply)); | 314 CreateAndCompleteGetJob(GURL("https://example.com"), reply)); |
238 | 315 |
239 const int kBufferSize = 256; | 316 const int kBufferSize = 256; |
240 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize)); | 317 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize)); |
241 int bytes_read; | 318 int bytes_read; |
242 EXPECT_TRUE(request->Read(buffer.get(), kBufferSize, &bytes_read)); | 319 EXPECT_TRUE(request->Read(buffer.get(), kBufferSize, &bytes_read)); |
243 EXPECT_EQ(5, bytes_read); | 320 EXPECT_EQ(5, bytes_read); |
244 EXPECT_EQ("Reply", std::string(buffer->data(), 5)); | 321 EXPECT_EQ("Reply", std::string(buffer->data(), 5)); |
245 | 322 |
246 net::LoadTimingInfo load_timing_info; | 323 net::LoadTimingInfo load_timing_info; |
247 request->GetLoadTimingInfo(&load_timing_info); | 324 request->GetLoadTimingInfo(&load_timing_info); |
248 EXPECT_FALSE(load_timing_info.receive_headers_end.is_null()); | 325 EXPECT_FALSE(load_timing_info.receive_headers_end.is_null()); |
249 } | 326 } |
250 | 327 |
251 TEST_F(GenericURLRequestJobTest, ReadInParts) { | 328 TEST_F(GenericURLRequestJobTest, ReadInParts) { |
252 std::string reply = | 329 std::string reply = R"( |
253 "{\"url\":\"https://example.com\"," | 330 { |
254 " \"http_response_code\":200," | 331 "url": "https://example.com", |
255 " \"data\":\"Reply\"," | 332 "http_response_code": 200, |
256 " \"headers\":{\"Content-Type\":\"text/html; charset=UTF-8\"}}"; | 333 "data": "Reply", |
| 334 "headers": { |
| 335 "Content-Type": "text/html; charset=UTF-8" |
| 336 } |
| 337 })"; |
257 | 338 |
258 std::unique_ptr<net::URLRequest> request( | 339 std::unique_ptr<net::URLRequest> request( |
259 CreateAndCompleteJob(GURL("https://example.com"), reply)); | 340 CreateAndCompleteGetJob(GURL("https://example.com"), reply)); |
260 | 341 |
261 const int kBufferSize = 3; | 342 const int kBufferSize = 3; |
262 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize)); | 343 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize)); |
263 int bytes_read; | 344 int bytes_read; |
264 EXPECT_TRUE(request->Read(buffer.get(), kBufferSize, &bytes_read)); | 345 EXPECT_TRUE(request->Read(buffer.get(), kBufferSize, &bytes_read)); |
265 EXPECT_EQ(3, bytes_read); | 346 EXPECT_EQ(3, bytes_read); |
266 EXPECT_EQ("Rep", std::string(buffer->data(), bytes_read)); | 347 EXPECT_EQ("Rep", std::string(buffer->data(), bytes_read)); |
267 | 348 |
268 EXPECT_TRUE(request->Read(buffer.get(), kBufferSize, &bytes_read)); | 349 EXPECT_TRUE(request->Read(buffer.get(), kBufferSize, &bytes_read)); |
269 EXPECT_EQ(2, bytes_read); | 350 EXPECT_EQ(2, bytes_read); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
325 net::COOKIE_PRIORITY_DEFAULT)); | 406 net::COOKIE_PRIORITY_DEFAULT)); |
326 | 407 |
327 // Non-matching cookie (different path). | 408 // Non-matching cookie (different path). |
328 cookies->push_back(*net::CanonicalCookie::Create( | 409 cookies->push_back(*net::CanonicalCookie::Create( |
329 GURL("https://example.com"), "bad_path_cookie", "7", "example.com", | 410 GURL("https://example.com"), "bad_path_cookie", "7", "example.com", |
330 "/gadgets", base::Time(), base::Time(), | 411 "/gadgets", base::Time(), base::Time(), |
331 /* secure */ false, | 412 /* secure */ false, |
332 /* http_only */ false, net::CookieSameSite::NO_RESTRICTION, | 413 /* http_only */ false, net::CookieSameSite::NO_RESTRICTION, |
333 net::COOKIE_PRIORITY_DEFAULT)); | 414 net::COOKIE_PRIORITY_DEFAULT)); |
334 | 415 |
335 std::string reply = | 416 std::string reply = R"( |
336 "{\"url\":\"https://example.com\"," | 417 { |
337 " \"http_response_code\":200," | 418 "url": "https://example.com", |
338 " \"data\":\"Reply\"," | 419 "http_response_code": 200, |
339 " \"headers\":{\"Content-Type\":\"text/html; charset=UTF-8\"}}"; | 420 "data": "Reply", |
| 421 "headers": { |
| 422 "Content-Type": "text/html; charset=UTF-8" |
| 423 } |
| 424 })"; |
340 | 425 |
341 std::unique_ptr<net::URLRequest> request( | 426 std::unique_ptr<net::URLRequest> request( |
342 CreateAndCompleteJob(GURL("https://example.com"), reply)); | 427 CreateAndCompleteGetJob(GURL("https://example.com"), reply)); |
343 | 428 |
344 std::string expected_request_json = | 429 std::string expected_request_json = R"( |
345 "{\"url\": \"https://example.com/\"," | 430 { |
346 " \"method\": \"GET\"," | 431 "url": "https://example.com/", |
347 " \"headers\": {" | 432 "method": "GET", |
348 " \"Cookie\": \"basic_cookie=1; secure_cookie=2; http_only_cookie=3\"," | 433 "headers": { |
349 " \"Referer\": \"\"" | 434 "Cookie": "basic_cookie=1; secure_cookie=2; http_only_cookie=3", |
350 " }" | 435 "Referer": "" |
351 "}"; | 436 } |
| 437 })"; |
352 | 438 |
353 EXPECT_THAT(fetch_request_, MatchesJson(expected_request_json)); | 439 EXPECT_THAT(fetch_request_, MatchesJson(expected_request_json)); |
354 } | 440 } |
355 | 441 |
356 TEST_F(GenericURLRequestJobTest, DelegateBlocksLoading) { | 442 TEST_F(GenericURLRequestJobTest, DelegateBlocksLoading) { |
357 std::string reply = | 443 std::string reply = R"( |
358 "{\"url\":\"https://example.com\"," | 444 { |
359 " \"http_response_code\":200," | 445 "url": "https://example.com", |
360 " \"data\":\"Reply\"," | 446 "http_response_code": 200, |
361 " \"headers\":{\"Content-Type\":\"text/html; charset=UTF-8\"}}"; | 447 "data": "Reply", |
362 | 448 "headers": { |
363 job_delegate_.SetShouldBlock(true); | 449 "Content-Type": "text/html; charset=UTF-8" |
| 450 } |
| 451 })"; |
| 452 |
| 453 job_delegate_.SetPolicy(base::Bind([](PendingRequest* pending_request) { |
| 454 pending_request->BlockRequest(net::ERR_FILE_NOT_FOUND); |
| 455 })); |
364 | 456 |
365 std::unique_ptr<net::URLRequest> request( | 457 std::unique_ptr<net::URLRequest> request( |
366 CreateAndCompleteJob(GURL("https://example.com"), reply)); | 458 CreateAndCompleteGetJob(GURL("https://example.com"), reply)); |
367 | 459 |
368 EXPECT_EQ(net::URLRequestStatus::FAILED, request->status().status()); | 460 EXPECT_EQ(net::URLRequestStatus::FAILED, request->status().status()); |
369 EXPECT_EQ(net::ERR_FILE_NOT_FOUND, request->status().error()); | 461 EXPECT_EQ(net::ERR_FILE_NOT_FOUND, request->status().error()); |
370 } | 462 } |
371 | 463 |
| 464 TEST_F(GenericURLRequestJobTest, DelegateModifiesRequest) { |
| 465 json_fetch_reply_map_["https://example.com/"] = R"( |
| 466 { |
| 467 "url": "https://example.com", |
| 468 "http_response_code": 200, |
| 469 "data": "Welcome to example.com", |
| 470 "headers": { |
| 471 "Content-Type": "text/html; charset=UTF-8" |
| 472 } |
| 473 })"; |
| 474 |
| 475 json_fetch_reply_map_["https://othersite.com/"] = R"( |
| 476 { |
| 477 "url": "https://example.com", |
| 478 "http_response_code": 200, |
| 479 "data": "Welcome to othersite.com", |
| 480 "headers": { |
| 481 "Content-Type": "text/html; charset=UTF-8" |
| 482 } |
| 483 })"; |
| 484 |
| 485 // Turn the GET into a POST to a different site. |
| 486 job_delegate_.SetPolicy(base::Bind([](PendingRequest* pending_request) { |
| 487 net::HttpRequestHeaders headers; |
| 488 headers.SetHeader("TestHeader", "Hello"); |
| 489 pending_request->ModifyRequest(GURL("https://othersite.com"), "POST", |
| 490 "Some post data!", headers); |
| 491 })); |
| 492 |
| 493 std::unique_ptr<net::URLRequest> request(url_request_context_.CreateRequest( |
| 494 GURL("https://example.com"), net::DEFAULT_PRIORITY, &request_delegate_)); |
| 495 request->Start(); |
| 496 base::RunLoop().RunUntilIdle(); |
| 497 |
| 498 std::string expected_request_json = R"( |
| 499 { |
| 500 "url": "https://othersite.com/", |
| 501 "method": "POST", |
| 502 "post_data": "Some post data!", |
| 503 "headers": { |
| 504 "TestHeader": "Hello" |
| 505 } |
| 506 })"; |
| 507 |
| 508 EXPECT_THAT(fetch_request_, MatchesJson(expected_request_json)); |
| 509 |
| 510 EXPECT_EQ(200, request->GetResponseCode()); |
| 511 // The modification should not be visible to the URlRequest. |
| 512 EXPECT_EQ("https://example.com/", request->url().spec()); |
| 513 EXPECT_EQ("GET", request->method()); |
| 514 |
| 515 const int kBufferSize = 256; |
| 516 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize)); |
| 517 int bytes_read; |
| 518 EXPECT_TRUE(request->Read(buffer.get(), kBufferSize, &bytes_read)); |
| 519 EXPECT_EQ(24, bytes_read); |
| 520 EXPECT_EQ("Welcome to othersite.com", |
| 521 std::string(buffer->data(), bytes_read)); |
| 522 } |
| 523 |
| 524 TEST_F(GenericURLRequestJobTest, DelegateMocks404Response) { |
| 525 std::string reply = R"( |
| 526 { |
| 527 "url": "https://example.com", |
| 528 "http_response_code": 200, |
| 529 "data": "Reply", |
| 530 "headers": { |
| 531 "Content-Type": "text/html; charset=UTF-8" |
| 532 } |
| 533 })"; |
| 534 |
| 535 job_delegate_.SetPolicy(base::Bind([](PendingRequest* pending_request) { |
| 536 std::unique_ptr<GenericURLRequestJob::MockResponseData> mock_response_data( |
| 537 new GenericURLRequestJob::MockResponseData()); |
| 538 mock_response_data->http_response_code = 404; |
| 539 mock_response_data->response_data = "HTTP/1.1 404 Not Found\r\n\r\n"; |
| 540 pending_request->MockResponse(std::move(mock_response_data)); |
| 541 })); |
| 542 |
| 543 std::unique_ptr<net::URLRequest> request( |
| 544 CreateAndCompleteGetJob(GURL("https://example.com"), reply)); |
| 545 |
| 546 EXPECT_EQ(404, request->GetResponseCode()); |
| 547 } |
| 548 |
| 549 TEST_F(GenericURLRequestJobTest, DelegateMocks302Response) { |
| 550 job_delegate_.SetPolicy(base::Bind([](PendingRequest* pending_request) { |
| 551 if (pending_request->GetRequest()->GetURLRequest()->url().spec() == |
| 552 "https://example.com/") { |
| 553 std::unique_ptr<GenericURLRequestJob::MockResponseData> |
| 554 mock_response_data(new GenericURLRequestJob::MockResponseData()); |
| 555 mock_response_data->http_response_code = 302; |
| 556 mock_response_data->response_data = |
| 557 "HTTP/1.1 302 Found\r\n" |
| 558 "Location: https://foo.com/\r\n\r\n"; |
| 559 pending_request->MockResponse(std::move(mock_response_data)); |
| 560 } else { |
| 561 pending_request->AllowRequest(); |
| 562 } |
| 563 })); |
| 564 |
| 565 json_fetch_reply_map_["https://example.com/"] = R"( |
| 566 { |
| 567 "url": "https://example.com", |
| 568 "http_response_code": 200, |
| 569 "data": "Welcome to example.com", |
| 570 "headers": { |
| 571 "Content-Type": "text/html; charset=UTF-8" |
| 572 } |
| 573 })"; |
| 574 |
| 575 json_fetch_reply_map_["https://foo.com/"] = R"( |
| 576 { |
| 577 "url": "https://example.com", |
| 578 "http_response_code": 200, |
| 579 "data": "Welcome to foo.com", |
| 580 "headers": { |
| 581 "Content-Type": "text/html; charset=UTF-8" |
| 582 } |
| 583 })"; |
| 584 |
| 585 std::unique_ptr<net::URLRequest> request(url_request_context_.CreateRequest( |
| 586 GURL("https://example.com"), net::DEFAULT_PRIORITY, &request_delegate_)); |
| 587 request->Start(); |
| 588 base::RunLoop().RunUntilIdle(); |
| 589 |
| 590 EXPECT_EQ(200, request->GetResponseCode()); |
| 591 EXPECT_EQ("https://foo.com/", request->url().spec()); |
| 592 |
| 593 const int kBufferSize = 256; |
| 594 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize)); |
| 595 int bytes_read; |
| 596 EXPECT_TRUE(request->Read(buffer.get(), kBufferSize, &bytes_read)); |
| 597 EXPECT_EQ(18, bytes_read); |
| 598 EXPECT_EQ("Welcome to foo.com", std::string(buffer->data(), bytes_read)); |
| 599 } |
| 600 |
| 601 TEST_F(GenericURLRequestJobTest, OnResourceLoadFailed) { |
| 602 EXPECT_CALL(job_delegate_, |
| 603 OnResourceLoadFailed(_, net::ERR_ADDRESS_UNREACHABLE)); |
| 604 |
| 605 std::unique_ptr<net::URLRequest> request(url_request_context_.CreateRequest( |
| 606 GURL("https://i-dont-exist.com"), net::DEFAULT_PRIORITY, |
| 607 &request_delegate_)); |
| 608 request->Start(); |
| 609 base::RunLoop().RunUntilIdle(); |
| 610 } |
| 611 |
372 } // namespace headless | 612 } // namespace headless |
OLD | NEW |