DevTools: cut host and port from webSocketDebuggerUrl in addition to ws:// prefix
[chromium-blink-merge.git] / content / browser / frame_host / navigator_impl_unittest.cc
bloba600dbf7fa7ad22136d6375ac02fa81fcd54c94e
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/command_line.h"
6 #include "base/macros.h"
7 #include "base/time/time.h"
8 #include "content/browser/frame_host/navigation_controller_impl.h"
9 #include "content/browser/frame_host/navigation_entry_impl.h"
10 #include "content/browser/frame_host/navigation_request.h"
11 #include "content/browser/frame_host/navigation_request_info.h"
12 #include "content/browser/frame_host/navigator.h"
13 #include "content/browser/frame_host/navigator_impl.h"
14 #include "content/browser/frame_host/render_frame_host_manager.h"
15 #include "content/browser/site_instance_impl.h"
16 #include "content/browser/streams/stream.h"
17 #include "content/common/frame_messages.h"
18 #include "content/common/navigation_params.h"
19 #include "content/public/browser/stream_handle.h"
20 #include "content/public/common/content_switches.h"
21 #include "content/public/common/url_constants.h"
22 #include "content/public/common/url_utils.h"
23 #include "content/public/test/mock_render_process_host.h"
24 #include "content/test/browser_side_navigation_test_utils.h"
25 #include "content/test/test_navigation_url_loader.h"
26 #include "content/test/test_render_frame_host.h"
27 #include "content/test/test_web_contents.h"
28 #include "net/base/load_flags.h"
29 #include "net/http/http_response_headers.h"
30 #include "net/url_request/redirect_info.h"
31 #include "ui/base/page_transition_types.h"
32 #include "url/url_constants.h"
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));
277 // Simulate a beforeUnload denial.
278 main_test_rfh()->SendBeforeUnloadACK(false);
279 EXPECT_FALSE(node->navigation_request());
280 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
283 // PlzNavigate: Test that a proper NavigationRequest is created by
284 // RequestNavigation.
285 TEST_F(NavigatorTestWithBrowserSideNavigation, BeginNavigation) {
286 const GURL kUrl1("http://www.google.com/");
287 const GURL kUrl2("http://www.chromium.org/");
288 const GURL kUrl3("http://www.gmail.com/");
290 contents()->NavigateAndCommit(kUrl1);
292 // Add a subframe.
293 FrameTreeNode* root_node = contents()->GetFrameTree()->root();
294 TestRenderFrameHost* subframe_rfh = main_test_rfh()->AppendChild("Child");
295 ASSERT_TRUE(subframe_rfh);
297 // Start a navigation at the subframe.
298 FrameTreeNode* subframe_node = subframe_rfh->frame_tree_node();
299 RequestNavigation(subframe_node, kUrl2);
300 NavigationRequest* subframe_request = subframe_node->navigation_request();
301 TestNavigationURLLoader* subframe_loader =
302 GetLoaderForNavigationRequest(subframe_request);
304 // Subframe navigations should start right away as they don't have to request
305 // beforeUnload to run at the renderer.
306 ASSERT_TRUE(subframe_request);
307 ASSERT_TRUE(subframe_loader);
308 EXPECT_EQ(NavigationRequest::STARTED, subframe_request->state());
309 EXPECT_EQ(kUrl2, subframe_request->common_params().url);
310 EXPECT_EQ(kUrl2, subframe_loader->request_info()->common_params.url);
311 // First party for cookies url should be that of the main frame.
312 EXPECT_EQ(kUrl1, subframe_loader->request_info()->first_party_for_cookies);
313 EXPECT_FALSE(subframe_loader->request_info()->is_main_frame);
314 EXPECT_TRUE(subframe_loader->request_info()->parent_is_main_frame);
315 EXPECT_TRUE(subframe_request->browser_initiated());
316 EXPECT_FALSE(GetSpeculativeRenderFrameHost(root_node));
318 // Subframe navigations should never create a speculative RenderFrameHost,
319 // unless site-per-process is enabled. In that case, as the subframe
320 // navigation is to a different site and is still ongoing, it should have one.
321 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
322 switches::kSitePerProcess)) {
323 EXPECT_TRUE(GetSpeculativeRenderFrameHost(subframe_node));
324 } else {
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
336 // RenderFrameHost.
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
350 // have started.
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 (base::CommandLine::ForCurrentProcess()->HasSwitch(
357 switches::kSitePerProcess)) {
358 EXPECT_TRUE(GetSpeculativeRenderFrameHost(subframe_node));
359 } else {
360 EXPECT_FALSE(GetSpeculativeRenderFrameHost(subframe_node));
364 // PlzNavigate: Test that committing an HTTP 204 or HTTP 205 response cancels
365 // the navigation.
366 TEST_F(NavigatorTestWithBrowserSideNavigation, NoContent) {
367 const GURL kUrl1("http://www.chromium.org/");
368 const GURL kUrl2("http://www.google.com/");
370 // Load a URL.
371 contents()->NavigateAndCommit(kUrl1);
372 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
374 // Navigate to a different site.
375 process()->sink().ClearMessages();
376 RequestNavigation(node, kUrl2);
377 main_test_rfh()->SendBeforeUnloadACK(true);
379 NavigationRequest* main_request = node->navigation_request();
380 ASSERT_TRUE(main_request);
382 // Navigations to a different site do create a speculative RenderFrameHost.
383 EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
385 // Commit an HTTP 204 response.
386 scoped_refptr<ResourceResponse> response(new ResourceResponse);
387 const char kNoContentHeaders[] = "HTTP/1.1 204 No Content\0\0";
388 response->head.headers = new net::HttpResponseHeaders(
389 std::string(kNoContentHeaders, arraysize(kNoContentHeaders)));
390 GetLoaderForNavigationRequest(main_request)->CallOnResponseStarted(
391 response, MakeEmptyStream());
393 // There should be no pending nor speculative RenderFrameHost; the navigation
394 // was aborted.
395 EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh()));
396 EXPECT_FALSE(node->navigation_request());
397 EXPECT_FALSE(node->render_manager()->pending_frame_host());
398 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
400 // Now, repeat the test with 205 Reset Content.
402 // Navigate to a different site again.
403 process()->sink().ClearMessages();
404 RequestNavigation(node, kUrl2);
405 main_test_rfh()->SendBeforeUnloadACK(true);
407 main_request = node->navigation_request();
408 ASSERT_TRUE(main_request);
409 EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
411 // Commit an HTTP 205 response.
412 response = new ResourceResponse;
413 const char kResetContentHeaders[] = "HTTP/1.1 205 Reset Content\0\0";
414 response->head.headers = new net::HttpResponseHeaders(
415 std::string(kResetContentHeaders, arraysize(kResetContentHeaders)));
416 GetLoaderForNavigationRequest(main_request)->CallOnResponseStarted(
417 response, MakeEmptyStream());
419 // There should be no pending nor speculative RenderFrameHost; the navigation
420 // was aborted.
421 EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh()));
422 EXPECT_FALSE(node->navigation_request());
423 EXPECT_FALSE(node->render_manager()->pending_frame_host());
424 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
427 // PlzNavigate: Test that a new RenderFrameHost is created when doing a cross
428 // site navigation.
429 TEST_F(NavigatorTestWithBrowserSideNavigation, CrossSiteNavigation) {
430 const GURL kUrl1("http://www.chromium.org/");
431 const GURL kUrl2("http://www.google.com/");
433 contents()->NavigateAndCommit(kUrl1);
434 RenderFrameHostImpl* initial_rfh = main_test_rfh();
435 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
437 // Navigate to a different site.
438 process()->sink().ClearMessages();
439 int entry_id = RequestNavigation(node, kUrl2);
440 NavigationRequest* main_request = node->navigation_request();
441 ASSERT_TRUE(main_request);
442 TestRenderFrameHost* speculative_rfh = GetSpeculativeRenderFrameHost(node);
443 ASSERT_TRUE(speculative_rfh);
445 // Receive the beforeUnload ACK.
446 main_test_rfh()->SendBeforeUnloadACK(true);
447 EXPECT_EQ(speculative_rfh, GetSpeculativeRenderFrameHost(node));
448 EXPECT_FALSE(contents()->CrossProcessNavigationPending());
450 scoped_refptr<ResourceResponse> response(new ResourceResponse);
451 GetLoaderForNavigationRequest(main_request)->CallOnResponseStarted(
452 response, MakeEmptyStream());
453 EXPECT_EQ(speculative_rfh, GetSpeculativeRenderFrameHost(node));
454 EXPECT_TRUE(DidRenderFrameHostRequestCommit(speculative_rfh));
455 EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh()));
456 EXPECT_TRUE(contents()->CrossProcessNavigationPending());
458 speculative_rfh->SendNavigate(0, entry_id, true, kUrl2);
460 RenderFrameHostImpl* final_rfh = main_test_rfh();
461 EXPECT_EQ(speculative_rfh, final_rfh);
462 EXPECT_NE(initial_rfh, final_rfh);
463 EXPECT_TRUE(final_rfh->IsRenderFrameLive());
464 EXPECT_TRUE(final_rfh->render_view_host()->IsRenderViewLive());
465 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
468 // PlzNavigate: Test that redirects are followed and the speculative
469 // RenderFrameHost logic behaves as expected.
470 TEST_F(NavigatorTestWithBrowserSideNavigation, RedirectCrossSite) {
471 const GURL kUrl1("http://www.chromium.org/");
472 const GURL kUrl2("http://www.google.com/");
474 contents()->NavigateAndCommit(kUrl1);
475 RenderFrameHostImpl* rfh = main_test_rfh();
476 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
478 // Navigate to a URL on the same site.
479 process()->sink().ClearMessages();
480 int entry_id = RequestNavigation(node, kUrl1);
481 main_test_rfh()->SendBeforeUnloadACK(true);
482 NavigationRequest* main_request = node->navigation_request();
483 ASSERT_TRUE(main_request);
484 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
486 // It then redirects to another site.
487 GetLoaderForNavigationRequest(main_request)->SimulateServerRedirect(kUrl2);
489 // The redirect should have been followed.
490 EXPECT_EQ(1, GetLoaderForNavigationRequest(main_request)->redirect_count());
491 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
493 // Have the RenderFrameHost commit the navigation.
494 scoped_refptr<ResourceResponse> response(new ResourceResponse);
495 GetLoaderForNavigationRequest(main_request)->CallOnResponseStarted(
496 response, MakeEmptyStream());
497 TestRenderFrameHost* final_speculative_rfh =
498 GetSpeculativeRenderFrameHost(node);
499 EXPECT_TRUE(final_speculative_rfh);
500 EXPECT_TRUE(DidRenderFrameHostRequestCommit(final_speculative_rfh));
502 // Commit the navigation.
503 final_speculative_rfh->SendNavigate(0, entry_id, true, kUrl2);
504 RenderFrameHostImpl* final_rfh = main_test_rfh();
505 ASSERT_TRUE(final_rfh);
506 EXPECT_NE(rfh, final_rfh);
507 EXPECT_EQ(final_speculative_rfh, final_rfh);
508 EXPECT_TRUE(final_rfh->IsRenderFrameLive());
509 EXPECT_TRUE(final_rfh->render_view_host()->IsRenderViewLive());
510 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
513 // PlzNavigate: Test that a navigation is canceled if another browser-initiated
514 // request has been issued in the meantime. Also confirms that the speculative
515 // RenderFrameHost is correctly updated in the process.
516 TEST_F(NavigatorTestWithBrowserSideNavigation,
517 BrowserInitiatedNavigationCancel) {
518 const GURL kUrl0("http://www.wikipedia.org/");
519 const GURL kUrl1("http://www.chromium.org/");
520 const GURL kUrl1_site = SiteInstance::GetSiteForURL(browser_context(), kUrl1);
521 const GURL kUrl2("http://www.google.com/");
522 const GURL kUrl2_site = SiteInstance::GetSiteForURL(browser_context(), kUrl2);
524 // Initialization.
525 contents()->NavigateAndCommit(kUrl0);
526 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
528 // Request navigation to the 1st URL.
529 process()->sink().ClearMessages();
530 RequestNavigation(node, kUrl1);
531 main_test_rfh()->SendBeforeUnloadACK(true);
532 NavigationRequest* request1 = node->navigation_request();
533 ASSERT_TRUE(request1);
534 EXPECT_EQ(kUrl1, request1->common_params().url);
535 EXPECT_TRUE(request1->browser_initiated());
536 base::WeakPtr<TestNavigationURLLoader> loader1 =
537 GetLoaderForNavigationRequest(request1)->AsWeakPtr();
538 EXPECT_TRUE(loader1);
540 // Confirm a speculative RenderFrameHost was created.
541 TestRenderFrameHost* speculative_rfh = GetSpeculativeRenderFrameHost(node);
542 ASSERT_TRUE(speculative_rfh);
543 int32 site_instance_id_1 = speculative_rfh->GetSiteInstance()->GetId();
544 EXPECT_EQ(kUrl1_site, speculative_rfh->GetSiteInstance()->GetSiteURL());
546 // Request navigation to the 2nd URL; the NavigationRequest must have been
547 // replaced by a new one with a different URL.
548 int entry_id = RequestNavigation(node, kUrl2);
549 main_test_rfh()->SendBeforeUnloadACK(true);
550 NavigationRequest* request2 = node->navigation_request();
551 ASSERT_TRUE(request2);
552 EXPECT_EQ(kUrl2, request2->common_params().url);
553 EXPECT_TRUE(request2->browser_initiated());
555 // Confirm that the first loader got destroyed.
556 EXPECT_FALSE(loader1);
558 // Confirm that a new speculative RenderFrameHost was created.
559 speculative_rfh = GetSpeculativeRenderFrameHost(node);
560 ASSERT_TRUE(speculative_rfh);
561 int32 site_instance_id_2 = speculative_rfh->GetSiteInstance()->GetId();
562 EXPECT_NE(site_instance_id_1, site_instance_id_2);
564 // Have the RenderFrameHost commit the navigation.
565 scoped_refptr<ResourceResponse> response(new ResourceResponse);
566 GetLoaderForNavigationRequest(request2)->CallOnResponseStarted(
567 response, MakeEmptyStream());
568 EXPECT_TRUE(DidRenderFrameHostRequestCommit(speculative_rfh));
569 EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh()));
571 // Commit the navigation.
572 speculative_rfh->SendNavigate(0, entry_id, true, kUrl2);
574 // Confirm that the commit corresponds to the new request.
575 ASSERT_TRUE(main_test_rfh());
576 EXPECT_EQ(kUrl2_site, main_test_rfh()->GetSiteInstance()->GetSiteURL());
577 EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL());
579 // Confirm that the committed RenderFrameHost is the latest speculative one.
580 EXPECT_EQ(site_instance_id_2, main_test_rfh()->GetSiteInstance()->GetId());
583 // PlzNavigate: Test that a browser-initiated navigation is canceled if a
584 // renderer-initiated user-initiated request has been issued in the meantime.
585 TEST_F(NavigatorTestWithBrowserSideNavigation,
586 RendererUserInitiatedNavigationCancel) {
587 const GURL kUrl0("http://www.wikipedia.org/");
588 const GURL kUrl1("http://www.chromium.org/");
589 const GURL kUrl2("http://www.google.com/");
591 // Initialization.
592 contents()->NavigateAndCommit(kUrl0);
593 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
595 // Start a browser-initiated navigation to the 1st URL and receive its
596 // beforeUnload ACK.
597 process()->sink().ClearMessages();
598 RequestNavigation(node, kUrl1);
599 main_test_rfh()->SendBeforeUnloadACK(true);
600 NavigationRequest* request1 = node->navigation_request();
601 ASSERT_TRUE(request1);
602 EXPECT_EQ(kUrl1, request1->common_params().url);
603 EXPECT_TRUE(request1->browser_initiated());
604 base::WeakPtr<TestNavigationURLLoader> loader1 =
605 GetLoaderForNavigationRequest(request1)->AsWeakPtr();
606 EXPECT_TRUE(loader1);
608 // Confirm that a speculative RenderFrameHost was created.
609 ASSERT_TRUE(GetSpeculativeRenderFrameHost(node));
611 // Now receive a renderer-initiated user-initiated request. It should replace
612 // the current NavigationRequest.
613 main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl2, true);
614 NavigationRequest* request2 = node->navigation_request();
615 ASSERT_TRUE(request2);
616 EXPECT_EQ(kUrl2, request2->common_params().url);
617 EXPECT_FALSE(request2->browser_initiated());
618 EXPECT_TRUE(request2->begin_params().has_user_gesture);
620 // Confirm that the first loader got destroyed.
621 EXPECT_FALSE(loader1);
623 // Confirm that the speculative RenderFrameHost was destroyed.
624 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
626 // Have the RenderFrameHost commit the navigation.
627 scoped_refptr<ResourceResponse> response(new ResourceResponse);
628 GetLoaderForNavigationRequest(request2)
629 ->CallOnResponseStarted(response, MakeEmptyStream());
630 EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh()));
632 // Commit the navigation.
633 main_test_rfh()->SendNavigate(1, 0, true, kUrl2);
635 // Confirm that the commit corresponds to the new request.
636 ASSERT_TRUE(main_test_rfh());
637 EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL());
640 // PlzNavigate: Test that a renderer-initiated user-initiated navigation is NOT
641 // canceled if a renderer-initiated non-user-initiated request is issued in the
642 // meantime.
643 TEST_F(NavigatorTestWithBrowserSideNavigation,
644 RendererNonUserInitiatedNavigationDoesntCancelRendererUserInitiated) {
645 const GURL kUrl0("http://www.wikipedia.org/");
646 const GURL kUrl1("http://www.chromium.org/");
647 const GURL kUrl2("http://www.google.com/");
649 // Initialization.
650 contents()->NavigateAndCommit(kUrl0);
651 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
653 // Start a renderer-initiated user-initiated navigation to the 1st URL.
654 process()->sink().ClearMessages();
655 main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl1, true);
656 NavigationRequest* request1 = node->navigation_request();
657 ASSERT_TRUE(request1);
658 EXPECT_EQ(kUrl1, request1->common_params().url);
659 EXPECT_FALSE(request1->browser_initiated());
660 EXPECT_TRUE(request1->begin_params().has_user_gesture);
661 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
663 // Now receive a renderer-initiated non-user-initiated request. Nothing should
664 // change.
665 main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl2, false);
666 NavigationRequest* request2 = node->navigation_request();
667 ASSERT_TRUE(request2);
668 EXPECT_EQ(request1, request2);
669 EXPECT_EQ(kUrl1, request2->common_params().url);
670 EXPECT_FALSE(request2->browser_initiated());
671 EXPECT_TRUE(request2->begin_params().has_user_gesture);
672 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
674 // Have the RenderFrameHost commit the navigation.
675 scoped_refptr<ResourceResponse> response(new ResourceResponse);
676 GetLoaderForNavigationRequest(request2)
677 ->CallOnResponseStarted(response, MakeEmptyStream());
678 EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh()));
680 // Commit the navigation.
681 main_test_rfh()->SendNavigate(1, 0, true, kUrl1);
682 EXPECT_EQ(kUrl1, contents()->GetLastCommittedURL());
685 // PlzNavigate: Test that a browser-initiated navigation is NOT canceled if a
686 // renderer-initiated non-user-initiated request is issued in the meantime.
687 TEST_F(NavigatorTestWithBrowserSideNavigation,
688 RendererNonUserInitiatedNavigationDoesntCancelBrowserInitiated) {
689 const GURL kUrl0("http://www.wikipedia.org/");
690 const GURL kUrl1("http://www.chromium.org/");
691 const GURL kUrl2("http://www.google.com/");
693 // Initialization.
694 contents()->NavigateAndCommit(kUrl0);
695 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
697 // Start a browser-initiated navigation to the 1st URL.
698 process()->sink().ClearMessages();
699 int entry_id = RequestNavigation(node, kUrl1);
700 NavigationRequest* request1 = node->navigation_request();
701 ASSERT_TRUE(request1);
702 EXPECT_EQ(kUrl1, request1->common_params().url);
703 EXPECT_TRUE(request1->browser_initiated());
704 EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
706 // Now receive a renderer-initiated non-user-initiated request. Nothing should
707 // change.
708 main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl2, false);
709 NavigationRequest* request2 = node->navigation_request();
710 ASSERT_TRUE(request2);
711 EXPECT_EQ(request1, request2);
712 EXPECT_EQ(kUrl1, request2->common_params().url);
713 EXPECT_TRUE(request2->browser_initiated());
714 EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
716 // Now receive the beforeUnload ACK from the still ongoing navigation.
717 main_test_rfh()->SendBeforeUnloadACK(true);
718 TestRenderFrameHost* speculative_rfh = GetSpeculativeRenderFrameHost(node);
719 ASSERT_TRUE(speculative_rfh);
721 // Have the RenderFrameHost commit the navigation.
722 scoped_refptr<ResourceResponse> response(new ResourceResponse);
723 GetLoaderForNavigationRequest(request2)
724 ->CallOnResponseStarted(response, MakeEmptyStream());
725 EXPECT_TRUE(DidRenderFrameHostRequestCommit(speculative_rfh));
726 EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh()));
728 // Commit the navigation.
729 speculative_rfh->SendNavigate(0, entry_id, true, kUrl1);
730 EXPECT_EQ(kUrl1, contents()->GetLastCommittedURL());
733 // PlzNavigate: Test that a renderer-initiated non-user-initiated navigation is
734 // canceled if a another similar request is issued in the meantime.
735 TEST_F(NavigatorTestWithBrowserSideNavigation,
736 RendererNonUserInitiatedNavigationCancelSimilarNavigation) {
737 const GURL kUrl0("http://www.wikipedia.org/");
738 const GURL kUrl1("http://www.chromium.org/");
739 const GURL kUrl2("http://www.google.com/");
741 // Initialization.
742 contents()->NavigateAndCommit(kUrl0);
743 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
744 int32 site_instance_id_0 = main_test_rfh()->GetSiteInstance()->GetId();
746 // Start a renderer-initiated non-user-initiated navigation to the 1st URL.
747 process()->sink().ClearMessages();
748 main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl1, false);
749 NavigationRequest* request1 = node->navigation_request();
750 ASSERT_TRUE(request1);
751 EXPECT_EQ(kUrl1, request1->common_params().url);
752 EXPECT_FALSE(request1->browser_initiated());
753 EXPECT_FALSE(request1->begin_params().has_user_gesture);
754 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
755 base::WeakPtr<TestNavigationURLLoader> loader1 =
756 GetLoaderForNavigationRequest(request1)->AsWeakPtr();
757 EXPECT_TRUE(loader1);
759 // Now receive a 2nd similar request that should replace the current one.
760 main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl2, false);
761 NavigationRequest* request2 = node->navigation_request();
762 EXPECT_EQ(kUrl2, request2->common_params().url);
763 EXPECT_FALSE(request2->browser_initiated());
764 EXPECT_FALSE(request2->begin_params().has_user_gesture);
765 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
767 // Confirm that the first loader got destroyed.
768 EXPECT_FALSE(loader1);
770 // Have the RenderFrameHost commit the navigation.
771 scoped_refptr<ResourceResponse> response(new ResourceResponse);
772 GetLoaderForNavigationRequest(request2)
773 ->CallOnResponseStarted(response, MakeEmptyStream());
774 EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh()));
776 // Commit the navigation.
777 main_test_rfh()->SendNavigate(1, 0, true, kUrl2);
778 EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL());
780 // The SiteInstance did not change.
781 EXPECT_EQ(site_instance_id_0, main_test_rfh()->GetSiteInstance()->GetId());
784 // PlzNavigate: Test that a reload navigation is properly signaled to the
785 // RenderFrame when the navigation can commit. A speculative RenderFrameHost
786 // should not be created at any step.
787 TEST_F(NavigatorTestWithBrowserSideNavigation, Reload) {
788 const GURL kUrl("http://www.google.com/");
789 contents()->NavigateAndCommit(kUrl);
791 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
792 controller().Reload(false);
793 int entry_id = controller().GetPendingEntry()->GetUniqueID();
794 // A NavigationRequest should have been generated.
795 NavigationRequest* main_request = node->navigation_request();
796 ASSERT_TRUE(main_request != NULL);
797 EXPECT_EQ(FrameMsg_Navigate_Type::RELOAD,
798 main_request->common_params().navigation_type);
799 main_test_rfh()->PrepareForCommit();
800 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
802 main_test_rfh()->SendNavigate(0, entry_id, false, kUrl);
803 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
805 // Now do a shift+reload.
806 controller().ReloadIgnoringCache(false);
807 // A NavigationRequest should have been generated.
808 main_request = node->navigation_request();
809 ASSERT_TRUE(main_request != NULL);
810 EXPECT_EQ(FrameMsg_Navigate_Type::RELOAD_IGNORING_CACHE,
811 main_request->common_params().navigation_type);
812 main_test_rfh()->PrepareForCommit();
813 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
816 // PlzNavigate: Confirm that a speculative RenderFrameHost is used when
817 // navigating from one site to another.
818 TEST_F(NavigatorTestWithBrowserSideNavigation,
819 SpeculativeRendererWorksBaseCase) {
820 // Navigate to an initial site.
821 const GURL kUrlInit("http://wikipedia.org/");
822 contents()->NavigateAndCommit(kUrlInit);
823 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
825 // Begin navigating to another site.
826 const GURL kUrl("http://google.com/");
827 process()->sink().ClearMessages();
828 int entry_id = RequestNavigation(node, kUrl);
829 TestRenderFrameHost* speculative_rfh = GetSpeculativeRenderFrameHost(node);
830 ASSERT_TRUE(speculative_rfh);
831 EXPECT_NE(speculative_rfh, main_test_rfh());
833 // Receive the beforeUnload ACK.
834 main_test_rfh()->SendBeforeUnloadACK(true);
835 EXPECT_EQ(speculative_rfh, GetSpeculativeRenderFrameHost(node));
836 EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrl),
837 speculative_rfh->GetSiteInstance()->GetSiteURL());
838 EXPECT_FALSE(node->render_manager()->pending_frame_host());
839 int32 site_instance_id = speculative_rfh->GetSiteInstance()->GetId();
841 // Ask Navigator to commit the navigation by simulating a call to
842 // OnResponseStarted.
843 scoped_refptr<ResourceResponse> response(new ResourceResponse);
844 GetLoaderForNavigationRequest(node->navigation_request())
845 ->CallOnResponseStarted(response, MakeEmptyStream());
846 EXPECT_EQ(speculative_rfh, GetSpeculativeRenderFrameHost(node));
847 EXPECT_TRUE(DidRenderFrameHostRequestCommit(speculative_rfh));
848 EXPECT_EQ(site_instance_id, speculative_rfh->GetSiteInstance()->GetId());
849 EXPECT_FALSE(node->render_manager()->pending_frame_host());
851 // Invoke OnDidCommitProvisionalLoad.
852 speculative_rfh->SendNavigate(0, entry_id, true, kUrl);
853 EXPECT_EQ(site_instance_id, main_test_rfh()->GetSiteInstance()->GetId());
854 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
855 EXPECT_FALSE(node->render_manager()->pending_frame_host());
858 // PlzNavigate: Confirm that a speculative RenderFrameHost is thrown away when
859 // the final URL's site differs from the initial one due to redirects.
860 TEST_F(NavigatorTestWithBrowserSideNavigation,
861 SpeculativeRendererDiscardedAfterRedirectToAnotherSite) {
862 // Navigate to an initial site.
863 const GURL kUrlInit("http://wikipedia.org/");
864 contents()->NavigateAndCommit(kUrlInit);
865 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
866 int32 init_site_instance_id = main_test_rfh()->GetSiteInstance()->GetId();
868 // Begin navigating to another site.
869 const GURL kUrl("http://google.com/");
870 process()->sink().ClearMessages();
871 int entry_id = RequestNavigation(node, kUrl);
872 TestRenderFrameHost* speculative_rfh = GetSpeculativeRenderFrameHost(node);
873 ASSERT_TRUE(speculative_rfh);
874 int32 site_instance_id = speculative_rfh->GetSiteInstance()->GetId();
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
894 // the redirect.
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());
900 // Commit the navigation with Navigator by simulating the call to
901 // OnResponseStarted.
902 scoped_refptr<ResourceResponse> response(new ResourceResponse);
903 GetLoaderForNavigationRequest(main_request)
904 ->CallOnResponseStarted(response, MakeEmptyStream());
905 speculative_rfh = GetSpeculativeRenderFrameHost(node);
906 ASSERT_TRUE(speculative_rfh);
907 EXPECT_TRUE(DidRenderFrameHostRequestCommit(speculative_rfh));
908 EXPECT_EQ(init_site_instance_id, main_test_rfh()->GetSiteInstance()->GetId());
910 // Once commit happens the speculative RenderFrameHost is updated to match the
911 // known final SiteInstance.
912 EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrlRedirect),
913 speculative_rfh->GetSiteInstance()->GetSiteURL());
914 int32 redirect_site_instance_id = speculative_rfh->GetSiteInstance()->GetId();
915 EXPECT_NE(init_site_instance_id, redirect_site_instance_id);
916 EXPECT_NE(site_instance_id, redirect_site_instance_id);
918 // Invoke OnDidCommitProvisionalLoad.
919 speculative_rfh->SendNavigate(0, entry_id, true, kUrlRedirect);
921 // Check that the speculative RenderFrameHost was swapped in.
922 EXPECT_EQ(redirect_site_instance_id,
923 main_test_rfh()->GetSiteInstance()->GetId());
924 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
927 // PlzNavigate: Verify that a previously swapped out RenderFrameHost is
928 // correctly reused when spawning a speculative RenderFrameHost in a navigation
929 // using the same SiteInstance.
930 TEST_F(NavigatorTestWithBrowserSideNavigation,
931 SpeculativeRendererReuseSwappedOutRFH) {
932 // This test doesn't make sense in --site-per-process where swapped out
933 // RenderFrameHost is no longer used.
934 if (RenderFrameHostManager::IsSwappedOutStateForbidden())
935 return;
937 // Navigate to an initial site.
938 const GURL kUrl1("http://wikipedia.org/");
939 contents()->NavigateAndCommit(kUrl1);
940 TestRenderFrameHost* rfh1 = main_test_rfh();
941 FrameTreeNode* node = rfh1->frame_tree_node();
942 RenderFrameHostManager* rfhm = node->render_manager();
944 // Increment active frame count to cause the RenderFrameHost to be swapped out
945 // (instead of immediately destroyed).
946 rfh1->GetSiteInstance()->increment_active_frame_count();
948 // Navigate to another site to swap out the initial RenderFrameHost.
949 const GURL kUrl2("http://chromium.org/");
950 contents()->NavigateAndCommit(kUrl2);
951 ASSERT_NE(rfh1, main_test_rfh());
952 EXPECT_NE(RenderFrameHostImpl::STATE_DEFAULT, rfh1->rfh_state());
953 EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, main_test_rfh()->rfh_state());
954 EXPECT_TRUE(rfhm->IsOnSwappedOutList(rfh1));
956 // Now go back to the initial site so that the swapped out RenderFrameHost
957 // should be reused.
958 process()->sink().ClearMessages();
959 rfh1->GetProcess()->sink().ClearMessages();
960 int entry_id = RequestNavigation(node, kUrl1);
961 EXPECT_EQ(rfh1, GetSpeculativeRenderFrameHost(node));
963 main_test_rfh()->SendBeforeUnloadACK(true);
964 EXPECT_EQ(rfh1, GetSpeculativeRenderFrameHost(node));
965 EXPECT_NE(RenderFrameHostImpl::STATE_DEFAULT,
966 GetSpeculativeRenderFrameHost(node)->rfh_state());
968 scoped_refptr<ResourceResponse> response(new ResourceResponse);
969 GetLoaderForNavigationRequest(node->navigation_request())
970 ->CallOnResponseStarted(response, MakeEmptyStream());
971 EXPECT_EQ(rfh1, GetSpeculativeRenderFrameHost(node));
972 EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT,
973 GetSpeculativeRenderFrameHost(node)->rfh_state());
974 EXPECT_TRUE(DidRenderFrameHostRequestCommit(rfh1));
975 EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh()));
977 rfh1->SendNavigate(1, entry_id, true, kUrl1);
978 EXPECT_EQ(rfh1, main_test_rfh());
979 EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, rfh1->rfh_state());
980 EXPECT_FALSE(rfhm->IsOnSwappedOutList(rfh1));
983 // PlzNavigate: Verify that data urls are properly handled.
984 TEST_F(NavigatorTestWithBrowserSideNavigation, DataUrls) {
985 const GURL kUrl1("http://wikipedia.org/");
986 const GURL kUrl2("data:text/html,test");
988 // Navigate to an initial site.
989 contents()->NavigateAndCommit(kUrl1);
990 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
992 // Navigate to a data url. The request should not have been sent to the IO
993 // thread but committed immediately.
994 int entry_id = RequestNavigation(node, kUrl2);
995 TestRenderFrameHost* speculative_rfh = GetSpeculativeRenderFrameHost(node);
996 ASSERT_TRUE(speculative_rfh);
997 EXPECT_TRUE(speculative_rfh->is_loading());
998 EXPECT_FALSE(node->navigation_request());
999 speculative_rfh->SendNavigate(0, entry_id, true, kUrl2);
1000 EXPECT_EQ(main_test_rfh(), speculative_rfh);
1002 // Go back to the initial site.
1003 contents()->NavigateAndCommit(kUrl1);
1005 // Do a renderer-initiated navigation to a data url. The request should not be
1006 // sent to the IO thread, nor committed.
1007 TestRenderFrameHost* main_rfh = main_test_rfh();
1008 main_rfh->SendRendererInitiatedNavigationRequest(kUrl2, true);
1009 EXPECT_TRUE(main_rfh->is_loading());
1010 EXPECT_FALSE(node->navigation_request());
1011 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
1014 // Tests several cases for converting SiteInstanceDescriptors into
1015 // SiteInstances:
1016 // 1) Pointer to the current SiteInstance.
1017 // 2) Pointer to an unrelated SiteInstance.
1018 // 3) Same-site URL, related.
1019 // 4) Cross-site URL, related.
1020 // 5) Same-site URL, unrelated (with and without candidate SiteInstances).
1021 // 6) Cross-site URL, unrelated (with candidate SiteInstance).
1022 TEST_F(NavigatorTestWithBrowserSideNavigation,
1023 SiteInstanceDescriptionConversion) {
1024 // Navigate to set a current SiteInstance on the RenderFrameHost.
1025 GURL kUrl1("http://a.com");
1026 contents()->NavigateAndCommit(kUrl1);
1027 SiteInstance* current_instance = main_test_rfh()->GetSiteInstance();
1028 ASSERT_TRUE(current_instance);
1030 // 1) Convert a descriptor pointing to the current instance.
1031 RenderFrameHostManager* rfhm =
1032 main_test_rfh()->frame_tree_node()->render_manager();
1034 SiteInstanceDescriptor descriptor(current_instance);
1035 SiteInstance* converted_instance =
1036 ConvertToSiteInstance(rfhm, descriptor, nullptr);
1037 EXPECT_EQ(current_instance, converted_instance);
1040 // 2) Convert a descriptor pointing an instance unrelated to the current one,
1041 // with a different site.
1042 GURL kUrl2("http://b.com");
1043 scoped_refptr<SiteInstance> unrelated_instance(
1044 SiteInstance::CreateForURL(browser_context(), kUrl2));
1045 EXPECT_FALSE(
1046 current_instance->IsRelatedSiteInstance(unrelated_instance.get()));
1048 SiteInstanceDescriptor descriptor(unrelated_instance.get());
1049 SiteInstance* converted_instance =
1050 ConvertToSiteInstance(rfhm, descriptor, nullptr);
1051 EXPECT_EQ(unrelated_instance.get(), converted_instance);
1054 // 3) Convert a descriptor of a related instance with the same site as the
1055 // current one.
1056 GURL kUrlSameSiteAs1("http://www.a.com/foo");
1058 SiteInstanceDescriptor descriptor(browser_context(), kUrlSameSiteAs1, true);
1059 SiteInstance* converted_instance =
1060 ConvertToSiteInstance(rfhm, descriptor, nullptr);
1061 EXPECT_EQ(current_instance, converted_instance);
1064 // 4) Convert a descriptor of a related instance with a site different from
1065 // the current one.
1066 GURL kUrlSameSiteAs2("http://www.b.com/foo");
1067 scoped_refptr<SiteInstance> related_instance;
1069 SiteInstanceDescriptor descriptor(browser_context(), kUrlSameSiteAs2, true);
1070 related_instance = ConvertToSiteInstance(rfhm, descriptor, nullptr);
1071 // Should return a new instance, related to the current, set to the new site
1072 // URL.
1073 EXPECT_TRUE(
1074 current_instance->IsRelatedSiteInstance(related_instance.get()));
1075 EXPECT_NE(current_instance, related_instance.get());
1076 EXPECT_NE(unrelated_instance.get(), related_instance.get());
1077 EXPECT_EQ(SiteInstance::GetSiteForURL(browser_context(), kUrlSameSiteAs2),
1078 related_instance->GetSiteURL());
1081 // 5) Convert a descriptor of an unrelated instance with the same site as the
1082 // current one, several times, with and without candidate sites.
1084 SiteInstanceDescriptor descriptor(browser_context(), kUrlSameSiteAs1,
1085 false);
1086 scoped_refptr<SiteInstance> converted_instance_1 =
1087 ConvertToSiteInstance(rfhm, descriptor, nullptr);
1088 // Should return a new instance, unrelated to the current one, set to the
1089 // provided site URL.
1090 EXPECT_FALSE(
1091 current_instance->IsRelatedSiteInstance(converted_instance_1.get()));
1092 EXPECT_NE(current_instance, converted_instance_1.get());
1093 EXPECT_NE(unrelated_instance.get(), converted_instance_1.get());
1094 EXPECT_EQ(SiteInstance::GetSiteForURL(browser_context(), kUrlSameSiteAs1),
1095 converted_instance_1->GetSiteURL());
1097 // Does the same but this time using unrelated_instance as a candidate,
1098 // which has a different site.
1099 scoped_refptr<SiteInstance> converted_instance_2 =
1100 ConvertToSiteInstance(rfhm, descriptor, unrelated_instance.get());
1101 // Should return yet another new instance, unrelated to the current one, set
1102 // to the same site URL.
1103 EXPECT_FALSE(
1104 current_instance->IsRelatedSiteInstance(converted_instance_2.get()));
1105 EXPECT_NE(current_instance, converted_instance_2.get());
1106 EXPECT_NE(unrelated_instance.get(), converted_instance_2.get());
1107 EXPECT_NE(converted_instance_1.get(), converted_instance_2.get());
1108 EXPECT_EQ(SiteInstance::GetSiteForURL(browser_context(), kUrlSameSiteAs1),
1109 converted_instance_2->GetSiteURL());
1111 // Converts once more but with |converted_instance_1| as a candidate.
1112 SiteInstance* converted_instance_3 =
1113 ConvertToSiteInstance(rfhm, descriptor, converted_instance_1.get());
1114 // Should return |converted_instance_1| because its site matches and it is
1115 // unrelated to the current SiteInstance.
1116 EXPECT_EQ(converted_instance_1.get(), converted_instance_3);
1119 // 6) Convert a descriptor of an unrelated instance with the same site of
1120 // related_instance and using it as a candidate.
1122 SiteInstanceDescriptor descriptor(browser_context(), kUrlSameSiteAs2,
1123 false);
1124 scoped_refptr<SiteInstance> converted_instance_1 =
1125 ConvertToSiteInstance(rfhm, descriptor, related_instance.get());
1126 // Should return a new instance, unrelated to the current, set to the
1127 // provided site URL.
1128 EXPECT_FALSE(
1129 current_instance->IsRelatedSiteInstance(converted_instance_1.get()));
1130 EXPECT_NE(related_instance.get(), converted_instance_1.get());
1131 EXPECT_NE(unrelated_instance.get(), converted_instance_1.get());
1132 EXPECT_EQ(SiteInstance::GetSiteForURL(browser_context(), kUrlSameSiteAs2),
1133 converted_instance_1->GetSiteURL());
1135 SiteInstance* converted_instance_2 =
1136 ConvertToSiteInstance(rfhm, descriptor, unrelated_instance.get());
1137 // Should return |unrelated_instance| because its site matches and it is
1138 // unrelated to the current SiteInstance.
1139 EXPECT_EQ(unrelated_instance.get(), converted_instance_2);
1143 } // namespace content