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/macros.h"
6 #include "base/time/time.h"
7 #include "content/browser/frame_host/navigation_controller_impl.h"
8 #include "content/browser/frame_host/navigation_entry_impl.h"
9 #include "content/browser/frame_host/navigation_request.h"
10 #include "content/browser/frame_host/navigation_request_info.h"
11 #include "content/browser/frame_host/navigator.h"
12 #include "content/browser/frame_host/navigator_impl.h"
13 #include "content/browser/frame_host/render_frame_host_manager.h"
14 #include "content/browser/site_instance_impl.h"
15 #include "content/browser/streams/stream.h"
16 #include "content/common/frame_messages.h"
17 #include "content/common/navigation_params.h"
18 #include "content/common/site_isolation_policy.h"
19 #include "content/public/browser/stream_handle.h"
20 #include "content/public/common/url_constants.h"
21 #include "content/public/common/url_utils.h"
22 #include "content/public/test/mock_render_process_host.h"
23 #include "content/public/test/test_utils.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"
34 #if !defined(OS_ANDROID)
35 #include "content/browser/compositor/test/no_transport_image_transport_factory.h"
40 class NavigatorTestWithBrowserSideNavigation
41 : public RenderViewHostImplTestHarness
{
43 // Re-defines the private RenderFrameHostManager::SiteInstanceDescriptor here
44 // to allow access to it from tests.
45 typedef RenderFrameHostManager::SiteInstanceDescriptor SiteInstanceDescriptor
;
47 void SetUp() override
{
48 #if !defined(OS_ANDROID)
49 ImageTransportFactory::InitializeForUnitTests(
50 scoped_ptr
<ImageTransportFactory
>(
51 new NoTransportImageTransportFactory
));
53 EnableBrowserSideNavigation();
54 RenderViewHostImplTestHarness::SetUp();
57 void TearDown() override
{
58 RenderViewHostImplTestHarness::TearDown();
59 #if !defined(OS_ANDROID)
60 ImageTransportFactory::Terminate();
64 TestNavigationURLLoader
* GetLoaderForNavigationRequest(
65 NavigationRequest
* request
) const {
66 return static_cast<TestNavigationURLLoader
*>(request
->loader_for_testing());
69 // Requests a navigation of the specified FrameTreeNode to the specified URL;
70 // returns the unique ID of the pending NavigationEntry.
71 int RequestNavigation(FrameTreeNode
* node
, const GURL
& url
) {
72 return RequestNavigationWithParameters(node
, url
, Referrer(),
73 ui::PAGE_TRANSITION_LINK
);
76 // Requests a navigation of the specified FrameTreeNode to the specified URL,
77 // using other specified parameters; returns the unique ID of the pending
79 int RequestNavigationWithParameters(
82 const Referrer
& referrer
,
83 ui::PageTransition transition_type
) {
84 NavigationController::LoadURLParams
load_params(url
);
85 load_params
.frame_tree_node_id
= node
->frame_tree_node_id();
86 load_params
.referrer
= referrer
;
87 load_params
.transition_type
= transition_type
;
89 controller().LoadURLWithParams(load_params
);
90 return controller().GetPendingEntry()->GetUniqueID();
93 TestRenderFrameHost
* GetSpeculativeRenderFrameHost(FrameTreeNode
* node
) {
94 return static_cast<TestRenderFrameHost
*>(
95 node
->render_manager()->speculative_render_frame_host_
.get());
98 // Checks if this RenderFrameHost sent a single FrameMsg_CommitNavigation
99 // since the last clearing of the sink.
100 // Note: caller must invoke ClearMessages on the sink at some point before
101 // the tracked commit happens to clear up commit messages from previous
103 bool DidRenderFrameHostRequestCommit(TestRenderFrameHost
* rfh
) {
104 const IPC::Message
* message
=
105 rfh
->GetProcess()->sink().GetUniqueMessageMatching(
106 FrameMsg_CommitNavigation::ID
);
107 return message
&& rfh
->GetRoutingID() == message
->routing_id();
110 SiteInstance
* ConvertToSiteInstance(RenderFrameHostManager
* rfhm
,
111 const SiteInstanceDescriptor
& descriptor
,
112 SiteInstance
* candidate_instance
) {
113 return rfhm
->ConvertToSiteInstance(descriptor
, candidate_instance
);
117 // PlzNavigate: Test a complete browser-initiated navigation starting with a
118 // non-live renderer.
119 TEST_F(NavigatorTestWithBrowserSideNavigation
,
120 SimpleBrowserInitiatedNavigationFromNonLiveRenderer
) {
121 const GURL
kUrl("http://chromium.org/");
123 EXPECT_FALSE(main_test_rfh()->IsRenderFrameLive());
125 // Start a browser-initiated navigation.
126 int32 site_instance_id
= main_test_rfh()->GetSiteInstance()->GetId();
127 FrameTreeNode
* node
= main_test_rfh()->frame_tree_node();
128 int entry_id
= RequestNavigation(node
, kUrl
);
129 NavigationRequest
* request
= node
->navigation_request();
130 ASSERT_TRUE(request
);
131 EXPECT_EQ(kUrl
, request
->common_params().url
);
132 EXPECT_TRUE(request
->browser_initiated());
134 // As there's no live renderer the navigation should not wait for a
135 // beforeUnload ACK from the renderer and start right away.
136 EXPECT_EQ(NavigationRequest::STARTED
, request
->state());
137 ASSERT_TRUE(GetLoaderForNavigationRequest(request
));
138 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
139 EXPECT_FALSE(node
->render_manager()->pending_frame_host());
141 // Have the current RenderFrameHost commit the navigation.
142 scoped_refptr
<ResourceResponse
> response(new ResourceResponse
);
143 GetLoaderForNavigationRequest(request
)
144 ->CallOnResponseStarted(response
, MakeEmptyStream());
145 EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh()));
146 EXPECT_TRUE(main_test_rfh()->is_loading());
147 EXPECT_FALSE(node
->navigation_request());
149 // Commit the navigation.
150 main_test_rfh()->SendNavigate(0, entry_id
, true, kUrl
);
151 EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT
, main_test_rfh()->rfh_state());
152 EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrl
),
153 main_test_rfh()->GetSiteInstance()->GetSiteURL());
154 EXPECT_EQ(kUrl
, contents()->GetLastCommittedURL());
155 EXPECT_FALSE(node
->render_manager()->pending_frame_host());
157 // The main RenderFrameHost should not have been changed, and the renderer
158 // should have been initialized.
159 EXPECT_EQ(site_instance_id
, main_test_rfh()->GetSiteInstance()->GetId());
160 EXPECT_TRUE(main_test_rfh()->IsRenderFrameLive());
162 // After a navigation is finished no speculative RenderFrameHost should
164 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
166 // With PlzNavigate enabled a pending RenderFrameHost should never exist.
167 EXPECT_FALSE(node
->render_manager()->pending_frame_host());
170 // PlzNavigate: Test a complete renderer-initiated same-site navigation.
171 TEST_F(NavigatorTestWithBrowserSideNavigation
,
172 SimpleRendererInitiatedSameSiteNavigation
) {
173 const GURL
kUrl1("http://www.chromium.org/");
174 const GURL
kUrl2("http://www.chromium.org/Home");
176 contents()->NavigateAndCommit(kUrl1
);
177 EXPECT_TRUE(main_test_rfh()->IsRenderFrameLive());
179 // Start a renderer-initiated non-user-initiated navigation.
180 process()->sink().ClearMessages();
181 main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl2
, false);
182 FrameTreeNode
* node
= main_test_rfh()->frame_tree_node();
183 NavigationRequest
* request
= node
->navigation_request();
184 ASSERT_TRUE(request
);
186 // The navigation is immediately started as there's no need to wait for
187 // beforeUnload to be executed.
188 EXPECT_EQ(NavigationRequest::STARTED
, request
->state());
189 EXPECT_FALSE(request
->begin_params().has_user_gesture
);
190 EXPECT_EQ(kUrl2
, request
->common_params().url
);
191 EXPECT_FALSE(request
->browser_initiated());
192 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
194 // Have the current RenderFrameHost commit the navigation.
195 scoped_refptr
<ResourceResponse
> response(new ResourceResponse
);
196 GetLoaderForNavigationRequest(request
)
197 ->CallOnResponseStarted(response
, MakeEmptyStream());
198 EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh()));
199 EXPECT_TRUE(main_test_rfh()->is_loading());
200 EXPECT_FALSE(node
->navigation_request());
202 // Commit the navigation.
203 main_test_rfh()->SendNavigate(1, 0, true, kUrl2
);
204 EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT
, main_test_rfh()->rfh_state());
205 EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrl2
),
206 main_test_rfh()->GetSiteInstance()->GetSiteURL());
207 EXPECT_EQ(kUrl2
, contents()->GetLastCommittedURL());
208 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
209 EXPECT_FALSE(node
->render_manager()->pending_frame_host());
212 // PlzNavigate: Test a complete renderer-initiated navigation that should be
213 // cross-site but does not result in a SiteInstance swap because its
214 // renderer-initiated.
215 TEST_F(NavigatorTestWithBrowserSideNavigation
,
216 SimpleRendererInitiatedCrossSiteNavigation
) {
217 const GURL
kUrl1("http://www.chromium.org/");
218 const GURL
kUrl2("http://www.google.com");
220 contents()->NavigateAndCommit(kUrl1
);
221 EXPECT_TRUE(main_test_rfh()->IsRenderFrameLive());
222 int32 site_instance_id_1
= main_test_rfh()->GetSiteInstance()->GetId();
224 // Start a renderer-initiated non-user-initiated navigation.
225 process()->sink().ClearMessages();
226 main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl2
, false);
227 FrameTreeNode
* node
= main_test_rfh()->frame_tree_node();
228 NavigationRequest
* request
= node
->navigation_request();
229 ASSERT_TRUE(request
);
231 // The navigation is immediately started as there's no need to wait for
232 // beforeUnload to be executed.
233 EXPECT_EQ(NavigationRequest::STARTED
, request
->state());
234 EXPECT_FALSE(request
->begin_params().has_user_gesture
);
235 EXPECT_EQ(kUrl2
, request
->common_params().url
);
236 EXPECT_FALSE(request
->browser_initiated());
237 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
239 // Have the current RenderFrameHost commit the navigation.
240 scoped_refptr
<ResourceResponse
> response(new ResourceResponse
);
241 GetLoaderForNavigationRequest(request
)
242 ->CallOnResponseStarted(response
, MakeEmptyStream());
243 EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh()));
244 EXPECT_TRUE(main_test_rfh()->is_loading());
245 EXPECT_FALSE(node
->navigation_request());
247 // Commit the navigation.
248 main_test_rfh()->SendNavigate(1, 0, true, kUrl2
);
249 EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT
, main_test_rfh()->rfh_state());
250 EXPECT_EQ(kUrl2
, contents()->GetLastCommittedURL());
251 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
252 EXPECT_FALSE(node
->render_manager()->pending_frame_host());
254 // The SiteInstance did not change.
255 EXPECT_EQ(site_instance_id_1
, main_test_rfh()->GetSiteInstance()->GetId());
258 // PlzNavigate: Test that a beforeUnload denial cancels the navigation.
259 TEST_F(NavigatorTestWithBrowserSideNavigation
,
260 BeforeUnloadDenialCancelNavigation
) {
261 const GURL
kUrl1("http://www.google.com/");
262 const GURL
kUrl2("http://www.chromium.org/");
264 contents()->NavigateAndCommit(kUrl1
);
266 // Start a new navigation.
267 FrameTreeNode
* node
= main_test_rfh()->frame_tree_node();
268 RequestNavigation(node
, kUrl2
);
269 NavigationRequest
* request
= node
->navigation_request();
270 ASSERT_TRUE(request
);
271 EXPECT_TRUE(request
->browser_initiated());
272 EXPECT_EQ(NavigationRequest::WAITING_FOR_RENDERER_RESPONSE
, request
->state());
273 EXPECT_TRUE(GetSpeculativeRenderFrameHost(node
));
274 RenderFrameDeletedObserver
rfh_deleted_observer(
275 GetSpeculativeRenderFrameHost(node
));
277 // Simulate a beforeUnload denial.
278 main_test_rfh()->SendBeforeUnloadACK(false);
279 EXPECT_FALSE(node
->navigation_request());
280 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
281 EXPECT_TRUE(rfh_deleted_observer
.deleted());
284 // PlzNavigate: Test that a proper NavigationRequest is created by
285 // RequestNavigation.
286 TEST_F(NavigatorTestWithBrowserSideNavigation
, BeginNavigation
) {
287 const GURL
kUrl1("http://www.google.com/");
288 const GURL
kUrl2("http://www.chromium.org/");
289 const GURL
kUrl3("http://www.gmail.com/");
291 contents()->NavigateAndCommit(kUrl1
);
294 FrameTreeNode
* root_node
= contents()->GetFrameTree()->root();
295 TestRenderFrameHost
* subframe_rfh
= main_test_rfh()->AppendChild("Child");
296 ASSERT_TRUE(subframe_rfh
);
298 // Start a navigation at the subframe.
299 FrameTreeNode
* subframe_node
= subframe_rfh
->frame_tree_node();
300 RequestNavigation(subframe_node
, kUrl2
);
301 NavigationRequest
* subframe_request
= subframe_node
->navigation_request();
302 TestNavigationURLLoader
* subframe_loader
=
303 GetLoaderForNavigationRequest(subframe_request
);
305 // Subframe navigations should start right away as they don't have to request
306 // beforeUnload to run at the renderer.
307 ASSERT_TRUE(subframe_request
);
308 ASSERT_TRUE(subframe_loader
);
309 EXPECT_EQ(NavigationRequest::STARTED
, subframe_request
->state());
310 EXPECT_EQ(kUrl2
, subframe_request
->common_params().url
);
311 EXPECT_EQ(kUrl2
, subframe_loader
->request_info()->common_params
.url
);
312 // First party for cookies url should be that of the main frame.
313 EXPECT_EQ(kUrl1
, subframe_loader
->request_info()->first_party_for_cookies
);
314 EXPECT_FALSE(subframe_loader
->request_info()->is_main_frame
);
315 EXPECT_TRUE(subframe_loader
->request_info()->parent_is_main_frame
);
316 EXPECT_TRUE(subframe_request
->browser_initiated());
317 EXPECT_FALSE(GetSpeculativeRenderFrameHost(root_node
));
319 // Subframe navigations should never create a speculative RenderFrameHost,
320 // unless site-per-process is enabled. In that case, as the subframe
321 // navigation is to a different site and is still ongoing, it should have one.
322 if (AreAllSitesIsolatedForTesting()) {
323 EXPECT_TRUE(GetSpeculativeRenderFrameHost(subframe_node
));
325 EXPECT_FALSE(GetSpeculativeRenderFrameHost(subframe_node
));
328 // Now start a navigation at the root node.
329 RequestNavigation(root_node
, kUrl3
);
330 NavigationRequest
* main_request
= root_node
->navigation_request();
331 ASSERT_TRUE(main_request
);
332 EXPECT_EQ(NavigationRequest::WAITING_FOR_RENDERER_RESPONSE
,
333 main_request
->state());
335 // Main frame navigation to a different site should use a speculative
337 EXPECT_TRUE(GetSpeculativeRenderFrameHost(root_node
));
339 // Simulate a BeforeUnloadACK IPC on the main frame.
340 main_test_rfh()->SendBeforeUnloadACK(true);
341 TestNavigationURLLoader
* main_loader
=
342 GetLoaderForNavigationRequest(main_request
);
343 EXPECT_EQ(kUrl3
, main_request
->common_params().url
);
344 EXPECT_EQ(kUrl3
, main_loader
->request_info()->common_params
.url
);
345 EXPECT_EQ(kUrl3
, main_loader
->request_info()->first_party_for_cookies
);
346 EXPECT_TRUE(main_loader
->request_info()->is_main_frame
);
347 EXPECT_FALSE(main_loader
->request_info()->parent_is_main_frame
);
348 EXPECT_TRUE(main_request
->browser_initiated());
349 // BeforeUnloadACK was received from the renderer so the navigation should
351 EXPECT_EQ(NavigationRequest::STARTED
, main_request
->state());
352 EXPECT_TRUE(GetSpeculativeRenderFrameHost(root_node
));
354 // As the main frame hasn't yet committed the subframe still exists. Thus, the
355 // above situation regarding subframe navigations is valid here.
356 if (AreAllSitesIsolatedForTesting()) {
357 EXPECT_TRUE(GetSpeculativeRenderFrameHost(subframe_node
));
359 EXPECT_FALSE(GetSpeculativeRenderFrameHost(subframe_node
));
363 // PlzNavigate: Test that committing an HTTP 204 or HTTP 205 response cancels
365 TEST_F(NavigatorTestWithBrowserSideNavigation
, NoContent
) {
366 const GURL
kUrl1("http://www.chromium.org/");
367 const GURL
kUrl2("http://www.google.com/");
370 contents()->NavigateAndCommit(kUrl1
);
371 FrameTreeNode
* node
= main_test_rfh()->frame_tree_node();
373 // Navigate to a different site.
374 process()->sink().ClearMessages();
375 RequestNavigation(node
, kUrl2
);
376 main_test_rfh()->SendBeforeUnloadACK(true);
378 NavigationRequest
* main_request
= node
->navigation_request();
379 ASSERT_TRUE(main_request
);
381 // Navigations to a different site do create a speculative RenderFrameHost.
382 EXPECT_TRUE(GetSpeculativeRenderFrameHost(node
));
384 // Commit an HTTP 204 response.
385 scoped_refptr
<ResourceResponse
> response(new ResourceResponse
);
386 const char kNoContentHeaders
[] = "HTTP/1.1 204 No Content\0\0";
387 response
->head
.headers
= new net::HttpResponseHeaders(
388 std::string(kNoContentHeaders
, arraysize(kNoContentHeaders
)));
389 GetLoaderForNavigationRequest(main_request
)->CallOnResponseStarted(
390 response
, MakeEmptyStream());
392 // There should be no pending nor speculative RenderFrameHost; the navigation
394 EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh()));
395 EXPECT_FALSE(node
->navigation_request());
396 EXPECT_FALSE(node
->render_manager()->pending_frame_host());
397 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
399 // Now, repeat the test with 205 Reset Content.
401 // Navigate to a different site again.
402 process()->sink().ClearMessages();
403 RequestNavigation(node
, kUrl2
);
404 main_test_rfh()->SendBeforeUnloadACK(true);
406 main_request
= node
->navigation_request();
407 ASSERT_TRUE(main_request
);
408 EXPECT_TRUE(GetSpeculativeRenderFrameHost(node
));
410 // Commit an HTTP 205 response.
411 response
= new ResourceResponse
;
412 const char kResetContentHeaders
[] = "HTTP/1.1 205 Reset Content\0\0";
413 response
->head
.headers
= new net::HttpResponseHeaders(
414 std::string(kResetContentHeaders
, arraysize(kResetContentHeaders
)));
415 GetLoaderForNavigationRequest(main_request
)->CallOnResponseStarted(
416 response
, MakeEmptyStream());
418 // There should be no pending nor speculative RenderFrameHost; the navigation
420 EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh()));
421 EXPECT_FALSE(node
->navigation_request());
422 EXPECT_FALSE(node
->render_manager()->pending_frame_host());
423 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
426 // PlzNavigate: Test that a new RenderFrameHost is created when doing a cross
428 TEST_F(NavigatorTestWithBrowserSideNavigation
, CrossSiteNavigation
) {
429 const GURL
kUrl1("http://www.chromium.org/");
430 const GURL
kUrl2("http://www.google.com/");
432 contents()->NavigateAndCommit(kUrl1
);
433 RenderFrameHostImpl
* initial_rfh
= main_test_rfh();
434 FrameTreeNode
* node
= main_test_rfh()->frame_tree_node();
436 // Navigate to a different site.
437 process()->sink().ClearMessages();
438 int entry_id
= RequestNavigation(node
, kUrl2
);
439 NavigationRequest
* main_request
= node
->navigation_request();
440 ASSERT_TRUE(main_request
);
441 TestRenderFrameHost
* speculative_rfh
= GetSpeculativeRenderFrameHost(node
);
442 ASSERT_TRUE(speculative_rfh
);
444 // Receive the beforeUnload ACK.
445 main_test_rfh()->SendBeforeUnloadACK(true);
446 EXPECT_EQ(speculative_rfh
, GetSpeculativeRenderFrameHost(node
));
447 EXPECT_FALSE(contents()->CrossProcessNavigationPending());
449 scoped_refptr
<ResourceResponse
> response(new ResourceResponse
);
450 GetLoaderForNavigationRequest(main_request
)->CallOnResponseStarted(
451 response
, MakeEmptyStream());
452 EXPECT_EQ(speculative_rfh
, GetSpeculativeRenderFrameHost(node
));
453 EXPECT_TRUE(DidRenderFrameHostRequestCommit(speculative_rfh
));
454 EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh()));
455 EXPECT_TRUE(contents()->CrossProcessNavigationPending());
457 speculative_rfh
->SendNavigate(0, entry_id
, true, kUrl2
);
459 RenderFrameHostImpl
* final_rfh
= main_test_rfh();
460 EXPECT_EQ(speculative_rfh
, final_rfh
);
461 EXPECT_NE(initial_rfh
, final_rfh
);
462 EXPECT_TRUE(final_rfh
->IsRenderFrameLive());
463 EXPECT_TRUE(final_rfh
->render_view_host()->IsRenderViewLive());
464 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
467 // PlzNavigate: Test that redirects are followed and the speculative
468 // RenderFrameHost logic behaves as expected.
469 TEST_F(NavigatorTestWithBrowserSideNavigation
, RedirectCrossSite
) {
470 const GURL
kUrl1("http://www.chromium.org/");
471 const GURL
kUrl2("http://www.google.com/");
473 contents()->NavigateAndCommit(kUrl1
);
474 RenderFrameHostImpl
* rfh
= main_test_rfh();
475 FrameTreeNode
* node
= main_test_rfh()->frame_tree_node();
477 // Navigate to a URL on the same site.
478 process()->sink().ClearMessages();
479 int entry_id
= RequestNavigation(node
, kUrl1
);
480 main_test_rfh()->SendBeforeUnloadACK(true);
481 NavigationRequest
* main_request
= node
->navigation_request();
482 ASSERT_TRUE(main_request
);
483 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
485 // It then redirects to another site.
486 GetLoaderForNavigationRequest(main_request
)->SimulateServerRedirect(kUrl2
);
488 // The redirect should have been followed.
489 EXPECT_EQ(1, GetLoaderForNavigationRequest(main_request
)->redirect_count());
490 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
492 // Have the RenderFrameHost commit the navigation.
493 scoped_refptr
<ResourceResponse
> response(new ResourceResponse
);
494 GetLoaderForNavigationRequest(main_request
)->CallOnResponseStarted(
495 response
, MakeEmptyStream());
496 TestRenderFrameHost
* final_speculative_rfh
=
497 GetSpeculativeRenderFrameHost(node
);
498 EXPECT_TRUE(final_speculative_rfh
);
499 EXPECT_TRUE(DidRenderFrameHostRequestCommit(final_speculative_rfh
));
501 // Commit the navigation.
502 final_speculative_rfh
->SendNavigate(0, entry_id
, true, kUrl2
);
503 RenderFrameHostImpl
* final_rfh
= main_test_rfh();
504 ASSERT_TRUE(final_rfh
);
505 EXPECT_NE(rfh
, final_rfh
);
506 EXPECT_EQ(final_speculative_rfh
, final_rfh
);
507 EXPECT_TRUE(final_rfh
->IsRenderFrameLive());
508 EXPECT_TRUE(final_rfh
->render_view_host()->IsRenderViewLive());
509 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
512 // PlzNavigate: Test that a navigation is canceled if another browser-initiated
513 // request has been issued in the meantime. Also confirms that the speculative
514 // RenderFrameHost is correctly updated in the process.
515 TEST_F(NavigatorTestWithBrowserSideNavigation
,
516 BrowserInitiatedNavigationCancel
) {
517 const GURL
kUrl0("http://www.wikipedia.org/");
518 const GURL
kUrl1("http://www.chromium.org/");
519 const GURL kUrl1_site
= SiteInstance::GetSiteForURL(browser_context(), kUrl1
);
520 const GURL
kUrl2("http://www.google.com/");
521 const GURL kUrl2_site
= SiteInstance::GetSiteForURL(browser_context(), kUrl2
);
524 contents()->NavigateAndCommit(kUrl0
);
525 FrameTreeNode
* node
= main_test_rfh()->frame_tree_node();
527 // Request navigation to the 1st URL.
528 process()->sink().ClearMessages();
529 RequestNavigation(node
, kUrl1
);
530 main_test_rfh()->SendBeforeUnloadACK(true);
531 NavigationRequest
* request1
= node
->navigation_request();
532 ASSERT_TRUE(request1
);
533 EXPECT_EQ(kUrl1
, request1
->common_params().url
);
534 EXPECT_TRUE(request1
->browser_initiated());
535 base::WeakPtr
<TestNavigationURLLoader
> loader1
=
536 GetLoaderForNavigationRequest(request1
)->AsWeakPtr();
537 EXPECT_TRUE(loader1
);
539 // Confirm a speculative RenderFrameHost was created.
540 TestRenderFrameHost
* speculative_rfh
= GetSpeculativeRenderFrameHost(node
);
541 ASSERT_TRUE(speculative_rfh
);
542 int32 site_instance_id_1
= speculative_rfh
->GetSiteInstance()->GetId();
543 EXPECT_EQ(kUrl1_site
, speculative_rfh
->GetSiteInstance()->GetSiteURL());
545 // Request navigation to the 2nd URL; the NavigationRequest must have been
546 // replaced by a new one with a different URL.
547 int entry_id
= RequestNavigation(node
, kUrl2
);
548 main_test_rfh()->SendBeforeUnloadACK(true);
549 NavigationRequest
* request2
= node
->navigation_request();
550 ASSERT_TRUE(request2
);
551 EXPECT_EQ(kUrl2
, request2
->common_params().url
);
552 EXPECT_TRUE(request2
->browser_initiated());
554 // Confirm that the first loader got destroyed.
555 EXPECT_FALSE(loader1
);
557 // Confirm that a new speculative RenderFrameHost was created.
558 speculative_rfh
= GetSpeculativeRenderFrameHost(node
);
559 ASSERT_TRUE(speculative_rfh
);
560 int32 site_instance_id_2
= speculative_rfh
->GetSiteInstance()->GetId();
561 EXPECT_NE(site_instance_id_1
, site_instance_id_2
);
563 // Have the RenderFrameHost commit the navigation.
564 scoped_refptr
<ResourceResponse
> response(new ResourceResponse
);
565 GetLoaderForNavigationRequest(request2
)->CallOnResponseStarted(
566 response
, MakeEmptyStream());
567 EXPECT_TRUE(DidRenderFrameHostRequestCommit(speculative_rfh
));
568 EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh()));
570 // Commit the navigation.
571 speculative_rfh
->SendNavigate(0, entry_id
, true, kUrl2
);
573 // Confirm that the commit corresponds to the new request.
574 ASSERT_TRUE(main_test_rfh());
575 EXPECT_EQ(kUrl2_site
, main_test_rfh()->GetSiteInstance()->GetSiteURL());
576 EXPECT_EQ(kUrl2
, contents()->GetLastCommittedURL());
578 // Confirm that the committed RenderFrameHost is the latest speculative one.
579 EXPECT_EQ(site_instance_id_2
, main_test_rfh()->GetSiteInstance()->GetId());
582 // PlzNavigate: Test that a browser-initiated navigation is canceled if a
583 // renderer-initiated user-initiated request has been issued in the meantime.
584 TEST_F(NavigatorTestWithBrowserSideNavigation
,
585 RendererUserInitiatedNavigationCancel
) {
586 const GURL
kUrl0("http://www.wikipedia.org/");
587 const GURL
kUrl1("http://www.chromium.org/");
588 const GURL
kUrl2("http://www.google.com/");
591 contents()->NavigateAndCommit(kUrl0
);
592 FrameTreeNode
* node
= main_test_rfh()->frame_tree_node();
594 // Start a browser-initiated navigation to the 1st URL and receive its
596 process()->sink().ClearMessages();
597 RequestNavigation(node
, kUrl1
);
598 main_test_rfh()->SendBeforeUnloadACK(true);
599 NavigationRequest
* request1
= node
->navigation_request();
600 ASSERT_TRUE(request1
);
601 EXPECT_EQ(kUrl1
, request1
->common_params().url
);
602 EXPECT_TRUE(request1
->browser_initiated());
603 base::WeakPtr
<TestNavigationURLLoader
> loader1
=
604 GetLoaderForNavigationRequest(request1
)->AsWeakPtr();
605 EXPECT_TRUE(loader1
);
607 // Confirm that a speculative RenderFrameHost was created.
608 ASSERT_TRUE(GetSpeculativeRenderFrameHost(node
));
610 // Now receive a renderer-initiated user-initiated request. It should replace
611 // the current NavigationRequest.
612 main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl2
, true);
613 NavigationRequest
* request2
= node
->navigation_request();
614 ASSERT_TRUE(request2
);
615 EXPECT_EQ(kUrl2
, request2
->common_params().url
);
616 EXPECT_FALSE(request2
->browser_initiated());
617 EXPECT_TRUE(request2
->begin_params().has_user_gesture
);
619 // Confirm that the first loader got destroyed.
620 EXPECT_FALSE(loader1
);
622 // Confirm that the speculative RenderFrameHost was destroyed.
623 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
625 // Have the RenderFrameHost commit the navigation.
626 scoped_refptr
<ResourceResponse
> response(new ResourceResponse
);
627 GetLoaderForNavigationRequest(request2
)
628 ->CallOnResponseStarted(response
, MakeEmptyStream());
629 EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh()));
631 // Commit the navigation.
632 main_test_rfh()->SendNavigate(1, 0, true, kUrl2
);
634 // Confirm that the commit corresponds to the new request.
635 ASSERT_TRUE(main_test_rfh());
636 EXPECT_EQ(kUrl2
, contents()->GetLastCommittedURL());
639 // PlzNavigate: Test that a renderer-initiated user-initiated navigation is NOT
640 // canceled if a renderer-initiated non-user-initiated request is issued in the
642 TEST_F(NavigatorTestWithBrowserSideNavigation
,
643 RendererNonUserInitiatedNavigationDoesntCancelRendererUserInitiated
) {
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 renderer-initiated user-initiated navigation to the 1st URL.
653 process()->sink().ClearMessages();
654 main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl1
, true);
655 NavigationRequest
* request1
= node
->navigation_request();
656 ASSERT_TRUE(request1
);
657 EXPECT_EQ(kUrl1
, request1
->common_params().url
);
658 EXPECT_FALSE(request1
->browser_initiated());
659 EXPECT_TRUE(request1
->begin_params().has_user_gesture
);
660 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
662 // Now receive a renderer-initiated non-user-initiated request. Nothing should
664 main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl2
, false);
665 NavigationRequest
* request2
= node
->navigation_request();
666 ASSERT_TRUE(request2
);
667 EXPECT_EQ(request1
, request2
);
668 EXPECT_EQ(kUrl1
, request2
->common_params().url
);
669 EXPECT_FALSE(request2
->browser_initiated());
670 EXPECT_TRUE(request2
->begin_params().has_user_gesture
);
671 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
673 // Have the RenderFrameHost commit the navigation.
674 scoped_refptr
<ResourceResponse
> response(new ResourceResponse
);
675 GetLoaderForNavigationRequest(request2
)
676 ->CallOnResponseStarted(response
, MakeEmptyStream());
677 EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh()));
679 // Commit the navigation.
680 main_test_rfh()->SendNavigate(1, 0, true, kUrl1
);
681 EXPECT_EQ(kUrl1
, contents()->GetLastCommittedURL());
684 // PlzNavigate: Test that a browser-initiated navigation is NOT canceled if a
685 // renderer-initiated non-user-initiated request is issued in the meantime.
686 TEST_F(NavigatorTestWithBrowserSideNavigation
,
687 RendererNonUserInitiatedNavigationDoesntCancelBrowserInitiated
) {
688 const GURL
kUrl0("http://www.wikipedia.org/");
689 const GURL
kUrl1("http://www.chromium.org/");
690 const GURL
kUrl2("http://www.google.com/");
693 contents()->NavigateAndCommit(kUrl0
);
694 FrameTreeNode
* node
= main_test_rfh()->frame_tree_node();
696 // Start a browser-initiated navigation to the 1st URL.
697 process()->sink().ClearMessages();
698 int entry_id
= RequestNavigation(node
, kUrl1
);
699 NavigationRequest
* request1
= node
->navigation_request();
700 ASSERT_TRUE(request1
);
701 EXPECT_EQ(kUrl1
, request1
->common_params().url
);
702 EXPECT_TRUE(request1
->browser_initiated());
703 EXPECT_TRUE(GetSpeculativeRenderFrameHost(node
));
705 // Now receive a renderer-initiated non-user-initiated request. Nothing should
707 main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl2
, false);
708 NavigationRequest
* request2
= node
->navigation_request();
709 ASSERT_TRUE(request2
);
710 EXPECT_EQ(request1
, request2
);
711 EXPECT_EQ(kUrl1
, request2
->common_params().url
);
712 EXPECT_TRUE(request2
->browser_initiated());
713 EXPECT_TRUE(GetSpeculativeRenderFrameHost(node
));
715 // Now receive the beforeUnload ACK from the still ongoing navigation.
716 main_test_rfh()->SendBeforeUnloadACK(true);
717 TestRenderFrameHost
* speculative_rfh
= GetSpeculativeRenderFrameHost(node
);
718 ASSERT_TRUE(speculative_rfh
);
720 // Have the RenderFrameHost commit the navigation.
721 scoped_refptr
<ResourceResponse
> response(new ResourceResponse
);
722 GetLoaderForNavigationRequest(request2
)
723 ->CallOnResponseStarted(response
, MakeEmptyStream());
724 EXPECT_TRUE(DidRenderFrameHostRequestCommit(speculative_rfh
));
725 EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh()));
727 // Commit the navigation.
728 speculative_rfh
->SendNavigate(0, entry_id
, true, kUrl1
);
729 EXPECT_EQ(kUrl1
, contents()->GetLastCommittedURL());
732 // PlzNavigate: Test that a renderer-initiated non-user-initiated navigation is
733 // canceled if a another similar request is issued in the meantime.
734 TEST_F(NavigatorTestWithBrowserSideNavigation
,
735 RendererNonUserInitiatedNavigationCancelSimilarNavigation
) {
736 const GURL
kUrl0("http://www.wikipedia.org/");
737 const GURL
kUrl1("http://www.chromium.org/");
738 const GURL
kUrl2("http://www.google.com/");
741 contents()->NavigateAndCommit(kUrl0
);
742 FrameTreeNode
* node
= main_test_rfh()->frame_tree_node();
743 int32 site_instance_id_0
= main_test_rfh()->GetSiteInstance()->GetId();
745 // Start a renderer-initiated non-user-initiated navigation to the 1st URL.
746 process()->sink().ClearMessages();
747 main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl1
, false);
748 NavigationRequest
* request1
= node
->navigation_request();
749 ASSERT_TRUE(request1
);
750 EXPECT_EQ(kUrl1
, request1
->common_params().url
);
751 EXPECT_FALSE(request1
->browser_initiated());
752 EXPECT_FALSE(request1
->begin_params().has_user_gesture
);
753 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
754 base::WeakPtr
<TestNavigationURLLoader
> loader1
=
755 GetLoaderForNavigationRequest(request1
)->AsWeakPtr();
756 EXPECT_TRUE(loader1
);
758 // Now receive a 2nd similar request that should replace the current one.
759 main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl2
, false);
760 NavigationRequest
* request2
= node
->navigation_request();
761 EXPECT_EQ(kUrl2
, request2
->common_params().url
);
762 EXPECT_FALSE(request2
->browser_initiated());
763 EXPECT_FALSE(request2
->begin_params().has_user_gesture
);
764 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
766 // Confirm that the first loader got destroyed.
767 EXPECT_FALSE(loader1
);
769 // Have the RenderFrameHost commit the navigation.
770 scoped_refptr
<ResourceResponse
> response(new ResourceResponse
);
771 GetLoaderForNavigationRequest(request2
)
772 ->CallOnResponseStarted(response
, MakeEmptyStream());
773 EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh()));
775 // Commit the navigation.
776 main_test_rfh()->SendNavigate(1, 0, true, kUrl2
);
777 EXPECT_EQ(kUrl2
, contents()->GetLastCommittedURL());
779 // The SiteInstance did not change.
780 EXPECT_EQ(site_instance_id_0
, main_test_rfh()->GetSiteInstance()->GetId());
783 // PlzNavigate: Test that a reload navigation is properly signaled to the
784 // RenderFrame when the navigation can commit. A speculative RenderFrameHost
785 // should not be created at any step.
786 TEST_F(NavigatorTestWithBrowserSideNavigation
, Reload
) {
787 const GURL
kUrl("http://www.google.com/");
788 contents()->NavigateAndCommit(kUrl
);
790 FrameTreeNode
* node
= main_test_rfh()->frame_tree_node();
791 controller().Reload(false);
792 int entry_id
= controller().GetPendingEntry()->GetUniqueID();
793 // A NavigationRequest should have been generated.
794 NavigationRequest
* main_request
= node
->navigation_request();
795 ASSERT_TRUE(main_request
!= NULL
);
796 EXPECT_EQ(FrameMsg_Navigate_Type::RELOAD
,
797 main_request
->common_params().navigation_type
);
798 main_test_rfh()->PrepareForCommit();
799 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
801 main_test_rfh()->SendNavigate(0, entry_id
, false, kUrl
);
802 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
804 // Now do a shift+reload.
805 controller().ReloadIgnoringCache(false);
806 // A NavigationRequest should have been generated.
807 main_request
= node
->navigation_request();
808 ASSERT_TRUE(main_request
!= NULL
);
809 EXPECT_EQ(FrameMsg_Navigate_Type::RELOAD_IGNORING_CACHE
,
810 main_request
->common_params().navigation_type
);
811 main_test_rfh()->PrepareForCommit();
812 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
815 // PlzNavigate: Confirm that a speculative RenderFrameHost is used when
816 // navigating from one site to another.
817 TEST_F(NavigatorTestWithBrowserSideNavigation
,
818 SpeculativeRendererWorksBaseCase
) {
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();
824 // Begin navigating to another site.
825 const GURL
kUrl("http://google.com/");
826 process()->sink().ClearMessages();
827 int entry_id
= RequestNavigation(node
, kUrl
);
828 TestRenderFrameHost
* speculative_rfh
= GetSpeculativeRenderFrameHost(node
);
829 ASSERT_TRUE(speculative_rfh
);
830 EXPECT_NE(speculative_rfh
, main_test_rfh());
832 // Receive the beforeUnload ACK.
833 main_test_rfh()->SendBeforeUnloadACK(true);
834 EXPECT_EQ(speculative_rfh
, GetSpeculativeRenderFrameHost(node
));
835 EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrl
),
836 speculative_rfh
->GetSiteInstance()->GetSiteURL());
837 EXPECT_FALSE(node
->render_manager()->pending_frame_host());
838 int32 site_instance_id
= speculative_rfh
->GetSiteInstance()->GetId();
840 // Ask Navigator to commit the navigation by simulating a call to
841 // OnResponseStarted.
842 scoped_refptr
<ResourceResponse
> response(new ResourceResponse
);
843 GetLoaderForNavigationRequest(node
->navigation_request())
844 ->CallOnResponseStarted(response
, MakeEmptyStream());
845 EXPECT_EQ(speculative_rfh
, GetSpeculativeRenderFrameHost(node
));
846 EXPECT_TRUE(DidRenderFrameHostRequestCommit(speculative_rfh
));
847 EXPECT_EQ(site_instance_id
, speculative_rfh
->GetSiteInstance()->GetId());
848 EXPECT_FALSE(node
->render_manager()->pending_frame_host());
850 // Invoke OnDidCommitProvisionalLoad.
851 speculative_rfh
->SendNavigate(0, entry_id
, true, kUrl
);
852 EXPECT_EQ(site_instance_id
, main_test_rfh()->GetSiteInstance()->GetId());
853 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
854 EXPECT_FALSE(node
->render_manager()->pending_frame_host());
857 // PlzNavigate: Confirm that a speculative RenderFrameHost is thrown away when
858 // the final URL's site differs from the initial one due to redirects.
859 TEST_F(NavigatorTestWithBrowserSideNavigation
,
860 SpeculativeRendererDiscardedAfterRedirectToAnotherSite
) {
861 // Navigate to an initial site.
862 const GURL
kUrlInit("http://wikipedia.org/");
863 contents()->NavigateAndCommit(kUrlInit
);
864 FrameTreeNode
* node
= main_test_rfh()->frame_tree_node();
865 int32 init_site_instance_id
= main_test_rfh()->GetSiteInstance()->GetId();
867 // Begin navigating to another site.
868 const GURL
kUrl("http://google.com/");
869 process()->sink().ClearMessages();
870 int entry_id
= RequestNavigation(node
, kUrl
);
871 TestRenderFrameHost
* speculative_rfh
= GetSpeculativeRenderFrameHost(node
);
872 ASSERT_TRUE(speculative_rfh
);
873 int32 site_instance_id
= speculative_rfh
->GetSiteInstance()->GetId();
874 RenderFrameDeletedObserver
rfh_deleted_observer(speculative_rfh
);
875 EXPECT_NE(init_site_instance_id
, site_instance_id
);
876 EXPECT_EQ(init_site_instance_id
, main_test_rfh()->GetSiteInstance()->GetId());
877 EXPECT_NE(speculative_rfh
, main_test_rfh());
878 EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrl
),
879 speculative_rfh
->GetSiteInstance()->GetSiteURL());
881 // Receive the beforeUnload ACK.
882 main_test_rfh()->SendBeforeUnloadACK(true);
883 EXPECT_EQ(speculative_rfh
, GetSpeculativeRenderFrameHost(node
));
885 // It then redirects to yet another site.
886 NavigationRequest
* main_request
= node
->navigation_request();
887 ASSERT_TRUE(main_request
);
888 const GURL
kUrlRedirect("https://www.google.com/");
889 GetLoaderForNavigationRequest(main_request
)
890 ->SimulateServerRedirect(kUrlRedirect
);
891 EXPECT_EQ(init_site_instance_id
, main_test_rfh()->GetSiteInstance()->GetId());
893 // For now, ensure that the speculative RenderFrameHost does not change after
895 // TODO(carlosk): once the speculative RenderFrameHost updates with redirects
896 // this next check will be changed to verify that it actually happens.
897 EXPECT_EQ(speculative_rfh
, GetSpeculativeRenderFrameHost(node
));
898 EXPECT_EQ(site_instance_id
, speculative_rfh
->GetSiteInstance()->GetId());
899 EXPECT_FALSE(rfh_deleted_observer
.deleted());
901 // Commit the navigation with Navigator by simulating the call to
902 // OnResponseStarted.
903 scoped_refptr
<ResourceResponse
> response(new ResourceResponse
);
904 GetLoaderForNavigationRequest(main_request
)
905 ->CallOnResponseStarted(response
, MakeEmptyStream());
906 speculative_rfh
= GetSpeculativeRenderFrameHost(node
);
907 ASSERT_TRUE(speculative_rfh
);
908 EXPECT_TRUE(DidRenderFrameHostRequestCommit(speculative_rfh
));
909 EXPECT_EQ(init_site_instance_id
, main_test_rfh()->GetSiteInstance()->GetId());
910 EXPECT_TRUE(rfh_deleted_observer
.deleted());
912 // Once commit happens the speculative RenderFrameHost is updated to match the
913 // known final SiteInstance.
914 EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrlRedirect
),
915 speculative_rfh
->GetSiteInstance()->GetSiteURL());
916 int32 redirect_site_instance_id
= speculative_rfh
->GetSiteInstance()->GetId();
917 EXPECT_NE(init_site_instance_id
, redirect_site_instance_id
);
918 EXPECT_NE(site_instance_id
, redirect_site_instance_id
);
920 // Invoke OnDidCommitProvisionalLoad.
921 speculative_rfh
->SendNavigate(0, entry_id
, true, kUrlRedirect
);
923 // Check that the speculative RenderFrameHost was swapped in.
924 EXPECT_EQ(redirect_site_instance_id
,
925 main_test_rfh()->GetSiteInstance()->GetId());
926 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
929 // PlzNavigate: Verify that a previously swapped out RenderFrameHost is
930 // correctly reused when spawning a speculative RenderFrameHost in a navigation
931 // using the same SiteInstance.
932 TEST_F(NavigatorTestWithBrowserSideNavigation
,
933 SpeculativeRendererReuseSwappedOutRFH
) {
934 // This test doesn't make sense in --site-per-process where swapped out
935 // RenderFrameHost is no longer used.
936 if (SiteIsolationPolicy::IsSwappedOutStateForbidden())
939 // Navigate to an initial site.
940 const GURL
kUrl1("http://wikipedia.org/");
941 contents()->NavigateAndCommit(kUrl1
);
942 TestRenderFrameHost
* rfh1
= main_test_rfh();
943 FrameTreeNode
* node
= rfh1
->frame_tree_node();
944 RenderFrameHostManager
* rfhm
= node
->render_manager();
946 // Increment active frame count to cause the RenderFrameHost to be swapped out
947 // (instead of immediately destroyed).
948 rfh1
->GetSiteInstance()->increment_active_frame_count();
950 // Navigate to another site to swap out the initial RenderFrameHost.
951 const GURL
kUrl2("http://chromium.org/");
952 contents()->NavigateAndCommit(kUrl2
);
953 ASSERT_NE(rfh1
, main_test_rfh());
954 EXPECT_NE(RenderFrameHostImpl::STATE_DEFAULT
, rfh1
->rfh_state());
955 EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT
, main_test_rfh()->rfh_state());
956 EXPECT_TRUE(rfhm
->IsOnSwappedOutList(rfh1
));
958 // Now go back to the initial site so that the swapped out RenderFrameHost
960 process()->sink().ClearMessages();
961 rfh1
->GetProcess()->sink().ClearMessages();
962 int entry_id
= RequestNavigation(node
, kUrl1
);
963 EXPECT_EQ(rfh1
, GetSpeculativeRenderFrameHost(node
));
965 main_test_rfh()->SendBeforeUnloadACK(true);
966 EXPECT_EQ(rfh1
, GetSpeculativeRenderFrameHost(node
));
967 EXPECT_NE(RenderFrameHostImpl::STATE_DEFAULT
,
968 GetSpeculativeRenderFrameHost(node
)->rfh_state());
970 scoped_refptr
<ResourceResponse
> response(new ResourceResponse
);
971 GetLoaderForNavigationRequest(node
->navigation_request())
972 ->CallOnResponseStarted(response
, MakeEmptyStream());
973 EXPECT_EQ(rfh1
, GetSpeculativeRenderFrameHost(node
));
974 EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT
,
975 GetSpeculativeRenderFrameHost(node
)->rfh_state());
976 EXPECT_TRUE(DidRenderFrameHostRequestCommit(rfh1
));
977 EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh()));
979 rfh1
->SendNavigate(1, entry_id
, true, kUrl1
);
980 EXPECT_EQ(rfh1
, main_test_rfh());
981 EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT
, rfh1
->rfh_state());
982 EXPECT_FALSE(rfhm
->IsOnSwappedOutList(rfh1
));
985 // PlzNavigate: Verify that data urls are properly handled.
986 TEST_F(NavigatorTestWithBrowserSideNavigation
, DataUrls
) {
987 const GURL
kUrl1("http://wikipedia.org/");
988 const GURL
kUrl2("data:text/html,test");
990 // Navigate to an initial site.
991 contents()->NavigateAndCommit(kUrl1
);
992 FrameTreeNode
* node
= main_test_rfh()->frame_tree_node();
994 // Navigate to a data url. The request should not have been sent to the IO
995 // thread but committed immediately.
996 int entry_id
= RequestNavigation(node
, kUrl2
);
997 TestRenderFrameHost
* speculative_rfh
= GetSpeculativeRenderFrameHost(node
);
998 ASSERT_TRUE(speculative_rfh
);
999 EXPECT_TRUE(speculative_rfh
->is_loading());
1000 EXPECT_FALSE(node
->navigation_request());
1001 speculative_rfh
->SendNavigate(0, entry_id
, true, kUrl2
);
1002 EXPECT_EQ(main_test_rfh(), speculative_rfh
);
1004 // Go back to the initial site.
1005 contents()->NavigateAndCommit(kUrl1
);
1007 // Do a renderer-initiated navigation to a data url. The request should not be
1008 // sent to the IO thread, nor committed.
1009 TestRenderFrameHost
* main_rfh
= main_test_rfh();
1010 main_rfh
->SendRendererInitiatedNavigationRequest(kUrl2
, true);
1011 EXPECT_TRUE(main_rfh
->is_loading());
1012 EXPECT_FALSE(node
->navigation_request());
1013 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node
));
1016 // Tests several cases for converting SiteInstanceDescriptors into
1018 // 1) Pointer to the current SiteInstance.
1019 // 2) Pointer to an unrelated SiteInstance.
1020 // 3) Same-site URL, related.
1021 // 4) Cross-site URL, related.
1022 // 5) Same-site URL, unrelated (with and without candidate SiteInstances).
1023 // 6) Cross-site URL, unrelated (with candidate SiteInstance).
1024 TEST_F(NavigatorTestWithBrowserSideNavigation
,
1025 SiteInstanceDescriptionConversion
) {
1026 // Navigate to set a current SiteInstance on the RenderFrameHost.
1027 GURL
kUrl1("http://a.com");
1028 contents()->NavigateAndCommit(kUrl1
);
1029 SiteInstance
* current_instance
= main_test_rfh()->GetSiteInstance();
1030 ASSERT_TRUE(current_instance
);
1032 // 1) Convert a descriptor pointing to the current instance.
1033 RenderFrameHostManager
* rfhm
=
1034 main_test_rfh()->frame_tree_node()->render_manager();
1036 SiteInstanceDescriptor
descriptor(current_instance
);
1037 SiteInstance
* converted_instance
=
1038 ConvertToSiteInstance(rfhm
, descriptor
, nullptr);
1039 EXPECT_EQ(current_instance
, converted_instance
);
1042 // 2) Convert a descriptor pointing an instance unrelated to the current one,
1043 // with a different site.
1044 GURL
kUrl2("http://b.com");
1045 scoped_refptr
<SiteInstance
> unrelated_instance(
1046 SiteInstance::CreateForURL(browser_context(), kUrl2
));
1048 current_instance
->IsRelatedSiteInstance(unrelated_instance
.get()));
1050 SiteInstanceDescriptor
descriptor(unrelated_instance
.get());
1051 SiteInstance
* converted_instance
=
1052 ConvertToSiteInstance(rfhm
, descriptor
, nullptr);
1053 EXPECT_EQ(unrelated_instance
.get(), converted_instance
);
1056 // 3) Convert a descriptor of a related instance with the same site as the
1058 GURL
kUrlSameSiteAs1("http://www.a.com/foo");
1060 SiteInstanceDescriptor
descriptor(browser_context(), kUrlSameSiteAs1
, true);
1061 SiteInstance
* converted_instance
=
1062 ConvertToSiteInstance(rfhm
, descriptor
, nullptr);
1063 EXPECT_EQ(current_instance
, converted_instance
);
1066 // 4) Convert a descriptor of a related instance with a site different from
1068 GURL
kUrlSameSiteAs2("http://www.b.com/foo");
1069 scoped_refptr
<SiteInstance
> related_instance
;
1071 SiteInstanceDescriptor
descriptor(browser_context(), kUrlSameSiteAs2
, true);
1072 related_instance
= ConvertToSiteInstance(rfhm
, descriptor
, nullptr);
1073 // Should return a new instance, related to the current, set to the new site
1076 current_instance
->IsRelatedSiteInstance(related_instance
.get()));
1077 EXPECT_NE(current_instance
, related_instance
.get());
1078 EXPECT_NE(unrelated_instance
.get(), related_instance
.get());
1079 EXPECT_EQ(SiteInstance::GetSiteForURL(browser_context(), kUrlSameSiteAs2
),
1080 related_instance
->GetSiteURL());
1083 // 5) Convert a descriptor of an unrelated instance with the same site as the
1084 // current one, several times, with and without candidate sites.
1086 SiteInstanceDescriptor
descriptor(browser_context(), kUrlSameSiteAs1
,
1088 scoped_refptr
<SiteInstance
> converted_instance_1
=
1089 ConvertToSiteInstance(rfhm
, descriptor
, nullptr);
1090 // Should return a new instance, unrelated to the current one, set to the
1091 // provided site URL.
1093 current_instance
->IsRelatedSiteInstance(converted_instance_1
.get()));
1094 EXPECT_NE(current_instance
, converted_instance_1
.get());
1095 EXPECT_NE(unrelated_instance
.get(), converted_instance_1
.get());
1096 EXPECT_EQ(SiteInstance::GetSiteForURL(browser_context(), kUrlSameSiteAs1
),
1097 converted_instance_1
->GetSiteURL());
1099 // Does the same but this time using unrelated_instance as a candidate,
1100 // which has a different site.
1101 scoped_refptr
<SiteInstance
> converted_instance_2
=
1102 ConvertToSiteInstance(rfhm
, descriptor
, unrelated_instance
.get());
1103 // Should return yet another new instance, unrelated to the current one, set
1104 // to the same site URL.
1106 current_instance
->IsRelatedSiteInstance(converted_instance_2
.get()));
1107 EXPECT_NE(current_instance
, converted_instance_2
.get());
1108 EXPECT_NE(unrelated_instance
.get(), converted_instance_2
.get());
1109 EXPECT_NE(converted_instance_1
.get(), converted_instance_2
.get());
1110 EXPECT_EQ(SiteInstance::GetSiteForURL(browser_context(), kUrlSameSiteAs1
),
1111 converted_instance_2
->GetSiteURL());
1113 // Converts once more but with |converted_instance_1| as a candidate.
1114 SiteInstance
* converted_instance_3
=
1115 ConvertToSiteInstance(rfhm
, descriptor
, converted_instance_1
.get());
1116 // Should return |converted_instance_1| because its site matches and it is
1117 // unrelated to the current SiteInstance.
1118 EXPECT_EQ(converted_instance_1
.get(), converted_instance_3
);
1121 // 6) Convert a descriptor of an unrelated instance with the same site of
1122 // related_instance and using it as a candidate.
1124 SiteInstanceDescriptor
descriptor(browser_context(), kUrlSameSiteAs2
,
1126 scoped_refptr
<SiteInstance
> converted_instance_1
=
1127 ConvertToSiteInstance(rfhm
, descriptor
, related_instance
.get());
1128 // Should return a new instance, unrelated to the current, set to the
1129 // provided site URL.
1131 current_instance
->IsRelatedSiteInstance(converted_instance_1
.get()));
1132 EXPECT_NE(related_instance
.get(), converted_instance_1
.get());
1133 EXPECT_NE(unrelated_instance
.get(), converted_instance_1
.get());
1134 EXPECT_EQ(SiteInstance::GetSiteForURL(browser_context(), kUrlSameSiteAs2
),
1135 converted_instance_1
->GetSiteURL());
1137 SiteInstance
* converted_instance_2
=
1138 ConvertToSiteInstance(rfhm
, descriptor
, unrelated_instance
.get());
1139 // Should return |unrelated_instance| because its site matches and it is
1140 // unrelated to the current SiteInstance.
1141 EXPECT_EQ(unrelated_instance
.get(), converted_instance_2
);
1145 } // namespace content