Use multiline attribute to check for IA2_STATE_MULTILINE.
[chromium-blink-merge.git] / content / browser / frame_host / navigator_impl_unittest.cc
blobf8069f526fb74391a0d02ab6efb8e9ed30a98633
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 namespace content {
36 class NavigatorTestWithBrowserSideNavigation
37 : public RenderViewHostImplTestHarness {
38 public:
39 // Re-defines the private RenderFrameHostManager::SiteInstanceDescriptor here
40 // to allow access to it from tests.
41 typedef RenderFrameHostManager::SiteInstanceDescriptor SiteInstanceDescriptor;
43 void SetUp() override {
44 EnableBrowserSideNavigation();
45 RenderViewHostImplTestHarness::SetUp();
48 TestNavigationURLLoader* GetLoaderForNavigationRequest(
49 NavigationRequest* request) const {
50 return static_cast<TestNavigationURLLoader*>(request->loader_for_testing());
53 void RequestNavigation(FrameTreeNode* node, const GURL& url) {
54 RequestNavigationWithParameters(node, url, Referrer(),
55 ui::PAGE_TRANSITION_LINK);
58 void RequestNavigationWithParameters(
59 FrameTreeNode* node,
60 const GURL& url,
61 const Referrer& referrer,
62 ui::PageTransition transition_type) {
63 NavigationController::LoadURLParams load_params(url);
64 load_params.frame_tree_node_id = node->frame_tree_node_id();
65 load_params.referrer = referrer;
66 load_params.transition_type = transition_type;
68 controller().LoadURLWithParams(load_params);
71 NavigationRequest* GetNavigationRequestForFrameTreeNode(
72 FrameTreeNode* frame_tree_node) {
73 return static_cast<NavigatorImpl*>(frame_tree_node->navigator())
74 ->GetNavigationRequestForNodeForTesting(frame_tree_node);
77 TestRenderFrameHost* GetSpeculativeRenderFrameHost(FrameTreeNode* node) {
78 return static_cast<TestRenderFrameHost*>(
79 node->render_manager()->speculative_render_frame_host_.get());
82 // Checks if this RenderFrameHost sent a single FrameMsg_CommitNavigation
83 // since the last clearing of the sink.
84 // Note: caller must invoke ClearMessages on the sink at some point before
85 // the tracked commit happens to clear up commit messages from previous
86 // navigations.
87 bool DidRenderFrameHostRequestCommit(RenderFrameHostImpl* rfh) {
88 MockRenderProcessHost* rph =
89 static_cast<MockRenderProcessHost*>(rfh->GetProcess());
90 const FrameMsg_CommitNavigation* commit_message =
91 static_cast<const FrameMsg_CommitNavigation*>(
92 rph->sink().GetUniqueMessageMatching(
93 FrameMsg_CommitNavigation::ID));
94 return commit_message &&
95 rfh->GetRoutingID() == commit_message->routing_id();
98 SiteInstance* ConvertToSiteInstance(RenderFrameHostManager* rfhm,
99 const SiteInstanceDescriptor& descriptor,
100 SiteInstance* candidate_instance) {
101 return rfhm->ConvertToSiteInstance(descriptor, candidate_instance);
105 // PlzNavigate: Test a complete browser-initiated navigation starting with a
106 // non-live renderer.
107 TEST_F(NavigatorTestWithBrowserSideNavigation,
108 SimpleBrowserInitiatedNavigationFromNonLiveRenderer) {
109 const GURL kUrl("http://chromium.org/");
111 EXPECT_FALSE(main_test_rfh()->IsRenderFrameLive());
113 // Start a browser-initiated navigation.
114 int32 site_instance_id = main_test_rfh()->GetSiteInstance()->GetId();
115 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
116 RequestNavigation(node, kUrl);
117 NavigationRequest* request = GetNavigationRequestForFrameTreeNode(node);
118 ASSERT_TRUE(request);
119 EXPECT_EQ(kUrl, request->common_params().url);
120 EXPECT_TRUE(request->browser_initiated());
122 // As there's no live renderer the navigation should not wait for a
123 // beforeUnload ACK from the renderer and start right away.
124 EXPECT_EQ(NavigationRequest::STARTED, request->state());
125 ASSERT_TRUE(GetLoaderForNavigationRequest(request));
126 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
127 EXPECT_FALSE(node->render_manager()->pending_frame_host());
129 // Have the current RenderFrameHost commit the navigation.
130 scoped_refptr<ResourceResponse> response(new ResourceResponse);
131 GetLoaderForNavigationRequest(request)
132 ->CallOnResponseStarted(response, MakeEmptyStream());
133 EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh()));
134 EXPECT_EQ(NavigationRequest::RESPONSE_STARTED, request->state());
136 // Commit the navigation.
137 main_test_rfh()->SendNavigate(0, kUrl);
138 EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, main_test_rfh()->rfh_state());
139 EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrl),
140 main_test_rfh()->GetSiteInstance()->GetSiteURL());
141 EXPECT_EQ(kUrl, contents()->GetLastCommittedURL());
142 EXPECT_FALSE(GetNavigationRequestForFrameTreeNode(node));
143 EXPECT_FALSE(node->render_manager()->pending_frame_host());
145 // The main RenderFrameHost should not have been changed, and the renderer
146 // should have been initialized.
147 EXPECT_EQ(site_instance_id, main_test_rfh()->GetSiteInstance()->GetId());
148 EXPECT_TRUE(main_test_rfh()->IsRenderFrameLive());
150 // After a navigation is finished no speculative RenderFrameHost should
151 // exist.
152 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
154 // With PlzNavigate enabled a pending RenderFrameHost should never exist.
155 EXPECT_FALSE(node->render_manager()->pending_frame_host());
158 // PlzNavigate: Test a complete renderer-initiated same-site navigation.
159 TEST_F(NavigatorTestWithBrowserSideNavigation,
160 SimpleRendererInitiatedSameSiteNavigation) {
161 const GURL kUrl1("http://www.chromium.org/");
162 const GURL kUrl2("http://www.chromium.org/Home");
164 contents()->NavigateAndCommit(kUrl1);
165 EXPECT_TRUE(main_test_rfh()->IsRenderFrameLive());
167 // Start a renderer-initiated non-user-initiated navigation.
168 process()->sink().ClearMessages();
169 main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl2, false);
170 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
171 NavigationRequest* request = GetNavigationRequestForFrameTreeNode(node);
172 ASSERT_TRUE(request);
174 // The navigation is immediately started as there's no need to wait for
175 // beforeUnload to be executed.
176 EXPECT_EQ(NavigationRequest::STARTED, request->state());
177 EXPECT_FALSE(request->begin_params().has_user_gesture);
178 EXPECT_EQ(kUrl2, request->common_params().url);
179 EXPECT_FALSE(request->browser_initiated());
180 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
182 // Have the current RenderFrameHost commit the navigation.
183 scoped_refptr<ResourceResponse> response(new ResourceResponse);
184 GetLoaderForNavigationRequest(request)
185 ->CallOnResponseStarted(response, MakeEmptyStream());
186 EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh()));
187 EXPECT_EQ(NavigationRequest::RESPONSE_STARTED, request->state());
189 // Commit the navigation.
190 main_test_rfh()->SendNavigate(0, kUrl2);
191 EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, main_test_rfh()->rfh_state());
192 EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrl2),
193 main_test_rfh()->GetSiteInstance()->GetSiteURL());
194 EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL());
195 EXPECT_FALSE(GetNavigationRequestForFrameTreeNode(node));
196 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
197 EXPECT_FALSE(node->render_manager()->pending_frame_host());
200 // PlzNavigate: Test a complete renderer-initiated navigation that should be
201 // cross-site but does not result in a SiteInstance swap because its
202 // renderer-initiated.
203 TEST_F(NavigatorTestWithBrowserSideNavigation,
204 SimpleRendererInitiatedCrossSiteNavigation) {
205 const GURL kUrl1("http://www.chromium.org/");
206 const GURL kUrl2("http://www.google.com");
208 contents()->NavigateAndCommit(kUrl1);
209 EXPECT_TRUE(main_test_rfh()->IsRenderFrameLive());
210 int32 site_instance_id_1 = main_test_rfh()->GetSiteInstance()->GetId();
212 // Start a renderer-initiated non-user-initiated navigation.
213 process()->sink().ClearMessages();
214 main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl2, false);
215 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
216 NavigationRequest* request = GetNavigationRequestForFrameTreeNode(node);
217 ASSERT_TRUE(request);
219 // The navigation is immediately started as there's no need to wait for
220 // beforeUnload to be executed.
221 EXPECT_EQ(NavigationRequest::STARTED, request->state());
222 EXPECT_FALSE(request->begin_params().has_user_gesture);
223 EXPECT_EQ(kUrl2, request->common_params().url);
224 EXPECT_FALSE(request->browser_initiated());
225 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
227 // Have the current RenderFrameHost commit the navigation.
228 scoped_refptr<ResourceResponse> response(new ResourceResponse);
229 GetLoaderForNavigationRequest(request)
230 ->CallOnResponseStarted(response, MakeEmptyStream());
231 EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh()));
232 EXPECT_EQ(NavigationRequest::RESPONSE_STARTED, request->state());
234 // Commit the navigation.
235 main_test_rfh()->SendNavigate(0, kUrl2);
236 EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, main_test_rfh()->rfh_state());
237 EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL());
238 EXPECT_FALSE(GetNavigationRequestForFrameTreeNode(node));
239 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
240 EXPECT_FALSE(node->render_manager()->pending_frame_host());
242 // The SiteInstance did not change.
243 EXPECT_EQ(site_instance_id_1, main_test_rfh()->GetSiteInstance()->GetId());
246 // PlzNavigate: Test that a beforeUnload denial cancels the navigation.
247 TEST_F(NavigatorTestWithBrowserSideNavigation,
248 BeforeUnloadDenialCancelNavigation) {
249 const GURL kUrl1("http://www.google.com/");
250 const GURL kUrl2("http://www.chromium.org/");
252 contents()->NavigateAndCommit(kUrl1);
254 // Start a new navigation.
255 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
256 RequestNavigation(node, kUrl2);
257 NavigationRequest* request = GetNavigationRequestForFrameTreeNode(node);
258 ASSERT_TRUE(request);
259 EXPECT_TRUE(request->browser_initiated());
260 EXPECT_EQ(NavigationRequest::WAITING_FOR_RENDERER_RESPONSE, request->state());
261 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
263 // Simulate a beforeUnload denial.
264 main_test_rfh()->SendBeforeUnloadACK(false);
265 EXPECT_FALSE(GetNavigationRequestForFrameTreeNode(node));
266 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
269 // PlzNavigate: Test that a proper NavigationRequest is created by
270 // RequestNavigation.
271 TEST_F(NavigatorTestWithBrowserSideNavigation, BeginNavigation) {
272 const GURL kUrl1("http://www.google.com/");
273 const GURL kUrl2("http://www.chromium.org/");
274 const GURL kUrl3("http://www.gmail.com/");
276 contents()->NavigateAndCommit(kUrl1);
278 // Add a subframe.
279 FrameTreeNode* root_node = contents()->GetFrameTree()->root();
280 TestRenderFrameHost* subframe_rfh = main_test_rfh()->AppendChild("Child");
281 ASSERT_TRUE(subframe_rfh);
283 // Start a navigation at the subframe.
284 FrameTreeNode* subframe_node = subframe_rfh->frame_tree_node();
285 RequestNavigation(subframe_node, kUrl2);
286 NavigationRequest* subframe_request =
287 GetNavigationRequestForFrameTreeNode(subframe_node);
288 TestNavigationURLLoader* subframe_loader =
289 GetLoaderForNavigationRequest(subframe_request);
291 // Subframe navigations should start right away as they don't have to request
292 // beforeUnload to run at the renderer.
293 ASSERT_TRUE(subframe_request);
294 ASSERT_TRUE(subframe_loader);
295 EXPECT_EQ(NavigationRequest::STARTED, subframe_request->state());
296 EXPECT_EQ(kUrl2, subframe_request->common_params().url);
297 EXPECT_EQ(kUrl2, subframe_loader->request_info()->common_params.url);
298 // First party for cookies url should be that of the main frame.
299 EXPECT_EQ(kUrl1, subframe_loader->request_info()->first_party_for_cookies);
300 EXPECT_FALSE(subframe_loader->request_info()->is_main_frame);
301 EXPECT_TRUE(subframe_loader->request_info()->parent_is_main_frame);
302 EXPECT_TRUE(subframe_request->browser_initiated());
303 EXPECT_FALSE(GetSpeculativeRenderFrameHost(root_node));
305 // Subframe navigations should never create a speculative RenderFrameHost,
306 // unless site-per-process is enabled. In that case, as the subframe
307 // navigation is to a different site and is still ongoing, it should have one.
308 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
309 switches::kSitePerProcess)) {
310 EXPECT_TRUE(GetSpeculativeRenderFrameHost(subframe_node));
311 } else {
312 EXPECT_FALSE(GetSpeculativeRenderFrameHost(subframe_node));
315 // Now start a navigation at the root node.
316 RequestNavigation(root_node, kUrl3);
317 NavigationRequest* main_request =
318 GetNavigationRequestForFrameTreeNode(root_node);
319 ASSERT_TRUE(main_request);
320 EXPECT_EQ(NavigationRequest::WAITING_FOR_RENDERER_RESPONSE,
321 main_request->state());
322 EXPECT_FALSE(GetSpeculativeRenderFrameHost(root_node));
324 // Simulate a BeforeUnloadACK IPC on the main frame.
325 main_test_rfh()->SendBeforeUnloadACK(true);
326 TestNavigationURLLoader* main_loader =
327 GetLoaderForNavigationRequest(main_request);
328 EXPECT_EQ(kUrl3, main_request->common_params().url);
329 EXPECT_EQ(kUrl3, main_loader->request_info()->common_params.url);
330 EXPECT_EQ(kUrl3, main_loader->request_info()->first_party_for_cookies);
331 EXPECT_TRUE(main_loader->request_info()->is_main_frame);
332 EXPECT_FALSE(main_loader->request_info()->parent_is_main_frame);
333 EXPECT_TRUE(main_request->browser_initiated());
334 // BeforeUnloadACK was received from the renderer so the navigation should
335 // have started.
336 EXPECT_EQ(NavigationRequest::STARTED, main_request->state());
338 // Main frame navigation to a different site should use a speculative
339 // RenderFrameHost.
340 EXPECT_TRUE(GetSpeculativeRenderFrameHost(root_node));
342 // As the main frame hasn't yet committed the subframe still exists. Thus, the
343 // above situation regarding subframe navigations is valid here.
344 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
345 switches::kSitePerProcess)) {
346 EXPECT_TRUE(GetSpeculativeRenderFrameHost(subframe_node));
347 } else {
348 EXPECT_FALSE(GetSpeculativeRenderFrameHost(subframe_node));
352 // PlzNavigate: Test that committing an HTTP 204 or HTTP 205 response cancels
353 // the navigation.
354 TEST_F(NavigatorTestWithBrowserSideNavigation, NoContent) {
355 const GURL kUrl1("http://www.chromium.org/");
356 const GURL kUrl2("http://www.google.com/");
358 // Load a URL.
359 contents()->NavigateAndCommit(kUrl1);
360 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
362 // Navigate to a different site.
363 process()->sink().ClearMessages();
364 RequestNavigation(node, kUrl2);
365 main_test_rfh()->SendBeforeUnloadACK(true);
367 NavigationRequest* main_request = GetNavigationRequestForFrameTreeNode(node);
368 ASSERT_TRUE(main_request);
370 // Navigations to a different site do create a speculative RenderFrameHost.
371 EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
373 // Commit an HTTP 204 response.
374 scoped_refptr<ResourceResponse> response(new ResourceResponse);
375 const char kNoContentHeaders[] = "HTTP/1.1 204 No Content\0\0";
376 response->head.headers = new net::HttpResponseHeaders(
377 std::string(kNoContentHeaders, arraysize(kNoContentHeaders)));
378 GetLoaderForNavigationRequest(main_request)->CallOnResponseStarted(
379 response, MakeEmptyStream());
381 // There should be no pending nor speculative RenderFrameHost; the navigation
382 // was aborted.
383 EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh()));
384 EXPECT_FALSE(GetNavigationRequestForFrameTreeNode(node));
385 EXPECT_FALSE(node->render_manager()->pending_frame_host());
386 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
388 // Now, repeat the test with 205 Reset Content.
390 // Navigate to a different site again.
391 process()->sink().ClearMessages();
392 RequestNavigation(node, kUrl2);
393 main_test_rfh()->SendBeforeUnloadACK(true);
395 main_request = GetNavigationRequestForFrameTreeNode(node);
396 ASSERT_TRUE(main_request);
397 EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
399 // Commit an HTTP 205 response.
400 response = new ResourceResponse;
401 const char kResetContentHeaders[] = "HTTP/1.1 205 Reset Content\0\0";
402 response->head.headers = new net::HttpResponseHeaders(
403 std::string(kResetContentHeaders, arraysize(kResetContentHeaders)));
404 GetLoaderForNavigationRequest(main_request)->CallOnResponseStarted(
405 response, MakeEmptyStream());
407 // There should be no pending nor speculative RenderFrameHost; the navigation
408 // was aborted.
409 EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh()));
410 EXPECT_FALSE(GetNavigationRequestForFrameTreeNode(node));
411 EXPECT_FALSE(node->render_manager()->pending_frame_host());
412 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
415 // PlzNavigate: Test that a new RenderFrameHost is created when doing a cross
416 // site navigation.
417 TEST_F(NavigatorTestWithBrowserSideNavigation, CrossSiteNavigation) {
418 const GURL kUrl1("http://www.chromium.org/");
419 const GURL kUrl2("http://www.google.com/");
421 contents()->NavigateAndCommit(kUrl1);
422 RenderFrameHostImpl* initial_rfh = main_test_rfh();
423 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
425 // Navigate to a different site.
426 process()->sink().ClearMessages();
427 RequestNavigation(node, kUrl2);
428 NavigationRequest* main_request = GetNavigationRequestForFrameTreeNode(node);
429 ASSERT_TRUE(main_request);
430 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
432 // Receive the beforeUnload ACK.
433 main_test_rfh()->SendBeforeUnloadACK(true);
434 EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
436 scoped_refptr<ResourceResponse> response(new ResourceResponse);
437 GetLoaderForNavigationRequest(main_request)->CallOnResponseStarted(
438 response, MakeEmptyStream());
439 TestRenderFrameHost* speculative_rfh = GetSpeculativeRenderFrameHost(node);
440 ASSERT_TRUE(speculative_rfh);
441 EXPECT_TRUE(DidRenderFrameHostRequestCommit(speculative_rfh));
442 EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh()));
444 speculative_rfh->SendNavigate(0, kUrl2);
446 RenderFrameHostImpl* final_rfh = main_test_rfh();
447 EXPECT_EQ(speculative_rfh, final_rfh);
448 EXPECT_NE(initial_rfh, final_rfh);
449 EXPECT_TRUE(final_rfh->IsRenderFrameLive());
450 EXPECT_TRUE(final_rfh->render_view_host()->IsRenderViewLive());
451 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
454 // PlzNavigate: Test that redirects are followed and the speculative
455 // RenderFrameHost logic behaves as expected.
456 TEST_F(NavigatorTestWithBrowserSideNavigation, RedirectCrossSite) {
457 const GURL kUrl1("http://www.chromium.org/");
458 const GURL kUrl2("http://www.google.com/");
460 contents()->NavigateAndCommit(kUrl1);
461 RenderFrameHostImpl* rfh = main_test_rfh();
462 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
464 // Navigate to a URL on the same site.
465 process()->sink().ClearMessages();
466 RequestNavigation(node, kUrl1);
467 main_test_rfh()->SendBeforeUnloadACK(true);
468 NavigationRequest* main_request = GetNavigationRequestForFrameTreeNode(node);
469 ASSERT_TRUE(main_request);
470 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
472 // It then redirects to another site.
473 GetLoaderForNavigationRequest(main_request)->SimulateServerRedirect(kUrl2);
475 // The redirect should have been followed.
476 EXPECT_EQ(1, GetLoaderForNavigationRequest(main_request)->redirect_count());
477 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
479 // Have the RenderFrameHost commit the navigation.
480 scoped_refptr<ResourceResponse> response(new ResourceResponse);
481 GetLoaderForNavigationRequest(main_request)->CallOnResponseStarted(
482 response, MakeEmptyStream());
483 TestRenderFrameHost* final_speculative_rfh =
484 GetSpeculativeRenderFrameHost(node);
485 EXPECT_TRUE(final_speculative_rfh);
486 EXPECT_TRUE(DidRenderFrameHostRequestCommit(final_speculative_rfh));
488 // Commit the navigation.
489 final_speculative_rfh->SendNavigate(0, kUrl2);
490 RenderFrameHostImpl* final_rfh = main_test_rfh();
491 ASSERT_TRUE(final_rfh);
492 EXPECT_NE(rfh, final_rfh);
493 EXPECT_EQ(final_speculative_rfh, final_rfh);
494 EXPECT_TRUE(final_rfh->IsRenderFrameLive());
495 EXPECT_TRUE(final_rfh->render_view_host()->IsRenderViewLive());
496 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
499 // PlzNavigate: Test that a navigation is canceled if another browser-initiated
500 // request has been issued in the meantime. Also confirms that the speculative
501 // RenderFrameHost is correctly updated in the process.
502 TEST_F(NavigatorTestWithBrowserSideNavigation,
503 BrowserInitiatedNavigationCancel) {
504 const GURL kUrl0("http://www.wikipedia.org/");
505 const GURL kUrl1("http://www.chromium.org/");
506 const GURL kUrl1_site = SiteInstance::GetSiteForURL(browser_context(), kUrl1);
507 const GURL kUrl2("http://www.google.com/");
508 const GURL kUrl2_site = SiteInstance::GetSiteForURL(browser_context(), kUrl2);
510 // Initialization.
511 contents()->NavigateAndCommit(kUrl0);
512 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
514 // Request navigation to the 1st URL.
515 process()->sink().ClearMessages();
516 RequestNavigation(node, kUrl1);
517 main_test_rfh()->SendBeforeUnloadACK(true);
518 NavigationRequest* request1 = GetNavigationRequestForFrameTreeNode(node);
519 ASSERT_TRUE(request1);
520 EXPECT_EQ(kUrl1, request1->common_params().url);
521 EXPECT_TRUE(request1->browser_initiated());
522 base::WeakPtr<TestNavigationURLLoader> loader1 =
523 GetLoaderForNavigationRequest(request1)->AsWeakPtr();
524 EXPECT_TRUE(loader1);
526 // Confirm a speculative RenderFrameHost was created.
527 TestRenderFrameHost* speculative_rfh = GetSpeculativeRenderFrameHost(node);
528 ASSERT_TRUE(speculative_rfh);
529 int32 site_instance_id_1 = speculative_rfh->GetSiteInstance()->GetId();
530 EXPECT_EQ(kUrl1_site, speculative_rfh->GetSiteInstance()->GetSiteURL());
532 // Request navigation to the 2nd URL; the NavigationRequest must have been
533 // replaced by a new one with a different URL.
534 RequestNavigation(node, kUrl2);
535 main_test_rfh()->SendBeforeUnloadACK(true);
536 NavigationRequest* request2 = GetNavigationRequestForFrameTreeNode(node);
537 ASSERT_TRUE(request2);
538 EXPECT_EQ(kUrl2, request2->common_params().url);
539 EXPECT_TRUE(request2->browser_initiated());
541 // Confirm that the first loader got destroyed.
542 EXPECT_FALSE(loader1);
544 // Confirm that a new speculative RenderFrameHost was created.
545 speculative_rfh = GetSpeculativeRenderFrameHost(node);
546 ASSERT_TRUE(speculative_rfh);
547 int32 site_instance_id_2 = speculative_rfh->GetSiteInstance()->GetId();
548 EXPECT_NE(site_instance_id_1, site_instance_id_2);
550 // Have the RenderFrameHost commit the navigation.
551 scoped_refptr<ResourceResponse> response(new ResourceResponse);
552 GetLoaderForNavigationRequest(request2)->CallOnResponseStarted(
553 response, MakeEmptyStream());
554 EXPECT_TRUE(DidRenderFrameHostRequestCommit(speculative_rfh));
555 EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh()));
557 // Commit the navigation.
558 speculative_rfh->SendNavigate(0, kUrl2);
560 // Confirm that the commit corresponds to the new request.
561 ASSERT_TRUE(main_test_rfh());
562 EXPECT_EQ(kUrl2_site, main_test_rfh()->GetSiteInstance()->GetSiteURL());
563 EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL());
565 // Confirm that the committed RenderFrameHost is the latest speculative one.
566 EXPECT_EQ(site_instance_id_2, main_test_rfh()->GetSiteInstance()->GetId());
569 // PlzNavigate: Test that a browser-initiated navigation is canceled if a
570 // renderer-initiated user-initiated request has been issued in the meantime.
571 TEST_F(NavigatorTestWithBrowserSideNavigation,
572 RendererUserInitiatedNavigationCancel) {
573 const GURL kUrl0("http://www.wikipedia.org/");
574 const GURL kUrl1("http://www.chromium.org/");
575 const GURL kUrl2("http://www.google.com/");
577 // Initialization.
578 contents()->NavigateAndCommit(kUrl0);
579 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
581 // Start a browser-initiated navigation to the 1st URL and receive its
582 // beforeUnload ACK.
583 process()->sink().ClearMessages();
584 RequestNavigation(node, kUrl1);
585 main_test_rfh()->SendBeforeUnloadACK(true);
586 NavigationRequest* request1 = GetNavigationRequestForFrameTreeNode(node);
587 ASSERT_TRUE(request1);
588 EXPECT_EQ(kUrl1, request1->common_params().url);
589 EXPECT_TRUE(request1->browser_initiated());
590 base::WeakPtr<TestNavigationURLLoader> loader1 =
591 GetLoaderForNavigationRequest(request1)->AsWeakPtr();
592 EXPECT_TRUE(loader1);
594 // Confirm that a speculative RenderFrameHost was created.
595 ASSERT_TRUE(GetSpeculativeRenderFrameHost(node));
597 // Now receive a renderer-initiated user-initiated request. It should replace
598 // the current NavigationRequest.
599 main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl2, true);
600 NavigationRequest* request2 = GetNavigationRequestForFrameTreeNode(node);
601 ASSERT_TRUE(request2);
602 EXPECT_EQ(kUrl2, request2->common_params().url);
603 EXPECT_FALSE(request2->browser_initiated());
604 EXPECT_TRUE(request2->begin_params().has_user_gesture);
606 // Confirm that the first loader got destroyed.
607 EXPECT_FALSE(loader1);
609 // Confirm that the speculative RenderFrameHost was destroyed.
610 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
612 // Have the RenderFrameHost commit the navigation.
613 scoped_refptr<ResourceResponse> response(new ResourceResponse);
614 GetLoaderForNavigationRequest(request2)
615 ->CallOnResponseStarted(response, MakeEmptyStream());
616 EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh()));
618 // Commit the navigation.
619 main_test_rfh()->SendNavigate(0, kUrl2);
621 // Confirm that the commit corresponds to the new request.
622 ASSERT_TRUE(main_test_rfh());
623 EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL());
626 // PlzNavigate: Test that a renderer-initiated user-initiated navigation is NOT
627 // canceled if a renderer-initiated non-user-initiated request is issued in the
628 // meantime.
629 TEST_F(NavigatorTestWithBrowserSideNavigation,
630 RendererNonUserInitiatedNavigationDoesntCancelRendererUserInitiated) {
631 const GURL kUrl0("http://www.wikipedia.org/");
632 const GURL kUrl1("http://www.chromium.org/");
633 const GURL kUrl2("http://www.google.com/");
635 // Initialization.
636 contents()->NavigateAndCommit(kUrl0);
637 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
639 // Start a renderer-initiated user-initiated navigation to the 1st URL.
640 process()->sink().ClearMessages();
641 main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl1, true);
642 NavigationRequest* request1 = GetNavigationRequestForFrameTreeNode(node);
643 ASSERT_TRUE(request1);
644 EXPECT_EQ(kUrl1, request1->common_params().url);
645 EXPECT_FALSE(request1->browser_initiated());
646 EXPECT_TRUE(request1->begin_params().has_user_gesture);
647 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
649 // Now receive a renderer-initiated non-user-initiated request. Nothing should
650 // change.
651 main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl2, false);
652 NavigationRequest* request2 = GetNavigationRequestForFrameTreeNode(node);
653 ASSERT_TRUE(request2);
654 EXPECT_EQ(request1, request2);
655 EXPECT_EQ(kUrl1, request2->common_params().url);
656 EXPECT_FALSE(request2->browser_initiated());
657 EXPECT_TRUE(request2->begin_params().has_user_gesture);
658 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
660 // Have the RenderFrameHost commit the navigation.
661 scoped_refptr<ResourceResponse> response(new ResourceResponse);
662 GetLoaderForNavigationRequest(request2)
663 ->CallOnResponseStarted(response, MakeEmptyStream());
664 EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh()));
666 // Commit the navigation.
667 main_test_rfh()->SendNavigate(0, kUrl1);
668 EXPECT_EQ(kUrl1, contents()->GetLastCommittedURL());
671 // PlzNavigate: Test that a browser-initiated navigation is NOT canceled if a
672 // renderer-initiated non-user-initiated request is issued in the meantime.
673 TEST_F(NavigatorTestWithBrowserSideNavigation,
674 RendererNonUserInitiatedNavigationDoesntCancelBrowserInitiated) {
675 const GURL kUrl0("http://www.wikipedia.org/");
676 const GURL kUrl1("http://www.chromium.org/");
677 const GURL kUrl2("http://www.google.com/");
679 // Initialization.
680 contents()->NavigateAndCommit(kUrl0);
681 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
683 // Start a browser-initiated navigation to the 1st URL.
684 process()->sink().ClearMessages();
685 RequestNavigation(node, kUrl1);
686 NavigationRequest* request1 = GetNavigationRequestForFrameTreeNode(node);
687 ASSERT_TRUE(request1);
688 EXPECT_EQ(kUrl1, request1->common_params().url);
689 EXPECT_TRUE(request1->browser_initiated());
690 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
692 // Now receive a renderer-initiated non-user-initiated request. Nothing should
693 // change.
694 main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl2, false);
695 NavigationRequest* request2 = GetNavigationRequestForFrameTreeNode(node);
696 ASSERT_TRUE(request2);
697 EXPECT_EQ(request1, request2);
698 EXPECT_EQ(kUrl1, request2->common_params().url);
699 EXPECT_TRUE(request2->browser_initiated());
700 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
702 // Now receive the beforeUnload ACK from the still ongoing navigation.
703 main_test_rfh()->SendBeforeUnloadACK(true);
704 TestRenderFrameHost* speculative_rfh = GetSpeculativeRenderFrameHost(node);
705 ASSERT_TRUE(speculative_rfh);
707 // Have the RenderFrameHost commit the navigation.
708 scoped_refptr<ResourceResponse> response(new ResourceResponse);
709 GetLoaderForNavigationRequest(request2)
710 ->CallOnResponseStarted(response, MakeEmptyStream());
711 EXPECT_TRUE(DidRenderFrameHostRequestCommit(speculative_rfh));
712 EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh()));
714 // Commit the navigation.
715 speculative_rfh->SendNavigate(0, kUrl1);
716 EXPECT_EQ(kUrl1, contents()->GetLastCommittedURL());
719 // PlzNavigate: Test that a renderer-initiated non-user-initiated navigation is
720 // canceled if a another similar request is issued in the meantime.
721 TEST_F(NavigatorTestWithBrowserSideNavigation,
722 RendererNonUserInitiatedNavigationCancelSimilarNavigation) {
723 const GURL kUrl0("http://www.wikipedia.org/");
724 const GURL kUrl1("http://www.chromium.org/");
725 const GURL kUrl2("http://www.google.com/");
727 // Initialization.
728 contents()->NavigateAndCommit(kUrl0);
729 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
730 int32 site_instance_id_0 = main_test_rfh()->GetSiteInstance()->GetId();
732 // Start a renderer-initiated non-user-initiated navigation to the 1st URL.
733 process()->sink().ClearMessages();
734 main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl1, false);
735 NavigationRequest* request1 = GetNavigationRequestForFrameTreeNode(node);
736 ASSERT_TRUE(request1);
737 EXPECT_EQ(kUrl1, request1->common_params().url);
738 EXPECT_FALSE(request1->browser_initiated());
739 EXPECT_FALSE(request1->begin_params().has_user_gesture);
740 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
741 base::WeakPtr<TestNavigationURLLoader> loader1 =
742 GetLoaderForNavigationRequest(request1)->AsWeakPtr();
743 EXPECT_TRUE(loader1);
745 // Now receive a 2nd similar request that should replace the current one.
746 main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl2, false);
747 NavigationRequest* request2 = GetNavigationRequestForFrameTreeNode(node);
748 EXPECT_EQ(kUrl2, request2->common_params().url);
749 EXPECT_FALSE(request2->browser_initiated());
750 EXPECT_FALSE(request2->begin_params().has_user_gesture);
751 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
753 // Confirm that the first loader got destroyed.
754 EXPECT_FALSE(loader1);
756 // Have the RenderFrameHost commit the navigation.
757 scoped_refptr<ResourceResponse> response(new ResourceResponse);
758 GetLoaderForNavigationRequest(request2)
759 ->CallOnResponseStarted(response, MakeEmptyStream());
760 EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh()));
762 // Commit the navigation.
763 main_test_rfh()->SendNavigate(0, kUrl2);
764 EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL());
766 // The SiteInstance did not change.
767 EXPECT_EQ(site_instance_id_0, main_test_rfh()->GetSiteInstance()->GetId());
770 // PlzNavigate: Test that a reload navigation is properly signaled to the
771 // RenderFrame when the navigation can commit. A speculative RenderFrameHost
772 // should not be created at any step.
773 TEST_F(NavigatorTestWithBrowserSideNavigation, Reload) {
774 const GURL kUrl("http://www.google.com/");
775 contents()->NavigateAndCommit(kUrl);
777 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
778 controller().Reload(false);
779 // A NavigationRequest should have been generated.
780 NavigationRequest* main_request = GetNavigationRequestForFrameTreeNode(node);
781 ASSERT_TRUE(main_request != NULL);
782 EXPECT_EQ(FrameMsg_Navigate_Type::RELOAD,
783 main_request->common_params().navigation_type);
784 main_test_rfh()->PrepareForCommit();
785 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
787 main_test_rfh()->SendNavigate(0, kUrl);
788 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
790 // Now do a shift+reload.
791 controller().ReloadIgnoringCache(false);
792 // A NavigationRequest should have been generated.
793 main_request = GetNavigationRequestForFrameTreeNode(node);
794 ASSERT_TRUE(main_request != NULL);
795 EXPECT_EQ(FrameMsg_Navigate_Type::RELOAD_IGNORING_CACHE,
796 main_request->common_params().navigation_type);
797 main_test_rfh()->PrepareForCommit();
798 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
801 // PlzNavigate: Confirm that a speculative RenderFrameHost is used when
802 // navigating from one site to another.
803 TEST_F(NavigatorTestWithBrowserSideNavigation,
804 SpeculativeRendererWorksBaseCase) {
805 // Navigate to an initial site.
806 const GURL kUrlInit("http://wikipedia.org/");
807 contents()->NavigateAndCommit(kUrlInit);
808 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
810 // Begin navigating to another site.
811 const GURL kUrl("http://google.com/");
812 process()->sink().ClearMessages();
813 RequestNavigation(node, kUrl);
814 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
816 // Receive the beforeUnload ACK.
817 main_test_rfh()->SendBeforeUnloadACK(true);
818 TestRenderFrameHost* speculative_rfh = GetSpeculativeRenderFrameHost(node);
819 ASSERT_TRUE(speculative_rfh);
820 EXPECT_NE(speculative_rfh, main_test_rfh());
821 EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrl),
822 speculative_rfh->GetSiteInstance()->GetSiteURL());
823 EXPECT_FALSE(node->render_manager()->pending_frame_host());
824 int32 site_instance_id = speculative_rfh->GetSiteInstance()->GetId();
826 // Ask Navigator to commit the navigation by simulating a call to
827 // OnResponseStarted.
828 scoped_refptr<ResourceResponse> response(new ResourceResponse);
829 GetLoaderForNavigationRequest(GetNavigationRequestForFrameTreeNode(node))
830 ->CallOnResponseStarted(response, MakeEmptyStream());
831 speculative_rfh = GetSpeculativeRenderFrameHost(node);
832 ASSERT_TRUE(speculative_rfh);
833 EXPECT_TRUE(DidRenderFrameHostRequestCommit(speculative_rfh));
834 EXPECT_EQ(site_instance_id, speculative_rfh->GetSiteInstance()->GetId());
835 EXPECT_FALSE(node->render_manager()->pending_frame_host());
837 // Invoke OnDidCommitProvisionalLoad.
838 speculative_rfh->SendNavigate(0, kUrl);
839 EXPECT_EQ(site_instance_id, main_test_rfh()->GetSiteInstance()->GetId());
840 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
841 EXPECT_FALSE(node->render_manager()->pending_frame_host());
844 // PlzNavigate: Confirm that a speculative RenderFrameHost is thrown away when
845 // the final URL's site differs from the initial one due to redirects.
846 TEST_F(NavigatorTestWithBrowserSideNavigation,
847 SpeculativeRendererDiscardedAfterRedirectToAnotherSite) {
848 // Navigate to an initial site.
849 const GURL kUrlInit("http://wikipedia.org/");
850 contents()->NavigateAndCommit(kUrlInit);
851 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
852 int32 init_site_instance_id = main_test_rfh()->GetSiteInstance()->GetId();
854 // Begin navigating to another site.
855 const GURL kUrl("http://google.com/");
856 process()->sink().ClearMessages();
857 RequestNavigation(node, kUrl);
858 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
860 // Receive the beforeUnload ACK.
861 main_test_rfh()->SendBeforeUnloadACK(true);
862 TestRenderFrameHost* speculative_rfh = GetSpeculativeRenderFrameHost(node);
863 int32 site_instance_id = speculative_rfh->GetSiteInstance()->GetId();
864 EXPECT_NE(init_site_instance_id, site_instance_id);
865 EXPECT_EQ(init_site_instance_id, main_test_rfh()->GetSiteInstance()->GetId());
866 ASSERT_TRUE(speculative_rfh);
867 EXPECT_NE(speculative_rfh, main_test_rfh());
868 EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrl),
869 speculative_rfh->GetSiteInstance()->GetSiteURL());
871 // It then redirects to yet another site.
872 NavigationRequest* main_request = GetNavigationRequestForFrameTreeNode(node);
873 ASSERT_TRUE(main_request);
874 const GURL kUrlRedirect("https://www.google.com/");
875 GetLoaderForNavigationRequest(main_request)
876 ->SimulateServerRedirect(kUrlRedirect);
877 EXPECT_EQ(init_site_instance_id, main_test_rfh()->GetSiteInstance()->GetId());
878 speculative_rfh = GetSpeculativeRenderFrameHost(node);
879 ASSERT_TRUE(speculative_rfh);
881 // For now, ensure that the speculative RenderFrameHost does not change after
882 // the redirect.
883 // TODO(carlosk): once the speculative RenderFrameHost updates with redirects
884 // this next check will be changed to verify that it actually happens.
885 EXPECT_EQ(site_instance_id, speculative_rfh->GetSiteInstance()->GetId());
887 // Commit the navigation with Navigator by simulating the call to
888 // OnResponseStarted.
889 scoped_refptr<ResourceResponse> response(new ResourceResponse);
890 GetLoaderForNavigationRequest(main_request)
891 ->CallOnResponseStarted(response, MakeEmptyStream());
892 speculative_rfh = GetSpeculativeRenderFrameHost(node);
893 EXPECT_TRUE(DidRenderFrameHostRequestCommit(speculative_rfh));
894 EXPECT_EQ(init_site_instance_id, main_test_rfh()->GetSiteInstance()->GetId());
896 // Once commit happens the speculative RenderFrameHost is updated to match the
897 // known final SiteInstance.
898 ASSERT_TRUE(speculative_rfh);
899 EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrlRedirect),
900 speculative_rfh->GetSiteInstance()->GetSiteURL());
901 int32 redirect_site_instance_id = speculative_rfh->GetSiteInstance()->GetId();
902 EXPECT_NE(init_site_instance_id, redirect_site_instance_id);
903 EXPECT_NE(site_instance_id, redirect_site_instance_id);
905 // Invoke OnDidCommitProvisionalLoad.
906 speculative_rfh->SendNavigate(0, kUrlRedirect);
908 // Check that the speculative RenderFrameHost was swapped in.
909 EXPECT_EQ(redirect_site_instance_id,
910 main_test_rfh()->GetSiteInstance()->GetId());
911 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
914 // PlzNavigate: Verify that a previously swapped out RenderFrameHost is
915 // correctly reused when spawning a speculative RenderFrameHost in a navigation
916 // using the same SiteInstance.
917 TEST_F(NavigatorTestWithBrowserSideNavigation,
918 SpeculativeRendererReuseSwappedOutRFH) {
919 // Navigate to an initial site.
920 const GURL kUrl1("http://wikipedia.org/");
921 contents()->NavigateAndCommit(kUrl1);
922 TestRenderFrameHost* rfh1 = main_test_rfh();
923 FrameTreeNode* node = rfh1->frame_tree_node();
924 RenderFrameHostManager* rfhm = node->render_manager();
926 // Increment active frame count to cause the RenderFrameHost to be swapped out
927 // (instead of immediately destroyed).
928 rfh1->GetSiteInstance()->increment_active_frame_count();
930 // Navigate to another site to swap out the initial RenderFrameHost.
931 const GURL kUrl2("http://chromium.org/");
932 contents()->NavigateAndCommit(kUrl2);
933 ASSERT_NE(rfh1, main_test_rfh());
934 EXPECT_NE(RenderFrameHostImpl::STATE_DEFAULT, rfh1->rfh_state());
935 EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, main_test_rfh()->rfh_state());
936 EXPECT_TRUE(rfhm->IsOnSwappedOutList(rfh1));
938 // Now go back to the initial site so that the swapped out RenderFrameHost
939 // should be reused.
940 process()->sink().ClearMessages();
941 static_cast<MockRenderProcessHost*>(rfh1->GetProcess())
942 ->sink()
943 .ClearMessages();
944 RequestNavigation(node, kUrl1);
945 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
947 main_test_rfh()->SendBeforeUnloadACK(true);
948 EXPECT_EQ(rfh1, GetSpeculativeRenderFrameHost(node));
949 EXPECT_NE(RenderFrameHostImpl::STATE_DEFAULT,
950 GetSpeculativeRenderFrameHost(node)->rfh_state());
952 scoped_refptr<ResourceResponse> response(new ResourceResponse);
953 GetLoaderForNavigationRequest(GetNavigationRequestForFrameTreeNode(node))
954 ->CallOnResponseStarted(response, MakeEmptyStream());
955 EXPECT_EQ(rfh1, GetSpeculativeRenderFrameHost(node));
956 EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT,
957 GetSpeculativeRenderFrameHost(node)->rfh_state());
958 EXPECT_TRUE(DidRenderFrameHostRequestCommit(rfh1));
959 EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh()));
961 rfh1->SendNavigate(1, kUrl1);
962 EXPECT_EQ(rfh1, main_test_rfh());
963 EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, rfh1->rfh_state());
964 EXPECT_FALSE(rfhm->IsOnSwappedOutList(rfh1));
967 // PlzNavigate: Verify that data urls are properly handled.
968 TEST_F(NavigatorTestWithBrowserSideNavigation, DataUrls) {
969 const GURL kUrl1("http://wikipedia.org/");
970 const GURL kUrl2("data:text/html,test");
972 // Navigate to an initial site.
973 contents()->NavigateAndCommit(kUrl1);
974 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
976 // Navigate to a data url.
977 RequestNavigation(node, kUrl2);
978 NavigationRequest* navigation_request =
979 GetNavigationRequestForFrameTreeNode(node);
980 ASSERT_TRUE(navigation_request);
981 EXPECT_EQ(NavigationRequest::WAITING_FOR_RENDERER_RESPONSE,
982 navigation_request->state());
983 main_test_rfh()->SendBeforeUnloadACK(true);
985 // The request should not have been sent to the IO thread but committed
986 // immediately.
987 EXPECT_EQ(NavigationRequest::RESPONSE_STARTED,
988 navigation_request->state());
989 EXPECT_FALSE(navigation_request->loader_for_testing());
990 TestRenderFrameHost* speculative_rfh = GetSpeculativeRenderFrameHost(node);
991 ASSERT_TRUE(speculative_rfh);
992 speculative_rfh->SendNavigate(0, kUrl2);
993 EXPECT_EQ(main_test_rfh(), speculative_rfh);
995 // Go back to the initial site.
996 contents()->NavigateAndCommit(kUrl1);
998 // Do a renderer-initiated navigation to a data url. The request should not be
999 // sent to the IO thread, nor committed.
1000 TestRenderFrameHost* main_rfh = main_test_rfh();
1001 main_rfh->SendRendererInitiatedNavigationRequest(kUrl2, true);
1002 navigation_request = GetNavigationRequestForFrameTreeNode(node);
1003 ASSERT_TRUE(navigation_request);
1004 EXPECT_EQ(NavigationRequest::RESPONSE_STARTED,
1005 navigation_request->state());
1006 EXPECT_FALSE(navigation_request->loader_for_testing());
1007 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
1010 // Tests several cases for converting SiteInstanceDescriptors into
1011 // SiteInstances:
1012 // 1) Pointer to the current SiteInstance.
1013 // 2) Pointer to an unrelated SiteInstance.
1014 // 3) Same-site URL, related.
1015 // 4) Cross-site URL, related.
1016 // 5) Same-site URL, unrelated (with and without candidate SiteInstances).
1017 // 6) Cross-site URL, unrelated (with candidate SiteInstance).
1018 TEST_F(NavigatorTestWithBrowserSideNavigation,
1019 SiteInstanceDescriptionConversion) {
1020 // Navigate to set a current SiteInstance on the RenderFrameHost.
1021 GURL kUrl1("http://a.com");
1022 contents()->NavigateAndCommit(kUrl1);
1023 SiteInstance* current_instance = main_test_rfh()->GetSiteInstance();
1024 ASSERT_TRUE(current_instance);
1026 // 1) Convert a descriptor pointing to the current instance.
1027 RenderFrameHostManager* rfhm =
1028 main_test_rfh()->frame_tree_node()->render_manager();
1030 SiteInstanceDescriptor descriptor(current_instance);
1031 SiteInstance* converted_instance =
1032 ConvertToSiteInstance(rfhm, descriptor, nullptr);
1033 EXPECT_EQ(current_instance, converted_instance);
1036 // 2) Convert a descriptor pointing an instance unrelated to the current one,
1037 // with a different site.
1038 GURL kUrl2("http://b.com");
1039 scoped_refptr<SiteInstance> unrelated_instance(
1040 SiteInstance::CreateForURL(browser_context(), kUrl2));
1041 EXPECT_FALSE(
1042 current_instance->IsRelatedSiteInstance(unrelated_instance.get()));
1044 SiteInstanceDescriptor descriptor(unrelated_instance.get());
1045 SiteInstance* converted_instance =
1046 ConvertToSiteInstance(rfhm, descriptor, nullptr);
1047 EXPECT_EQ(unrelated_instance.get(), converted_instance);
1050 // 3) Convert a descriptor of a related instance with the same site as the
1051 // current one.
1052 GURL kUrlSameSiteAs1("http://www.a.com/foo");
1054 SiteInstanceDescriptor descriptor(browser_context(), kUrlSameSiteAs1, true);
1055 SiteInstance* converted_instance =
1056 ConvertToSiteInstance(rfhm, descriptor, nullptr);
1057 EXPECT_EQ(current_instance, converted_instance);
1060 // 4) Convert a descriptor of a related instance with a site different from
1061 // the current one.
1062 GURL kUrlSameSiteAs2("http://www.b.com/foo");
1063 scoped_refptr<SiteInstance> related_instance;
1065 SiteInstanceDescriptor descriptor(browser_context(), kUrlSameSiteAs2, true);
1066 related_instance = ConvertToSiteInstance(rfhm, descriptor, nullptr);
1067 // Should return a new instance, related to the current, set to the new site
1068 // URL.
1069 EXPECT_TRUE(
1070 current_instance->IsRelatedSiteInstance(related_instance.get()));
1071 EXPECT_NE(current_instance, related_instance.get());
1072 EXPECT_NE(unrelated_instance.get(), related_instance.get());
1073 EXPECT_EQ(SiteInstance::GetSiteForURL(browser_context(), kUrlSameSiteAs2),
1074 related_instance->GetSiteURL());
1077 // 5) Convert a descriptor of an unrelated instance with the same site as the
1078 // current one, several times, with and without candidate sites.
1080 SiteInstanceDescriptor descriptor(browser_context(), kUrlSameSiteAs1,
1081 false);
1082 scoped_refptr<SiteInstance> converted_instance_1 =
1083 ConvertToSiteInstance(rfhm, descriptor, nullptr);
1084 // Should return a new instance, unrelated to the current one, set to the
1085 // provided site URL.
1086 EXPECT_FALSE(
1087 current_instance->IsRelatedSiteInstance(converted_instance_1.get()));
1088 EXPECT_NE(current_instance, converted_instance_1.get());
1089 EXPECT_NE(unrelated_instance.get(), converted_instance_1.get());
1090 EXPECT_EQ(SiteInstance::GetSiteForURL(browser_context(), kUrlSameSiteAs1),
1091 converted_instance_1->GetSiteURL());
1093 // Does the same but this time using unrelated_instance as a candidate,
1094 // which has a different site.
1095 scoped_refptr<SiteInstance> converted_instance_2 =
1096 ConvertToSiteInstance(rfhm, descriptor, unrelated_instance.get());
1097 // Should return yet another new instance, unrelated to the current one, set
1098 // to the same site URL.
1099 EXPECT_FALSE(
1100 current_instance->IsRelatedSiteInstance(converted_instance_2.get()));
1101 EXPECT_NE(current_instance, converted_instance_2.get());
1102 EXPECT_NE(unrelated_instance.get(), converted_instance_2.get());
1103 EXPECT_NE(converted_instance_1.get(), converted_instance_2.get());
1104 EXPECT_EQ(SiteInstance::GetSiteForURL(browser_context(), kUrlSameSiteAs1),
1105 converted_instance_2->GetSiteURL());
1107 // Converts once more but with |converted_instance_1| as a candidate.
1108 SiteInstance* converted_instance_3 =
1109 ConvertToSiteInstance(rfhm, descriptor, converted_instance_1.get());
1110 // Should return |converted_instance_1| because its site matches and it is
1111 // unrelated to the current SiteInstance.
1112 EXPECT_EQ(converted_instance_1.get(), converted_instance_3);
1115 // 6) Convert a descriptor of an unrelated instance with the same site of
1116 // related_instance and using it as a candidate.
1118 SiteInstanceDescriptor descriptor(browser_context(), kUrlSameSiteAs2,
1119 false);
1120 scoped_refptr<SiteInstance> converted_instance_1 =
1121 ConvertToSiteInstance(rfhm, descriptor, related_instance.get());
1122 // Should return a new instance, unrelated to the current, set to the
1123 // provided site URL.
1124 EXPECT_FALSE(
1125 current_instance->IsRelatedSiteInstance(converted_instance_1.get()));
1126 EXPECT_NE(related_instance.get(), converted_instance_1.get());
1127 EXPECT_NE(unrelated_instance.get(), converted_instance_1.get());
1128 EXPECT_EQ(SiteInstance::GetSiteForURL(browser_context(), kUrlSameSiteAs2),
1129 converted_instance_1->GetSiteURL());
1131 SiteInstance* converted_instance_2 =
1132 ConvertToSiteInstance(rfhm, descriptor, unrelated_instance.get());
1133 // Should return |unrelated_instance| because its site matches and it is
1134 // unrelated to the current SiteInstance.
1135 EXPECT_EQ(unrelated_instance.get(), converted_instance_2);
1139 } // namespace content