Process Alt-Svc headers.
[chromium-blink-merge.git] / content / browser / frame_host / navigator_impl_unittest.cc
blobae3f9b47d37801cbac91f35efe70f55dcf85feb1
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"
36 #endif
38 namespace content {
40 class NavigatorTestWithBrowserSideNavigation
41 : public RenderViewHostImplTestHarness {
42 public:
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));
52 #endif
53 EnableBrowserSideNavigation();
54 RenderViewHostImplTestHarness::SetUp();
57 void TearDown() override {
58 #if !defined(OS_ANDROID)
59 ImageTransportFactory::Terminate();
60 #endif
61 RenderViewHostImplTestHarness::TearDown();
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
78 // NavigationEntry.
79 int RequestNavigationWithParameters(
80 FrameTreeNode* node,
81 const GURL& url,
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
102 // navigations.
103 bool DidRenderFrameHostRequestCommit(TestRenderFrameHost* rfh) {
104 const FrameMsg_CommitNavigation* commit_message =
105 static_cast<const FrameMsg_CommitNavigation*>(
106 rfh->GetProcess()->sink().GetUniqueMessageMatching(
107 FrameMsg_CommitNavigation::ID));
108 return commit_message &&
109 rfh->GetRoutingID() == commit_message->routing_id();
112 SiteInstance* ConvertToSiteInstance(RenderFrameHostManager* rfhm,
113 const SiteInstanceDescriptor& descriptor,
114 SiteInstance* candidate_instance) {
115 return rfhm->ConvertToSiteInstance(descriptor, candidate_instance);
119 // PlzNavigate: Test a complete browser-initiated navigation starting with a
120 // non-live renderer.
121 TEST_F(NavigatorTestWithBrowserSideNavigation,
122 SimpleBrowserInitiatedNavigationFromNonLiveRenderer) {
123 const GURL kUrl("http://chromium.org/");
125 EXPECT_FALSE(main_test_rfh()->IsRenderFrameLive());
127 // Start a browser-initiated navigation.
128 int32 site_instance_id = main_test_rfh()->GetSiteInstance()->GetId();
129 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
130 int entry_id = RequestNavigation(node, kUrl);
131 NavigationRequest* request = node->navigation_request();
132 ASSERT_TRUE(request);
133 EXPECT_EQ(kUrl, request->common_params().url);
134 EXPECT_TRUE(request->browser_initiated());
136 // As there's no live renderer the navigation should not wait for a
137 // beforeUnload ACK from the renderer and start right away.
138 EXPECT_EQ(NavigationRequest::STARTED, request->state());
139 ASSERT_TRUE(GetLoaderForNavigationRequest(request));
140 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
141 EXPECT_FALSE(node->render_manager()->pending_frame_host());
143 // Have the current RenderFrameHost commit the navigation.
144 scoped_refptr<ResourceResponse> response(new ResourceResponse);
145 GetLoaderForNavigationRequest(request)
146 ->CallOnResponseStarted(response, MakeEmptyStream());
147 EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh()));
148 EXPECT_TRUE(main_test_rfh()->is_loading());
149 EXPECT_FALSE(node->navigation_request());
151 // Commit the navigation.
152 main_test_rfh()->SendNavigate(0, entry_id, true, kUrl);
153 EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, main_test_rfh()->rfh_state());
154 EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrl),
155 main_test_rfh()->GetSiteInstance()->GetSiteURL());
156 EXPECT_EQ(kUrl, contents()->GetLastCommittedURL());
157 EXPECT_FALSE(node->render_manager()->pending_frame_host());
159 // The main RenderFrameHost should not have been changed, and the renderer
160 // should have been initialized.
161 EXPECT_EQ(site_instance_id, main_test_rfh()->GetSiteInstance()->GetId());
162 EXPECT_TRUE(main_test_rfh()->IsRenderFrameLive());
164 // After a navigation is finished no speculative RenderFrameHost should
165 // exist.
166 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
168 // With PlzNavigate enabled a pending RenderFrameHost should never exist.
169 EXPECT_FALSE(node->render_manager()->pending_frame_host());
172 // PlzNavigate: Test a complete renderer-initiated same-site navigation.
173 TEST_F(NavigatorTestWithBrowserSideNavigation,
174 SimpleRendererInitiatedSameSiteNavigation) {
175 const GURL kUrl1("http://www.chromium.org/");
176 const GURL kUrl2("http://www.chromium.org/Home");
178 contents()->NavigateAndCommit(kUrl1);
179 EXPECT_TRUE(main_test_rfh()->IsRenderFrameLive());
181 // Start a renderer-initiated non-user-initiated navigation.
182 process()->sink().ClearMessages();
183 main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl2, false);
184 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
185 NavigationRequest* request = node->navigation_request();
186 ASSERT_TRUE(request);
188 // The navigation is immediately started as there's no need to wait for
189 // beforeUnload to be executed.
190 EXPECT_EQ(NavigationRequest::STARTED, request->state());
191 EXPECT_FALSE(request->begin_params().has_user_gesture);
192 EXPECT_EQ(kUrl2, request->common_params().url);
193 EXPECT_FALSE(request->browser_initiated());
194 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
196 // Have the current RenderFrameHost commit the navigation.
197 scoped_refptr<ResourceResponse> response(new ResourceResponse);
198 GetLoaderForNavigationRequest(request)
199 ->CallOnResponseStarted(response, MakeEmptyStream());
200 EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh()));
201 EXPECT_TRUE(main_test_rfh()->is_loading());
202 EXPECT_FALSE(node->navigation_request());
204 // Commit the navigation.
205 main_test_rfh()->SendNavigate(1, 0, true, kUrl2);
206 EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, main_test_rfh()->rfh_state());
207 EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrl2),
208 main_test_rfh()->GetSiteInstance()->GetSiteURL());
209 EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL());
210 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
211 EXPECT_FALSE(node->render_manager()->pending_frame_host());
214 // PlzNavigate: Test a complete renderer-initiated navigation that should be
215 // cross-site but does not result in a SiteInstance swap because its
216 // renderer-initiated.
217 TEST_F(NavigatorTestWithBrowserSideNavigation,
218 SimpleRendererInitiatedCrossSiteNavigation) {
219 const GURL kUrl1("http://www.chromium.org/");
220 const GURL kUrl2("http://www.google.com");
222 contents()->NavigateAndCommit(kUrl1);
223 EXPECT_TRUE(main_test_rfh()->IsRenderFrameLive());
224 int32 site_instance_id_1 = main_test_rfh()->GetSiteInstance()->GetId();
226 // Start a renderer-initiated non-user-initiated navigation.
227 process()->sink().ClearMessages();
228 main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl2, false);
229 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
230 NavigationRequest* request = node->navigation_request();
231 ASSERT_TRUE(request);
233 // The navigation is immediately started as there's no need to wait for
234 // beforeUnload to be executed.
235 EXPECT_EQ(NavigationRequest::STARTED, request->state());
236 EXPECT_FALSE(request->begin_params().has_user_gesture);
237 EXPECT_EQ(kUrl2, request->common_params().url);
238 EXPECT_FALSE(request->browser_initiated());
239 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
241 // Have the current RenderFrameHost commit the navigation.
242 scoped_refptr<ResourceResponse> response(new ResourceResponse);
243 GetLoaderForNavigationRequest(request)
244 ->CallOnResponseStarted(response, MakeEmptyStream());
245 EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh()));
246 EXPECT_TRUE(main_test_rfh()->is_loading());
247 EXPECT_FALSE(node->navigation_request());
249 // Commit the navigation.
250 main_test_rfh()->SendNavigate(1, 0, true, kUrl2);
251 EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, main_test_rfh()->rfh_state());
252 EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL());
253 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
254 EXPECT_FALSE(node->render_manager()->pending_frame_host());
256 // The SiteInstance did not change.
257 EXPECT_EQ(site_instance_id_1, main_test_rfh()->GetSiteInstance()->GetId());
260 // PlzNavigate: Test that a beforeUnload denial cancels the navigation.
261 TEST_F(NavigatorTestWithBrowserSideNavigation,
262 BeforeUnloadDenialCancelNavigation) {
263 const GURL kUrl1("http://www.google.com/");
264 const GURL kUrl2("http://www.chromium.org/");
266 contents()->NavigateAndCommit(kUrl1);
268 // Start a new navigation.
269 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
270 RequestNavigation(node, kUrl2);
271 NavigationRequest* request = node->navigation_request();
272 ASSERT_TRUE(request);
273 EXPECT_TRUE(request->browser_initiated());
274 EXPECT_EQ(NavigationRequest::WAITING_FOR_RENDERER_RESPONSE, request->state());
275 EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
276 RenderFrameDeletedObserver rfh_deleted_observer(
277 GetSpeculativeRenderFrameHost(node));
279 // Simulate a beforeUnload denial.
280 main_test_rfh()->SendBeforeUnloadACK(false);
281 EXPECT_FALSE(node->navigation_request());
282 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
283 EXPECT_TRUE(rfh_deleted_observer.deleted());
286 // PlzNavigate: Test that a proper NavigationRequest is created by
287 // RequestNavigation.
288 TEST_F(NavigatorTestWithBrowserSideNavigation, BeginNavigation) {
289 const GURL kUrl1("http://www.google.com/");
290 const GURL kUrl2("http://www.chromium.org/");
291 const GURL kUrl3("http://www.gmail.com/");
293 contents()->NavigateAndCommit(kUrl1);
295 // Add a subframe.
296 FrameTreeNode* root_node = contents()->GetFrameTree()->root();
297 TestRenderFrameHost* subframe_rfh = main_test_rfh()->AppendChild("Child");
298 ASSERT_TRUE(subframe_rfh);
300 // Start a navigation at the subframe.
301 FrameTreeNode* subframe_node = subframe_rfh->frame_tree_node();
302 RequestNavigation(subframe_node, kUrl2);
303 NavigationRequest* subframe_request = subframe_node->navigation_request();
304 TestNavigationURLLoader* subframe_loader =
305 GetLoaderForNavigationRequest(subframe_request);
307 // Subframe navigations should start right away as they don't have to request
308 // beforeUnload to run at the renderer.
309 ASSERT_TRUE(subframe_request);
310 ASSERT_TRUE(subframe_loader);
311 EXPECT_EQ(NavigationRequest::STARTED, subframe_request->state());
312 EXPECT_EQ(kUrl2, subframe_request->common_params().url);
313 EXPECT_EQ(kUrl2, subframe_loader->request_info()->common_params.url);
314 // First party for cookies url should be that of the main frame.
315 EXPECT_EQ(kUrl1, subframe_loader->request_info()->first_party_for_cookies);
316 EXPECT_FALSE(subframe_loader->request_info()->is_main_frame);
317 EXPECT_TRUE(subframe_loader->request_info()->parent_is_main_frame);
318 EXPECT_TRUE(subframe_request->browser_initiated());
319 EXPECT_FALSE(GetSpeculativeRenderFrameHost(root_node));
321 // Subframe navigations should never create a speculative RenderFrameHost,
322 // unless site-per-process is enabled. In that case, as the subframe
323 // navigation is to a different site and is still ongoing, it should have one.
324 if (AreAllSitesIsolatedForTesting()) {
325 EXPECT_TRUE(GetSpeculativeRenderFrameHost(subframe_node));
326 } else {
327 EXPECT_FALSE(GetSpeculativeRenderFrameHost(subframe_node));
330 // Now start a navigation at the root node.
331 RequestNavigation(root_node, kUrl3);
332 NavigationRequest* main_request = root_node->navigation_request();
333 ASSERT_TRUE(main_request);
334 EXPECT_EQ(NavigationRequest::WAITING_FOR_RENDERER_RESPONSE,
335 main_request->state());
337 // Main frame navigation to a different site should use a speculative
338 // RenderFrameHost.
339 EXPECT_TRUE(GetSpeculativeRenderFrameHost(root_node));
341 // Simulate a BeforeUnloadACK IPC on the main frame.
342 main_test_rfh()->SendBeforeUnloadACK(true);
343 TestNavigationURLLoader* main_loader =
344 GetLoaderForNavigationRequest(main_request);
345 EXPECT_EQ(kUrl3, main_request->common_params().url);
346 EXPECT_EQ(kUrl3, main_loader->request_info()->common_params.url);
347 EXPECT_EQ(kUrl3, main_loader->request_info()->first_party_for_cookies);
348 EXPECT_TRUE(main_loader->request_info()->is_main_frame);
349 EXPECT_FALSE(main_loader->request_info()->parent_is_main_frame);
350 EXPECT_TRUE(main_request->browser_initiated());
351 // BeforeUnloadACK was received from the renderer so the navigation should
352 // have started.
353 EXPECT_EQ(NavigationRequest::STARTED, main_request->state());
354 EXPECT_TRUE(GetSpeculativeRenderFrameHost(root_node));
356 // As the main frame hasn't yet committed the subframe still exists. Thus, the
357 // above situation regarding subframe navigations is valid here.
358 if (AreAllSitesIsolatedForTesting()) {
359 EXPECT_TRUE(GetSpeculativeRenderFrameHost(subframe_node));
360 } else {
361 EXPECT_FALSE(GetSpeculativeRenderFrameHost(subframe_node));
365 // PlzNavigate: Test that committing an HTTP 204 or HTTP 205 response cancels
366 // the navigation.
367 TEST_F(NavigatorTestWithBrowserSideNavigation, NoContent) {
368 const GURL kUrl1("http://www.chromium.org/");
369 const GURL kUrl2("http://www.google.com/");
371 // Load a URL.
372 contents()->NavigateAndCommit(kUrl1);
373 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
375 // Navigate to a different site.
376 process()->sink().ClearMessages();
377 RequestNavigation(node, kUrl2);
378 main_test_rfh()->SendBeforeUnloadACK(true);
380 NavigationRequest* main_request = node->navigation_request();
381 ASSERT_TRUE(main_request);
383 // Navigations to a different site do create a speculative RenderFrameHost.
384 EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
386 // Commit an HTTP 204 response.
387 scoped_refptr<ResourceResponse> response(new ResourceResponse);
388 const char kNoContentHeaders[] = "HTTP/1.1 204 No Content\0\0";
389 response->head.headers = new net::HttpResponseHeaders(
390 std::string(kNoContentHeaders, arraysize(kNoContentHeaders)));
391 GetLoaderForNavigationRequest(main_request)->CallOnResponseStarted(
392 response, MakeEmptyStream());
394 // There should be no pending nor speculative RenderFrameHost; the navigation
395 // was aborted.
396 EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh()));
397 EXPECT_FALSE(node->navigation_request());
398 EXPECT_FALSE(node->render_manager()->pending_frame_host());
399 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
401 // Now, repeat the test with 205 Reset Content.
403 // Navigate to a different site again.
404 process()->sink().ClearMessages();
405 RequestNavigation(node, kUrl2);
406 main_test_rfh()->SendBeforeUnloadACK(true);
408 main_request = node->navigation_request();
409 ASSERT_TRUE(main_request);
410 EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
412 // Commit an HTTP 205 response.
413 response = new ResourceResponse;
414 const char kResetContentHeaders[] = "HTTP/1.1 205 Reset Content\0\0";
415 response->head.headers = new net::HttpResponseHeaders(
416 std::string(kResetContentHeaders, arraysize(kResetContentHeaders)));
417 GetLoaderForNavigationRequest(main_request)->CallOnResponseStarted(
418 response, MakeEmptyStream());
420 // There should be no pending nor speculative RenderFrameHost; the navigation
421 // was aborted.
422 EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh()));
423 EXPECT_FALSE(node->navigation_request());
424 EXPECT_FALSE(node->render_manager()->pending_frame_host());
425 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
428 // PlzNavigate: Test that a new RenderFrameHost is created when doing a cross
429 // site navigation.
430 TEST_F(NavigatorTestWithBrowserSideNavigation, CrossSiteNavigation) {
431 const GURL kUrl1("http://www.chromium.org/");
432 const GURL kUrl2("http://www.google.com/");
434 contents()->NavigateAndCommit(kUrl1);
435 RenderFrameHostImpl* initial_rfh = main_test_rfh();
436 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
438 // Navigate to a different site.
439 process()->sink().ClearMessages();
440 int entry_id = RequestNavigation(node, kUrl2);
441 NavigationRequest* main_request = node->navigation_request();
442 ASSERT_TRUE(main_request);
443 TestRenderFrameHost* speculative_rfh = GetSpeculativeRenderFrameHost(node);
444 ASSERT_TRUE(speculative_rfh);
446 // Receive the beforeUnload ACK.
447 main_test_rfh()->SendBeforeUnloadACK(true);
448 EXPECT_EQ(speculative_rfh, GetSpeculativeRenderFrameHost(node));
449 EXPECT_FALSE(contents()->CrossProcessNavigationPending());
451 scoped_refptr<ResourceResponse> response(new ResourceResponse);
452 GetLoaderForNavigationRequest(main_request)->CallOnResponseStarted(
453 response, MakeEmptyStream());
454 EXPECT_EQ(speculative_rfh, GetSpeculativeRenderFrameHost(node));
455 EXPECT_TRUE(DidRenderFrameHostRequestCommit(speculative_rfh));
456 EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh()));
457 EXPECT_TRUE(contents()->CrossProcessNavigationPending());
459 speculative_rfh->SendNavigate(0, entry_id, true, kUrl2);
461 RenderFrameHostImpl* final_rfh = main_test_rfh();
462 EXPECT_EQ(speculative_rfh, final_rfh);
463 EXPECT_NE(initial_rfh, final_rfh);
464 EXPECT_TRUE(final_rfh->IsRenderFrameLive());
465 EXPECT_TRUE(final_rfh->render_view_host()->IsRenderViewLive());
466 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
469 // PlzNavigate: Test that redirects are followed and the speculative
470 // RenderFrameHost logic behaves as expected.
471 TEST_F(NavigatorTestWithBrowserSideNavigation, RedirectCrossSite) {
472 const GURL kUrl1("http://www.chromium.org/");
473 const GURL kUrl2("http://www.google.com/");
475 contents()->NavigateAndCommit(kUrl1);
476 RenderFrameHostImpl* rfh = main_test_rfh();
477 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
479 // Navigate to a URL on the same site.
480 process()->sink().ClearMessages();
481 int entry_id = RequestNavigation(node, kUrl1);
482 main_test_rfh()->SendBeforeUnloadACK(true);
483 NavigationRequest* main_request = node->navigation_request();
484 ASSERT_TRUE(main_request);
485 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
487 // It then redirects to another site.
488 GetLoaderForNavigationRequest(main_request)->SimulateServerRedirect(kUrl2);
490 // The redirect should have been followed.
491 EXPECT_EQ(1, GetLoaderForNavigationRequest(main_request)->redirect_count());
492 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
494 // Have the RenderFrameHost commit the navigation.
495 scoped_refptr<ResourceResponse> response(new ResourceResponse);
496 GetLoaderForNavigationRequest(main_request)->CallOnResponseStarted(
497 response, MakeEmptyStream());
498 TestRenderFrameHost* final_speculative_rfh =
499 GetSpeculativeRenderFrameHost(node);
500 EXPECT_TRUE(final_speculative_rfh);
501 EXPECT_TRUE(DidRenderFrameHostRequestCommit(final_speculative_rfh));
503 // Commit the navigation.
504 final_speculative_rfh->SendNavigate(0, entry_id, true, kUrl2);
505 RenderFrameHostImpl* final_rfh = main_test_rfh();
506 ASSERT_TRUE(final_rfh);
507 EXPECT_NE(rfh, final_rfh);
508 EXPECT_EQ(final_speculative_rfh, final_rfh);
509 EXPECT_TRUE(final_rfh->IsRenderFrameLive());
510 EXPECT_TRUE(final_rfh->render_view_host()->IsRenderViewLive());
511 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
514 // PlzNavigate: Test that a navigation is canceled if another browser-initiated
515 // request has been issued in the meantime. Also confirms that the speculative
516 // RenderFrameHost is correctly updated in the process.
517 TEST_F(NavigatorTestWithBrowserSideNavigation,
518 BrowserInitiatedNavigationCancel) {
519 const GURL kUrl0("http://www.wikipedia.org/");
520 const GURL kUrl1("http://www.chromium.org/");
521 const GURL kUrl1_site = SiteInstance::GetSiteForURL(browser_context(), kUrl1);
522 const GURL kUrl2("http://www.google.com/");
523 const GURL kUrl2_site = SiteInstance::GetSiteForURL(browser_context(), kUrl2);
525 // Initialization.
526 contents()->NavigateAndCommit(kUrl0);
527 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
529 // Request navigation to the 1st URL.
530 process()->sink().ClearMessages();
531 RequestNavigation(node, kUrl1);
532 main_test_rfh()->SendBeforeUnloadACK(true);
533 NavigationRequest* request1 = node->navigation_request();
534 ASSERT_TRUE(request1);
535 EXPECT_EQ(kUrl1, request1->common_params().url);
536 EXPECT_TRUE(request1->browser_initiated());
537 base::WeakPtr<TestNavigationURLLoader> loader1 =
538 GetLoaderForNavigationRequest(request1)->AsWeakPtr();
539 EXPECT_TRUE(loader1);
541 // Confirm a speculative RenderFrameHost was created.
542 TestRenderFrameHost* speculative_rfh = GetSpeculativeRenderFrameHost(node);
543 ASSERT_TRUE(speculative_rfh);
544 int32 site_instance_id_1 = speculative_rfh->GetSiteInstance()->GetId();
545 EXPECT_EQ(kUrl1_site, speculative_rfh->GetSiteInstance()->GetSiteURL());
547 // Request navigation to the 2nd URL; the NavigationRequest must have been
548 // replaced by a new one with a different URL.
549 int entry_id = RequestNavigation(node, kUrl2);
550 main_test_rfh()->SendBeforeUnloadACK(true);
551 NavigationRequest* request2 = node->navigation_request();
552 ASSERT_TRUE(request2);
553 EXPECT_EQ(kUrl2, request2->common_params().url);
554 EXPECT_TRUE(request2->browser_initiated());
556 // Confirm that the first loader got destroyed.
557 EXPECT_FALSE(loader1);
559 // Confirm that a new speculative RenderFrameHost was created.
560 speculative_rfh = GetSpeculativeRenderFrameHost(node);
561 ASSERT_TRUE(speculative_rfh);
562 int32 site_instance_id_2 = speculative_rfh->GetSiteInstance()->GetId();
563 EXPECT_NE(site_instance_id_1, site_instance_id_2);
565 // Have the RenderFrameHost commit the navigation.
566 scoped_refptr<ResourceResponse> response(new ResourceResponse);
567 GetLoaderForNavigationRequest(request2)->CallOnResponseStarted(
568 response, MakeEmptyStream());
569 EXPECT_TRUE(DidRenderFrameHostRequestCommit(speculative_rfh));
570 EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh()));
572 // Commit the navigation.
573 speculative_rfh->SendNavigate(0, entry_id, true, kUrl2);
575 // Confirm that the commit corresponds to the new request.
576 ASSERT_TRUE(main_test_rfh());
577 EXPECT_EQ(kUrl2_site, main_test_rfh()->GetSiteInstance()->GetSiteURL());
578 EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL());
580 // Confirm that the committed RenderFrameHost is the latest speculative one.
581 EXPECT_EQ(site_instance_id_2, main_test_rfh()->GetSiteInstance()->GetId());
584 // PlzNavigate: Test that a browser-initiated navigation is canceled if a
585 // renderer-initiated user-initiated request has been issued in the meantime.
586 TEST_F(NavigatorTestWithBrowserSideNavigation,
587 RendererUserInitiatedNavigationCancel) {
588 const GURL kUrl0("http://www.wikipedia.org/");
589 const GURL kUrl1("http://www.chromium.org/");
590 const GURL kUrl2("http://www.google.com/");
592 // Initialization.
593 contents()->NavigateAndCommit(kUrl0);
594 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
596 // Start a browser-initiated navigation to the 1st URL and receive its
597 // beforeUnload ACK.
598 process()->sink().ClearMessages();
599 RequestNavigation(node, kUrl1);
600 main_test_rfh()->SendBeforeUnloadACK(true);
601 NavigationRequest* request1 = node->navigation_request();
602 ASSERT_TRUE(request1);
603 EXPECT_EQ(kUrl1, request1->common_params().url);
604 EXPECT_TRUE(request1->browser_initiated());
605 base::WeakPtr<TestNavigationURLLoader> loader1 =
606 GetLoaderForNavigationRequest(request1)->AsWeakPtr();
607 EXPECT_TRUE(loader1);
609 // Confirm that a speculative RenderFrameHost was created.
610 ASSERT_TRUE(GetSpeculativeRenderFrameHost(node));
612 // Now receive a renderer-initiated user-initiated request. It should replace
613 // the current NavigationRequest.
614 main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl2, true);
615 NavigationRequest* request2 = node->navigation_request();
616 ASSERT_TRUE(request2);
617 EXPECT_EQ(kUrl2, request2->common_params().url);
618 EXPECT_FALSE(request2->browser_initiated());
619 EXPECT_TRUE(request2->begin_params().has_user_gesture);
621 // Confirm that the first loader got destroyed.
622 EXPECT_FALSE(loader1);
624 // Confirm that the speculative RenderFrameHost was destroyed.
625 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
627 // Have the RenderFrameHost commit the navigation.
628 scoped_refptr<ResourceResponse> response(new ResourceResponse);
629 GetLoaderForNavigationRequest(request2)
630 ->CallOnResponseStarted(response, MakeEmptyStream());
631 EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh()));
633 // Commit the navigation.
634 main_test_rfh()->SendNavigate(1, 0, true, kUrl2);
636 // Confirm that the commit corresponds to the new request.
637 ASSERT_TRUE(main_test_rfh());
638 EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL());
641 // PlzNavigate: Test that a renderer-initiated user-initiated navigation is NOT
642 // canceled if a renderer-initiated non-user-initiated request is issued in the
643 // meantime.
644 TEST_F(NavigatorTestWithBrowserSideNavigation,
645 RendererNonUserInitiatedNavigationDoesntCancelRendererUserInitiated) {
646 const GURL kUrl0("http://www.wikipedia.org/");
647 const GURL kUrl1("http://www.chromium.org/");
648 const GURL kUrl2("http://www.google.com/");
650 // Initialization.
651 contents()->NavigateAndCommit(kUrl0);
652 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
654 // Start a renderer-initiated user-initiated navigation to the 1st URL.
655 process()->sink().ClearMessages();
656 main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl1, true);
657 NavigationRequest* request1 = node->navigation_request();
658 ASSERT_TRUE(request1);
659 EXPECT_EQ(kUrl1, request1->common_params().url);
660 EXPECT_FALSE(request1->browser_initiated());
661 EXPECT_TRUE(request1->begin_params().has_user_gesture);
662 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
664 // Now receive a renderer-initiated non-user-initiated request. Nothing should
665 // change.
666 main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl2, false);
667 NavigationRequest* request2 = node->navigation_request();
668 ASSERT_TRUE(request2);
669 EXPECT_EQ(request1, request2);
670 EXPECT_EQ(kUrl1, request2->common_params().url);
671 EXPECT_FALSE(request2->browser_initiated());
672 EXPECT_TRUE(request2->begin_params().has_user_gesture);
673 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
675 // Have the RenderFrameHost commit the navigation.
676 scoped_refptr<ResourceResponse> response(new ResourceResponse);
677 GetLoaderForNavigationRequest(request2)
678 ->CallOnResponseStarted(response, MakeEmptyStream());
679 EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh()));
681 // Commit the navigation.
682 main_test_rfh()->SendNavigate(1, 0, true, kUrl1);
683 EXPECT_EQ(kUrl1, contents()->GetLastCommittedURL());
686 // PlzNavigate: Test that a browser-initiated navigation is NOT canceled if a
687 // renderer-initiated non-user-initiated request is issued in the meantime.
688 TEST_F(NavigatorTestWithBrowserSideNavigation,
689 RendererNonUserInitiatedNavigationDoesntCancelBrowserInitiated) {
690 const GURL kUrl0("http://www.wikipedia.org/");
691 const GURL kUrl1("http://www.chromium.org/");
692 const GURL kUrl2("http://www.google.com/");
694 // Initialization.
695 contents()->NavigateAndCommit(kUrl0);
696 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
698 // Start a browser-initiated navigation to the 1st URL.
699 process()->sink().ClearMessages();
700 int entry_id = RequestNavigation(node, kUrl1);
701 NavigationRequest* request1 = node->navigation_request();
702 ASSERT_TRUE(request1);
703 EXPECT_EQ(kUrl1, request1->common_params().url);
704 EXPECT_TRUE(request1->browser_initiated());
705 EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
707 // Now receive a renderer-initiated non-user-initiated request. Nothing should
708 // change.
709 main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl2, false);
710 NavigationRequest* request2 = node->navigation_request();
711 ASSERT_TRUE(request2);
712 EXPECT_EQ(request1, request2);
713 EXPECT_EQ(kUrl1, request2->common_params().url);
714 EXPECT_TRUE(request2->browser_initiated());
715 EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
717 // Now receive the beforeUnload ACK from the still ongoing navigation.
718 main_test_rfh()->SendBeforeUnloadACK(true);
719 TestRenderFrameHost* speculative_rfh = GetSpeculativeRenderFrameHost(node);
720 ASSERT_TRUE(speculative_rfh);
722 // Have the RenderFrameHost commit the navigation.
723 scoped_refptr<ResourceResponse> response(new ResourceResponse);
724 GetLoaderForNavigationRequest(request2)
725 ->CallOnResponseStarted(response, MakeEmptyStream());
726 EXPECT_TRUE(DidRenderFrameHostRequestCommit(speculative_rfh));
727 EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh()));
729 // Commit the navigation.
730 speculative_rfh->SendNavigate(0, entry_id, true, kUrl1);
731 EXPECT_EQ(kUrl1, contents()->GetLastCommittedURL());
734 // PlzNavigate: Test that a renderer-initiated non-user-initiated navigation is
735 // canceled if a another similar request is issued in the meantime.
736 TEST_F(NavigatorTestWithBrowserSideNavigation,
737 RendererNonUserInitiatedNavigationCancelSimilarNavigation) {
738 const GURL kUrl0("http://www.wikipedia.org/");
739 const GURL kUrl1("http://www.chromium.org/");
740 const GURL kUrl2("http://www.google.com/");
742 // Initialization.
743 contents()->NavigateAndCommit(kUrl0);
744 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
745 int32 site_instance_id_0 = main_test_rfh()->GetSiteInstance()->GetId();
747 // Start a renderer-initiated non-user-initiated navigation to the 1st URL.
748 process()->sink().ClearMessages();
749 main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl1, false);
750 NavigationRequest* request1 = node->navigation_request();
751 ASSERT_TRUE(request1);
752 EXPECT_EQ(kUrl1, request1->common_params().url);
753 EXPECT_FALSE(request1->browser_initiated());
754 EXPECT_FALSE(request1->begin_params().has_user_gesture);
755 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
756 base::WeakPtr<TestNavigationURLLoader> loader1 =
757 GetLoaderForNavigationRequest(request1)->AsWeakPtr();
758 EXPECT_TRUE(loader1);
760 // Now receive a 2nd similar request that should replace the current one.
761 main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl2, false);
762 NavigationRequest* request2 = node->navigation_request();
763 EXPECT_EQ(kUrl2, request2->common_params().url);
764 EXPECT_FALSE(request2->browser_initiated());
765 EXPECT_FALSE(request2->begin_params().has_user_gesture);
766 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
768 // Confirm that the first loader got destroyed.
769 EXPECT_FALSE(loader1);
771 // Have the RenderFrameHost commit the navigation.
772 scoped_refptr<ResourceResponse> response(new ResourceResponse);
773 GetLoaderForNavigationRequest(request2)
774 ->CallOnResponseStarted(response, MakeEmptyStream());
775 EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh()));
777 // Commit the navigation.
778 main_test_rfh()->SendNavigate(1, 0, true, kUrl2);
779 EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL());
781 // The SiteInstance did not change.
782 EXPECT_EQ(site_instance_id_0, main_test_rfh()->GetSiteInstance()->GetId());
785 // PlzNavigate: Test that a reload navigation is properly signaled to the
786 // RenderFrame when the navigation can commit. A speculative RenderFrameHost
787 // should not be created at any step.
788 TEST_F(NavigatorTestWithBrowserSideNavigation, Reload) {
789 const GURL kUrl("http://www.google.com/");
790 contents()->NavigateAndCommit(kUrl);
792 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
793 controller().Reload(false);
794 int entry_id = controller().GetPendingEntry()->GetUniqueID();
795 // A NavigationRequest should have been generated.
796 NavigationRequest* main_request = node->navigation_request();
797 ASSERT_TRUE(main_request != NULL);
798 EXPECT_EQ(FrameMsg_Navigate_Type::RELOAD,
799 main_request->common_params().navigation_type);
800 main_test_rfh()->PrepareForCommit();
801 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
803 main_test_rfh()->SendNavigate(0, entry_id, false, kUrl);
804 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
806 // Now do a shift+reload.
807 controller().ReloadIgnoringCache(false);
808 // A NavigationRequest should have been generated.
809 main_request = node->navigation_request();
810 ASSERT_TRUE(main_request != NULL);
811 EXPECT_EQ(FrameMsg_Navigate_Type::RELOAD_IGNORING_CACHE,
812 main_request->common_params().navigation_type);
813 main_test_rfh()->PrepareForCommit();
814 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
817 // PlzNavigate: Confirm that a speculative RenderFrameHost is used when
818 // navigating from one site to another.
819 TEST_F(NavigatorTestWithBrowserSideNavigation,
820 SpeculativeRendererWorksBaseCase) {
821 // Navigate to an initial site.
822 const GURL kUrlInit("http://wikipedia.org/");
823 contents()->NavigateAndCommit(kUrlInit);
824 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
826 // Begin navigating to another site.
827 const GURL kUrl("http://google.com/");
828 process()->sink().ClearMessages();
829 int entry_id = RequestNavigation(node, kUrl);
830 TestRenderFrameHost* speculative_rfh = GetSpeculativeRenderFrameHost(node);
831 ASSERT_TRUE(speculative_rfh);
832 EXPECT_NE(speculative_rfh, main_test_rfh());
834 // Receive the beforeUnload ACK.
835 main_test_rfh()->SendBeforeUnloadACK(true);
836 EXPECT_EQ(speculative_rfh, GetSpeculativeRenderFrameHost(node));
837 EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrl),
838 speculative_rfh->GetSiteInstance()->GetSiteURL());
839 EXPECT_FALSE(node->render_manager()->pending_frame_host());
840 int32 site_instance_id = speculative_rfh->GetSiteInstance()->GetId();
842 // Ask Navigator to commit the navigation by simulating a call to
843 // OnResponseStarted.
844 scoped_refptr<ResourceResponse> response(new ResourceResponse);
845 GetLoaderForNavigationRequest(node->navigation_request())
846 ->CallOnResponseStarted(response, MakeEmptyStream());
847 EXPECT_EQ(speculative_rfh, GetSpeculativeRenderFrameHost(node));
848 EXPECT_TRUE(DidRenderFrameHostRequestCommit(speculative_rfh));
849 EXPECT_EQ(site_instance_id, speculative_rfh->GetSiteInstance()->GetId());
850 EXPECT_FALSE(node->render_manager()->pending_frame_host());
852 // Invoke OnDidCommitProvisionalLoad.
853 speculative_rfh->SendNavigate(0, entry_id, true, kUrl);
854 EXPECT_EQ(site_instance_id, main_test_rfh()->GetSiteInstance()->GetId());
855 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
856 EXPECT_FALSE(node->render_manager()->pending_frame_host());
859 // PlzNavigate: Confirm that a speculative RenderFrameHost is thrown away when
860 // the final URL's site differs from the initial one due to redirects.
861 TEST_F(NavigatorTestWithBrowserSideNavigation,
862 SpeculativeRendererDiscardedAfterRedirectToAnotherSite) {
863 // Navigate to an initial site.
864 const GURL kUrlInit("http://wikipedia.org/");
865 contents()->NavigateAndCommit(kUrlInit);
866 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
867 int32 init_site_instance_id = main_test_rfh()->GetSiteInstance()->GetId();
869 // Begin navigating to another site.
870 const GURL kUrl("http://google.com/");
871 process()->sink().ClearMessages();
872 int entry_id = RequestNavigation(node, kUrl);
873 TestRenderFrameHost* speculative_rfh = GetSpeculativeRenderFrameHost(node);
874 ASSERT_TRUE(speculative_rfh);
875 int32 site_instance_id = speculative_rfh->GetSiteInstance()->GetId();
876 RenderFrameDeletedObserver rfh_deleted_observer(speculative_rfh);
877 EXPECT_NE(init_site_instance_id, site_instance_id);
878 EXPECT_EQ(init_site_instance_id, main_test_rfh()->GetSiteInstance()->GetId());
879 EXPECT_NE(speculative_rfh, main_test_rfh());
880 EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrl),
881 speculative_rfh->GetSiteInstance()->GetSiteURL());
883 // Receive the beforeUnload ACK.
884 main_test_rfh()->SendBeforeUnloadACK(true);
885 EXPECT_EQ(speculative_rfh, GetSpeculativeRenderFrameHost(node));
887 // It then redirects to yet another site.
888 NavigationRequest* main_request = node->navigation_request();
889 ASSERT_TRUE(main_request);
890 const GURL kUrlRedirect("https://www.google.com/");
891 GetLoaderForNavigationRequest(main_request)
892 ->SimulateServerRedirect(kUrlRedirect);
893 EXPECT_EQ(init_site_instance_id, main_test_rfh()->GetSiteInstance()->GetId());
895 // For now, ensure that the speculative RenderFrameHost does not change after
896 // the redirect.
897 // TODO(carlosk): once the speculative RenderFrameHost updates with redirects
898 // this next check will be changed to verify that it actually happens.
899 EXPECT_EQ(speculative_rfh, GetSpeculativeRenderFrameHost(node));
900 EXPECT_EQ(site_instance_id, speculative_rfh->GetSiteInstance()->GetId());
901 EXPECT_FALSE(rfh_deleted_observer.deleted());
903 // Commit the navigation with Navigator by simulating the call to
904 // OnResponseStarted.
905 scoped_refptr<ResourceResponse> response(new ResourceResponse);
906 GetLoaderForNavigationRequest(main_request)
907 ->CallOnResponseStarted(response, MakeEmptyStream());
908 speculative_rfh = GetSpeculativeRenderFrameHost(node);
909 ASSERT_TRUE(speculative_rfh);
910 EXPECT_TRUE(DidRenderFrameHostRequestCommit(speculative_rfh));
911 EXPECT_EQ(init_site_instance_id, main_test_rfh()->GetSiteInstance()->GetId());
912 EXPECT_TRUE(rfh_deleted_observer.deleted());
914 // Once commit happens the speculative RenderFrameHost is updated to match the
915 // known final SiteInstance.
916 EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrlRedirect),
917 speculative_rfh->GetSiteInstance()->GetSiteURL());
918 int32 redirect_site_instance_id = speculative_rfh->GetSiteInstance()->GetId();
919 EXPECT_NE(init_site_instance_id, redirect_site_instance_id);
920 EXPECT_NE(site_instance_id, redirect_site_instance_id);
922 // Invoke OnDidCommitProvisionalLoad.
923 speculative_rfh->SendNavigate(0, entry_id, true, kUrlRedirect);
925 // Check that the speculative RenderFrameHost was swapped in.
926 EXPECT_EQ(redirect_site_instance_id,
927 main_test_rfh()->GetSiteInstance()->GetId());
928 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
931 // PlzNavigate: Verify that a previously swapped out RenderFrameHost is
932 // correctly reused when spawning a speculative RenderFrameHost in a navigation
933 // using the same SiteInstance.
934 TEST_F(NavigatorTestWithBrowserSideNavigation,
935 SpeculativeRendererReuseSwappedOutRFH) {
936 // This test doesn't make sense in --site-per-process where swapped out
937 // RenderFrameHost is no longer used.
938 if (SiteIsolationPolicy::IsSwappedOutStateForbidden())
939 return;
941 // Navigate to an initial site.
942 const GURL kUrl1("http://wikipedia.org/");
943 contents()->NavigateAndCommit(kUrl1);
944 TestRenderFrameHost* rfh1 = main_test_rfh();
945 FrameTreeNode* node = rfh1->frame_tree_node();
946 RenderFrameHostManager* rfhm = node->render_manager();
948 // Increment active frame count to cause the RenderFrameHost to be swapped out
949 // (instead of immediately destroyed).
950 rfh1->GetSiteInstance()->increment_active_frame_count();
952 // Navigate to another site to swap out the initial RenderFrameHost.
953 const GURL kUrl2("http://chromium.org/");
954 contents()->NavigateAndCommit(kUrl2);
955 ASSERT_NE(rfh1, main_test_rfh());
956 EXPECT_NE(RenderFrameHostImpl::STATE_DEFAULT, rfh1->rfh_state());
957 EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, main_test_rfh()->rfh_state());
958 EXPECT_TRUE(rfhm->IsOnSwappedOutList(rfh1));
960 // Now go back to the initial site so that the swapped out RenderFrameHost
961 // should be reused.
962 process()->sink().ClearMessages();
963 rfh1->GetProcess()->sink().ClearMessages();
964 int entry_id = RequestNavigation(node, kUrl1);
965 EXPECT_EQ(rfh1, GetSpeculativeRenderFrameHost(node));
967 main_test_rfh()->SendBeforeUnloadACK(true);
968 EXPECT_EQ(rfh1, GetSpeculativeRenderFrameHost(node));
969 EXPECT_NE(RenderFrameHostImpl::STATE_DEFAULT,
970 GetSpeculativeRenderFrameHost(node)->rfh_state());
972 scoped_refptr<ResourceResponse> response(new ResourceResponse);
973 GetLoaderForNavigationRequest(node->navigation_request())
974 ->CallOnResponseStarted(response, MakeEmptyStream());
975 EXPECT_EQ(rfh1, GetSpeculativeRenderFrameHost(node));
976 EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT,
977 GetSpeculativeRenderFrameHost(node)->rfh_state());
978 EXPECT_TRUE(DidRenderFrameHostRequestCommit(rfh1));
979 EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh()));
981 rfh1->SendNavigate(1, entry_id, true, kUrl1);
982 EXPECT_EQ(rfh1, main_test_rfh());
983 EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, rfh1->rfh_state());
984 EXPECT_FALSE(rfhm->IsOnSwappedOutList(rfh1));
987 // PlzNavigate: Verify that data urls are properly handled.
988 TEST_F(NavigatorTestWithBrowserSideNavigation, DataUrls) {
989 const GURL kUrl1("http://wikipedia.org/");
990 const GURL kUrl2("data:text/html,test");
992 // Navigate to an initial site.
993 contents()->NavigateAndCommit(kUrl1);
994 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
996 // Navigate to a data url. The request should not have been sent to the IO
997 // thread but committed immediately.
998 int entry_id = RequestNavigation(node, kUrl2);
999 TestRenderFrameHost* speculative_rfh = GetSpeculativeRenderFrameHost(node);
1000 ASSERT_TRUE(speculative_rfh);
1001 EXPECT_TRUE(speculative_rfh->is_loading());
1002 EXPECT_FALSE(node->navigation_request());
1003 speculative_rfh->SendNavigate(0, entry_id, true, kUrl2);
1004 EXPECT_EQ(main_test_rfh(), speculative_rfh);
1006 // Go back to the initial site.
1007 contents()->NavigateAndCommit(kUrl1);
1009 // Do a renderer-initiated navigation to a data url. The request should not be
1010 // sent to the IO thread, nor committed.
1011 TestRenderFrameHost* main_rfh = main_test_rfh();
1012 main_rfh->SendRendererInitiatedNavigationRequest(kUrl2, true);
1013 EXPECT_TRUE(main_rfh->is_loading());
1014 EXPECT_FALSE(node->navigation_request());
1015 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
1018 // Tests several cases for converting SiteInstanceDescriptors into
1019 // SiteInstances:
1020 // 1) Pointer to the current SiteInstance.
1021 // 2) Pointer to an unrelated SiteInstance.
1022 // 3) Same-site URL, related.
1023 // 4) Cross-site URL, related.
1024 // 5) Same-site URL, unrelated (with and without candidate SiteInstances).
1025 // 6) Cross-site URL, unrelated (with candidate SiteInstance).
1026 TEST_F(NavigatorTestWithBrowserSideNavigation,
1027 SiteInstanceDescriptionConversion) {
1028 // Navigate to set a current SiteInstance on the RenderFrameHost.
1029 GURL kUrl1("http://a.com");
1030 contents()->NavigateAndCommit(kUrl1);
1031 SiteInstance* current_instance = main_test_rfh()->GetSiteInstance();
1032 ASSERT_TRUE(current_instance);
1034 // 1) Convert a descriptor pointing to the current instance.
1035 RenderFrameHostManager* rfhm =
1036 main_test_rfh()->frame_tree_node()->render_manager();
1038 SiteInstanceDescriptor descriptor(current_instance);
1039 SiteInstance* converted_instance =
1040 ConvertToSiteInstance(rfhm, descriptor, nullptr);
1041 EXPECT_EQ(current_instance, converted_instance);
1044 // 2) Convert a descriptor pointing an instance unrelated to the current one,
1045 // with a different site.
1046 GURL kUrl2("http://b.com");
1047 scoped_refptr<SiteInstance> unrelated_instance(
1048 SiteInstance::CreateForURL(browser_context(), kUrl2));
1049 EXPECT_FALSE(
1050 current_instance->IsRelatedSiteInstance(unrelated_instance.get()));
1052 SiteInstanceDescriptor descriptor(unrelated_instance.get());
1053 SiteInstance* converted_instance =
1054 ConvertToSiteInstance(rfhm, descriptor, nullptr);
1055 EXPECT_EQ(unrelated_instance.get(), converted_instance);
1058 // 3) Convert a descriptor of a related instance with the same site as the
1059 // current one.
1060 GURL kUrlSameSiteAs1("http://www.a.com/foo");
1062 SiteInstanceDescriptor descriptor(browser_context(), kUrlSameSiteAs1, true);
1063 SiteInstance* converted_instance =
1064 ConvertToSiteInstance(rfhm, descriptor, nullptr);
1065 EXPECT_EQ(current_instance, converted_instance);
1068 // 4) Convert a descriptor of a related instance with a site different from
1069 // the current one.
1070 GURL kUrlSameSiteAs2("http://www.b.com/foo");
1071 scoped_refptr<SiteInstance> related_instance;
1073 SiteInstanceDescriptor descriptor(browser_context(), kUrlSameSiteAs2, true);
1074 related_instance = ConvertToSiteInstance(rfhm, descriptor, nullptr);
1075 // Should return a new instance, related to the current, set to the new site
1076 // URL.
1077 EXPECT_TRUE(
1078 current_instance->IsRelatedSiteInstance(related_instance.get()));
1079 EXPECT_NE(current_instance, related_instance.get());
1080 EXPECT_NE(unrelated_instance.get(), related_instance.get());
1081 EXPECT_EQ(SiteInstance::GetSiteForURL(browser_context(), kUrlSameSiteAs2),
1082 related_instance->GetSiteURL());
1085 // 5) Convert a descriptor of an unrelated instance with the same site as the
1086 // current one, several times, with and without candidate sites.
1088 SiteInstanceDescriptor descriptor(browser_context(), kUrlSameSiteAs1,
1089 false);
1090 scoped_refptr<SiteInstance> converted_instance_1 =
1091 ConvertToSiteInstance(rfhm, descriptor, nullptr);
1092 // Should return a new instance, unrelated to the current one, set to the
1093 // provided site URL.
1094 EXPECT_FALSE(
1095 current_instance->IsRelatedSiteInstance(converted_instance_1.get()));
1096 EXPECT_NE(current_instance, converted_instance_1.get());
1097 EXPECT_NE(unrelated_instance.get(), converted_instance_1.get());
1098 EXPECT_EQ(SiteInstance::GetSiteForURL(browser_context(), kUrlSameSiteAs1),
1099 converted_instance_1->GetSiteURL());
1101 // Does the same but this time using unrelated_instance as a candidate,
1102 // which has a different site.
1103 scoped_refptr<SiteInstance> converted_instance_2 =
1104 ConvertToSiteInstance(rfhm, descriptor, unrelated_instance.get());
1105 // Should return yet another new instance, unrelated to the current one, set
1106 // to the same site URL.
1107 EXPECT_FALSE(
1108 current_instance->IsRelatedSiteInstance(converted_instance_2.get()));
1109 EXPECT_NE(current_instance, converted_instance_2.get());
1110 EXPECT_NE(unrelated_instance.get(), converted_instance_2.get());
1111 EXPECT_NE(converted_instance_1.get(), converted_instance_2.get());
1112 EXPECT_EQ(SiteInstance::GetSiteForURL(browser_context(), kUrlSameSiteAs1),
1113 converted_instance_2->GetSiteURL());
1115 // Converts once more but with |converted_instance_1| as a candidate.
1116 SiteInstance* converted_instance_3 =
1117 ConvertToSiteInstance(rfhm, descriptor, converted_instance_1.get());
1118 // Should return |converted_instance_1| because its site matches and it is
1119 // unrelated to the current SiteInstance.
1120 EXPECT_EQ(converted_instance_1.get(), converted_instance_3);
1123 // 6) Convert a descriptor of an unrelated instance with the same site of
1124 // related_instance and using it as a candidate.
1126 SiteInstanceDescriptor descriptor(browser_context(), kUrlSameSiteAs2,
1127 false);
1128 scoped_refptr<SiteInstance> converted_instance_1 =
1129 ConvertToSiteInstance(rfhm, descriptor, related_instance.get());
1130 // Should return a new instance, unrelated to the current, set to the
1131 // provided site URL.
1132 EXPECT_FALSE(
1133 current_instance->IsRelatedSiteInstance(converted_instance_1.get()));
1134 EXPECT_NE(related_instance.get(), converted_instance_1.get());
1135 EXPECT_NE(unrelated_instance.get(), converted_instance_1.get());
1136 EXPECT_EQ(SiteInstance::GetSiteForURL(browser_context(), kUrlSameSiteAs2),
1137 converted_instance_1->GetSiteURL());
1139 SiteInstance* converted_instance_2 =
1140 ConvertToSiteInstance(rfhm, descriptor, unrelated_instance.get());
1141 // Should return |unrelated_instance| because its site matches and it is
1142 // unrelated to the current SiteInstance.
1143 EXPECT_EQ(unrelated_instance.get(), converted_instance_2);
1147 } // namespace content