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