1 // Copyright 2015 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 "content/browser/frame_host/navigation_request.h"
6 #include "base/bind.h"
7 #include "base/macros.h"
8 #include "base/optional.h"
9 #include "build/build_config.h"
10 #include "content/public/browser/navigation_throttle.h"
11 #include "content/public/browser/ssl_status.h"
12 #include "content/public/common/content_client.h"
13 #include "content/public/common/url_constants.h"
14 #include "content/public/test/test_navigation_throttle.h"
15 #include "content/test/navigation_simulator_impl.h"
16 #include "content/test/test_content_browser_client.h"
17 #include "content/test/test_render_frame_host.h"
18 #include "content/test/test_web_contents.h"
19 #include "net/ssl/ssl_connection_status_flags.h"
20 #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h"
21
22 namespace content {
23
24 // Test version of a NavigationThrottle that will execute a callback when
25 // called.
26 class DeletingNavigationThrottle : public NavigationThrottle {
27 public:
DeletingNavigationThrottle(NavigationHandle * handle,const base::RepeatingClosure & deletion_callback)28 DeletingNavigationThrottle(NavigationHandle* handle,
29 const base::RepeatingClosure& deletion_callback)
30 : NavigationThrottle(handle), deletion_callback_(deletion_callback) {}
~DeletingNavigationThrottle()31 ~DeletingNavigationThrottle() override {}
32
WillStartRequest()33 NavigationThrottle::ThrottleCheckResult WillStartRequest() override {
34 deletion_callback_.Run();
35 return NavigationThrottle::PROCEED;
36 }
37
WillRedirectRequest()38 NavigationThrottle::ThrottleCheckResult WillRedirectRequest() override {
39 deletion_callback_.Run();
40 return NavigationThrottle::PROCEED;
41 }
42
WillFailRequest()43 NavigationThrottle::ThrottleCheckResult WillFailRequest() override {
44 deletion_callback_.Run();
45 return NavigationThrottle::PROCEED;
46 }
47
WillProcessResponse()48 NavigationThrottle::ThrottleCheckResult WillProcessResponse() override {
49 deletion_callback_.Run();
50 return NavigationThrottle::PROCEED;
51 }
52
GetNameForLogging()53 const char* GetNameForLogging() override {
54 return "DeletingNavigationThrottle";
55 }
56
57 private:
58 base::RepeatingClosure deletion_callback_;
59 };
60
61 class NavigationRequestTest : public RenderViewHostImplTestHarness {
62 public:
NavigationRequestTest()63 NavigationRequestTest()
64 : was_callback_called_(false),
65 callback_result_(NavigationThrottle::DEFER) {}
66
SetUp()67 void SetUp() override {
68 RenderViewHostImplTestHarness::SetUp();
69 CreateNavigationHandle();
70 contents()->GetMainFrame()->InitializeRenderFrameIfNeeded();
71 }
72
TearDown()73 void TearDown() override {
74 // Release the |request_| before destroying the WebContents, to match
75 // the WebContentsObserverSanityChecker expectations.
76 request_.reset();
77 RenderViewHostImplTestHarness::TearDown();
78 }
79
CancelDeferredNavigation(NavigationThrottle::ThrottleCheckResult result)80 void CancelDeferredNavigation(
81 NavigationThrottle::ThrottleCheckResult result) {
82 request_->CancelDeferredNavigationInternal(result);
83 }
84
85 // Helper function to call WillStartRequest on |handle|. If this function
86 // returns DEFER, |callback_result_| will be set to the actual result of
87 // the throttle checks when they are finished.
SimulateWillStartRequest()88 void SimulateWillStartRequest() {
89 was_callback_called_ = false;
90 callback_result_ = NavigationThrottle::DEFER;
91
92 // It's safe to use base::Unretained since the NavigationRequest is owned by
93 // the NavigationRequestTest.
94 request_->set_complete_callback_for_testing(
95 base::BindOnce(&NavigationRequestTest::UpdateThrottleCheckResult,
96 base::Unretained(this)));
97
98 request_->WillStartRequest();
99 }
100
101 // Helper function to call WillRedirectRequest on |handle|. If this function
102 // returns DEFER, |callback_result_| will be set to the actual result of the
103 // throttle checks when they are finished.
104 // TODO(clamy): this should also simulate that WillStartRequest was called if
105 // it has not been called before.
SimulateWillRedirectRequest()106 void SimulateWillRedirectRequest() {
107 was_callback_called_ = false;
108 callback_result_ = NavigationThrottle::DEFER;
109
110 // It's safe to use base::Unretained since the NavigationRequest is owned by
111 // the NavigationRequestTest.
112 request_->set_complete_callback_for_testing(
113 base::BindOnce(&NavigationRequestTest::UpdateThrottleCheckResult,
114 base::Unretained(this)));
115
116 request_->WillRedirectRequest(GURL(), nullptr);
117 }
118
119 // Helper function to call WillFailRequest on |handle|. If this function
120 // returns DEFER, |callback_result_| will be set to the actual result of the
121 // throttle checks when they are finished.
SimulateWillFailRequest(net::Error net_error_code,const base::Optional<net::SSLInfo> ssl_info=base::nullopt)122 void SimulateWillFailRequest(
123 net::Error net_error_code,
124 const base::Optional<net::SSLInfo> ssl_info = base::nullopt) {
125 was_callback_called_ = false;
126 callback_result_ = NavigationThrottle::DEFER;
127 request_->set_net_error(net_error_code);
128
129 // It's safe to use base::Unretained since the NavigationRequest is owned by
130 // the NavigationRequestTest.
131 request_->set_complete_callback_for_testing(
132 base::BindOnce(&NavigationRequestTest::UpdateThrottleCheckResult,
133 base::Unretained(this)));
134
135 request_->WillFailRequest();
136 }
137
138 // Whether the callback was called.
was_callback_called() const139 bool was_callback_called() const { return was_callback_called_; }
140
141 // Returns the callback_result.
callback_result() const142 NavigationThrottle::ThrottleCheckResult callback_result() const {
143 return callback_result_;
144 }
145
state()146 NavigationRequest::NavigationState state() { return request_->state(); }
147
call_counts_match(TestNavigationThrottle * throttle,int start,int redirect,int failure,int process)148 bool call_counts_match(TestNavigationThrottle* throttle,
149 int start,
150 int redirect,
151 int failure,
152 int process) {
153 return start == throttle->GetCallCount(
154 TestNavigationThrottle::WILL_START_REQUEST) &&
155 redirect == throttle->GetCallCount(
156 TestNavigationThrottle::WILL_REDIRECT_REQUEST) &&
157 failure == throttle->GetCallCount(
158 TestNavigationThrottle::WILL_FAIL_REQUEST) &&
159 process == throttle->GetCallCount(
160 TestNavigationThrottle::WILL_PROCESS_RESPONSE);
161 }
162
163 // Creates, register and returns a TestNavigationThrottle that will
164 // synchronously return |result| on checks by default.
CreateTestNavigationThrottle(NavigationThrottle::ThrottleCheckResult result)165 TestNavigationThrottle* CreateTestNavigationThrottle(
166 NavigationThrottle::ThrottleCheckResult result) {
167 TestNavigationThrottle* test_throttle =
168 new TestNavigationThrottle(request_.get());
169 test_throttle->SetResponseForAllMethods(TestNavigationThrottle::SYNCHRONOUS,
170 result);
171 request_->RegisterThrottleForTesting(
172 std::unique_ptr<TestNavigationThrottle>(test_throttle));
173 return test_throttle;
174 }
175
176 // Creates, register and returns a TestNavigationThrottle that will
177 // synchronously return |result| on check for the given |method|, and
178 // NavigationThrottle::PROCEED otherwise.
CreateTestNavigationThrottle(TestNavigationThrottle::ThrottleMethod method,NavigationThrottle::ThrottleCheckResult result)179 TestNavigationThrottle* CreateTestNavigationThrottle(
180 TestNavigationThrottle::ThrottleMethod method,
181 NavigationThrottle::ThrottleCheckResult result) {
182 TestNavigationThrottle* test_throttle =
183 CreateTestNavigationThrottle(NavigationThrottle::PROCEED);
184 test_throttle->SetResponse(method, TestNavigationThrottle::SYNCHRONOUS,
185 result);
186 return test_throttle;
187 }
188
189 // TODO(zetamoo): Use NavigationSimulator instead of creating
190 // NavigationRequest and NavigationHandleImpl.
CreateNavigationHandle()191 void CreateNavigationHandle() {
192 auto common_params = CreateCommonNavigationParams();
193 common_params->initiator_origin =
194 url::Origin::Create(GURL("https://initiator.example.com"));
195 request_ = NavigationRequest::CreateBrowserInitiated(
196 main_test_rfh()->frame_tree_node(), std::move(common_params),
197 CreateCommitNavigationParams(), false /* browser-initiated */,
198 std::string(), nullptr, nullptr, nullptr, nullptr);
199 request_->StartNavigation(true);
200 }
201
202 private:
203 // The callback provided to NavigationRequest::WillStartRequest,
204 // NavigationRequest::WillRedirectRequest, and
205 // NavigationRequest::WillFailRequest during the tests.
UpdateThrottleCheckResult(NavigationThrottle::ThrottleCheckResult result)206 bool UpdateThrottleCheckResult(
207 NavigationThrottle::ThrottleCheckResult result) {
208 callback_result_ = result;
209 was_callback_called_ = true;
210 return true;
211 }
212
213 std::unique_ptr<NavigationRequest> request_;
214 bool was_callback_called_;
215 NavigationThrottle::ThrottleCheckResult callback_result_;
216 };
217
218 // Checks that the request_context_type is properly set.
219 // Note: can be extended to cover more internal members.
TEST_F(NavigationRequestTest,SimpleDataChecksRedirectAndProcess)220 TEST_F(NavigationRequestTest, SimpleDataChecksRedirectAndProcess) {
221 const GURL kUrl1 = GURL("http://chromium.org");
222 const GURL kUrl2 = GURL("http://google.com");
223 auto navigation =
224 NavigationSimulatorImpl::CreateRendererInitiated(kUrl1, main_rfh());
225 navigation->Start();
226 EXPECT_EQ(blink::mojom::RequestContextType::HYPERLINK,
227 NavigationRequest::From(navigation->GetNavigationHandle())
228 ->request_context_type());
229 EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN,
230 navigation->GetNavigationHandle()->GetConnectionInfo());
231
232 navigation->set_http_connection_info(
233 net::HttpResponseInfo::CONNECTION_INFO_HTTP1_1);
234 navigation->Redirect(kUrl2);
235 EXPECT_EQ(blink::mojom::RequestContextType::HYPERLINK,
236 NavigationRequest::From(navigation->GetNavigationHandle())
237 ->request_context_type());
238 EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_HTTP1_1,
239 navigation->GetNavigationHandle()->GetConnectionInfo());
240
241 navigation->set_http_connection_info(
242 net::HttpResponseInfo::CONNECTION_INFO_QUIC_35);
243 navigation->ReadyToCommit();
244 EXPECT_EQ(blink::mojom::RequestContextType::HYPERLINK,
245 NavigationRequest::From(navigation->GetNavigationHandle())
246 ->request_context_type());
247 EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_QUIC_35,
248 navigation->GetNavigationHandle()->GetConnectionInfo());
249 }
250
TEST_F(NavigationRequestTest,SimpleDataCheckNoRedirect)251 TEST_F(NavigationRequestTest, SimpleDataCheckNoRedirect) {
252 const GURL kUrl = GURL("http://chromium.org");
253 auto navigation =
254 NavigationSimulatorImpl::CreateRendererInitiated(kUrl, main_rfh());
255 navigation->Start();
256 EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN,
257 navigation->GetNavigationHandle()->GetConnectionInfo());
258
259 navigation->set_http_connection_info(
260 net::HttpResponseInfo::CONNECTION_INFO_QUIC_35);
261 navigation->ReadyToCommit();
262 EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_QUIC_35,
263 navigation->GetNavigationHandle()->GetConnectionInfo());
264 }
265
TEST_F(NavigationRequestTest,SimpleDataChecksFailure)266 TEST_F(NavigationRequestTest, SimpleDataChecksFailure) {
267 const GURL kUrl = GURL("http://chromium.org");
268 auto navigation =
269 NavigationSimulatorImpl::CreateRendererInitiated(kUrl, main_rfh());
270 navigation->Start();
271 EXPECT_EQ(blink::mojom::RequestContextType::HYPERLINK,
272 NavigationRequest::From(navigation->GetNavigationHandle())
273 ->request_context_type());
274 EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN,
275 navigation->GetNavigationHandle()->GetConnectionInfo());
276
277 navigation->Fail(net::ERR_CERT_DATE_INVALID);
278 EXPECT_EQ(blink::mojom::RequestContextType::HYPERLINK,
279 NavigationRequest::From(navigation->GetNavigationHandle())
280 ->request_context_type());
281 EXPECT_EQ(net::ERR_CERT_DATE_INVALID,
282 navigation->GetNavigationHandle()->GetNetErrorCode());
283 }
284
285 // Checks that a navigation deferred during WillStartRequest can be properly
286 // cancelled.
TEST_F(NavigationRequestTest,CancelDeferredWillStart)287 TEST_F(NavigationRequestTest, CancelDeferredWillStart) {
288 TestNavigationThrottle* test_throttle =
289 CreateTestNavigationThrottle(NavigationThrottle::DEFER);
290 EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, state());
291 EXPECT_TRUE(call_counts_match(test_throttle, 0, 0, 0, 0));
292
293 // Simulate WillStartRequest. The request should be deferred. The callback
294 // should not have been called.
295 SimulateWillStartRequest();
296 EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, state());
297 EXPECT_FALSE(was_callback_called());
298 EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 0, 0));
299
300 // Cancel the request. The callback should have been called.
301 CancelDeferredNavigation(NavigationThrottle::CANCEL_AND_IGNORE);
302 EXPECT_EQ(NavigationRequest::CANCELING, state());
303 EXPECT_TRUE(was_callback_called());
304 EXPECT_EQ(NavigationThrottle::CANCEL_AND_IGNORE, callback_result());
305 EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 0, 0));
306 }
307
308 // Checks that a navigation deferred during WillRedirectRequest can be properly
309 // cancelled.
TEST_F(NavigationRequestTest,CancelDeferredWillRedirect)310 TEST_F(NavigationRequestTest, CancelDeferredWillRedirect) {
311 TestNavigationThrottle* test_throttle =
312 CreateTestNavigationThrottle(NavigationThrottle::DEFER);
313 EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, state());
314 EXPECT_TRUE(call_counts_match(test_throttle, 0, 0, 0, 0));
315
316 // Simulate WillRedirectRequest. The request should be deferred. The callback
317 // should not have been called.
318 SimulateWillRedirectRequest();
319 EXPECT_EQ(NavigationRequest::WILL_REDIRECT_REQUEST, state());
320 EXPECT_FALSE(was_callback_called());
321 EXPECT_TRUE(call_counts_match(test_throttle, 0, 1, 0, 0));
322
323 // Cancel the request. The callback should have been called.
324 CancelDeferredNavigation(NavigationThrottle::CANCEL_AND_IGNORE);
325 EXPECT_EQ(NavigationRequest::CANCELING, state());
326 EXPECT_TRUE(was_callback_called());
327 EXPECT_EQ(NavigationThrottle::CANCEL_AND_IGNORE, callback_result());
328 EXPECT_TRUE(call_counts_match(test_throttle, 0, 1, 0, 0));
329 }
330
331 // Checks that a navigation deferred during WillFailRequest can be properly
332 // cancelled.
TEST_F(NavigationRequestTest,CancelDeferredWillFail)333 TEST_F(NavigationRequestTest, CancelDeferredWillFail) {
334 TestNavigationThrottle* test_throttle = CreateTestNavigationThrottle(
335 TestNavigationThrottle::WILL_FAIL_REQUEST, NavigationThrottle::DEFER);
336 EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, state());
337 EXPECT_TRUE(call_counts_match(test_throttle, 0, 0, 0, 0));
338
339 // Simulate WillStartRequest.
340 SimulateWillStartRequest();
341 EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 0, 0));
342
343 // Simulate WillFailRequest. The request should be deferred. The callback
344 // should not have been called.
345 SimulateWillFailRequest(net::ERR_CERT_DATE_INVALID);
346 EXPECT_EQ(NavigationRequest::WILL_FAIL_REQUEST, state());
347 EXPECT_FALSE(was_callback_called());
348 EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 1, 0));
349
350 // Cancel the request. The callback should have been called.
351 CancelDeferredNavigation(NavigationThrottle::CANCEL_AND_IGNORE);
352 EXPECT_EQ(NavigationRequest::CANCELING, state());
353 EXPECT_TRUE(was_callback_called());
354 EXPECT_EQ(NavigationThrottle::CANCEL_AND_IGNORE, callback_result());
355 EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 1, 0));
356 }
357
358 // Checks that a navigation deferred can be canceled and not ignored.
TEST_F(NavigationRequestTest,CancelDeferredWillRedirectNoIgnore)359 TEST_F(NavigationRequestTest, CancelDeferredWillRedirectNoIgnore) {
360 TestNavigationThrottle* test_throttle =
361 CreateTestNavigationThrottle(NavigationThrottle::DEFER);
362 EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, state());
363 EXPECT_TRUE(call_counts_match(test_throttle, 0, 0, 0, 0));
364
365 // Simulate WillStartRequest. The request should be deferred. The callback
366 // should not have been called.
367 SimulateWillStartRequest();
368 EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, state());
369 EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 0, 0));
370
371 // Cancel the request. The callback should have been called with CANCEL, and
372 // not CANCEL_AND_IGNORE.
373 CancelDeferredNavigation(NavigationThrottle::CANCEL);
374 EXPECT_EQ(NavigationRequest::CANCELING, state());
375 EXPECT_TRUE(was_callback_called());
376 EXPECT_EQ(NavigationThrottle::CANCEL, callback_result());
377 EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 0, 0));
378 }
379
380 // Checks that a navigation deferred by WillFailRequest can be canceled and not
381 // ignored.
TEST_F(NavigationRequestTest,CancelDeferredWillFailNoIgnore)382 TEST_F(NavigationRequestTest, CancelDeferredWillFailNoIgnore) {
383 TestNavigationThrottle* test_throttle = CreateTestNavigationThrottle(
384 TestNavigationThrottle::WILL_FAIL_REQUEST, NavigationThrottle::DEFER);
385 EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, state());
386 EXPECT_TRUE(call_counts_match(test_throttle, 0, 0, 0, 0));
387
388 // Simulate WillStartRequest.
389 SimulateWillStartRequest();
390 EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 0, 0));
391
392 // Simulate WillFailRequest. The request should be deferred. The callback
393 // should not have been called.
394 SimulateWillFailRequest(net::ERR_CERT_DATE_INVALID);
395 EXPECT_EQ(NavigationRequest::WILL_FAIL_REQUEST, state());
396 EXPECT_FALSE(was_callback_called());
397 EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 1, 0));
398
399 // Cancel the request. The callback should have been called with CANCEL, and
400 // not CANCEL_AND_IGNORE.
401 CancelDeferredNavigation(NavigationThrottle::CANCEL);
402 EXPECT_EQ(NavigationRequest::CANCELING, state());
403 EXPECT_TRUE(was_callback_called());
404 EXPECT_EQ(NavigationThrottle::CANCEL, callback_result());
405 EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 1, 0));
406 }
407
408 // Checks that data from the SSLInfo passed into SimulateWillStartRequest() is
409 // stored on the handle.
TEST_F(NavigationRequestTest,WillFailRequestSetsSSLInfo)410 TEST_F(NavigationRequestTest, WillFailRequestSetsSSLInfo) {
411 uint16_t cipher_suite = 0xc02f; // TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
412 int connection_status = 0;
413 net::SSLConnectionStatusSetCipherSuite(cipher_suite, &connection_status);
414
415 // Set some test values.
416 net::SSLInfo ssl_info;
417 ssl_info.cert_status = net::CERT_STATUS_AUTHORITY_INVALID;
418 ssl_info.connection_status = connection_status;
419
420 const GURL kUrl = GURL("https://chromium.org");
421 auto navigation =
422 NavigationSimulatorImpl::CreateRendererInitiated(kUrl, main_rfh());
423 navigation->SetSSLInfo(ssl_info);
424 navigation->Fail(net::ERR_CERT_DATE_INVALID);
425
426 EXPECT_EQ(net::CERT_STATUS_AUTHORITY_INVALID,
427 navigation->GetNavigationHandle()->GetSSLInfo()->cert_status);
428 EXPECT_EQ(connection_status,
429 navigation->GetNavigationHandle()->GetSSLInfo()->connection_status);
430 }
431
432 namespace {
433
434 // Helper throttle which checks that it can access NavigationHandle's
435 // RenderFrameHost in WillFailRequest() and then defers the failure.
436 class GetRenderFrameHostOnFailureNavigationThrottle
437 : public NavigationThrottle {
438 public:
GetRenderFrameHostOnFailureNavigationThrottle(NavigationHandle * handle)439 GetRenderFrameHostOnFailureNavigationThrottle(NavigationHandle* handle)
440 : NavigationThrottle(handle) {}
~GetRenderFrameHostOnFailureNavigationThrottle()441 ~GetRenderFrameHostOnFailureNavigationThrottle() override {}
442
WillFailRequest()443 NavigationThrottle::ThrottleCheckResult WillFailRequest() override {
444 EXPECT_TRUE(navigation_handle()->GetRenderFrameHost());
445 return NavigationThrottle::DEFER;
446 }
447
GetNameForLogging()448 const char* GetNameForLogging() override {
449 return "GetRenderFrameHostOnFailureNavigationThrottle";
450 }
451
452 private:
453 DISALLOW_COPY_AND_ASSIGN(GetRenderFrameHostOnFailureNavigationThrottle);
454 };
455
456 class ThrottleTestContentBrowserClient : public ContentBrowserClient {
CreateThrottlesForNavigation(NavigationHandle * navigation_handle)457 std::vector<std::unique_ptr<NavigationThrottle>> CreateThrottlesForNavigation(
458 NavigationHandle* navigation_handle) override {
459 std::vector<std::unique_ptr<NavigationThrottle>> throttle;
460 throttle.push_back(
461 std::make_unique<GetRenderFrameHostOnFailureNavigationThrottle>(
462 navigation_handle));
463 return throttle;
464 }
465 };
466
467 } // namespace
468
469 // Verify that the NavigationHandle::GetRenderFrameHost() can be retrieved by a
470 // throttle in WillFailRequest(), as well as after deferring the failure. This
471 // is allowed, since at that point the final RenderFrameHost will have already
472 // been chosen. See https://crbug.com/817881.
TEST_F(NavigationRequestTest,WillFailRequestCanAccessRenderFrameHost)473 TEST_F(NavigationRequestTest, WillFailRequestCanAccessRenderFrameHost) {
474 std::unique_ptr<ContentBrowserClient> client(
475 new ThrottleTestContentBrowserClient);
476 ContentBrowserClient* old_browser_client =
477 SetBrowserClientForTesting(client.get());
478
479 const GURL kUrl = GURL("http://chromium.org");
480 auto navigation =
481 NavigationSimulatorImpl::CreateRendererInitiated(kUrl, main_rfh());
482 navigation->SetAutoAdvance(false);
483 navigation->Start();
484 navigation->Fail(net::ERR_CERT_DATE_INVALID);
485 EXPECT_EQ(
486 NavigationRequest::WILL_FAIL_REQUEST,
487 NavigationRequest::From(navigation->GetNavigationHandle())->state());
488 EXPECT_TRUE(navigation->GetNavigationHandle()->GetRenderFrameHost());
489 NavigationRequest::From(navigation->GetNavigationHandle())
490 ->CallResumeForTesting();
491 EXPECT_TRUE(navigation->GetNavigationHandle()->GetRenderFrameHost());
492
493 SetBrowserClientForTesting(old_browser_client);
494 }
495
496 } // namespace content
497