Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(288)

Side by Side Diff: content/browser/loader/navigation_url_loader_unittest.cc

Issue 519533002: Initial PlzNavigate RDH-side logic. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/command_line.h"
6 #include "base/memory/ref_counted.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "base/run_loop.h"
9 #include "content/browser/frame_host/navigation_request_info.h"
10 #include "content/browser/loader/navigation_url_loader_impl.h"
11 #include "content/browser/loader/resource_dispatcher_host_impl.h"
12 #include "content/browser/streams/stream.h"
13 #include "content/browser/streams/stream_context.h"
14 #include "content/browser/streams/stream_registry.h"
15 #include "content/browser/streams/stream_url_request_job.h"
16 #include "content/public/browser/browser_context.h"
17 #include "content/public/browser/resource_context.h"
18 #include "content/public/browser/resource_dispatcher_host_delegate.h"
19 #include "content/public/browser/stream_handle.h"
20 #include "content/public/common/content_switches.h"
21 #include "content/public/common/resource_response.h"
22 #include "content/public/test/test_browser_context.h"
23 #include "content/public/test/test_browser_thread_bundle.h"
24 #include "net/base/net_errors.h"
25 #include "net/http/http_response_headers.h"
26 #include "net/url_request/redirect_info.h"
27 #include "net/url_request/url_request.h"
28 #include "net/url_request/url_request_context.h"
29 #include "net/url_request/url_request_job_factory_impl.h"
30 #include "net/url_request/url_request_test_job.h"
31 #include "net/url_request/url_request_test_util.h"
32 #include "testing/gtest/include/gtest/gtest.h"
33
34 namespace content {
35
36 namespace {
37
38 class StreamProtocolHandler
39 : public net::URLRequestJobFactory::ProtocolHandler {
40 public:
41 StreamProtocolHandler(StreamRegistry* registry) : registry_(registry) {}
42
43 // net::URLRequestJobFactory::ProtocolHandler implementation.
44 virtual net::URLRequestJob* MaybeCreateJob(
45 net::URLRequest* request,
46 net::NetworkDelegate* network_delegate) const OVERRIDE {
47 scoped_refptr<Stream> stream = registry_->GetStream(request->url());
48 if (stream.get())
49 return new StreamURLRequestJob(request, network_delegate, stream);
50 return NULL;
51 }
52 private:
53 StreamRegistry* registry_;
54 };
55
56 class TestNavigationURLLoaderDelegate : public NavigationURLLoader::Delegate {
57 public:
58 TestNavigationURLLoaderDelegate()
59 : net_error_(0),
60 request_redirected_(new base::RunLoop),
61 response_started_(new base::RunLoop),
62 request_failed_(new base::RunLoop) {
63 }
64
65 const net::RedirectInfo& redirect_info() const { return redirect_info_; }
66 ResourceResponse* response() const { return response_.get(); }
67 StreamHandle* body() const { return body_.get(); }
68 int net_error() const { return net_error_; }
69
70 void WaitForRequestRedirected() {
71 request_redirected_->Run();
72 request_redirected_.reset(new base::RunLoop);
73 }
74
75 void WaitForResponseStarted() {
76 response_started_->Run();
77 response_started_.reset(new base::RunLoop);
78 }
79
80 void WaitForRequestFailed() {
81 request_failed_->Run();
82 request_failed_.reset(new base::RunLoop);
83 }
84
85 void ReleaseBody() {
86 body_.reset();
87 }
88
89 // NavigationURLLoader::Delegate implementation.
90 virtual void OnRequestRedirected(const net::RedirectInfo& redirect_info,
91 ResourceResponse* response) OVERRIDE {
92 redirect_info_ = redirect_info;
93 response_ = response;
94 request_redirected_->Quit();
95 }
96
97 virtual void OnResponseStarted(ResourceResponse* response,
98 scoped_ptr<StreamHandle> body) OVERRIDE {
99 response_ = response;
100 body_ = body.Pass();
101 response_started_->Quit();
102 }
103
104 virtual void OnRequestFailed(int net_error) OVERRIDE {
105 net_error_ = net_error;
106 request_failed_->Quit();
107 }
108
109 private:
110 net::RedirectInfo redirect_info_;
111 scoped_refptr<ResourceResponse> response_;
112 scoped_ptr<StreamHandle> body_;
113 int net_error_;
114
115 scoped_ptr<base::RunLoop> request_redirected_;
116 scoped_ptr<base::RunLoop> response_started_;
117 scoped_ptr<base::RunLoop> request_failed_;
118 };
119
120 class RequestBlockingResourceDispatcherHostDelegate
121 : public ResourceDispatcherHostDelegate {
122 public:
123 // ResourceDispatcherHostDelegate implementation:
124 virtual bool ShouldBeginRequest(const std::string& method,
125 const GURL& url,
126 ResourceType resource_type,
127 ResourceContext* resource_context) OVERRIDE {
128 return false;
129 }
130 };
131
132 } // namespace
133
134 class NavigationURLLoaderTest : public testing::Test {
135 public:
136 NavigationURLLoaderTest()
137 : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
138 browser_context_(new TestBrowserContext) {
139 BrowserContext::EnsureResourceContextInitialized(browser_context_.get());
140 base::RunLoop().RunUntilIdle();
141 net::URLRequestContext* request_context =
142 browser_context_->GetResourceContext()->GetRequestContext();
143 // Attach URLRequestTestJob and make streams work.
144 job_factory_.SetProtocolHandler(
145 "test", net::URLRequestTestJob::CreateProtocolHandler());
146 job_factory_.SetProtocolHandler(
147 "blob", new StreamProtocolHandler(
148 StreamContext::GetFor(browser_context_.get())->registry()));
149 request_context->set_job_factory(&job_factory_);
150
151 // NavigationURLLoader is only used for browser-side navigations.
152 CommandLine::ForCurrentProcess()->AppendSwitch(
153 switches::kEnableBrowserSideNavigation);
154 }
155
156 // Helper function for fetching the body of a URL to a string.
157 std::string FetchURL(const GURL& url) {
158 net::TestDelegate delegate;
159 net::URLRequestContext* request_context =
160 browser_context_->GetResourceContext()->GetRequestContext();
161 scoped_ptr<net::URLRequest> request(request_context->CreateRequest(
162 url, net::DEFAULT_PRIORITY, &delegate, NULL));
163 request->Start();
164 base::RunLoop().Run();
165
166 EXPECT_TRUE(request->status().is_success());
167 EXPECT_EQ(200, request->response_headers()->response_code());
168 return delegate.data_received();
169 }
170
171 protected:
172 TestBrowserThreadBundle thread_bundle_;
173 net::URLRequestJobFactoryImpl job_factory_;
174 scoped_ptr<TestBrowserContext> browser_context_;
175 ResourceDispatcherHostImpl host_;
176 };
177
178 // Tests that a basic request works.
179 TEST_F(NavigationURLLoaderTest, Basic) {
180 TestNavigationURLLoaderDelegate delegate;
181
182 // Fake a top-level request.
183 FrameHostMsg_BeginNavigation_Params params;
184 params.method = "GET";
185 params.url = net::URLRequestTestJob::test_url_1();
186 NavigationRequestInfo request_info(params);
187 request_info.first_party_for_cookies = params.url;
188 request_info.is_main_frame = true;
189
190 scoped_ptr<NavigationURLLoader> loader(
191 NavigationURLLoader::Create(browser_context_.get(),
192 0, request_info, NULL, &delegate));
193
194 // Wait for the response to come back.
195 delegate.WaitForResponseStarted();
196
197 // Check the response is correct.
198 EXPECT_EQ("text/html", delegate.response()->head.mime_type);
199 EXPECT_EQ("HTTP/1.1 200 OK",
200 delegate.response()->head.headers->GetStatusLine());
201
202 // Check the body is correct.
203 EXPECT_EQ(net::URLRequestTestJob::test_data_1(),
204 FetchURL(delegate.body()->GetURL()));
205 }
206
207 // Tests that request failures are propogated correctly.
208 TEST_F(NavigationURLLoaderTest, RequestFailed) {
209 TestNavigationURLLoaderDelegate delegate;
210
211 // Fake a top-level request.
212 FrameHostMsg_BeginNavigation_Params params;
213 params.method = "GET";
214 params.url = GURL("bogus:bogus");
215 NavigationRequestInfo request_info(params);
216 request_info.first_party_for_cookies = params.url;
217 request_info.is_main_frame = true;
218
219 scoped_ptr<NavigationURLLoader> loader(
220 NavigationURLLoader::Create(browser_context_.get(),
221 0, request_info, NULL, &delegate));
222
223 // Wait for the request to fail as expected.
224 delegate.WaitForRequestFailed();
225 EXPECT_EQ(net::ERR_UNKNOWN_URL_SCHEME, delegate.net_error());
226 }
227
228 // Test that redirects are sent to the delegate.
229 TEST_F(NavigationURLLoaderTest, RequestRedirected) {
230 TestNavigationURLLoaderDelegate delegate;
231
232 // Fake a top-level request.
233 FrameHostMsg_BeginNavigation_Params params;
234 params.method = "GET";
235 params.url = net::URLRequestTestJob::test_url_redirect_to_url_2();
236 NavigationRequestInfo request_info(params);
237 request_info.first_party_for_cookies = params.url;
238 request_info.is_main_frame = true;
239
240 scoped_ptr<NavigationURLLoader> loader(
241 NavigationURLLoader::Create(browser_context_.get(),
242 0, request_info, NULL, &delegate));
243
244 // Wait for the request to redirect.
245 delegate.WaitForRequestRedirected();
246 EXPECT_EQ(net::URLRequestTestJob::test_url_2(),
247 delegate.redirect_info().new_url);
248 EXPECT_EQ("GET", delegate.redirect_info().new_method);
249 EXPECT_EQ(net::URLRequestTestJob::test_url_2(),
250 delegate.redirect_info().new_first_party_for_cookies);
251 EXPECT_EQ("HTTP/1.1 302 MOVED",
252 delegate.response()->head.headers->GetStatusLine());
253
254 // Wait for the response to complete.
255 loader->FollowRedirect();
256 base::RunLoop().RunUntilIdle();
257 EXPECT_TRUE(net::URLRequestTestJob::ProcessOnePendingMessage());
258 delegate.WaitForResponseStarted();
259
260 // Check the response is correct.
261 EXPECT_EQ("text/html", delegate.response()->head.mime_type);
262 EXPECT_EQ("HTTP/1.1 200 OK",
263 delegate.response()->head.headers->GetStatusLine());
264
265 // Check the body is correct.
266 EXPECT_EQ(net::URLRequestTestJob::test_data_2(),
267 FetchURL(delegate.body()->GetURL()));
268 }
269
270 // Tests that the destroying the loader cancels the request.
271 TEST_F(NavigationURLLoaderTest, CancelOnDestruct) {
272 TestNavigationURLLoaderDelegate delegate;
273
274 // Fake a top-level request. Choose a URL which redirects so the request can
275 // be paused before the response comes in.
276 FrameHostMsg_BeginNavigation_Params params;
277 params.method = "GET";
278 params.url = net::URLRequestTestJob::test_url_redirect_to_url_2();
279 NavigationRequestInfo request_info(params);
280 request_info.first_party_for_cookies = params.url;
281 request_info.is_main_frame = true;
282
283 scoped_ptr<NavigationURLLoader> loader(
284 NavigationURLLoader::Create(browser_context_.get(),
285 0, request_info, NULL, &delegate));
286
287 // Wait for the request to redirect.
288 delegate.WaitForRequestRedirected();
289
290 // Destroy the loader and verify that URLRequestTestJob no longer has anything
291 // paused.
292 loader.reset();
293 base::RunLoop().RunUntilIdle();
294 EXPECT_FALSE(net::URLRequestTestJob::ProcessOnePendingMessage());
295 }
296
297 // Test that the delegate is not called if OnResponseStarted and destroying the
298 // loader race.
299 TEST_F(NavigationURLLoaderTest, CancelResponseRace) {
300 TestNavigationURLLoaderDelegate delegate;
301
302 // Fake a top-level request. Choose a URL which redirects so the request can
303 // be paused before the response comes in.
304 FrameHostMsg_BeginNavigation_Params params;
305 params.method = "GET";
306 params.url = net::URLRequestTestJob::test_url_redirect_to_url_2();
307 NavigationRequestInfo request_info(params);
308 request_info.first_party_for_cookies = params.url;
309 request_info.is_main_frame = true;
310
311 scoped_ptr<NavigationURLLoader> loader(
312 NavigationURLLoader::Create(browser_context_.get(),
313 0, request_info, NULL, &delegate));
314
315 // Wait for the request to redirect.
316 delegate.WaitForRequestRedirected();
317
318 // In the same event loop iteration, follow the redirect (allowing the
319 // response to go through) and destroy the loader.
320 loader->FollowRedirect();
321 loader.reset();
322
323 // Verify the URLRequestTestJob no longer has anything paused and that no
324 // response body was received.
325 base::RunLoop().RunUntilIdle();
326 EXPECT_FALSE(net::URLRequestTestJob::ProcessOnePendingMessage());
327 EXPECT_FALSE(delegate.body());
328 }
329
330 // Tests that the loader may be canceled by context.
331 TEST_F(NavigationURLLoaderTest, CancelByContext) {
332 TestNavigationURLLoaderDelegate delegate;
333
334 // Fake a top-level request.
335 FrameHostMsg_BeginNavigation_Params params;
336 params.method = "GET";
337 params.url = net::URLRequestTestJob::test_url_redirect_to_url_2();
338 NavigationRequestInfo request_info(params);
339 request_info.first_party_for_cookies = params.url;
340 request_info.is_main_frame = true;
341
342 scoped_ptr<NavigationURLLoader> loader(
343 NavigationURLLoader::Create(browser_context_.get(),
344 0, request_info, NULL, &delegate));
345
346 // Wait for the request to redirect.
347 delegate.WaitForRequestRedirected();
348
349 // Cancel all requests.
350 host_.CancelRequestsForContext(browser_context_->GetResourceContext());
351
352 // Wait for the request to now be aborted.
353 delegate.WaitForRequestFailed();
354 EXPECT_EQ(net::ERR_ABORTED, delegate.net_error());
355 }
356
357 // Tests that, if the request is blocked by the ResourceDispatcherHostDelegate,
358 // the caller is informed appropriately.
359 TEST_F(NavigationURLLoaderTest, RequestBlocked) {
360 RequestBlockingResourceDispatcherHostDelegate rdh_delegate;
361 host_.SetDelegate(&rdh_delegate);
362
363 TestNavigationURLLoaderDelegate delegate;
364
365 // Fake a top-level request.
366 FrameHostMsg_BeginNavigation_Params params;
367 params.method = "GET";
368 params.url = net::URLRequestTestJob::test_url_1();
369 NavigationRequestInfo request_info(params);
370 request_info.first_party_for_cookies = params.url;
371 request_info.is_main_frame = true;
372
373 scoped_ptr<NavigationURLLoader> loader(
374 NavigationURLLoader::Create(browser_context_.get(),
375 0, request_info, NULL, &delegate));
376
377 // Wait for the request to fail as expected.
378 delegate.WaitForRequestFailed();
379 EXPECT_EQ(net::ERR_ABORTED, delegate.net_error());
380
381 host_.SetDelegate(NULL);
382 }
383
384 // Tests that ownership leaves the loader once the response is received.
385 TEST_F(NavigationURLLoaderTest, LoaderDetached) {
386 TestNavigationURLLoaderDelegate delegate;
387
388 // Fake a top-level request to a URL whose body does not load immediately.
389 FrameHostMsg_BeginNavigation_Params params;
390 params.method = "GET";
391 params.url = net::URLRequestTestJob::test_url_2();
392 NavigationRequestInfo request_info(params);
393 request_info.first_party_for_cookies = params.url;
394 request_info.is_main_frame = true;
395
396 scoped_ptr<NavigationURLLoader> loader(
397 NavigationURLLoader::Create(browser_context_.get(),
398 0, request_info, NULL, &delegate));
399
400 // Wait for the response to come back.
401 delegate.WaitForResponseStarted();
402
403 // Check the response is correct.
404 EXPECT_EQ("text/html", delegate.response()->head.mime_type);
405 EXPECT_EQ("HTTP/1.1 200 OK",
406 delegate.response()->head.headers->GetStatusLine());
407
408 // Destroy the loader.
409 loader.reset();
410 base::RunLoop().RunUntilIdle();
411
412 // Check the body can still be fetched through the StreamHandle.
413 EXPECT_TRUE(net::URLRequestTestJob::ProcessOnePendingMessage());
414 EXPECT_EQ(net::URLRequestTestJob::test_data_2(),
415 FetchURL(delegate.body()->GetURL()));
416 }
417
418 // Tests that the request is owned by the body StreamHandle.
419 TEST_F(NavigationURLLoaderTest, OwnedByHandle) {
420 TestNavigationURLLoaderDelegate delegate;
421
422 // Fake a top-level request to a URL whose body does not load immediately.
423 FrameHostMsg_BeginNavigation_Params params;
424 params.method = "GET";
425 params.url = net::URLRequestTestJob::test_url_2();
426 NavigationRequestInfo request_info(params);
427 request_info.first_party_for_cookies = params.url;
428 request_info.is_main_frame = true;
429
430 scoped_ptr<NavigationURLLoader> loader(
431 NavigationURLLoader::Create(browser_context_.get(),
432 0, request_info, NULL, &delegate));
433
434 // Wait for the response to come back.
435 delegate.WaitForResponseStarted();
436
437 // Release the body.
438 delegate.ReleaseBody();
439 base::RunLoop().RunUntilIdle();
440
441 // Verify that URLRequestTestJob no longer has anything paused.
442 EXPECT_FALSE(net::URLRequestTestJob::ProcessOnePendingMessage());
443 }
444
445 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698