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.
5 #include "base/command_line.h"
6 #include "base/macros.h"
7 #include "base/time/time.h"
8 #include "content/browser/frame_host/navigation_controller_impl.h"
9 #include "content/browser/frame_host/navigation_entry_impl.h"
10 #include "content/browser/frame_host/navigation_request.h"
11 #include "content/browser/frame_host/navigation_request_info.h"
12 #include "content/browser/frame_host/navigator.h"
13 #include "content/browser/frame_host/navigator_impl.h"
14 #include "content/browser/frame_host/render_frame_host_manager.h"
15 #include "content/browser/site_instance_impl.h"
16 #include "content/browser/streams/stream.h"
17 #include "content/common/frame_messages.h"
18 #include "content/common/navigation_params.h"
19 #include "content/public/browser/stream_handle.h"
20 #include "content/public/common/content_switches.h"
21 #include "content/public/common/url_constants.h"
22 #include "content/public/common/url_utils.h"
23 #include "content/public/test/mock_render_process_host.h"
24 #include "content/test/browser_side_navigation_test_utils.h"
25 #include "content/test/test_navigation_url_loader.h"
26 #include "content/test/test_render_frame_host.h"
27 #include "content/test/test_web_contents.h"
28 #include "net/base/load_flags.h"
29 #include "net/http/http_response_headers.h"
30 #include "net/url_request/redirect_info.h"
31 #include "ui/base/page_transition_types.h"
32 #include "url/url_constants.h"
36 class NavigatorTestWithBrowserSideNavigation
37 : public RenderViewHostImplTestHarness
{
39 void SetUp() override
{
40 EnableBrowserSideNavigation();
41 RenderViewHostImplTestHarness::SetUp();
44 TestNavigationURLLoader
* GetLoaderForNavigationRequest(
45 NavigationRequest
* request
) const {
46 return static_cast<TestNavigationURLLoader
*>(request
->loader_for_testing());
49 void RequestNavigation(FrameTreeNode
* node
, const GURL
& url
) {
50 RequestNavigationWithParameters(node
, url
, Referrer(),
51 ui::PAGE_TRANSITION_LINK
,
52 NavigationController::NO_RELOAD
);
55 void RequestNavigationWithParameters(
58 const Referrer
& referrer
,
59 ui::PageTransition transition_type
,
60 NavigationController::ReloadType reload_type
) {
61 scoped_ptr
<NavigationEntryImpl
> entry(
62 NavigationEntryImpl::FromNavigationEntry(
63 NavigationController::CreateNavigationEntry(
69 controller().GetBrowserContext())));
70 static_cast<NavigatorImpl
*>(node
->navigator())->RequestNavigation(
71 node
, *entry
, reload_type
, base::TimeTicks::Now());
74 NavigationRequest
* GetNavigationRequestForFrameTreeNode(
75 FrameTreeNode
* frame_tree_node
) {
76 return static_cast<NavigatorImpl
*>(frame_tree_node
->navigator())
77 ->GetNavigationRequestForNodeForTesting(frame_tree_node
);
80 TestRenderFrameHost
* GetSpeculativeRenderFrameHost(FrameTreeNode
* node
) {
81 return static_cast<TestRenderFrameHost
*>(
82 node
->render_manager()->speculative_render_frame_host_
.get());
85 // Checks if this RenderFrameHost sent a single FrameMsg_CommitNavigation
86 // since the last clearing of the sink.
87 // Note: caller must invoke ClearMessages on the sink at some point before
88 // the tracked commit happens to clear up commit messages from previous
90 bool DidRenderFrameHostRequestCommit(RenderFrameHostImpl
* rfh
) {
91 MockRenderProcessHost
* rph
=
92 static_cast<MockRenderProcessHost
*>(rfh
->GetProcess());
93 const FrameMsg_CommitNavigation
* commit_message
=
94 static_cast<const FrameMsg_CommitNavigation
*>(
95 rph
->sink().GetUniqueMessageMatching(
96 FrameMsg_CommitNavigation::ID
));
97 return commit_message
&&
98 rfh
->GetRoutingID() == commit_message
->routing_id();
102 // PlzNavigate: Test a complete browser-initiated navigation starting with a
103 // non-live renderer.
104 TEST_F(NavigatorTestWithBrowserSideNavigation
,
105 SimpleBrowserInitiatedNavigationFromNonLiveRenderer
) {
106 const GURL
kUrl("http://chromium.org/");
108 EXPECT_FALSE(main_test_rfh()->IsRenderFrameLive());
110 // Start a browser-initiated navigation.
111 int32 site_instance_id
= main_test_rfh()->GetSiteInstance()->GetId();
112 FrameTreeNode
* node
= main_test_rfh()->frame_tree_node();
113 RequestNavigation(node
, kUrl
);
114 NavigationRequest
* request
= GetNavigationRequestForFrameTreeNode(node
);
115 ASSERT_TRUE(request
);
116 EXPECT_EQ(kUrl
, request
->common_params().url
);
117 EXPECT_TRUE(request
->browser_initiated());
119 // As there's no live renderer the navigation should not wait for a
120 // beforeUnload ACK from the renderer and start right away.
121 EXPECT_EQ(NavigationRequest::STARTED
, request
->state());
122 ASSERT_TRUE(GetLoaderForNavigationRequest(request
));
123 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
124 EXPECT_FALSE(node
->render_manager()->pending_frame_host());
126 // Have the current RenderFrameHost commit the navigation.
127 scoped_refptr
<ResourceResponse
> response(new ResourceResponse
);
128 GetLoaderForNavigationRequest(request
)
129 ->CallOnResponseStarted(response
, MakeEmptyStream());
130 EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh()));
131 EXPECT_EQ(NavigationRequest::RESPONSE_STARTED
, request
->state());
133 // Commit the navigation.
134 main_test_rfh()->SendNavigate(0, kUrl
);
135 EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT
, main_test_rfh()->rfh_state());
136 EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrl
),
137 main_test_rfh()->GetSiteInstance()->GetSiteURL());
138 EXPECT_EQ(kUrl
, contents()->GetLastCommittedURL());
139 EXPECT_FALSE(GetNavigationRequestForFrameTreeNode(node
));
140 EXPECT_FALSE(node
->render_manager()->pending_frame_host());
142 // The main RenderFrameHost should not have been changed, and the renderer
143 // should have been initialized.
144 EXPECT_EQ(site_instance_id
, main_test_rfh()->GetSiteInstance()->GetId());
145 EXPECT_TRUE(main_test_rfh()->IsRenderFrameLive());
147 // After a navigation is finished no speculative RenderFrameHost should
149 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
151 // With PlzNavigate enabled a pending RenderFrameHost should never exist.
152 EXPECT_FALSE(node
->render_manager()->pending_frame_host());
155 // PlzNavigate: Test a complete renderer-initiated same-site navigation.
156 TEST_F(NavigatorTestWithBrowserSideNavigation
,
157 SimpleRendererInitiatedNavigation
) {
158 const GURL
kUrl1("http://www.chromium.org/");
159 const GURL
kUrl2("http://www.chromium.org/Home");
161 contents()->NavigateAndCommit(kUrl1
);
162 EXPECT_TRUE(main_test_rfh()->IsRenderFrameLive());
164 // Start a renderer-initiated non-user-initiated navigation.
165 process()->sink().ClearMessages();
166 main_test_rfh()->SendBeginNavigationWithURL(kUrl2
, false);
167 FrameTreeNode
* node
= main_test_rfh()->frame_tree_node();
168 NavigationRequest
* request
= GetNavigationRequestForFrameTreeNode(node
);
169 ASSERT_TRUE(request
);
171 // The navigation is immediately started as there's no need to wait for
172 // beforeUnload to be executed.
173 EXPECT_EQ(NavigationRequest::STARTED
, request
->state());
174 EXPECT_FALSE(request
->begin_params().has_user_gesture
);
175 EXPECT_EQ(kUrl2
, request
->common_params().url
);
176 EXPECT_FALSE(request
->browser_initiated());
177 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
179 // Have the current RenderFrameHost commit the navigation.
180 scoped_refptr
<ResourceResponse
> response(new ResourceResponse
);
181 GetLoaderForNavigationRequest(request
)
182 ->CallOnResponseStarted(response
, MakeEmptyStream());
183 EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh()));
184 EXPECT_EQ(NavigationRequest::RESPONSE_STARTED
, request
->state());
186 // Commit the navigation.
187 main_test_rfh()->SendNavigate(0, kUrl2
);
188 EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT
, main_test_rfh()->rfh_state());
189 EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrl2
),
190 main_test_rfh()->GetSiteInstance()->GetSiteURL());
191 EXPECT_EQ(kUrl2
, contents()->GetLastCommittedURL());
192 EXPECT_FALSE(GetNavigationRequestForFrameTreeNode(node
));
193 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
194 EXPECT_FALSE(node
->render_manager()->pending_frame_host());
197 // PlzNavigate: Test that a beforeUnload denial cancels the navigation.
198 TEST_F(NavigatorTestWithBrowserSideNavigation
,
199 BeforeUnloadDenialCancelNavigation
) {
200 const GURL
kUrl1("http://www.google.com/");
201 const GURL
kUrl2("http://www.chromium.org/");
203 contents()->NavigateAndCommit(kUrl1
);
205 // Start a new navigation.
206 FrameTreeNode
* node
= main_test_rfh()->frame_tree_node();
207 RequestNavigation(node
, kUrl2
);
208 NavigationRequest
* request
= GetNavigationRequestForFrameTreeNode(node
);
209 ASSERT_TRUE(request
);
210 EXPECT_TRUE(request
->browser_initiated());
211 EXPECT_EQ(NavigationRequest::WAITING_FOR_RENDERER_RESPONSE
, request
->state());
212 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
214 // Simulate a beforeUnload denial.
215 main_test_rfh()->SendBeforeUnloadACK(false);
216 EXPECT_FALSE(GetNavigationRequestForFrameTreeNode(node
));
217 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
220 // PlzNavigate: Test that a proper NavigationRequest is created by
221 // RequestNavigation.
222 TEST_F(NavigatorTestWithBrowserSideNavigation
, BeginNavigation
) {
223 const GURL
kUrl1("http://www.google.com/");
224 const GURL
kUrl2("http://www.chromium.org/");
225 const GURL
kUrl3("http://www.gmail.com/");
227 contents()->NavigateAndCommit(kUrl1
);
230 FrameTreeNode
* root_node
= contents()->GetFrameTree()->root();
231 TestRenderFrameHost
* subframe_rfh
= main_test_rfh()->AppendChild("Child");
232 ASSERT_TRUE(subframe_rfh
);
234 // Start a navigation at the subframe.
235 FrameTreeNode
* subframe_node
= subframe_rfh
->frame_tree_node();
236 RequestNavigation(subframe_node
, kUrl2
);
237 NavigationRequest
* subframe_request
=
238 GetNavigationRequestForFrameTreeNode(subframe_node
);
239 TestNavigationURLLoader
* subframe_loader
=
240 GetLoaderForNavigationRequest(subframe_request
);
242 // Subframe navigations should start right away as they don't have to request
243 // beforeUnload to run at the renderer.
244 ASSERT_TRUE(subframe_request
);
245 ASSERT_TRUE(subframe_loader
);
246 EXPECT_EQ(NavigationRequest::STARTED
, subframe_request
->state());
247 EXPECT_EQ(kUrl2
, subframe_request
->common_params().url
);
248 EXPECT_EQ(kUrl2
, subframe_loader
->request_info()->common_params
.url
);
249 // First party for cookies url should be that of the main frame.
250 EXPECT_EQ(kUrl1
, subframe_loader
->request_info()->first_party_for_cookies
);
251 EXPECT_FALSE(subframe_loader
->request_info()->is_main_frame
);
252 EXPECT_TRUE(subframe_loader
->request_info()->parent_is_main_frame
);
253 EXPECT_TRUE(subframe_request
->browser_initiated());
254 EXPECT_FALSE(GetSpeculativeRenderFrameHost(root_node
));
256 // Subframe navigations should never create a speculative RenderFrameHost,
257 // unless site-per-process is enabled. In that case, as the subframe
258 // navigation is to a different site and is still ongoing, it should have one.
259 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
260 switches::kSitePerProcess
)) {
261 EXPECT_TRUE(GetSpeculativeRenderFrameHost(subframe_node
));
263 EXPECT_FALSE(GetSpeculativeRenderFrameHost(subframe_node
));
266 // Now start a navigation at the root node.
267 RequestNavigation(root_node
, kUrl3
);
268 NavigationRequest
* main_request
=
269 GetNavigationRequestForFrameTreeNode(root_node
);
270 ASSERT_TRUE(main_request
);
271 EXPECT_EQ(NavigationRequest::WAITING_FOR_RENDERER_RESPONSE
,
272 main_request
->state());
273 EXPECT_FALSE(GetSpeculativeRenderFrameHost(root_node
));
275 // Simulate a BeforeUnloadACK IPC on the main frame.
276 main_test_rfh()->SendBeforeUnloadACK(true);
277 TestNavigationURLLoader
* main_loader
=
278 GetLoaderForNavigationRequest(main_request
);
279 EXPECT_EQ(kUrl3
, main_request
->common_params().url
);
280 EXPECT_EQ(kUrl3
, main_loader
->request_info()->common_params
.url
);
281 EXPECT_EQ(kUrl3
, main_loader
->request_info()->first_party_for_cookies
);
282 EXPECT_TRUE(main_loader
->request_info()->is_main_frame
);
283 EXPECT_FALSE(main_loader
->request_info()->parent_is_main_frame
);
284 EXPECT_TRUE(main_request
->browser_initiated());
285 // BeforeUnloadACK was received from the renderer so the navigation should
287 EXPECT_EQ(NavigationRequest::STARTED
, main_request
->state());
289 // Main frame navigation to a different site should use a speculative
291 EXPECT_TRUE(GetSpeculativeRenderFrameHost(root_node
));
293 // As the main frame hasn't yet committed the subframe still exists. Thus, the
294 // above situation regarding subframe navigations is valid here.
295 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
296 switches::kSitePerProcess
)) {
297 EXPECT_TRUE(GetSpeculativeRenderFrameHost(subframe_node
));
299 EXPECT_FALSE(GetSpeculativeRenderFrameHost(subframe_node
));
303 // PlzNavigate: Test that committing an HTTP 204 or HTTP 205 response cancels
305 TEST_F(NavigatorTestWithBrowserSideNavigation
, NoContent
) {
306 const GURL
kUrl1("http://www.chromium.org/");
307 const GURL
kUrl2("http://www.google.com/");
310 contents()->NavigateAndCommit(kUrl1
);
311 FrameTreeNode
* node
= main_test_rfh()->frame_tree_node();
313 // Navigate to a different site.
314 process()->sink().ClearMessages();
315 RequestNavigation(node
, kUrl2
);
316 main_test_rfh()->SendBeforeUnloadACK(true);
318 NavigationRequest
* main_request
= GetNavigationRequestForFrameTreeNode(node
);
319 ASSERT_TRUE(main_request
);
321 // Navigations to a different site do create a speculative RenderFrameHost.
322 EXPECT_TRUE(GetSpeculativeRenderFrameHost(node
));
324 // Commit an HTTP 204 response.
325 scoped_refptr
<ResourceResponse
> response(new ResourceResponse
);
326 const char kNoContentHeaders
[] = "HTTP/1.1 204 No Content\0\0";
327 response
->head
.headers
= new net::HttpResponseHeaders(
328 std::string(kNoContentHeaders
, arraysize(kNoContentHeaders
)));
329 GetLoaderForNavigationRequest(main_request
)->CallOnResponseStarted(
330 response
, MakeEmptyStream());
332 // There should be no pending nor speculative RenderFrameHost; the navigation
334 EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh()));
335 EXPECT_FALSE(GetNavigationRequestForFrameTreeNode(node
));
336 EXPECT_FALSE(node
->render_manager()->pending_frame_host());
337 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
339 // Now, repeat the test with 205 Reset Content.
341 // Navigate to a different site again.
342 process()->sink().ClearMessages();
343 RequestNavigation(node
, kUrl2
);
344 main_test_rfh()->SendBeforeUnloadACK(true);
346 main_request
= GetNavigationRequestForFrameTreeNode(node
);
347 ASSERT_TRUE(main_request
);
348 EXPECT_TRUE(GetSpeculativeRenderFrameHost(node
));
350 // Commit an HTTP 205 response.
351 response
= new ResourceResponse
;
352 const char kResetContentHeaders
[] = "HTTP/1.1 205 Reset Content\0\0";
353 response
->head
.headers
= new net::HttpResponseHeaders(
354 std::string(kResetContentHeaders
, arraysize(kResetContentHeaders
)));
355 GetLoaderForNavigationRequest(main_request
)->CallOnResponseStarted(
356 response
, MakeEmptyStream());
358 // There should be no pending nor speculative RenderFrameHost; the navigation
360 EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh()));
361 EXPECT_FALSE(GetNavigationRequestForFrameTreeNode(node
));
362 EXPECT_FALSE(node
->render_manager()->pending_frame_host());
363 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
366 // PlzNavigate: Test that a new RenderFrameHost is created when doing a cross
368 TEST_F(NavigatorTestWithBrowserSideNavigation
, CrossSiteNavigation
) {
369 const GURL
kUrl1("http://www.chromium.org/");
370 const GURL
kUrl2("http://www.google.com/");
372 contents()->NavigateAndCommit(kUrl1
);
373 RenderFrameHostImpl
* initial_rfh
= main_test_rfh();
374 FrameTreeNode
* node
= main_test_rfh()->frame_tree_node();
376 // Navigate to a different site.
377 process()->sink().ClearMessages();
378 RequestNavigation(node
, kUrl2
);
379 NavigationRequest
* main_request
= GetNavigationRequestForFrameTreeNode(node
);
380 ASSERT_TRUE(main_request
);
381 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
383 // Receive the beforeUnload ACK.
384 main_test_rfh()->SendBeforeUnloadACK(true);
385 EXPECT_TRUE(GetSpeculativeRenderFrameHost(node
));
387 scoped_refptr
<ResourceResponse
> response(new ResourceResponse
);
388 GetLoaderForNavigationRequest(main_request
)->CallOnResponseStarted(
389 response
, MakeEmptyStream());
390 TestRenderFrameHost
* speculative_rfh
= GetSpeculativeRenderFrameHost(node
);
391 ASSERT_TRUE(speculative_rfh
);
392 EXPECT_TRUE(DidRenderFrameHostRequestCommit(speculative_rfh
));
393 EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh()));
395 speculative_rfh
->SendNavigate(0, kUrl2
);
397 RenderFrameHostImpl
* final_rfh
= main_test_rfh();
398 EXPECT_EQ(speculative_rfh
, final_rfh
);
399 EXPECT_NE(initial_rfh
, final_rfh
);
400 EXPECT_TRUE(final_rfh
->IsRenderFrameLive());
401 EXPECT_TRUE(final_rfh
->render_view_host()->IsRenderViewLive());
402 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
405 // PlzNavigate: Test that redirects are followed and the speculative
406 // RenderFrameHost logic behaves as expected.
407 TEST_F(NavigatorTestWithBrowserSideNavigation
, RedirectCrossSite
) {
408 const GURL
kUrl1("http://www.chromium.org/");
409 const GURL
kUrl2("http://www.google.com/");
411 contents()->NavigateAndCommit(kUrl1
);
412 RenderFrameHostImpl
* rfh
= main_test_rfh();
413 FrameTreeNode
* node
= main_test_rfh()->frame_tree_node();
415 // Navigate to a URL on the same site.
416 process()->sink().ClearMessages();
417 RequestNavigation(node
, kUrl1
);
418 main_test_rfh()->SendBeforeUnloadACK(true);
419 NavigationRequest
* main_request
= GetNavigationRequestForFrameTreeNode(node
);
420 ASSERT_TRUE(main_request
);
421 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
423 // It then redirects to another site.
424 net::RedirectInfo redirect_info
;
425 redirect_info
.status_code
= 302;
426 redirect_info
.new_method
= "GET";
427 redirect_info
.new_url
= kUrl2
;
428 redirect_info
.new_first_party_for_cookies
= kUrl2
;
429 scoped_refptr
<ResourceResponse
> response(new ResourceResponse
);
430 GetLoaderForNavigationRequest(main_request
)->CallOnRequestRedirected(
431 redirect_info
, response
);
433 // The redirect should have been followed.
434 EXPECT_EQ(1, GetLoaderForNavigationRequest(main_request
)->redirect_count());
435 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
437 // Have the RenderFrameHost commit the navigation.
438 response
= new ResourceResponse
;
439 GetLoaderForNavigationRequest(main_request
)->CallOnResponseStarted(
440 response
, MakeEmptyStream());
441 TestRenderFrameHost
* final_speculative_rfh
=
442 GetSpeculativeRenderFrameHost(node
);
443 EXPECT_TRUE(final_speculative_rfh
);
444 EXPECT_TRUE(DidRenderFrameHostRequestCommit(final_speculative_rfh
));
446 // Commit the navigation.
447 final_speculative_rfh
->SendNavigate(0, kUrl2
);
448 RenderFrameHostImpl
* final_rfh
= main_test_rfh();
449 ASSERT_TRUE(final_rfh
);
450 EXPECT_NE(rfh
, final_rfh
);
451 EXPECT_EQ(final_speculative_rfh
, final_rfh
);
452 EXPECT_TRUE(final_rfh
->IsRenderFrameLive());
453 EXPECT_TRUE(final_rfh
->render_view_host()->IsRenderViewLive());
454 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
457 // PlzNavigate: Test that a navigation is canceled if another browser-initiated
458 // request has been issued in the meantime. Also confirms that the speculative
459 // RenderFrameHost is correctly updated in the process.
460 TEST_F(NavigatorTestWithBrowserSideNavigation
,
461 BrowserInitiatedNavigationCancel
) {
462 const GURL
kUrl0("http://www.wikipedia.org/");
463 const GURL
kUrl1("http://www.chromium.org/");
464 const GURL kUrl1_site
= SiteInstance::GetSiteForURL(browser_context(), kUrl1
);
465 const GURL
kUrl2("http://www.google.com/");
466 const GURL kUrl2_site
= SiteInstance::GetSiteForURL(browser_context(), kUrl2
);
469 contents()->NavigateAndCommit(kUrl0
);
470 FrameTreeNode
* node
= main_test_rfh()->frame_tree_node();
472 // Request navigation to the 1st URL.
473 process()->sink().ClearMessages();
474 RequestNavigation(node
, kUrl1
);
475 main_test_rfh()->SendBeforeUnloadACK(true);
476 NavigationRequest
* request1
= GetNavigationRequestForFrameTreeNode(node
);
477 ASSERT_TRUE(request1
);
478 EXPECT_EQ(kUrl1
, request1
->common_params().url
);
479 EXPECT_TRUE(request1
->browser_initiated());
480 base::WeakPtr
<TestNavigationURLLoader
> loader1
=
481 GetLoaderForNavigationRequest(request1
)->AsWeakPtr();
482 EXPECT_TRUE(loader1
);
484 // Confirm a speculative RenderFrameHost was created.
485 TestRenderFrameHost
* speculative_rfh
= GetSpeculativeRenderFrameHost(node
);
486 ASSERT_TRUE(speculative_rfh
);
487 int32 site_instance_id_1
= speculative_rfh
->GetSiteInstance()->GetId();
488 EXPECT_EQ(kUrl1_site
, speculative_rfh
->GetSiteInstance()->GetSiteURL());
490 // Request navigation to the 2nd URL; the NavigationRequest must have been
491 // replaced by a new one with a different URL.
492 RequestNavigation(node
, kUrl2
);
493 main_test_rfh()->SendBeforeUnloadACK(true);
494 NavigationRequest
* request2
= GetNavigationRequestForFrameTreeNode(node
);
495 ASSERT_TRUE(request2
);
496 EXPECT_EQ(kUrl2
, request2
->common_params().url
);
497 EXPECT_TRUE(request2
->browser_initiated());
499 // Confirm that the first loader got destroyed.
500 EXPECT_FALSE(loader1
);
502 // Confirm that a new speculative RenderFrameHost was created.
503 speculative_rfh
= GetSpeculativeRenderFrameHost(node
);
504 ASSERT_TRUE(speculative_rfh
);
505 int32 site_instance_id_2
= speculative_rfh
->GetSiteInstance()->GetId();
506 EXPECT_NE(site_instance_id_1
, site_instance_id_2
);
508 // Have the RenderFrameHost commit the navigation.
509 scoped_refptr
<ResourceResponse
> response(new ResourceResponse
);
510 GetLoaderForNavigationRequest(request2
)->CallOnResponseStarted(
511 response
, MakeEmptyStream());
512 EXPECT_TRUE(DidRenderFrameHostRequestCommit(speculative_rfh
));
513 EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh()));
515 // Commit the navigation.
516 speculative_rfh
->SendNavigate(0, kUrl2
);
518 // Confirm that the commit corresponds to the new request.
519 ASSERT_TRUE(main_test_rfh());
520 EXPECT_EQ(kUrl2_site
, main_test_rfh()->GetSiteInstance()->GetSiteURL());
521 EXPECT_EQ(kUrl2
, contents()->GetLastCommittedURL());
523 // Confirm that the committed RenderFrameHost is the latest speculative one.
524 EXPECT_EQ(site_instance_id_2
, main_test_rfh()->GetSiteInstance()->GetId());
527 // PlzNavigate: Test that a browser-initiated navigation is canceled if a
528 // renderer-initiated user-initiated request has been issued in the meantime.
529 TEST_F(NavigatorTestWithBrowserSideNavigation
,
530 RendererUserInitiatedNavigationCancel
) {
531 const GURL
kUrl0("http://www.wikipedia.org/");
532 const GURL
kUrl1("http://www.chromium.org/");
533 const GURL
kUrl2("http://www.google.com/");
536 contents()->NavigateAndCommit(kUrl0
);
537 FrameTreeNode
* node
= main_test_rfh()->frame_tree_node();
539 // Start a browser-initiated navigation to the 1st URL and receive its
541 process()->sink().ClearMessages();
542 RequestNavigation(node
, kUrl1
);
543 main_test_rfh()->SendBeforeUnloadACK(true);
544 NavigationRequest
* request1
= GetNavigationRequestForFrameTreeNode(node
);
545 ASSERT_TRUE(request1
);
546 EXPECT_EQ(kUrl1
, request1
->common_params().url
);
547 EXPECT_TRUE(request1
->browser_initiated());
548 base::WeakPtr
<TestNavigationURLLoader
> loader1
=
549 GetLoaderForNavigationRequest(request1
)->AsWeakPtr();
550 EXPECT_TRUE(loader1
);
552 // Confirm a speculative RenderFrameHost was created.
553 TestRenderFrameHost
* speculative_rfh
= GetSpeculativeRenderFrameHost(node
);
554 ASSERT_TRUE(speculative_rfh
);
555 int32 site_instance_id_1
= speculative_rfh
->GetSiteInstance()->GetId();
557 // Now receive a renderer-initiated user-initiated request. It should replace
558 // the current NavigationRequest.
559 main_test_rfh()->SendBeginNavigationWithURL(kUrl2
, true);
560 NavigationRequest
* request2
= GetNavigationRequestForFrameTreeNode(node
);
561 ASSERT_TRUE(request2
);
562 EXPECT_EQ(kUrl2
, request2
->common_params().url
);
563 EXPECT_FALSE(request2
->browser_initiated());
564 EXPECT_TRUE(request2
->begin_params().has_user_gesture
);
566 // Confirm that the first loader got destroyed.
567 EXPECT_FALSE(loader1
);
569 // Confirm that a new speculative RenderFrameHost was created.
570 speculative_rfh
= GetSpeculativeRenderFrameHost(node
);
571 ASSERT_TRUE(speculative_rfh
);
572 int32 site_instance_id_2
= speculative_rfh
->GetSiteInstance()->GetId();
573 EXPECT_NE(site_instance_id_1
, site_instance_id_2
);
575 // Have the RenderFrameHost commit the navigation.
576 scoped_refptr
<ResourceResponse
> response(new ResourceResponse
);
577 GetLoaderForNavigationRequest(request2
)
578 ->CallOnResponseStarted(response
, MakeEmptyStream());
579 EXPECT_TRUE(DidRenderFrameHostRequestCommit(speculative_rfh
));
580 EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh()));
582 // Commit the navigation.
583 speculative_rfh
->SendNavigate(0, kUrl2
);
585 // Confirm that the commit corresponds to the new request.
586 ASSERT_TRUE(main_test_rfh());
587 EXPECT_EQ(kUrl2
, contents()->GetLastCommittedURL());
589 // Confirm that the committed RenderFrameHost is the latest speculative one.
590 EXPECT_EQ(site_instance_id_2
, main_test_rfh()->GetSiteInstance()->GetId());
593 // PlzNavigate: Test that a renderer-initiated user-initiated navigation is NOT
594 // canceled if a renderer-initiated non-user-initiated request is issued in the
596 TEST_F(NavigatorTestWithBrowserSideNavigation
,
597 RendererNonUserInitiatedNavigationDoesntCancelRendererUserInitiated
) {
598 const GURL
kUrl0("http://www.wikipedia.org/");
599 const GURL
kUrl1("http://www.chromium.org/");
600 const GURL
kUrl2("http://www.google.com/");
603 contents()->NavigateAndCommit(kUrl0
);
604 FrameTreeNode
* node
= main_test_rfh()->frame_tree_node();
606 // Start a renderer-initiated user-initiated navigation to the 1st URL.
607 process()->sink().ClearMessages();
608 main_test_rfh()->SendBeginNavigationWithURL(kUrl1
, true);
609 NavigationRequest
* request1
= GetNavigationRequestForFrameTreeNode(node
);
610 ASSERT_TRUE(request1
);
611 EXPECT_EQ(kUrl1
, request1
->common_params().url
);
612 EXPECT_FALSE(request1
->browser_initiated());
613 EXPECT_TRUE(request1
->begin_params().has_user_gesture
);
614 EXPECT_TRUE(GetSpeculativeRenderFrameHost(node
));
616 // Now receive a renderer-initiated non-user-initiated request. Nothing should
618 main_test_rfh()->SendBeginNavigationWithURL(kUrl2
, false);
619 NavigationRequest
* request2
= GetNavigationRequestForFrameTreeNode(node
);
620 ASSERT_TRUE(request2
);
621 EXPECT_EQ(request1
, request2
);
622 EXPECT_EQ(kUrl1
, request2
->common_params().url
);
623 EXPECT_FALSE(request2
->browser_initiated());
624 EXPECT_TRUE(request2
->begin_params().has_user_gesture
);
625 TestRenderFrameHost
* speculative_rfh
= GetSpeculativeRenderFrameHost(node
);
626 ASSERT_TRUE(speculative_rfh
);
628 // Have the RenderFrameHost commit the navigation.
629 scoped_refptr
<ResourceResponse
> response(new ResourceResponse
);
630 GetLoaderForNavigationRequest(request2
)
631 ->CallOnResponseStarted(response
, MakeEmptyStream());
632 EXPECT_TRUE(DidRenderFrameHostRequestCommit(speculative_rfh
));
633 EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh()));
635 // Commit the navigation.
636 speculative_rfh
->SendNavigate(0, kUrl1
);
637 EXPECT_EQ(kUrl1
, contents()->GetLastCommittedURL());
640 // PlzNavigate: Test that a browser-initiated navigation is NOT canceled if a
641 // renderer-initiated non-user-initiated request is issued in the meantime.
642 TEST_F(NavigatorTestWithBrowserSideNavigation
,
643 RendererNonUserInitiatedNavigationDoesntCancelBrowserInitiated
) {
644 const GURL
kUrl0("http://www.wikipedia.org/");
645 const GURL
kUrl1("http://www.chromium.org/");
646 const GURL
kUrl2("http://www.google.com/");
649 contents()->NavigateAndCommit(kUrl0
);
650 FrameTreeNode
* node
= main_test_rfh()->frame_tree_node();
652 // Start a browser-initiated navigation to the 1st URL.
653 process()->sink().ClearMessages();
654 RequestNavigation(node
, kUrl1
);
655 NavigationRequest
* request1
= GetNavigationRequestForFrameTreeNode(node
);
656 ASSERT_TRUE(request1
);
657 EXPECT_EQ(kUrl1
, request1
->common_params().url
);
658 EXPECT_TRUE(request1
->browser_initiated());
659 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
661 // Now receive a renderer-initiated non-user-initiated request. Nothing should
663 main_test_rfh()->SendBeginNavigationWithURL(kUrl2
, false);
664 NavigationRequest
* request2
= GetNavigationRequestForFrameTreeNode(node
);
665 ASSERT_TRUE(request2
);
666 EXPECT_EQ(request1
, request2
);
667 EXPECT_EQ(kUrl1
, request2
->common_params().url
);
668 EXPECT_TRUE(request2
->browser_initiated());
669 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
671 // Now receive the beforeUnload ACK from the still ongoing navigation.
672 main_test_rfh()->SendBeforeUnloadACK(true);
673 TestRenderFrameHost
* speculative_rfh
= GetSpeculativeRenderFrameHost(node
);
674 ASSERT_TRUE(speculative_rfh
);
676 // Have the RenderFrameHost commit the navigation.
677 scoped_refptr
<ResourceResponse
> response(new ResourceResponse
);
678 GetLoaderForNavigationRequest(request2
)
679 ->CallOnResponseStarted(response
, MakeEmptyStream());
680 EXPECT_TRUE(DidRenderFrameHostRequestCommit(speculative_rfh
));
681 EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh()));
683 // Commit the navigation.
684 speculative_rfh
->SendNavigate(0, kUrl1
);
685 EXPECT_EQ(kUrl1
, contents()->GetLastCommittedURL());
688 // PlzNavigate: Test that a renderer-initiated non-user-initiated navigation is
689 // canceled if a another similar request is issued in the meantime.
690 TEST_F(NavigatorTestWithBrowserSideNavigation
,
691 RendererNonUserInitiatedNavigationCancelSimilarNavigation
) {
692 const GURL
kUrl0("http://www.wikipedia.org/");
693 const GURL
kUrl1("http://www.chromium.org/");
694 const GURL
kUrl2("http://www.google.com/");
697 contents()->NavigateAndCommit(kUrl0
);
698 FrameTreeNode
* node
= main_test_rfh()->frame_tree_node();
700 // Start a renderer-initiated non-user-initiated navigation to the 1st URL.
701 process()->sink().ClearMessages();
702 main_test_rfh()->SendBeginNavigationWithURL(kUrl1
, false);
703 NavigationRequest
* request1
= GetNavigationRequestForFrameTreeNode(node
);
704 ASSERT_TRUE(request1
);
705 EXPECT_EQ(kUrl1
, request1
->common_params().url
);
706 EXPECT_FALSE(request1
->browser_initiated());
707 EXPECT_FALSE(request1
->begin_params().has_user_gesture
);
708 EXPECT_TRUE(GetSpeculativeRenderFrameHost(node
));
709 base::WeakPtr
<TestNavigationURLLoader
> loader1
=
710 GetLoaderForNavigationRequest(request1
)->AsWeakPtr();
711 EXPECT_TRUE(loader1
);
713 // Now receive a 2nd similar request that should replace the current one.
714 main_test_rfh()->SendBeginNavigationWithURL(kUrl2
, false);
715 NavigationRequest
* request2
= GetNavigationRequestForFrameTreeNode(node
);
716 EXPECT_EQ(kUrl2
, request2
->common_params().url
);
717 EXPECT_FALSE(request2
->browser_initiated());
718 EXPECT_FALSE(request2
->begin_params().has_user_gesture
);
719 TestRenderFrameHost
* speculative_rfh
= GetSpeculativeRenderFrameHost(node
);
720 ASSERT_TRUE(speculative_rfh
);
722 // Confirm that the first loader got destroyed.
723 EXPECT_FALSE(loader1
);
725 // Have the RenderFrameHost commit the navigation.
726 scoped_refptr
<ResourceResponse
> response(new ResourceResponse
);
727 GetLoaderForNavigationRequest(request2
)
728 ->CallOnResponseStarted(response
, MakeEmptyStream());
729 EXPECT_TRUE(DidRenderFrameHostRequestCommit(speculative_rfh
));
730 EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh()));
732 // Commit the navigation.
733 speculative_rfh
->SendNavigate(0, kUrl2
);
734 EXPECT_EQ(kUrl2
, contents()->GetLastCommittedURL());
737 // PlzNavigate: Test that a reload navigation is properly signaled to the
738 // RenderFrame when the navigation can commit. A speculative RenderFrameHost
739 // should not be created at any step.
740 TEST_F(NavigatorTestWithBrowserSideNavigation
, Reload
) {
741 const GURL
kUrl("http://www.google.com/");
742 contents()->NavigateAndCommit(kUrl
);
744 FrameTreeNode
* node
= main_test_rfh()->frame_tree_node();
745 RequestNavigationWithParameters(node
, kUrl
, Referrer(),
746 ui::PAGE_TRANSITION_LINK
,
747 NavigationController::RELOAD
);
748 // A NavigationRequest should have been generated.
749 NavigationRequest
* main_request
= GetNavigationRequestForFrameTreeNode(node
);
750 ASSERT_TRUE(main_request
!= NULL
);
751 EXPECT_EQ(FrameMsg_Navigate_Type::RELOAD
,
752 main_request
->common_params().navigation_type
);
753 main_test_rfh()->PrepareForCommit(kUrl
);
754 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
756 main_test_rfh()->SendNavigate(0, kUrl
);
757 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
759 // Now do a shift+reload.
760 RequestNavigationWithParameters(node
, kUrl
, Referrer(),
761 ui::PAGE_TRANSITION_LINK
,
762 NavigationController::RELOAD_IGNORING_CACHE
);
763 // A NavigationRequest should have been generated.
764 main_request
= GetNavigationRequestForFrameTreeNode(node
);
765 ASSERT_TRUE(main_request
!= NULL
);
766 EXPECT_EQ(FrameMsg_Navigate_Type::RELOAD_IGNORING_CACHE
,
767 main_request
->common_params().navigation_type
);
768 main_test_rfh()->PrepareForCommit(kUrl
);
769 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
772 // PlzNavigate: Confirm that a speculative RenderFrameHost is used when
773 // navigating from one site to another.
774 TEST_F(NavigatorTestWithBrowserSideNavigation
,
775 SpeculativeRendererWorksBaseCase
) {
776 // Navigate to an initial site.
777 const GURL
kUrlInit("http://wikipedia.org/");
778 contents()->NavigateAndCommit(kUrlInit
);
779 FrameTreeNode
* node
= main_test_rfh()->frame_tree_node();
781 // Begin navigating to another site.
782 const GURL
kUrl("http://google.com/");
783 process()->sink().ClearMessages();
784 RequestNavigation(node
, kUrl
);
785 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
787 // Receive the beforeUnload ACK.
788 main_test_rfh()->SendBeforeUnloadACK(true);
789 TestRenderFrameHost
* speculative_rfh
= GetSpeculativeRenderFrameHost(node
);
790 ASSERT_TRUE(speculative_rfh
);
791 EXPECT_NE(speculative_rfh
, main_test_rfh());
792 EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrl
),
793 speculative_rfh
->GetSiteInstance()->GetSiteURL());
794 EXPECT_FALSE(node
->render_manager()->pending_frame_host());
795 int32 site_instance_id
= speculative_rfh
->GetSiteInstance()->GetId();
797 // Ask Navigator to commit the navigation by simulating a call to
798 // OnResponseStarted.
799 scoped_refptr
<ResourceResponse
> response(new ResourceResponse
);
800 GetLoaderForNavigationRequest(GetNavigationRequestForFrameTreeNode(node
))
801 ->CallOnResponseStarted(response
, MakeEmptyStream());
802 speculative_rfh
= GetSpeculativeRenderFrameHost(node
);
803 ASSERT_TRUE(speculative_rfh
);
804 EXPECT_TRUE(DidRenderFrameHostRequestCommit(speculative_rfh
));
805 EXPECT_EQ(site_instance_id
, speculative_rfh
->GetSiteInstance()->GetId());
806 EXPECT_FALSE(node
->render_manager()->pending_frame_host());
808 // Invoke OnDidCommitProvisionalLoad.
809 speculative_rfh
->SendNavigate(0, kUrl
);
810 EXPECT_EQ(site_instance_id
, main_test_rfh()->GetSiteInstance()->GetId());
811 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
812 EXPECT_FALSE(node
->render_manager()->pending_frame_host());
815 // PlzNavigate: Confirm that a speculative RenderFrameHost is thrown away when
816 // the final URL's site differs from the initial one due to redirects.
817 TEST_F(NavigatorTestWithBrowserSideNavigation
,
818 SpeculativeRendererDiscardedAfterRedirectToAnotherSite
) {
819 // Navigate to an initial site.
820 const GURL
kUrlInit("http://wikipedia.org/");
821 contents()->NavigateAndCommit(kUrlInit
);
822 FrameTreeNode
* node
= main_test_rfh()->frame_tree_node();
823 int32 init_site_instance_id
= main_test_rfh()->GetSiteInstance()->GetId();
825 // Begin navigating to another site.
826 const GURL
kUrl("http://google.com/");
827 process()->sink().ClearMessages();
828 RequestNavigation(node
, kUrl
);
829 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
831 // Receive the beforeUnload ACK.
832 main_test_rfh()->SendBeforeUnloadACK(true);
833 TestRenderFrameHost
* speculative_rfh
= GetSpeculativeRenderFrameHost(node
);
834 int32 site_instance_id
= speculative_rfh
->GetSiteInstance()->GetId();
835 EXPECT_NE(init_site_instance_id
, site_instance_id
);
836 EXPECT_EQ(init_site_instance_id
, main_test_rfh()->GetSiteInstance()->GetId());
837 ASSERT_TRUE(speculative_rfh
);
838 EXPECT_NE(speculative_rfh
, main_test_rfh());
839 EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrl
),
840 speculative_rfh
->GetSiteInstance()->GetSiteURL());
842 // It then redirects to yet another site.
843 NavigationRequest
* main_request
= GetNavigationRequestForFrameTreeNode(node
);
844 ASSERT_TRUE(main_request
);
845 const GURL
kUrlRedirect("https://www.google.com/");
846 net::RedirectInfo redirect_info
;
847 redirect_info
.status_code
= 302;
848 redirect_info
.new_method
= "GET";
849 redirect_info
.new_url
= kUrlRedirect
;
850 redirect_info
.new_first_party_for_cookies
= kUrlRedirect
;
851 scoped_refptr
<ResourceResponse
> response(new ResourceResponse
);
852 GetLoaderForNavigationRequest(main_request
)
853 ->CallOnRequestRedirected(redirect_info
, response
);
854 EXPECT_EQ(init_site_instance_id
, main_test_rfh()->GetSiteInstance()->GetId());
855 speculative_rfh
= GetSpeculativeRenderFrameHost(node
);
856 ASSERT_TRUE(speculative_rfh
);
858 // For now, ensure that the speculative RenderFrameHost does not change after
860 // TODO(carlosk): once the speculative RenderFrameHost updates with redirects
861 // this next check will be changed to verify that it actually happens.
862 EXPECT_EQ(site_instance_id
, speculative_rfh
->GetSiteInstance()->GetId());
864 // Commit the navigation with Navigator by simulating the call to
865 // OnResponseStarted.
866 response
= new ResourceResponse
;
867 GetLoaderForNavigationRequest(main_request
)
868 ->CallOnResponseStarted(response
, MakeEmptyStream());
869 speculative_rfh
= GetSpeculativeRenderFrameHost(node
);
870 EXPECT_TRUE(DidRenderFrameHostRequestCommit(speculative_rfh
));
871 EXPECT_EQ(init_site_instance_id
, main_test_rfh()->GetSiteInstance()->GetId());
873 // Once commit happens the speculative RenderFrameHost is updated to match the
874 // known final SiteInstance.
875 ASSERT_TRUE(speculative_rfh
);
876 EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrlRedirect
),
877 speculative_rfh
->GetSiteInstance()->GetSiteURL());
878 int32 redirect_site_instance_id
= speculative_rfh
->GetSiteInstance()->GetId();
879 EXPECT_NE(init_site_instance_id
, redirect_site_instance_id
);
880 EXPECT_NE(site_instance_id
, redirect_site_instance_id
);
882 // Invoke OnDidCommitProvisionalLoad.
883 speculative_rfh
->SendNavigate(0, kUrlRedirect
);
885 // Check that the speculative RenderFrameHost was swapped in.
886 EXPECT_EQ(redirect_site_instance_id
,
887 main_test_rfh()->GetSiteInstance()->GetId());
888 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
891 // PlzNavigate: Verify that a previously swapped out RenderFrameHost is
892 // correctly reused when spawning a speculative RenderFrameHost in a navigation
893 // using the same SiteInstance.
894 TEST_F(NavigatorTestWithBrowserSideNavigation
,
895 SpeculativeRendererReuseSwappedOutRFH
) {
896 // Navigate to an initial site.
897 const GURL
kUrl1("http://wikipedia.org/");
898 contents()->NavigateAndCommit(kUrl1
);
899 TestRenderFrameHost
* rfh1
= main_test_rfh();
900 FrameTreeNode
* node
= rfh1
->frame_tree_node();
901 RenderFrameHostManager
* rfhm
= node
->render_manager();
903 // Increment active frame count to cause the RenderFrameHost to be swapped out
904 // (instead of immediately destroyed).
905 rfh1
->GetSiteInstance()->increment_active_frame_count();
907 // Navigate to another site to swap out the initial RenderFrameHost.
908 const GURL
kUrl2("http://chromium.org/");
909 contents()->NavigateAndCommit(kUrl2
);
910 ASSERT_NE(rfh1
, main_test_rfh());
911 EXPECT_NE(RenderFrameHostImpl::STATE_DEFAULT
, rfh1
->rfh_state());
912 EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT
, main_test_rfh()->rfh_state());
913 EXPECT_TRUE(rfhm
->IsOnSwappedOutList(rfh1
));
915 // Now go back to the initial site so that the swapped out RenderFrameHost
917 process()->sink().ClearMessages();
918 static_cast<MockRenderProcessHost
*>(rfh1
->GetProcess())
921 RequestNavigation(node
, kUrl1
);
922 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
924 main_test_rfh()->SendBeforeUnloadACK(true);
925 EXPECT_EQ(rfh1
, GetSpeculativeRenderFrameHost(node
));
926 EXPECT_NE(RenderFrameHostImpl::STATE_DEFAULT
,
927 GetSpeculativeRenderFrameHost(node
)->rfh_state());
929 scoped_refptr
<ResourceResponse
> response(new ResourceResponse
);
930 GetLoaderForNavigationRequest(GetNavigationRequestForFrameTreeNode(node
))
931 ->CallOnResponseStarted(response
, MakeEmptyStream());
932 EXPECT_EQ(rfh1
, GetSpeculativeRenderFrameHost(node
));
933 EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT
,
934 GetSpeculativeRenderFrameHost(node
)->rfh_state());
935 EXPECT_TRUE(DidRenderFrameHostRequestCommit(rfh1
));
936 EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh()));
938 rfh1
->SendNavigate(1, kUrl1
);
939 EXPECT_EQ(rfh1
, main_test_rfh());
940 EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT
, rfh1
->rfh_state());
941 EXPECT_FALSE(rfhm
->IsOnSwappedOutList(rfh1
));
944 // PlzNavigate: Verify that data urls are properly handled.
945 TEST_F(NavigatorTestWithBrowserSideNavigation
, DataUrls
) {
946 const GURL
kUrl1("http://wikipedia.org/");
947 const GURL
kUrl2("data:text/html,test");
949 // Navigate to an initial site.
950 contents()->NavigateAndCommit(kUrl1
);
951 FrameTreeNode
* node
= main_test_rfh()->frame_tree_node();
953 // Navigate to a data url.
954 RequestNavigation(node
, kUrl2
);
955 NavigationRequest
* navigation_request
=
956 GetNavigationRequestForFrameTreeNode(node
);
957 ASSERT_TRUE(navigation_request
);
958 EXPECT_EQ(NavigationRequest::WAITING_FOR_RENDERER_RESPONSE
,
959 navigation_request
->state());
960 main_test_rfh()->SendBeforeUnloadACK(true);
962 // The request should not have been sent to the IO thread but committed
964 EXPECT_EQ(NavigationRequest::RESPONSE_STARTED
,
965 navigation_request
->state());
966 EXPECT_FALSE(navigation_request
->loader_for_testing());
967 TestRenderFrameHost
* speculative_rfh
= GetSpeculativeRenderFrameHost(node
);
968 ASSERT_TRUE(speculative_rfh
);
969 speculative_rfh
->SendNavigate(0, kUrl2
);
970 EXPECT_EQ(main_test_rfh(), speculative_rfh
);
972 // Go back to the initial site.
973 contents()->NavigateAndCommit(kUrl1
);
975 // Do a renderer-initiated navigation to a data url. The request should not be
976 // sent to the IO thread, nor committed.
977 TestRenderFrameHost
* main_rfh
= main_test_rfh();
978 main_rfh
->SendBeginNavigationWithURL(kUrl2
, true);
979 navigation_request
= GetNavigationRequestForFrameTreeNode(node
);
980 ASSERT_TRUE(navigation_request
);
981 EXPECT_EQ(NavigationRequest::RESPONSE_STARTED
,
982 navigation_request
->state());
983 EXPECT_FALSE(navigation_request
->loader_for_testing());
984 speculative_rfh
= GetSpeculativeRenderFrameHost(node
);
985 ASSERT_TRUE(speculative_rfh
);
986 speculative_rfh
->SendNavigate(0, kUrl2
);
987 EXPECT_EQ(main_test_rfh(), speculative_rfh
);
990 } // namespace content