blob: 8737f9416c93e036e135e6d86b585db02898e756 [file] [log] [blame]
Avi Drissman4e1b7bc32022-09-15 14:03:501// Copyright 2014 The Chromium Authors
clamy71a42ec2014-10-02 18:43:222// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
danakjc492bf82020-09-09 20:02:445#include "content/browser/renderer_host/navigator.h"
arthursonzognia2754522019-07-03 18:25:366
avib7348942015-12-25 20:57:107#include <stdint.h>
8
toyoshim7ae0fd52016-07-08 09:29:509#include "base/feature_list.h"
Todd Sahlb2f798302021-01-21 16:32:0710#include "base/test/test_simple_task_runner.h"
clamy71a42ec2014-10-02 18:43:2211#include "base/time/time.h"
avib7348942015-12-25 20:57:1012#include "build/build_config.h"
danakjc492bf82020-09-09 20:02:4413#include "content/browser/renderer_host/navigation_controller_impl.h"
14#include "content/browser/renderer_host/navigation_entry_impl.h"
15#include "content/browser/renderer_host/navigation_request.h"
16#include "content/browser/renderer_host/navigation_request_info.h"
danakjc492bf82020-09-09 20:02:4417#include "content/browser/renderer_host/render_frame_host_manager.h"
Sharon Yangd70a5392021-10-26 23:06:3218#include "content/browser/site_info.h"
clamy71a42ec2014-10-02 18:43:2219#include "content/browser/site_instance_impl.h"
[email protected]ee8ae332020-01-29 03:49:4520#include "content/common/content_navigation_policy.h"
Ken Rockot48785452017-10-25 19:33:1421#include "content/common/frame.mojom.h"
Aaron Colwellf45e3a852019-06-06 00:48:2722#include "content/public/browser/child_process_security_policy.h"
toyoshim7ae0fd52016-07-08 09:29:5023#include "content/public/common/content_features.h"
clamy71a42ec2014-10-02 18:43:2224#include "content/public/common/url_constants.h"
25#include "content/public/common/url_utils.h"
Dominique Fauteux-Chapleau3e8d3452021-07-14 17:20:0226#include "content/public/test/back_forward_cache_util.h"
carlosk39337112015-01-14 21:44:5127#include "content/public/test/mock_render_process_host.h"
arthursonzogni63aa3f372017-08-09 14:28:3928#include "content/public/test/navigation_simulator.h"
Todd Sahlb2f798302021-01-21 16:32:0729#include "content/public/test/test_navigation_throttle_inserter.h"
carlosk15fb0f02015-07-29 17:07:5130#include "content/public/test/test_utils.h"
Arthur Hemery4aa413c42019-01-14 18:53:3031#include "content/test/navigation_simulator_impl.h"
Todd Sahlb2f798302021-01-21 16:32:0732#include "content/test/task_runner_deferring_throttle.h"
clamy72c72792014-11-18 18:09:4633#include "content/test/test_navigation_url_loader.h"
clamy71a42ec2014-10-02 18:43:2234#include "content/test/test_render_frame_host.h"
35#include "content/test/test_web_contents.h"
36#include "net/base/load_flags.h"
davidben8b339132014-10-08 02:27:0137#include "net/http/http_response_headers.h"
davidben6b77cd72014-10-29 21:13:4538#include "net/url_request/redirect_info.h"
clamy71a42ec2014-10-02 18:43:2239#include "ui/base/page_transition_types.h"
davidben61814fd2014-10-15 19:45:0740#include "url/url_constants.h"
clamy71a42ec2014-10-02 18:43:2241
42namespace content {
43
Aaron Colwell5fb878042020-12-17 19:48:4444namespace {
45
46// Helper function that determines if a test should expect a cross-site
47// navigation to trigger a SiteInstance change based on the current process
48// model.
49bool ExpectSiteInstanceChange(SiteInstanceImpl* site_instance) {
50 return AreAllSitesIsolatedForTesting() ||
51 CanCrossSiteNavigationsProactivelySwapBrowsingInstances() ||
52 !site_instance->IsDefaultSiteInstance();
53}
54
Dominique Fauteux-Chapleau3e8d3452021-07-14 17:20:0255// Same as above but does not return true if back/forward cache is the only
56// trigger for SiteInstance change. This function is useful if, e.g. the test
57// intends to disable back/forward cache.
58bool ExpectSiteInstanceChangeWithoutBackForwardCache(
59 SiteInstanceImpl* site_instance) {
60 return AreAllSitesIsolatedForTesting() ||
Dominique Fauteux-Chapleau3e8d3452021-07-14 17:20:0261 !site_instance->IsDefaultSiteInstance();
62}
63
Aaron Colwell5fb878042020-12-17 19:48:4464} // namespace
65
Camille Lamy07c49cdf2019-03-11 15:53:5766class NavigatorTest : public RenderViewHostImplTestHarness {
davidben6b77cd72014-10-29 21:13:4567 public:
nickd5bbd0b2016-03-31 19:52:4468 using SiteInstanceDescriptor = RenderFrameHostManager::SiteInstanceDescriptor;
69 using SiteInstanceRelation = RenderFrameHostManager::SiteInstanceRelation;
carlosk078298a82015-04-07 10:33:2070
Aran Gilman37d11632019-10-08 23:07:1571 void SetUp() override { RenderViewHostImplTestHarness::SetUp(); }
davidben6b77cd72014-10-29 21:13:4572
Aran Gilman37d11632019-10-08 23:07:1573 void TearDown() override { RenderViewHostImplTestHarness::TearDown(); }
kenrb99afb082015-06-02 13:35:5874
davidben6b77cd72014-10-29 21:13:4575 TestNavigationURLLoader* GetLoaderForNavigationRequest(
76 NavigationRequest* request) const {
77 return static_cast<TestNavigationURLLoader*>(request->loader_for_testing());
78 }
79
carlosk39337112015-01-14 21:44:5180 TestRenderFrameHost* GetSpeculativeRenderFrameHost(FrameTreeNode* node) {
81 return static_cast<TestRenderFrameHost*>(
82 node->render_manager()->speculative_render_frame_host_.get());
83 }
84
Aaron Colwell91e32b12021-02-17 01:40:5685 scoped_refptr<SiteInstanceImpl> ConvertToSiteInstance(
dchengbccd6b82016-03-30 16:24:1986 RenderFrameHostManager* rfhm,
87 const SiteInstanceDescriptor& descriptor,
88 SiteInstance* candidate_instance) {
Aaron Colwell91e32b12021-02-17 01:40:5689 return static_cast<SiteInstanceImpl*>(
90 rfhm->ConvertToSiteInstance(
Arthur Hemery3a991c092021-12-22 12:04:2491 descriptor, static_cast<SiteInstanceImpl*>(candidate_instance))
Aaron Colwell91e32b12021-02-17 01:40:5692 .get());
93 }
94
95 SiteInfo CreateExpectedSiteInfo(const GURL& url) {
96 return SiteInfo::CreateForTesting(IsolationContext(browser_context()), url);
carlosk078298a82015-04-07 10:33:2097 }
clamy71a42ec2014-10-02 18:43:2298};
99
Arthur Hemery859f3462019-01-29 16:29:07100// Tests a complete browser-initiated navigation starting with a non-live
101// renderer.
Camille Lamy07c49cdf2019-03-11 15:53:57102TEST_F(NavigatorTest, SimpleBrowserInitiatedNavigationFromNonLiveRenderer) {
carlosk39337112015-01-14 21:44:51103 const GURL kUrl("http://chromium.org/");
carloske24d11782015-02-13 10:10:02104
105 EXPECT_FALSE(main_test_rfh()->IsRenderFrameLive());
106
107 // Start a browser-initiated navigation.
Arthur Hemery859f3462019-01-29 16:29:07108 auto navigation =
109 NavigationSimulator::CreateBrowserInitiated(kUrl, contents());
Lukasz Anforowicz1de0a222021-07-26 22:02:32110 auto site_instance_id = main_test_rfh()->GetSiteInstance()->GetId();
carloske24d11782015-02-13 10:10:02111 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
Arthur Hemery859f3462019-01-29 16:29:07112 navigation->Start();
clamydcb434c12015-04-16 19:29:16113 NavigationRequest* request = node->navigation_request();
carloske24d11782015-02-13 10:10:02114 ASSERT_TRUE(request);
115 EXPECT_EQ(kUrl, request->common_params().url);
116 EXPECT_TRUE(request->browser_initiated());
117
118 // As there's no live renderer the navigation should not wait for a
Antonio Gomes8678a202020-03-02 20:03:25119 // beforeUnload completion callback being invoked by the renderer and
120 // start right away.
Mohamed Abdelhalimccd149af2019-10-31 14:48:53121 EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, request->state());
carloske24d11782015-02-13 10:10:02122 ASSERT_TRUE(GetLoaderForNavigationRequest(request));
123 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
carloske24d11782015-02-13 10:10:02124
Arthur Hemery859f3462019-01-29 16:29:07125 navigation->ReadyToCommit();
clamyefdb7a42015-07-01 16:55:47126 EXPECT_TRUE(main_test_rfh()->is_loading());
127 EXPECT_FALSE(node->navigation_request());
carloske24d11782015-02-13 10:10:02128
129 // Commit the navigation.
Arthur Hemery859f3462019-01-29 16:29:07130 navigation->Commit();
Sreeja Kamishettye49854f82021-06-02 00:52:03131 EXPECT_TRUE(main_test_rfh()->IsActive());
Sreeja Kamishettye25ac752020-05-12 18:15:48132 EXPECT_EQ(main_test_rfh()->lifecycle_state(),
Sreeja Kamishetty299329ad2021-03-25 14:06:01133 RenderFrameHostImpl::LifecycleStateImpl::kActive);
Sharon Yang47453bb2025-04-25 14:48:09134 if (AreStrictSiteInstancesEnabled()) {
Aaron Colwell91e32b12021-02-17 01:40:56135 EXPECT_EQ(CreateExpectedSiteInfo(kUrl),
136 main_test_rfh()->GetSiteInstance()->GetSiteInfo());
Sharon Yang02279222025-01-15 19:09:19137 } else {
138 EXPECT_TRUE(main_test_rfh()->GetSiteInstance()->IsDefaultSiteInstance());
Aaron Colwelle953e562019-07-24 16:47:36139 }
carlosk39337112015-01-14 21:44:51140 EXPECT_EQ(kUrl, contents()->GetLastCommittedURL());
carloske24d11782015-02-13 10:10:02141
carloskf4707892015-02-19 18:47:40142 // The main RenderFrameHost should not have been changed, and the renderer
143 // should have been initialized.
carloske24d11782015-02-13 10:10:02144 EXPECT_EQ(site_instance_id, main_test_rfh()->GetSiteInstance()->GetId());
145 EXPECT_TRUE(main_test_rfh()->IsRenderFrameLive());
carlosk39337112015-01-14 21:44:51146
147 // After a navigation is finished no speculative RenderFrameHost should
148 // exist.
carlosk39337112015-01-14 21:44:51149 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
carlosk39337112015-01-14 21:44:51150}
151
Arthur Hemery0dd65812019-08-01 14:18:45152// Tests a complete renderer-initiated same-site navigation.
Camille Lamy07c49cdf2019-03-11 15:53:57153TEST_F(NavigatorTest, SimpleRendererInitiatedSameSiteNavigation) {
carloske24d11782015-02-13 10:10:02154 const GURL kUrl1("http://www.chromium.org/");
155 const GURL kUrl2("http://www.chromium.org/Home");
156
157 contents()->NavigateAndCommit(kUrl1);
158 EXPECT_TRUE(main_test_rfh()->IsRenderFrameLive());
Mario Sanchez Pradacb83d6c82020-09-11 13:11:51159 static_cast<mojom::FrameHost*>(main_test_rfh())->DidStopLoading();
Nasko Oskov2e9e0112020-12-22 21:34:43160 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
carloske24d11782015-02-13 10:10:02161
carloskf4707892015-02-19 18:47:40162 // Start a renderer-initiated non-user-initiated navigation.
Nasko Oskov2e9e0112020-12-22 21:34:43163 EXPECT_FALSE(node->navigation_request());
arthursonzogni91439432017-08-16 16:32:37164 auto navigation =
165 NavigationSimulator::CreateRendererInitiated(kUrl2, main_test_rfh());
166 navigation->SetTransition(ui::PageTransitionFromInt(
167 ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_CLIENT_REDIRECT));
168 navigation->SetHasUserGesture(false);
169 navigation->Start();
clamydcb434c12015-04-16 19:29:16170 NavigationRequest* request = node->navigation_request();
carloske24d11782015-02-13 10:10:02171 ASSERT_TRUE(request);
172
173 // The navigation is immediately started as there's no need to wait for
174 // beforeUnload to be executed.
Mohamed Abdelhalimccd149af2019-10-31 14:48:53175 EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, request->state());
Arthur Hemery14a71ad22017-10-27 10:54:39176 EXPECT_FALSE(request->common_params().has_user_gesture);
carloske24d11782015-02-13 10:10:02177 EXPECT_EQ(kUrl2, request->common_params().url);
178 EXPECT_FALSE(request->browser_initiated());
Rakina Zata Amni1d15cfb2020-08-05 02:32:55179
180 if (CanSameSiteMainFrameNavigationsChangeRenderFrameHosts()) {
181 // If same-site ProactivelySwapBrowsingInstance or main-frame RenderDocument
182 // is enabled, the RFH should change so we should have a speculative RFH.
183 EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
184 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node)->is_loading());
185 } else {
186 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
187 }
arthursonzogni91439432017-08-16 16:32:37188 EXPECT_FALSE(main_test_rfh()->is_loading());
carloske24d11782015-02-13 10:10:02189
arthursonzogni91439432017-08-16 16:32:37190 // Have the current RenderFrameHost commit the navigation
191 navigation->ReadyToCommit();
Rakina Zata Amni1d15cfb2020-08-05 02:32:55192 if (CanSameSiteMainFrameNavigationsChangeRenderFrameHosts()) {
193 EXPECT_TRUE(GetSpeculativeRenderFrameHost(node)->is_loading());
194 } else {
195 EXPECT_TRUE(main_test_rfh()->is_loading());
196 }
clamyefdb7a42015-07-01 16:55:47197 EXPECT_FALSE(node->navigation_request());
carloske24d11782015-02-13 10:10:02198
199 // Commit the navigation.
arthursonzogni91439432017-08-16 16:32:37200 navigation->Commit();
Sreeja Kamishettye49854f82021-06-02 00:52:03201 EXPECT_TRUE(main_test_rfh()->IsActive());
Sharon Yang47453bb2025-04-25 14:48:09202 if (AreStrictSiteInstancesEnabled()) {
Aaron Colwell91e32b12021-02-17 01:40:56203 EXPECT_EQ(CreateExpectedSiteInfo(kUrl2),
204 main_test_rfh()->GetSiteInstance()->GetSiteInfo());
Sharon Yang02279222025-01-15 19:09:19205 } else {
206 EXPECT_TRUE(main_test_rfh()->GetSiteInstance()->IsDefaultSiteInstance());
Aaron Colwelle953e562019-07-24 16:47:36207 }
carloske24d11782015-02-13 10:10:02208 EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL());
carloske24d11782015-02-13 10:10:02209 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
carloske24d11782015-02-13 10:10:02210}
211
Arthur Hemery0dd65812019-08-01 14:18:45212// Tests a complete renderer-initiated navigation that should be
carlosk42f59e62015-03-16 19:02:36213// cross-site but does not result in a SiteInstance swap because its
214// renderer-initiated.
Camille Lamy07c49cdf2019-03-11 15:53:57215TEST_F(NavigatorTest, SimpleRendererInitiatedCrossSiteNavigation) {
carlosk42f59e62015-03-16 19:02:36216 const GURL kUrl1("http://www.chromium.org/");
217 const GURL kUrl2("http://www.google.com");
218
219 contents()->NavigateAndCommit(kUrl1);
220 EXPECT_TRUE(main_test_rfh()->IsRenderFrameLive());
Aaron Colwell5fb878042020-12-17 19:48:44221 scoped_refptr<SiteInstanceImpl> site_instance_1 =
222 main_test_rfh()->GetSiteInstance();
223 bool expect_site_instance_change =
224 ExpectSiteInstanceChange(site_instance_1.get());
Nasko Oskov2e9e0112020-12-22 21:34:43225 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
carlosk42f59e62015-03-16 19:02:36226
arthursonzogni91439432017-08-16 16:32:37227 // Start a renderer-initiated navigation.
Nasko Oskov2e9e0112020-12-22 21:34:43228 EXPECT_FALSE(node->navigation_request());
arthursonzogni91439432017-08-16 16:32:37229 auto navigation =
230 NavigationSimulator::CreateRendererInitiated(kUrl2, main_test_rfh());
231 navigation->Start();
clamydcb434c12015-04-16 19:29:16232 NavigationRequest* request = node->navigation_request();
carlosk42f59e62015-03-16 19:02:36233 ASSERT_TRUE(request);
234
235 // The navigation is immediately started as there's no need to wait for
236 // beforeUnload to be executed.
Mohamed Abdelhalimccd149af2019-10-31 14:48:53237 EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, request->state());
carlosk42f59e62015-03-16 19:02:36238 EXPECT_EQ(kUrl2, request->common_params().url);
239 EXPECT_FALSE(request->browser_initiated());
Aaron Colwell5fb878042020-12-17 19:48:44240 if (expect_site_instance_change) {
clamy61dfb232016-02-26 18:08:49241 EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
242 } else {
243 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
244 }
carlosk42f59e62015-03-16 19:02:36245
246 // Have the current RenderFrameHost commit the navigation.
arthursonzogni91439432017-08-16 16:32:37247 navigation->ReadyToCommit();
Aaron Colwell5fb878042020-12-17 19:48:44248 if (expect_site_instance_change) {
arthursonzogni91439432017-08-16 16:32:37249 EXPECT_EQ(navigation->GetFinalRenderFrameHost(),
250 GetSpeculativeRenderFrameHost(node));
clamy61dfb232016-02-26 18:08:49251 }
clamyefdb7a42015-07-01 16:55:47252 EXPECT_FALSE(node->navigation_request());
carlosk42f59e62015-03-16 19:02:36253
254 // Commit the navigation.
arthursonzogni91439432017-08-16 16:32:37255 navigation->Commit();
Sreeja Kamishettye49854f82021-06-02 00:52:03256 EXPECT_TRUE(main_test_rfh()->IsActive());
carlosk42f59e62015-03-16 19:02:36257 EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL());
carlosk42f59e62015-03-16 19:02:36258 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
carlosk42f59e62015-03-16 19:02:36259
Aaron Colwell5fb878042020-12-17 19:48:44260 if (expect_site_instance_change) {
261 EXPECT_NE(site_instance_1->GetId(),
262 main_test_rfh()->GetSiteInstance()->GetId());
263 EXPECT_EQ(site_instance_1->IsDefaultSiteInstance(),
264 main_test_rfh()->GetSiteInstance()->IsDefaultSiteInstance());
clamy5d947f52017-05-24 19:51:18265 } else {
Aaron Colwell5fb878042020-12-17 19:48:44266 EXPECT_EQ(site_instance_1->GetId(),
267 main_test_rfh()->GetSiteInstance()->GetId());
clamy5d947f52017-05-24 19:51:18268 }
carlosk42f59e62015-03-16 19:02:36269}
270
Todd Sahlb2f798302021-01-21 16:32:07271// Tests that when a navigation to about:blank is renderer-aborted,
272// after another cross-site navigation has been initiated, that the
273// second navigation is undisturbed.
274TEST_F(NavigatorTest, RendererAbortedAboutBlankNavigation) {
275 const GURL kUrl0("http://www.google.com/");
276 const GURL kUrl1("about:blank");
277 const GURL kUrl2("http://www.chromium.org/Home");
278
279 contents()->NavigateAndCommit(kUrl0);
280 EXPECT_TRUE(main_test_rfh()->IsRenderFrameLive());
Dominique Fauteux-Chapleau3e8d3452021-07-14 17:20:02281
Rakina Zata Amnidfcab2e52023-08-26 07:11:59282 // The test expects cross-site navigations to change RenderFrameHosts, but not
283 // same-site navigations. Return if that can't be satisfied.
Dominique Fauteux-Chapleau3e8d3452021-07-14 17:20:02284 DisableBackForwardCacheForTesting(
285 contents(), BackForwardCache::TEST_ASSUMES_NO_RENDER_FRAME_CHANGE);
286 if (!ExpectSiteInstanceChangeWithoutBackForwardCache(
Rakina Zata Amnidfcab2e52023-08-26 07:11:59287 main_test_rfh()->GetSiteInstance()) ||
288 ShouldCreateNewHostForAllFrames()) {
289 GTEST_SKIP();
Dominique Fauteux-Chapleau3e8d3452021-07-14 17:20:02290 }
Todd Sahlb2f798302021-01-21 16:32:07291
292 // Start a renderer-initiated navigation to about:blank.
293 EXPECT_FALSE(main_test_rfh()->is_loading());
294 auto navigation1 =
295 NavigationSimulator::CreateRendererInitiated(kUrl1, main_test_rfh());
296 navigation1->SetTransition(ui::PAGE_TRANSITION_LINK);
297 navigation1->Start();
298 navigation1->ReadyToCommit();
299
300 // about:blank should load on the main rfhi, not a speculative one,
301 // and automatically advance to READY_TO_COMMIT since it requires
302 // no network resources.
303 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
304 ASSERT_FALSE(node->navigation_request());
305 EXPECT_TRUE(main_test_rfh()->is_loading());
306 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
307
308 // Start a second, cross-origin navigation.
309 auto navigation2 =
310 NavigationSimulator::CreateRendererInitiated(kUrl2, main_test_rfh());
311 navigation2->SetTransition(ui::PAGE_TRANSITION_LINK);
312 navigation2->Start();
313 ASSERT_TRUE(node->navigation_request());
314 EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
315
316 // Abort the initial navigation.
317 navigation1->AbortFromRenderer();
318
319 // But the speculative rfhi and second navigation request
320 // should be unaffected.
321 ASSERT_TRUE(node->navigation_request());
322 EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
323}
324
325// Tests that when a navigation to about:blank is renderer-aborted,
326// after another cross-site navigation has been initiated, that the
327// second navigation is undisturbed. In this variation, the second
328// navigation is initially same-site, then redirects cross-site,
329// and a throttle DEFERs during WillProcessResponse(). The initial
330// navigation gets aborted during this defer.
331TEST_F(NavigatorTest,
332 RedirectedRendererAbortedAboutBlankNavigationwithDeferredCommit) {
333 const GURL kUrl0("http://www.google.com/");
334 const GURL kUrl0SameSiteVariation("http://www.google.com/home");
335 const GURL kUrl1("about:blank");
336 const GURL kUrl2("http://www.chromium.org/Home");
337
338 contents()->NavigateAndCommit(kUrl0);
339 EXPECT_TRUE(main_test_rfh()->IsRenderFrameLive());
Dominique Fauteux-Chapleau3e8d3452021-07-14 17:20:02340
Rakina Zata Amnidfcab2e52023-08-26 07:11:59341 // The test expects cross-site navigations to change RenderFrameHosts, but not
342 // same-site navigations. Return if that can't be satisfied.
Dominique Fauteux-Chapleau3e8d3452021-07-14 17:20:02343 DisableBackForwardCacheForTesting(
344 contents(), BackForwardCache::TEST_ASSUMES_NO_RENDER_FRAME_CHANGE);
345 if (!ExpectSiteInstanceChangeWithoutBackForwardCache(
Rakina Zata Amnidfcab2e52023-08-26 07:11:59346 main_test_rfh()->GetSiteInstance()) ||
347 ShouldCreateNewHostForAllFrames()) {
348 GTEST_SKIP();
Dominique Fauteux-Chapleau3e8d3452021-07-14 17:20:02349 }
Todd Sahlb2f798302021-01-21 16:32:07350
351 // Start a renderer-initiated navigation to about:blank.
352 EXPECT_FALSE(main_test_rfh()->is_loading());
353 auto navigation1 =
354 NavigationSimulator::CreateRendererInitiated(kUrl1, main_test_rfh());
355 navigation1->SetTransition(ui::PAGE_TRANSITION_LINK);
356 navigation1->Start();
357 navigation1->ReadyToCommit();
358
359 // about:blank should load on the main rfhi, not a speculative one,
360 // and automatically advance to READY_TO_COMMIT since it requires
361 // no network resources.
362 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
363 ASSERT_FALSE(node->navigation_request());
364 EXPECT_TRUE(main_test_rfh()->is_loading());
365 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
366
367 // Start a second, same-origin navigation.
368 auto navigation2 = NavigationSimulator::CreateRendererInitiated(
369 kUrl0SameSiteVariation, main_test_rfh());
370 navigation2->SetTransition(ui::PAGE_TRANSITION_LINK);
371 navigation2->SetAutoAdvance(false);
372
373 // Insert a TaskRunnerDeferringThrottle that will defer
374 // during WillProcessResponse() of navigation2.
375 auto task_runner = base::MakeRefCounted<base::TestSimpleTaskRunner>();
376 auto* raw_runner = task_runner.get();
377 TestNavigationThrottleInserter throttle_inserter(
378 web_contents(),
379 base::BindRepeating(&TaskRunnerDeferringThrottle::Create,
380 std::move(task_runner), false /* defer_start */,
381 false /* defer-redirect */,
382 true /* defer_response */));
383
384 navigation2->Start();
385 ASSERT_TRUE(node->navigation_request());
386 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
387
388 // Redirect navigation2 cross-site, which, once ReadyCommit()
389 // is called, will force a speculative RFHI to be created,
390 // and update the associated site instance type of the
391 // NavigationRequest for navigation2. This will prevent
392 // the abort of navigation1 from destroying the speculative
393 // RFHI that navigation2 depends on.
394 navigation2->Redirect(kUrl2);
395 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
Rakina Zata Amni8d4ed052022-12-07 23:03:30396 EXPECT_TRUE(node->navigation_request()->GetAssociatedRFHType() ==
Rakina Zata Amni7af54b12022-06-28 10:36:17397 NavigationRequest::AssociatedRenderFrameHostType::CURRENT);
Todd Sahlb2f798302021-01-21 16:32:07398
399 navigation2->ReadyToCommit();
400 EXPECT_EQ(1u, raw_runner->NumPendingTasks());
401 EXPECT_TRUE(navigation2->IsDeferred());
402 EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
Rakina Zata Amni8d4ed052022-12-07 23:03:30403 EXPECT_EQ(node->navigation_request()->GetRenderFrameHost(),
404 GetSpeculativeRenderFrameHost(node));
Todd Sahlb2f798302021-01-21 16:32:07405
406 // Abort the initial navigation.
407 navigation1->AbortFromRenderer();
408
409 // The speculative rfhi and second navigation request
410 // should be unaffected.
411 ASSERT_TRUE(node->navigation_request());
412 EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
413}
414
Arthur Hemery0dd65812019-08-01 14:18:45415// Tests that a beforeUnload denial cancels the navigation.
Camille Lamy07c49cdf2019-03-11 15:53:57416TEST_F(NavigatorTest, BeforeUnloadDenialCancelNavigation) {
carloske24d11782015-02-13 10:10:02417 const GURL kUrl1("http://www.google.com/");
418 const GURL kUrl2("http://www.chromium.org/");
419
420 contents()->NavigateAndCommit(kUrl1);
Minoru Chikamune99f1bf6d2025-02-19 05:34:19421 // This test assumes a beforeunload handler is present.
422 main_test_rfh()->SuddenTerminationDisablerChanged(
423 true, blink::mojom::SuddenTerminationDisablerType::kBeforeUnloadHandler);
carloske24d11782015-02-13 10:10:02424
425 // Start a new navigation.
426 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
Arthur Hemery56fb25c2019-02-08 17:55:13427 auto navigation =
428 NavigationSimulatorImpl::CreateBrowserInitiated(kUrl2, contents());
429 navigation->BrowserInitiatedStartAndWaitBeforeUnload();
clamydcb434c12015-04-16 19:29:16430 NavigationRequest* request = node->navigation_request();
carloske24d11782015-02-13 10:10:02431 ASSERT_TRUE(request);
432 EXPECT_TRUE(request->browser_initiated());
433 EXPECT_EQ(NavigationRequest::WAITING_FOR_RENDERER_RESPONSE, request->state());
carloskc49005eb2015-06-16 11:25:07434 EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
carloska0350db2015-07-30 20:10:57435 RenderFrameDeletedObserver rfh_deleted_observer(
436 GetSpeculativeRenderFrameHost(node));
carloske24d11782015-02-13 10:10:02437
438 // Simulate a beforeUnload denial.
Antonio Gomes8678a202020-03-02 20:03:25439 main_test_rfh()->SimulateBeforeUnloadCompleted(false);
clamydcb434c12015-04-16 19:29:16440 EXPECT_FALSE(node->navigation_request());
carloske24d11782015-02-13 10:10:02441 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
carloska0350db2015-07-30 20:10:57442 EXPECT_TRUE(rfh_deleted_observer.deleted());
carloske24d11782015-02-13 10:10:02443}
444
Arthur Hemery56fb25c2019-02-08 17:55:13445// Test that a proper NavigationRequest is created at navigation start.
Camille Lamy07c49cdf2019-03-11 15:53:57446TEST_F(NavigatorTest, BeginNavigation) {
clamy71a42ec2014-10-02 18:43:22447 const GURL kUrl1("http://www.google.com/");
448 const GURL kUrl2("http://www.chromium.org/");
449 const GURL kUrl3("http://www.gmail.com/");
clamy71a42ec2014-10-02 18:43:22450
clamy71a42ec2014-10-02 18:43:22451 contents()->NavigateAndCommit(kUrl1);
452
453 // Add a subframe.
Carlos Caballero15caeeb2021-10-27 09:57:55454 FrameTreeNode* root_node = contents()->GetPrimaryFrameTree().root();
carloskfdf32b52015-02-06 17:58:30455 TestRenderFrameHost* subframe_rfh = main_test_rfh()->AppendChild("Child");
carlosk39337112015-01-14 21:44:51456 ASSERT_TRUE(subframe_rfh);
Minoru Chikamune99f1bf6d2025-02-19 05:34:19457 // This test assumes a beforeunload handler is present on the subframe.
458 subframe_rfh->SuddenTerminationDisablerChanged(
459 true, blink::mojom::SuddenTerminationDisablerType::kBeforeUnloadHandler);
clamy71a42ec2014-10-02 18:43:22460
carloske24d11782015-02-13 10:10:02461 // Start a navigation at the subframe.
clamy71a42ec2014-10-02 18:43:22462 FrameTreeNode* subframe_node = subframe_rfh->frame_tree_node();
Arthur Hemery56fb25c2019-02-08 17:55:13463 auto navigation =
464 NavigationSimulatorImpl::CreateBrowserInitiated(kUrl2, contents());
465 NavigationController::LoadURLParams load_url_params(kUrl2);
466 load_url_params.frame_tree_node_id = subframe_node->frame_tree_node_id();
467 navigation->SetLoadURLParams(&load_url_params);
468 navigation->BrowserInitiatedStartAndWaitBeforeUnload();
clamydcb434c12015-04-16 19:29:16469 NavigationRequest* subframe_request = subframe_node->navigation_request();
clamy3f8ab9c2017-01-26 14:42:14470
jam40444982017-04-11 03:01:41471 // We should be waiting for the BeforeUnload event to execute in the subframe.
clamy3f8ab9c2017-01-26 14:42:14472 ASSERT_TRUE(subframe_request);
jam40444982017-04-11 03:01:41473 EXPECT_EQ(NavigationRequest::WAITING_FOR_RENDERER_RESPONSE,
474 subframe_request->state());
Antonio Gomes8678a202020-03-02 20:03:25475 EXPECT_TRUE(subframe_rfh->is_waiting_for_beforeunload_completion());
clamy3f8ab9c2017-01-26 14:42:14476
Arthur Hemery56fb25c2019-02-08 17:55:13477 // Start the navigation, which will internally simulate that the beforeUnload
Antonio Gomes8678a202020-03-02 20:03:25478 // completion callback has been invoked.
Arthur Hemery56fb25c2019-02-08 17:55:13479 navigation->Start();
davidben6b77cd72014-10-29 21:13:45480 TestNavigationURLLoader* subframe_loader =
481 GetLoaderForNavigationRequest(subframe_request);
carloske24d11782015-02-13 10:10:02482 ASSERT_TRUE(subframe_loader);
Mohamed Abdelhalimccd149af2019-10-31 14:48:53483 EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, subframe_request->state());
clamy71a42ec2014-10-02 18:43:22484 EXPECT_EQ(kUrl2, subframe_request->common_params().url);
Lucas Furukawa Gadanief8290a2019-07-29 20:27:51485 EXPECT_EQ(kUrl2, subframe_loader->request_info()->common_params->url);
Matt Menkea56c5992020-04-10 20:53:56486 EXPECT_TRUE(
Joshua Thomas81febb32025-06-17 18:16:32487 net::IsolationInfo::Create(
488 net::IsolationInfo::RequestType::kSubFrame,
489 url::Origin::Create(kUrl1), url::Origin::Create(kUrl2),
490 net::SiteForCookies::FromUrl(kUrl1), /*nonce=*/std::nullopt,
491 net::NetworkIsolationPartition::kGeneral,
492 net::IsolationInfo::FrameAncestorRelation::kSameOrigin)
Matt Menkea56c5992020-04-10 20:53:56493 .IsEqualForTesting(subframe_loader->request_info()->isolation_info));
Shivani Sharma8ae506c2019-07-21 21:08:27494
davidben6b77cd72014-10-29 21:13:45495 EXPECT_FALSE(subframe_loader->request_info()->is_main_frame);
carloske24d11782015-02-13 10:10:02496 EXPECT_TRUE(subframe_request->browser_initiated());
carlosk39337112015-01-14 21:44:51497 EXPECT_FALSE(GetSpeculativeRenderFrameHost(root_node));
clamy71a42ec2014-10-02 18:43:22498
carlosk39337112015-01-14 21:44:51499 // Subframe navigations should never create a speculative RenderFrameHost,
Sharon Yang6a61229f2025-02-11 17:56:54500 // unless site-per-process or another mode where a SiteInstance cannot contain
501 // multiple sites is enabled. In that case, as the subframe navigation is to a
502 // different site and is still ongoing, it should have one.
Aaron Colwell5fb878042020-12-17 19:48:44503 bool expect_site_instance_change = AreStrictSiteInstancesEnabled();
504 if (expect_site_instance_change) {
carlosk39337112015-01-14 21:44:51505 EXPECT_TRUE(GetSpeculativeRenderFrameHost(subframe_node));
506 } else {
507 EXPECT_FALSE(GetSpeculativeRenderFrameHost(subframe_node));
508 }
509
carloske24d11782015-02-13 10:10:02510 // Now start a navigation at the root node.
Arthur Hemery56fb25c2019-02-08 17:55:13511 auto navigation2 =
512 NavigationSimulatorImpl::CreateBrowserInitiated(kUrl3, contents());
513 navigation2->BrowserInitiatedStartAndWaitBeforeUnload();
clamydcb434c12015-04-16 19:29:16514 NavigationRequest* main_request = root_node->navigation_request();
carloske24d11782015-02-13 10:10:02515 ASSERT_TRUE(main_request);
jam40444982017-04-11 03:01:41516 EXPECT_EQ(NavigationRequest::WAITING_FOR_RENDERER_RESPONSE,
517 main_request->state());
carloskc49005eb2015-06-16 11:25:07518
519 // Main frame navigation to a different site should use a speculative
520 // RenderFrameHost.
521 EXPECT_TRUE(GetSpeculativeRenderFrameHost(root_node));
carloske24d11782015-02-13 10:10:02522
Arthur Hemery56fb25c2019-02-08 17:55:13523 // Start the navigation, which will internally simulate that the beforeUnload
Antonio Gomes8678a202020-03-02 20:03:25524 // completion callback has been invoked.
Arthur Hemery56fb25c2019-02-08 17:55:13525 navigation2->Start();
davidben6b77cd72014-10-29 21:13:45526 TestNavigationURLLoader* main_loader =
527 GetLoaderForNavigationRequest(main_request);
clamy71a42ec2014-10-02 18:43:22528 EXPECT_EQ(kUrl3, main_request->common_params().url);
Lucas Furukawa Gadanief8290a2019-07-29 20:27:51529 EXPECT_EQ(kUrl3, main_loader->request_info()->common_params->url);
Matt Menkea56c5992020-04-10 20:53:56530 EXPECT_TRUE(
Chris Fredricksone7ba5212023-09-26 14:54:42531 net::IsolationInfo::Create(net::IsolationInfo::RequestType::kMainFrame,
532 url::Origin::Create(kUrl3),
533 url::Origin::Create(kUrl3),
534 net::SiteForCookies::FromUrl(kUrl3))
Matt Menkea56c5992020-04-10 20:53:56535 .IsEqualForTesting(main_loader->request_info()->isolation_info));
davidben6b77cd72014-10-29 21:13:45536 EXPECT_TRUE(main_loader->request_info()->is_main_frame);
carloske24d11782015-02-13 10:10:02537 EXPECT_TRUE(main_request->browser_initiated());
Antonio Gomes8678a202020-03-02 20:03:25538 // BeforeUnloadCompleted callback was invoked by the renderer so the
539 // navigation should have started.
Mohamed Abdelhalimccd149af2019-10-31 14:48:53540 EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, main_request->state());
carlosk39337112015-01-14 21:44:51541 EXPECT_TRUE(GetSpeculativeRenderFrameHost(root_node));
542
543 // As the main frame hasn't yet committed the subframe still exists. Thus, the
544 // above situation regarding subframe navigations is valid here.
Aaron Colwell5fb878042020-12-17 19:48:44545 if (expect_site_instance_change) {
carlosk39337112015-01-14 21:44:51546 EXPECT_TRUE(GetSpeculativeRenderFrameHost(subframe_node));
547 } else {
548 EXPECT_FALSE(GetSpeculativeRenderFrameHost(subframe_node));
549 }
clamy71a42ec2014-10-02 18:43:22550}
551
Arthur Hemery0dd65812019-08-01 14:18:45552// Tests that committing an HTTP 204 or HTTP 205 response cancels
carlosk39337112015-01-14 21:44:51553// the navigation.
Camille Lamy07c49cdf2019-03-11 15:53:57554TEST_F(NavigatorTest, NoContent) {
davidben8b339132014-10-08 02:27:01555 const GURL kUrl1("http://www.chromium.org/");
556 const GURL kUrl2("http://www.google.com/");
557
558 // Load a URL.
559 contents()->NavigateAndCommit(kUrl1);
davidben8b339132014-10-08 02:27:01560 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
561
davidben8b339132014-10-08 02:27:01562 // Navigate to a different site.
Nasko Oskov2e9e0112020-12-22 21:34:43563 EXPECT_FALSE(node->navigation_request());
Arthur Hemery56fb25c2019-02-08 17:55:13564 auto navigation =
565 NavigationSimulator::CreateBrowserInitiated(kUrl2, contents());
566 navigation->Start();
carlosk39337112015-01-14 21:44:51567
clamydcb434c12015-04-16 19:29:16568 NavigationRequest* main_request = node->navigation_request();
davidben8b339132014-10-08 02:27:01569 ASSERT_TRUE(main_request);
570
carlosk39337112015-01-14 21:44:51571 // Navigations to a different site do create a speculative RenderFrameHost.
572 EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
573
davidben8b339132014-10-08 02:27:01574 // Commit an HTTP 204 response.
Lucas Furukawa Gadanid661c0d2019-12-02 19:58:16575 auto response = network::mojom::URLResponseHead::New();
davidben8b339132014-10-08 02:27:01576 const char kNoContentHeaders[] = "HTTP/1.1 204 No Content\0\0";
Lucas Furukawa Gadanid661c0d2019-12-02 19:58:16577 response->headers = new net::HttpResponseHeaders(
Daniel Chengad44af2f2022-02-26 18:07:54578 std::string(kNoContentHeaders, std::size(kNoContentHeaders)));
Lucas Furukawa Gadanid661c0d2019-12-02 19:58:16579 GetLoaderForNavigationRequest(main_request)
Alexander Timin66dab132021-09-23 14:36:04580 ->CallOnResponseStarted(std::move(response),
Leszek Swirski154cddb2022-08-29 17:57:19581 mojo::ScopedDataPipeConsumerHandle(),
Arthur Sonzognic686e8f2024-01-11 08:36:37582 std::nullopt);
davidben8b339132014-10-08 02:27:01583
carlosk39337112015-01-14 21:44:51584 // There should be no pending nor speculative RenderFrameHost; the navigation
585 // was aborted.
clamydcb434c12015-04-16 19:29:16586 EXPECT_FALSE(node->navigation_request());
carlosk39337112015-01-14 21:44:51587 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
davidben8b339132014-10-08 02:27:01588
589 // Now, repeat the test with 205 Reset Content.
590
591 // Navigate to a different site again.
Arthur Hemery56fb25c2019-02-08 17:55:13592 auto navigation2 =
593 NavigationSimulator::CreateBrowserInitiated(kUrl2, contents());
594 navigation2->Start();
carlosk39337112015-01-14 21:44:51595
clamydcb434c12015-04-16 19:29:16596 main_request = node->navigation_request();
davidben8b339132014-10-08 02:27:01597 ASSERT_TRUE(main_request);
carlosk39337112015-01-14 21:44:51598 EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
davidben8b339132014-10-08 02:27:01599
600 // Commit an HTTP 205 response.
Lucas Furukawa Gadanid661c0d2019-12-02 19:58:16601 response = network::mojom::URLResponseHead::New();
davidben8b339132014-10-08 02:27:01602 const char kResetContentHeaders[] = "HTTP/1.1 205 Reset Content\0\0";
Lucas Furukawa Gadanid661c0d2019-12-02 19:58:16603 response->headers = new net::HttpResponseHeaders(
Daniel Chengad44af2f2022-02-26 18:07:54604 std::string(kResetContentHeaders, std::size(kResetContentHeaders)));
Lucas Furukawa Gadanid661c0d2019-12-02 19:58:16605 GetLoaderForNavigationRequest(main_request)
Alexander Timin66dab132021-09-23 14:36:04606 ->CallOnResponseStarted(std::move(response),
Leszek Swirski154cddb2022-08-29 17:57:19607 mojo::ScopedDataPipeConsumerHandle(),
Arthur Sonzognic686e8f2024-01-11 08:36:37608 std::nullopt);
davidben8b339132014-10-08 02:27:01609
carlosk39337112015-01-14 21:44:51610 // There should be no pending nor speculative RenderFrameHost; the navigation
611 // was aborted.
clamydcb434c12015-04-16 19:29:16612 EXPECT_FALSE(node->navigation_request());
carlosk39337112015-01-14 21:44:51613 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
davidben8b339132014-10-08 02:27:01614}
615
arthursonzognif34adf092018-04-24 17:06:13616// Test that a new RenderFrameHost is created when doing a cross site
617// navigation.
Camille Lamy07c49cdf2019-03-11 15:53:57618TEST_F(NavigatorTest, CrossSiteNavigation) {
clamy71a42ec2014-10-02 18:43:22619 const GURL kUrl1("http://www.chromium.org/");
620 const GURL kUrl2("http://www.google.com/");
621
clamy71a42ec2014-10-02 18:43:22622 contents()->NavigateAndCommit(kUrl1);
carlosk39337112015-01-14 21:44:51623 RenderFrameHostImpl* initial_rfh = main_test_rfh();
clamy71a42ec2014-10-02 18:43:22624 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
625
626 // Navigate to a different site.
Arthur Hemery859f3462019-01-29 16:29:07627 EXPECT_EQ(main_test_rfh()->navigation_requests().size(), 0u);
628 auto navigation =
629 NavigationSimulator::CreateBrowserInitiated(kUrl2, contents());
630 navigation->Start();
clamydcb434c12015-04-16 19:29:16631 NavigationRequest* main_request = node->navigation_request();
clamy71a42ec2014-10-02 18:43:22632 ASSERT_TRUE(main_request);
carloskc49005eb2015-06-16 11:25:07633 TestRenderFrameHost* speculative_rfh = GetSpeculativeRenderFrameHost(node);
634 ASSERT_TRUE(speculative_rfh);
carloskc49005eb2015-06-16 11:25:07635 EXPECT_EQ(speculative_rfh, GetSpeculativeRenderFrameHost(node));
clamy71a42ec2014-10-02 18:43:22636
Arthur Hemery859f3462019-01-29 16:29:07637 navigation->ReadyToCommit();
carloskc49005eb2015-06-16 11:25:07638 EXPECT_EQ(speculative_rfh, GetSpeculativeRenderFrameHost(node));
Arthur Hemery859f3462019-01-29 16:29:07639 EXPECT_EQ(speculative_rfh->navigation_requests().size(), 1u);
640 EXPECT_EQ(main_test_rfh()->navigation_requests().size(), 0u);
carlosk39337112015-01-14 21:44:51641
Arthur Hemery859f3462019-01-29 16:29:07642 navigation->Commit();
carlosk39337112015-01-14 21:44:51643 RenderFrameHostImpl* final_rfh = main_test_rfh();
644 EXPECT_EQ(speculative_rfh, final_rfh);
645 EXPECT_NE(initial_rfh, final_rfh);
646 EXPECT_TRUE(final_rfh->IsRenderFrameLive());
647 EXPECT_TRUE(final_rfh->render_view_host()->IsRenderViewLive());
648 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
davidben6b77cd72014-10-29 21:13:45649}
650
arthursonzognif34adf092018-04-24 17:06:13651// Test that redirects are followed and the speculative RenderFrameHost logic
652// behaves as expected.
Camille Lamy07c49cdf2019-03-11 15:53:57653TEST_F(NavigatorTest, RedirectCrossSite) {
davidben6b77cd72014-10-29 21:13:45654 const GURL kUrl1("http://www.chromium.org/");
655 const GURL kUrl2("http://www.google.com/");
656
657 contents()->NavigateAndCommit(kUrl1);
658 RenderFrameHostImpl* rfh = main_test_rfh();
davidben6b77cd72014-10-29 21:13:45659 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
660
davidben6b77cd72014-10-29 21:13:45661 // Navigate to a URL on the same site.
Arthur Hemery859f3462019-01-29 16:29:07662 EXPECT_EQ(main_test_rfh()->navigation_requests().size(), 0u);
663 auto navigation =
664 NavigationSimulator::CreateBrowserInitiated(kUrl1, contents());
665 navigation->Start();
clamydcb434c12015-04-16 19:29:16666 NavigationRequest* main_request = node->navigation_request();
davidben6b77cd72014-10-29 21:13:45667 ASSERT_TRUE(main_request);
Rakina Zata Amnidfcab2e52023-08-26 07:11:59668 if (ShouldCreateNewHostForAllFrames()) {
669 EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
670 } else {
671 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
672 }
davidben6b77cd72014-10-29 21:13:45673
674 // It then redirects to another site.
Arthur Hemery859f3462019-01-29 16:29:07675 navigation->Redirect(kUrl2);
davidben6b77cd72014-10-29 21:13:45676
677 // The redirect should have been followed.
678 EXPECT_EQ(1, GetLoaderForNavigationRequest(main_request)->redirect_count());
Rakina Zata Amnidfcab2e52023-08-26 07:11:59679 if (ShouldCreateNewHostForAllFrames()) {
680 EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
681 } else {
682 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
683 }
davidben6b77cd72014-10-29 21:13:45684
Arthur Hemery859f3462019-01-29 16:29:07685 navigation->ReadyToCommit();
carlosk39337112015-01-14 21:44:51686 TestRenderFrameHost* final_speculative_rfh =
687 GetSpeculativeRenderFrameHost(node);
688 EXPECT_TRUE(final_speculative_rfh);
Arthur Hemery859f3462019-01-29 16:29:07689 EXPECT_EQ(final_speculative_rfh->navigation_requests().size(), 1u);
carlosk39337112015-01-14 21:44:51690
Arthur Hemery859f3462019-01-29 16:29:07691 navigation->Commit();
carlosk39337112015-01-14 21:44:51692 RenderFrameHostImpl* final_rfh = main_test_rfh();
693 ASSERT_TRUE(final_rfh);
694 EXPECT_NE(rfh, final_rfh);
695 EXPECT_EQ(final_speculative_rfh, final_rfh);
696 EXPECT_TRUE(final_rfh->IsRenderFrameLive());
697 EXPECT_TRUE(final_rfh->render_view_host()->IsRenderViewLive());
698 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
clamy71a42ec2014-10-02 18:43:22699}
700
arthursonzognif34adf092018-04-24 17:06:13701// Test that a navigation is canceled if another browser-initiated request has
702// been issued in the meantime. Also confirms that the speculative
carloske24d11782015-02-13 10:10:02703// RenderFrameHost is correctly updated in the process.
Camille Lamy07c49cdf2019-03-11 15:53:57704TEST_F(NavigatorTest, BrowserInitiatedNavigationCancel) {
clamy71a42ec2014-10-02 18:43:22705 const GURL kUrl0("http://www.wikipedia.org/");
clamy71a42ec2014-10-02 18:43:22706 const GURL kUrl1("http://www.chromium.org/");
Aaron Colwell91e32b12021-02-17 01:40:56707 const auto kUrl1SiteInfo = CreateExpectedSiteInfo(kUrl1);
clamy71a42ec2014-10-02 18:43:22708 const GURL kUrl2("http://www.google.com/");
Aaron Colwell91e32b12021-02-17 01:40:56709 const auto kUrl2SiteInfo = CreateExpectedSiteInfo(kUrl2);
clamy71a42ec2014-10-02 18:43:22710
711 // Initialization.
712 contents()->NavigateAndCommit(kUrl0);
713 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
clamy71a42ec2014-10-02 18:43:22714
davidbena5496d62014-10-07 18:52:04715 // Request navigation to the 1st URL.
Nasko Oskov2e9e0112020-12-22 21:34:43716 EXPECT_FALSE(node->navigation_request());
Arthur Hemery859f3462019-01-29 16:29:07717 auto navigation1 =
718 NavigationSimulator::CreateBrowserInitiated(kUrl1, contents());
719 navigation1->Start();
clamydcb434c12015-04-16 19:29:16720 NavigationRequest* request1 = node->navigation_request();
clamy71a42ec2014-10-02 18:43:22721 ASSERT_TRUE(request1);
davidbena5496d62014-10-07 18:52:04722 EXPECT_EQ(kUrl1, request1->common_params().url);
carloske24d11782015-02-13 10:10:02723 EXPECT_TRUE(request1->browser_initiated());
davidben6b77cd72014-10-29 21:13:45724 base::WeakPtr<TestNavigationURLLoader> loader1 =
725 GetLoaderForNavigationRequest(request1)->AsWeakPtr();
carloskf4707892015-02-19 18:47:40726 EXPECT_TRUE(loader1);
clamy71a42ec2014-10-02 18:43:22727
carloskf4707892015-02-19 18:47:40728 // Confirm a speculative RenderFrameHost was created.
carlosk39337112015-01-14 21:44:51729 TestRenderFrameHost* speculative_rfh = GetSpeculativeRenderFrameHost(node);
730 ASSERT_TRUE(speculative_rfh);
Lukasz Anforowicz1de0a222021-07-26 22:02:32731 auto site_instance_id_1 = speculative_rfh->GetSiteInstance()->GetId();
Sharon Yang47453bb2025-04-25 14:48:09732 if (AreStrictSiteInstancesEnabled()) {
Aaron Colwell91e32b12021-02-17 01:40:56733 EXPECT_EQ(kUrl1SiteInfo, speculative_rfh->GetSiteInstance()->GetSiteInfo());
Sharon Yang02279222025-01-15 19:09:19734 } else {
735 EXPECT_TRUE(speculative_rfh->GetSiteInstance()->IsDefaultSiteInstance());
Aaron Colwellf45e3a852019-06-06 00:48:27736 }
carlosk39337112015-01-14 21:44:51737
davidbena5496d62014-10-07 18:52:04738 // Request navigation to the 2nd URL; the NavigationRequest must have been
739 // replaced by a new one with a different URL.
Arthur Hemery859f3462019-01-29 16:29:07740 auto navigation2 =
741 NavigationSimulator::CreateBrowserInitiated(kUrl2, contents());
742 navigation2->Start();
clamydcb434c12015-04-16 19:29:16743 NavigationRequest* request2 = node->navigation_request();
clamy71a42ec2014-10-02 18:43:22744 ASSERT_TRUE(request2);
davidbena5496d62014-10-07 18:52:04745 EXPECT_EQ(kUrl2, request2->common_params().url);
carloske24d11782015-02-13 10:10:02746 EXPECT_TRUE(request2->browser_initiated());
clamy71a42ec2014-10-02 18:43:22747
davidben6b77cd72014-10-29 21:13:45748 // Confirm that the first loader got destroyed.
749 EXPECT_FALSE(loader1);
750
carloskf4707892015-02-19 18:47:40751 // Confirm that a new speculative RenderFrameHost was created.
carlosk39337112015-01-14 21:44:51752 speculative_rfh = GetSpeculativeRenderFrameHost(node);
753 ASSERT_TRUE(speculative_rfh);
Lukasz Anforowicz1de0a222021-07-26 22:02:32754 auto site_instance_id_2 = speculative_rfh->GetSiteInstance()->GetId();
Aaron Colwellf45e3a852019-06-06 00:48:27755
Sharon Yang47453bb2025-04-25 14:48:09756 if (AreStrictSiteInstancesEnabled()) {
Sharon Yang02279222025-01-15 19:09:19757 EXPECT_NE(site_instance_id_1, site_instance_id_2);
758 } else {
Aaron Colwellf45e3a852019-06-06 00:48:27759 EXPECT_TRUE(speculative_rfh->GetSiteInstance()->IsDefaultSiteInstance());
760 EXPECT_EQ(site_instance_id_1, site_instance_id_2);
Aaron Colwellf45e3a852019-06-06 00:48:27761 }
carlosk39337112015-01-14 21:44:51762
Arthur Hemery859f3462019-01-29 16:29:07763 navigation2->ReadyToCommit();
764 EXPECT_EQ(speculative_rfh->navigation_requests().size(), 1u);
765 EXPECT_EQ(main_test_rfh()->navigation_requests().size(), 0u);
766
carloskf4707892015-02-19 18:47:40767 // Have the RenderFrameHost commit the navigation.
Arthur Hemery859f3462019-01-29 16:29:07768 navigation2->Commit();
carlosk39337112015-01-14 21:44:51769
770 // Confirm that the commit corresponds to the new request.
771 ASSERT_TRUE(main_test_rfh());
Sharon Yang47453bb2025-04-25 14:48:09772 if (AreStrictSiteInstancesEnabled()) {
Aaron Colwell91e32b12021-02-17 01:40:56773 EXPECT_EQ(kUrl2SiteInfo, main_test_rfh()->GetSiteInstance()->GetSiteInfo());
Sharon Yang02279222025-01-15 19:09:19774 } else {
775 EXPECT_TRUE(main_test_rfh()->GetSiteInstance()->IsDefaultSiteInstance());
Aaron Colwellf45e3a852019-06-06 00:48:27776 }
carlosk39337112015-01-14 21:44:51777 EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL());
778
carloskf4707892015-02-19 18:47:40779 // Confirm that the committed RenderFrameHost is the latest speculative one.
carlosk39337112015-01-14 21:44:51780 EXPECT_EQ(site_instance_id_2, main_test_rfh()->GetSiteInstance()->GetId());
clamy71a42ec2014-10-02 18:43:22781}
782
arthursonzognif34adf092018-04-24 17:06:13783// Test that a browser-initiated navigation is canceled if a renderer-initiated
784// user-initiated request has been issued in the meantime.
Camille Lamy07c49cdf2019-03-11 15:53:57785TEST_F(NavigatorTest, RendererUserInitiatedNavigationCancel) {
carloskf4707892015-02-19 18:47:40786 const GURL kUrl0("http://www.wikipedia.org/");
787 const GURL kUrl1("http://www.chromium.org/");
788 const GURL kUrl2("http://www.google.com/");
789
790 // Initialization.
791 contents()->NavigateAndCommit(kUrl0);
792 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
Aaron Colwell5fb878042020-12-17 19:48:44793 bool expect_site_instance_change =
794 ExpectSiteInstanceChange(main_test_rfh()->GetSiteInstance());
carloskf4707892015-02-19 18:47:40795
Antonio Gomes8678a202020-03-02 20:03:25796 // Start a browser-initiated navigation to the 1st URL and invoke its
797 // beforeUnload completion callback.
Nasko Oskov2e9e0112020-12-22 21:34:43798 EXPECT_FALSE(node->navigation_request());
Arthur Hemery56fb25c2019-02-08 17:55:13799 auto navigation2 =
800 NavigationSimulator::CreateBrowserInitiated(kUrl1, contents());
801 navigation2->Start();
clamydcb434c12015-04-16 19:29:16802 NavigationRequest* request1 = node->navigation_request();
carloskf4707892015-02-19 18:47:40803 ASSERT_TRUE(request1);
804 EXPECT_EQ(kUrl1, request1->common_params().url);
805 EXPECT_TRUE(request1->browser_initiated());
806 base::WeakPtr<TestNavigationURLLoader> loader1 =
807 GetLoaderForNavigationRequest(request1)->AsWeakPtr();
808 EXPECT_TRUE(loader1);
809
carlosk42f59e62015-03-16 19:02:36810 // Confirm that a speculative RenderFrameHost was created.
811 ASSERT_TRUE(GetSpeculativeRenderFrameHost(node));
carloskf4707892015-02-19 18:47:40812
813 // Now receive a renderer-initiated user-initiated request. It should replace
814 // the current NavigationRequest.
arthursonzogni91439432017-08-16 16:32:37815 auto navigation =
816 NavigationSimulator::CreateRendererInitiated(kUrl2, main_test_rfh());
817 navigation->SetTransition(ui::PAGE_TRANSITION_LINK);
818 navigation->SetHasUserGesture(true);
819 navigation->Start();
clamydcb434c12015-04-16 19:29:16820 NavigationRequest* request2 = node->navigation_request();
carloskf4707892015-02-19 18:47:40821 ASSERT_TRUE(request2);
822 EXPECT_EQ(kUrl2, request2->common_params().url);
823 EXPECT_FALSE(request2->browser_initiated());
Arthur Hemery14a71ad22017-10-27 10:54:39824 EXPECT_TRUE(request2->common_params().has_user_gesture);
carloskf4707892015-02-19 18:47:40825
826 // Confirm that the first loader got destroyed.
827 EXPECT_FALSE(loader1);
828
clamy61dfb232016-02-26 18:08:49829 // Confirm that the speculative RenderFrameHost was destroyed in the non
830 // SitePerProcess case.
Aaron Colwell5fb878042020-12-17 19:48:44831 if (expect_site_instance_change) {
clamy61dfb232016-02-26 18:08:49832 EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
833 } else {
834 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
835 }
carloskf4707892015-02-19 18:47:40836
carloskf4707892015-02-19 18:47:40837 // Commit the navigation.
arthursonzogni91439432017-08-16 16:32:37838 navigation->Commit();
carloskf4707892015-02-19 18:47:40839
840 // Confirm that the commit corresponds to the new request.
841 ASSERT_TRUE(main_test_rfh());
842 EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL());
carloskf4707892015-02-19 18:47:40843}
844
Arthur Hemery0dd65812019-08-01 14:18:45845// Tests that a renderer-initiated user-initiated navigation is
carloskf4707892015-02-19 18:47:40846// canceled if a renderer-initiated non-user-initiated request is issued in the
847// meantime.
Camille Lamy07c49cdf2019-03-11 15:53:57848TEST_F(NavigatorTest,
Nasko Oskov6cbfad52017-08-17 11:31:01849 RendererNonUserInitiatedNavigationCancelsRendererUserInitiated) {
carloskf4707892015-02-19 18:47:40850 const GURL kUrl0("http://www.wikipedia.org/");
851 const GURL kUrl1("http://www.chromium.org/");
852 const GURL kUrl2("http://www.google.com/");
853
854 // Initialization.
855 contents()->NavigateAndCommit(kUrl0);
856 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
Aaron Colwell5fb878042020-12-17 19:48:44857 bool expect_site_instance_change =
858 ExpectSiteInstanceChange(main_test_rfh()->GetSiteInstance());
carloskf4707892015-02-19 18:47:40859
860 // Start a renderer-initiated user-initiated navigation to the 1st URL.
Nasko Oskov2e9e0112020-12-22 21:34:43861 EXPECT_FALSE(node->navigation_request());
arthursonzogni91439432017-08-16 16:32:37862 auto user_initiated_navigation =
863 NavigationSimulator::CreateRendererInitiated(kUrl1, main_test_rfh());
864 user_initiated_navigation->SetTransition(ui::PAGE_TRANSITION_LINK);
865 user_initiated_navigation->SetHasUserGesture(true);
866 user_initiated_navigation->Start();
clamydcb434c12015-04-16 19:29:16867 NavigationRequest* request1 = node->navigation_request();
carloskf4707892015-02-19 18:47:40868 ASSERT_TRUE(request1);
869 EXPECT_EQ(kUrl1, request1->common_params().url);
870 EXPECT_FALSE(request1->browser_initiated());
Arthur Hemery14a71ad22017-10-27 10:54:39871 EXPECT_TRUE(request1->common_params().has_user_gesture);
Aaron Colwell5fb878042020-12-17 19:48:44872 if (expect_site_instance_change) {
clamy61dfb232016-02-26 18:08:49873 EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
874 } else {
875 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
876 }
carloskf4707892015-02-19 18:47:40877
Nasko Oskov6cbfad52017-08-17 11:31:01878 // Now receive a renderer-initiated non-user-initiated request. The previous
879 // navigation should be replaced.
880 auto non_user_initiated_navigation =
881 NavigationSimulator::CreateRendererInitiated(kUrl2, main_test_rfh());
882 non_user_initiated_navigation->SetTransition(ui::PAGE_TRANSITION_LINK);
883 non_user_initiated_navigation->SetHasUserGesture(false);
884 non_user_initiated_navigation->Start();
885
clamydcb434c12015-04-16 19:29:16886 NavigationRequest* request2 = node->navigation_request();
carloskf4707892015-02-19 18:47:40887 ASSERT_TRUE(request2);
Nasko Oskov6cbfad52017-08-17 11:31:01888 EXPECT_NE(request1, request2);
889 EXPECT_EQ(kUrl2, request2->common_params().url);
carloskf4707892015-02-19 18:47:40890 EXPECT_FALSE(request2->browser_initiated());
Arthur Hemery14a71ad22017-10-27 10:54:39891 EXPECT_FALSE(request2->common_params().has_user_gesture);
Aaron Colwell5fb878042020-12-17 19:48:44892 if (expect_site_instance_change) {
clamy61dfb232016-02-26 18:08:49893 EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
894 } else {
895 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
896 }
carloskf4707892015-02-19 18:47:40897
carloskf4707892015-02-19 18:47:40898 // Commit the navigation.
Nasko Oskov6cbfad52017-08-17 11:31:01899 non_user_initiated_navigation->Commit();
900 EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL());
carloskf4707892015-02-19 18:47:40901}
902
903// PlzNavigate: Test that a browser-initiated navigation is NOT canceled if a
904// renderer-initiated non-user-initiated request is issued in the meantime.
Camille Lamy07c49cdf2019-03-11 15:53:57905TEST_F(NavigatorTest,
carloskf4707892015-02-19 18:47:40906 RendererNonUserInitiatedNavigationDoesntCancelBrowserInitiated) {
907 const GURL kUrl0("http://www.wikipedia.org/");
908 const GURL kUrl1("http://www.chromium.org/");
909 const GURL kUrl2("http://www.google.com/");
910
911 // Initialization.
912 contents()->NavigateAndCommit(kUrl0);
913 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
914
915 // Start a browser-initiated navigation to the 1st URL.
Nasko Oskov2e9e0112020-12-22 21:34:43916 EXPECT_FALSE(node->navigation_request());
Arthur Hemery859f3462019-01-29 16:29:07917 auto navigation =
918 NavigationSimulator::CreateBrowserInitiated(kUrl1, contents());
919 navigation->Start();
clamydcb434c12015-04-16 19:29:16920 NavigationRequest* request1 = node->navigation_request();
carloskf4707892015-02-19 18:47:40921 ASSERT_TRUE(request1);
922 EXPECT_EQ(kUrl1, request1->common_params().url);
923 EXPECT_TRUE(request1->browser_initiated());
Arthur Hemery859f3462019-01-29 16:29:07924 TestRenderFrameHost* speculative_rfh = GetSpeculativeRenderFrameHost(node);
925 ASSERT_TRUE(speculative_rfh);
carloskf4707892015-02-19 18:47:40926
927 // Now receive a renderer-initiated non-user-initiated request. Nothing should
928 // change.
Arthur Hemery7b67a972017-12-01 15:24:49929 main_test_rfh()->SendRendererInitiatedNavigationRequest(
930 kUrl2, false /* has_user_gesture */);
clamydcb434c12015-04-16 19:29:16931 NavigationRequest* request2 = node->navigation_request();
carloskf4707892015-02-19 18:47:40932 ASSERT_TRUE(request2);
933 EXPECT_EQ(request1, request2);
934 EXPECT_EQ(kUrl1, request2->common_params().url);
935 EXPECT_TRUE(request2->browser_initiated());
Arthur Hemery859f3462019-01-29 16:29:07936 EXPECT_TRUE(speculative_rfh);
carloskf4707892015-02-19 18:47:40937
Arthur Hemery859f3462019-01-29 16:29:07938 navigation->ReadyToCommit();
939 EXPECT_EQ(speculative_rfh->navigation_requests().size(), 1u);
940 EXPECT_EQ(main_test_rfh()->navigation_requests().size(), 0u);
carloskf4707892015-02-19 18:47:40941
Arthur Hemery859f3462019-01-29 16:29:07942 navigation->Commit();
carloskf4707892015-02-19 18:47:40943 EXPECT_EQ(kUrl1, contents()->GetLastCommittedURL());
944}
945
946// PlzNavigate: Test that a renderer-initiated non-user-initiated navigation is
947// canceled if a another similar request is issued in the meantime.
Camille Lamy07c49cdf2019-03-11 15:53:57948TEST_F(NavigatorTest,
carloskf4707892015-02-19 18:47:40949 RendererNonUserInitiatedNavigationCancelSimilarNavigation) {
950 const GURL kUrl0("http://www.wikipedia.org/");
951 const GURL kUrl1("http://www.chromium.org/");
952 const GURL kUrl2("http://www.google.com/");
953
954 // Initialization.
955 contents()->NavigateAndCommit(kUrl0);
956 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
Lukasz Anforowicz1de0a222021-07-26 22:02:32957 auto site_instance_id_0 = main_test_rfh()->GetSiteInstance()->GetId();
Aaron Colwell5fb878042020-12-17 19:48:44958 bool expect_site_instance_change =
959 ExpectSiteInstanceChange(main_test_rfh()->GetSiteInstance());
carloskf4707892015-02-19 18:47:40960
961 // Start a renderer-initiated non-user-initiated navigation to the 1st URL.
Nasko Oskov2e9e0112020-12-22 21:34:43962 EXPECT_FALSE(node->navigation_request());
arthursonzogni91439432017-08-16 16:32:37963 auto navigation1 =
964 NavigationSimulator::CreateRendererInitiated(kUrl1, main_test_rfh());
965 navigation1->SetTransition(ui::PageTransitionFromInt(
966 ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_CLIENT_REDIRECT));
967 navigation1->SetHasUserGesture(false);
968 navigation1->Start();
clamydcb434c12015-04-16 19:29:16969 NavigationRequest* request1 = node->navigation_request();
carloskf4707892015-02-19 18:47:40970 ASSERT_TRUE(request1);
971 EXPECT_EQ(kUrl1, request1->common_params().url);
972 EXPECT_FALSE(request1->browser_initiated());
Arthur Hemery14a71ad22017-10-27 10:54:39973 EXPECT_FALSE(request1->common_params().has_user_gesture);
Aaron Colwell5fb878042020-12-17 19:48:44974 if (expect_site_instance_change) {
clamy61dfb232016-02-26 18:08:49975 EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
976 } else {
977 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
978 }
carloskf4707892015-02-19 18:47:40979 base::WeakPtr<TestNavigationURLLoader> loader1 =
980 GetLoaderForNavigationRequest(request1)->AsWeakPtr();
981 EXPECT_TRUE(loader1);
982
983 // Now receive a 2nd similar request that should replace the current one.
arthursonzogni91439432017-08-16 16:32:37984 auto navigation2 =
985 NavigationSimulator::CreateRendererInitiated(kUrl2, main_test_rfh());
986 navigation2->SetTransition(ui::PageTransitionFromInt(
987 ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_CLIENT_REDIRECT));
988 navigation2->SetHasUserGesture(false);
989 navigation2->Start();
clamydcb434c12015-04-16 19:29:16990 NavigationRequest* request2 = node->navigation_request();
carloskf4707892015-02-19 18:47:40991 EXPECT_EQ(kUrl2, request2->common_params().url);
992 EXPECT_FALSE(request2->browser_initiated());
Arthur Hemery14a71ad22017-10-27 10:54:39993 EXPECT_FALSE(request2->common_params().has_user_gesture);
Aaron Colwell5fb878042020-12-17 19:48:44994 if (expect_site_instance_change) {
clamy61dfb232016-02-26 18:08:49995 EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
996 } else {
997 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
998 }
carloskf4707892015-02-19 18:47:40999
1000 // Confirm that the first loader got destroyed.
1001 EXPECT_FALSE(loader1);
1002
carloskf4707892015-02-19 18:47:401003 // Commit the navigation.
arthursonzogni91439432017-08-16 16:32:371004 navigation2->Commit();
carloskf4707892015-02-19 18:47:401005 EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL());
carlosk42f59e62015-03-16 19:02:361006
Aaron Colwell5fb878042020-12-17 19:48:441007 if (expect_site_instance_change) {
arthursonzogni91439432017-08-16 16:32:371008 EXPECT_NE(site_instance_id_0, main_test_rfh()->GetSiteInstance()->GetId());
1009 } else {
1010 EXPECT_EQ(site_instance_id_0, main_test_rfh()->GetSiteInstance()->GetId());
1011 }
carloskf4707892015-02-19 18:47:401012}
1013
clamy71a42ec2014-10-02 18:43:221014// PlzNavigate: Test that a reload navigation is properly signaled to the
carlosk39337112015-01-14 21:44:511015// RenderFrame when the navigation can commit. A speculative RenderFrameHost
Rakina Zata Amnidfcab2e52023-08-26 07:11:591016// should not be created at any step, unless RenderDocument is enabled.
Camille Lamy07c49cdf2019-03-11 15:53:571017TEST_F(NavigatorTest, Reload) {
clamy71a42ec2014-10-02 18:43:221018 const GURL kUrl("http://www.google.com/");
1019 contents()->NavigateAndCommit(kUrl);
1020
clamy71a42ec2014-10-02 18:43:221021 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
toyoshim6142d96f2016-12-19 09:07:251022 controller().Reload(ReloadType::NORMAL, false);
Matt Falkenhagen197a3b6a2021-09-29 18:24:031023 auto reload1 =
1024 NavigationSimulator::CreateFromPending(contents()->GetController());
clamy71a42ec2014-10-02 18:43:221025 // A NavigationRequest should have been generated.
clamydcb434c12015-04-16 19:29:161026 NavigationRequest* main_request = node->navigation_request();
Ivan Kotenkov2c0d2bb32017-11-01 15:41:281027 ASSERT_TRUE(main_request != nullptr);
Minggang Wangb9f3fa92021-07-01 15:30:311028 EXPECT_EQ(blink::mojom::NavigationType::RELOAD,
toyoshim980f1172016-12-02 08:15:531029 main_request->common_params().navigation_type);
Camille Lamy07c49cdf2019-03-11 15:53:571030 reload1->ReadyToCommit();
Rakina Zata Amnidfcab2e52023-08-26 07:11:591031 if (ShouldCreateNewHostForAllFrames()) {
1032 EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
1033 } else {
1034 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
1035 }
carlosk39337112015-01-14 21:44:511036
Camille Lamy07c49cdf2019-03-11 15:53:571037 reload1->Commit();
carlosk39337112015-01-14 21:44:511038 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
clamy71a42ec2014-10-02 18:43:221039
1040 // Now do a shift+reload.
toyoshim6142d96f2016-12-19 09:07:251041 controller().Reload(ReloadType::BYPASSING_CACHE, false);
Matt Falkenhagen197a3b6a2021-09-29 18:24:031042 auto reload2 =
1043 NavigationSimulator::CreateFromPending(contents()->GetController());
clamy71a42ec2014-10-02 18:43:221044 // A NavigationRequest should have been generated.
clamydcb434c12015-04-16 19:29:161045 main_request = node->navigation_request();
Ivan Kotenkov2c0d2bb32017-11-01 15:41:281046 ASSERT_TRUE(main_request != nullptr);
Minggang Wangb9f3fa92021-07-01 15:30:311047 EXPECT_EQ(blink::mojom::NavigationType::RELOAD_BYPASSING_CACHE,
clamy71a42ec2014-10-02 18:43:221048 main_request->common_params().navigation_type);
Camille Lamy07c49cdf2019-03-11 15:53:571049 reload2->ReadyToCommit();
Rakina Zata Amnidfcab2e52023-08-26 07:11:591050 if (ShouldCreateNewHostForAllFrames()) {
1051 EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
1052 } else {
1053 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
1054 }
carlosk39337112015-01-14 21:44:511055}
1056
1057// PlzNavigate: Confirm that a speculative RenderFrameHost is used when
1058// navigating from one site to another.
Camille Lamy07c49cdf2019-03-11 15:53:571059TEST_F(NavigatorTest, SpeculativeRendererWorksBaseCase) {
carlosk39337112015-01-14 21:44:511060 // Navigate to an initial site.
1061 const GURL kUrlInit("http://wikipedia.org/");
1062 contents()->NavigateAndCommit(kUrlInit);
1063 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
1064
1065 // Begin navigating to another site.
1066 const GURL kUrl("http://google.com/");
Nasko Oskov2e9e0112020-12-22 21:34:431067 EXPECT_FALSE(node->navigation_request());
Arthur Hemery859f3462019-01-29 16:29:071068 auto navigation =
1069 NavigationSimulator::CreateBrowserInitiated(kUrl, contents());
1070 navigation->Start();
carlosk39337112015-01-14 21:44:511071 TestRenderFrameHost* speculative_rfh = GetSpeculativeRenderFrameHost(node);
Lukasz Anforowicz1de0a222021-07-26 22:02:321072 auto site_instance_id = speculative_rfh->GetSiteInstance()->GetId();
carlosk39337112015-01-14 21:44:511073 ASSERT_TRUE(speculative_rfh);
1074 EXPECT_NE(speculative_rfh, main_test_rfh());
Sharon Yang47453bb2025-04-25 14:48:091075 if (AreStrictSiteInstancesEnabled()) {
Aaron Colwell91e32b12021-02-17 01:40:561076 EXPECT_EQ(CreateExpectedSiteInfo(kUrl),
1077 speculative_rfh->GetSiteInstance()->GetSiteInfo());
Sharon Yang02279222025-01-15 19:09:191078 } else {
1079 EXPECT_TRUE(speculative_rfh->GetSiteInstance()->IsDefaultSiteInstance());
Aaron Colwellf45e3a852019-06-06 00:48:271080 }
carlosk39337112015-01-14 21:44:511081
Arthur Hemery859f3462019-01-29 16:29:071082 navigation->ReadyToCommit();
1083 EXPECT_EQ(speculative_rfh->navigation_requests().size(), 1u);
carlosk39337112015-01-14 21:44:511084
Arthur Hemery859f3462019-01-29 16:29:071085 // Ask the navigation to commit.
1086 navigation->Commit();
carlosk39337112015-01-14 21:44:511087 EXPECT_EQ(site_instance_id, main_test_rfh()->GetSiteInstance()->GetId());
1088 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
carlosk39337112015-01-14 21:44:511089}
1090
1091// PlzNavigate: Confirm that a speculative RenderFrameHost is thrown away when
1092// the final URL's site differs from the initial one due to redirects.
Camille Lamy07c49cdf2019-03-11 15:53:571093TEST_F(NavigatorTest, SpeculativeRendererDiscardedAfterRedirectToAnotherSite) {
carlosk39337112015-01-14 21:44:511094 // Navigate to an initial site.
1095 const GURL kUrlInit("http://wikipedia.org/");
1096 contents()->NavigateAndCommit(kUrlInit);
1097 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
Lukasz Anforowicz1de0a222021-07-26 22:02:321098 auto init_site_instance_id = main_test_rfh()->GetSiteInstance()->GetId();
carlosk39337112015-01-14 21:44:511099
1100 // Begin navigating to another site.
1101 const GURL kUrl("http://google.com/");
Nasko Oskov2e9e0112020-12-22 21:34:431102 EXPECT_FALSE(node->navigation_request());
Arthur Hemery859f3462019-01-29 16:29:071103 auto navigation =
1104 NavigationSimulator::CreateBrowserInitiated(kUrl, contents());
1105 navigation->Start();
1106
carlosk39337112015-01-14 21:44:511107 TestRenderFrameHost* speculative_rfh = GetSpeculativeRenderFrameHost(node);
carloskc49005eb2015-06-16 11:25:071108 ASSERT_TRUE(speculative_rfh);
Lukasz Anforowicz1de0a222021-07-26 22:02:321109 auto site_instance_id = speculative_rfh->GetSiteInstance()->GetId();
carloska0350db2015-07-30 20:10:571110 RenderFrameDeletedObserver rfh_deleted_observer(speculative_rfh);
carlosk39337112015-01-14 21:44:511111 EXPECT_NE(init_site_instance_id, site_instance_id);
1112 EXPECT_EQ(init_site_instance_id, main_test_rfh()->GetSiteInstance()->GetId());
carlosk39337112015-01-14 21:44:511113 EXPECT_NE(speculative_rfh, main_test_rfh());
Aaron Colwellf45e3a852019-06-06 00:48:271114
Sharon Yang47453bb2025-04-25 14:48:091115 if (AreStrictSiteInstancesEnabled()) {
Aaron Colwell91e32b12021-02-17 01:40:561116 EXPECT_EQ(CreateExpectedSiteInfo(kUrl),
1117 speculative_rfh->GetSiteInstance()->GetSiteInfo());
Sharon Yang02279222025-01-15 19:09:191118 } else {
1119 EXPECT_TRUE(speculative_rfh->GetSiteInstance()->IsDefaultSiteInstance());
Aaron Colwellf45e3a852019-06-06 00:48:271120 }
carlosk39337112015-01-14 21:44:511121
1122 // It then redirects to yet another site.
clamydcb434c12015-04-16 19:29:161123 NavigationRequest* main_request = node->navigation_request();
carlosk39337112015-01-14 21:44:511124 ASSERT_TRUE(main_request);
1125 const GURL kUrlRedirect("https://www.google.com/");
Arthur Hemery859f3462019-01-29 16:29:071126 navigation->Redirect(kUrlRedirect);
carlosk39337112015-01-14 21:44:511127 EXPECT_EQ(init_site_instance_id, main_test_rfh()->GetSiteInstance()->GetId());
carlosk39337112015-01-14 21:44:511128
carloskf4707892015-02-19 18:47:401129 // For now, ensure that the speculative RenderFrameHost does not change after
1130 // the redirect.
carlosk39337112015-01-14 21:44:511131 // TODO(carlosk): once the speculative RenderFrameHost updates with redirects
1132 // this next check will be changed to verify that it actually happens.
carloskc49005eb2015-06-16 11:25:071133 EXPECT_EQ(speculative_rfh, GetSpeculativeRenderFrameHost(node));
carlosk39337112015-01-14 21:44:511134 EXPECT_EQ(site_instance_id, speculative_rfh->GetSiteInstance()->GetId());
carloska0350db2015-07-30 20:10:571135 EXPECT_FALSE(rfh_deleted_observer.deleted());
carlosk39337112015-01-14 21:44:511136
Arthur Hemery859f3462019-01-29 16:29:071137 // Send the commit to the renderer.
1138 navigation->ReadyToCommit();
Aaron Colwellf45e3a852019-06-06 00:48:271139
1140 // Once commit happens the speculative RenderFrameHost is updated to match the
1141 // known final SiteInstance.
carlosk39337112015-01-14 21:44:511142 speculative_rfh = GetSpeculativeRenderFrameHost(node);
carloskc49005eb2015-06-16 11:25:071143 ASSERT_TRUE(speculative_rfh);
Arthur Hemery859f3462019-01-29 16:29:071144 EXPECT_EQ(speculative_rfh->navigation_requests().size(), 1u);
carlosk39337112015-01-14 21:44:511145 EXPECT_EQ(init_site_instance_id, main_test_rfh()->GetSiteInstance()->GetId());
1146
Lukasz Anforowicz1de0a222021-07-26 22:02:321147 auto redirect_site_instance_id = speculative_rfh->GetSiteInstance()->GetId();
Aaron Colwellf45e3a852019-06-06 00:48:271148
1149 // Expect the initial and redirect SiteInstances to be different because
1150 // they should be associated with different BrowsingInstances.
carlosk39337112015-01-14 21:44:511151 EXPECT_NE(init_site_instance_id, redirect_site_instance_id);
Aaron Colwellf45e3a852019-06-06 00:48:271152
Sharon Yang47453bb2025-04-25 14:48:091153 if (AreStrictSiteInstancesEnabled()) {
Aaron Colwell91e32b12021-02-17 01:40:561154 EXPECT_EQ(CreateExpectedSiteInfo(kUrlRedirect),
1155 speculative_rfh->GetSiteInstance()->GetSiteInfo());
Aaron Colwellf45e3a852019-06-06 00:48:271156 EXPECT_NE(site_instance_id, redirect_site_instance_id);
1157
1158 // Verify the old speculative RenderFrameHost was deleted because
1159 // the SiteInstance changed.
1160 EXPECT_TRUE(rfh_deleted_observer.deleted());
Sharon Yang02279222025-01-15 19:09:191161 } else {
1162 EXPECT_TRUE(speculative_rfh->GetSiteInstance()->IsDefaultSiteInstance());
1163 EXPECT_EQ(site_instance_id, redirect_site_instance_id);
1164
1165 // Verify the old speculative RenderFrameHost was not deleted because
1166 // the SiteInstance stayed the same.
1167 EXPECT_FALSE(rfh_deleted_observer.deleted());
Aaron Colwellf45e3a852019-06-06 00:48:271168 }
carlosk39337112015-01-14 21:44:511169
Balazs Engedya40712f2017-09-15 15:01:111170 // Invoke DidCommitProvisionalLoad.
Arthur Hemery859f3462019-01-29 16:29:071171 navigation->Commit();
carlosk39337112015-01-14 21:44:511172
1173 // Check that the speculative RenderFrameHost was swapped in.
1174 EXPECT_EQ(redirect_site_instance_id,
1175 main_test_rfh()->GetSiteInstance()->GetId());
1176 EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
1177}
1178
clamy4cc9b8202015-03-02 13:51:361179// PlzNavigate: Verify that data urls are properly handled.
Camille Lamy07c49cdf2019-03-11 15:53:571180TEST_F(NavigatorTest, DataUrls) {
clamy4cc9b8202015-03-02 13:51:361181 const GURL kUrl1("http://wikipedia.org/");
1182 const GURL kUrl2("data:text/html,test");
1183
Aaron Colwelle953e562019-07-24 16:47:361184 // Isolate kUrl1 so it can't be mapped into a default SiteInstance along with
1185 // kUrl2. This ensures that the speculative RenderFrameHost will always be
1186 // used because the URLs map to different SiteInstances.
Alex Moshchukef8c2562021-03-12 06:37:451187 ChildProcessSecurityPolicy::GetInstance()->AddFutureIsolatedOrigins(
Aaron Colwelle953e562019-07-24 16:47:361188 {url::Origin::Create(kUrl1)},
1189 ChildProcessSecurityPolicy::IsolatedOriginSource::TEST,
1190 browser_context());
1191
clamy4cc9b8202015-03-02 13:51:361192 // Navigate to an initial site.
1193 contents()->NavigateAndCommit(kUrl1);
1194 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
1195
Aaron Colwelle953e562019-07-24 16:47:361196 EXPECT_FALSE(main_test_rfh()->GetSiteInstance()->IsDefaultSiteInstance());
1197
arthursonzogni07499382016-09-20 10:24:291198 // Navigate to a data url. The request should have been sent to the IO
1199 // thread and not committed immediately.
Arthur Hemery56fb25c2019-02-08 17:55:131200 auto navigation =
1201 NavigationSimulator::CreateBrowserInitiated(kUrl2, contents());
1202 navigation->Start();
clamy4cc9b8202015-03-02 13:51:361203 TestRenderFrameHost* speculative_rfh = GetSpeculativeRenderFrameHost(node);
1204 ASSERT_TRUE(speculative_rfh);
arthursonzogni07499382016-09-20 10:24:291205 EXPECT_FALSE(speculative_rfh->is_loading());
1206 EXPECT_TRUE(node->navigation_request());
Arthur Hemery56fb25c2019-02-08 17:55:131207 navigation->ReadyToCommit();
clamyefdb7a42015-07-01 16:55:471208 EXPECT_TRUE(speculative_rfh->is_loading());
1209 EXPECT_FALSE(node->navigation_request());
arthursonzogni07499382016-09-20 10:24:291210 EXPECT_NE(main_test_rfh(), speculative_rfh);
Arthur Hemery56fb25c2019-02-08 17:55:131211 navigation->Commit();
clamy4cc9b8202015-03-02 13:51:361212 EXPECT_EQ(main_test_rfh(), speculative_rfh);
1213
1214 // Go back to the initial site.
1215 contents()->NavigateAndCommit(kUrl1);
1216
arthursonzogni07499382016-09-20 10:24:291217 // Do a renderer-initiated navigation to a data url. The request should be
1218 // sent to the IO thread.
arthursonzogni63aa3f372017-08-09 14:28:391219 auto navigation_to_data_url =
1220 NavigationSimulator::CreateRendererInitiated(kUrl2, main_test_rfh());
1221 navigation_to_data_url->Start();
Arthur Hemery70030a12019-08-05 10:51:161222 EXPECT_FALSE(main_test_rfh()->is_loading());
arthursonzogni07499382016-09-20 10:24:291223 EXPECT_TRUE(node->navigation_request());
clamy4cc9b8202015-03-02 13:51:361224}
1225
carlosk078298a82015-04-07 10:33:201226// Tests several cases for converting SiteInstanceDescriptors into
1227// SiteInstances:
1228// 1) Pointer to the current SiteInstance.
1229// 2) Pointer to an unrelated SiteInstance.
1230// 3) Same-site URL, related.
1231// 4) Cross-site URL, related.
1232// 5) Same-site URL, unrelated (with and without candidate SiteInstances).
1233// 6) Cross-site URL, unrelated (with candidate SiteInstance).
Camille Lamy07c49cdf2019-03-11 15:53:571234TEST_F(NavigatorTest, SiteInstanceDescriptionConversion) {
carlosk078298a82015-04-07 10:33:201235 // Navigate to set a current SiteInstance on the RenderFrameHost.
1236 GURL kUrl1("http://a.com");
Aaron Colwellf45e3a852019-06-06 00:48:271237 // Isolate one of the sites so the both can't be mapped to the default
1238 // site instance.
Alex Moshchukef8c2562021-03-12 06:37:451239 ChildProcessSecurityPolicy::GetInstance()->AddFutureIsolatedOrigins(
Alex Moshchukc4679422019-06-11 17:04:481240 {url::Origin::Create(kUrl1)},
1241 ChildProcessSecurityPolicy::IsolatedOriginSource::TEST,
Aaron Colwellf45e3a852019-06-06 00:48:271242 browser_context());
carlosk078298a82015-04-07 10:33:201243 contents()->NavigateAndCommit(kUrl1);
Aaron Colwell5fb878042020-12-17 19:48:441244 SiteInstanceImpl* current_instance = main_test_rfh()->GetSiteInstance();
carlosk078298a82015-04-07 10:33:201245 ASSERT_TRUE(current_instance);
1246
1247 // 1) Convert a descriptor pointing to the current instance.
1248 RenderFrameHostManager* rfhm =
1249 main_test_rfh()->frame_tree_node()->render_manager();
1250 {
1251 SiteInstanceDescriptor descriptor(current_instance);
dchengbccd6b82016-03-30 16:24:191252 scoped_refptr<SiteInstance> converted_instance =
carlosk078298a82015-04-07 10:33:201253 ConvertToSiteInstance(rfhm, descriptor, nullptr);
1254 EXPECT_EQ(current_instance, converted_instance);
1255 }
1256
1257 // 2) Convert a descriptor pointing an instance unrelated to the current one,
1258 // with a different site.
1259 GURL kUrl2("http://b.com");
Charlie Reis37be2682023-01-10 17:04:471260 scoped_refptr<SiteInstanceImpl> unrelated_instance(
1261 SiteInstanceImpl::CreateForURL(browser_context(), kUrl2));
carlosk078298a82015-04-07 10:33:201262 EXPECT_FALSE(
1263 current_instance->IsRelatedSiteInstance(unrelated_instance.get()));
1264 {
1265 SiteInstanceDescriptor descriptor(unrelated_instance.get());
dchengbccd6b82016-03-30 16:24:191266 scoped_refptr<SiteInstance> converted_instance =
carlosk078298a82015-04-07 10:33:201267 ConvertToSiteInstance(rfhm, descriptor, nullptr);
1268 EXPECT_EQ(unrelated_instance.get(), converted_instance);
1269 }
1270
1271 // 3) Convert a descriptor of a related instance with the same site as the
1272 // current one.
1273 GURL kUrlSameSiteAs1("http://www.a.com/foo");
1274 {
Arthur Hemery2e1d149b2020-08-21 14:23:541275 SiteInstanceDescriptor descriptor(
W. James MacLean46cf26212020-10-01 16:43:371276 UrlInfo::CreateForTesting(kUrlSameSiteAs1),
Arthur Hemery821fa5d2021-08-30 13:32:421277 SiteInstanceRelation::RELATED);
dchengbccd6b82016-03-30 16:24:191278 scoped_refptr<SiteInstance> converted_instance =
carlosk078298a82015-04-07 10:33:201279 ConvertToSiteInstance(rfhm, descriptor, nullptr);
1280 EXPECT_EQ(current_instance, converted_instance);
1281 }
1282
1283 // 4) Convert a descriptor of a related instance with a site different from
1284 // the current one.
1285 GURL kUrlSameSiteAs2("http://www.b.com/foo");
Aaron Colwell91e32b12021-02-17 01:40:561286 scoped_refptr<SiteInstanceImpl> related_instance;
carlosk078298a82015-04-07 10:33:201287 {
Arthur Hemery2e1d149b2020-08-21 14:23:541288 SiteInstanceDescriptor descriptor(
W. James MacLean46cf26212020-10-01 16:43:371289 UrlInfo::CreateForTesting(kUrlSameSiteAs2),
Arthur Hemery821fa5d2021-08-30 13:32:421290 SiteInstanceRelation::RELATED);
carlosk078298a82015-04-07 10:33:201291 related_instance = ConvertToSiteInstance(rfhm, descriptor, nullptr);
Aaron Colwellddeccbdb2019-03-08 01:11:031292 // If kUrlSameSiteAs2 requires a dedicated process on this platform, this
1293 // should return a new instance, related to the current and set to the new
1294 // site URL.
1295 // Otherwise, this should return the default site instance
carlosk078298a82015-04-07 10:33:201296 EXPECT_TRUE(
1297 current_instance->IsRelatedSiteInstance(related_instance.get()));
1298 EXPECT_NE(current_instance, related_instance.get());
1299 EXPECT_NE(unrelated_instance.get(), related_instance.get());
Aaron Colwellddeccbdb2019-03-08 01:11:031300
Sharon Yang47453bb2025-04-25 14:48:091301 if (AreStrictSiteInstancesEnabled()) {
Aaron Colwell9d0f9392021-02-11 21:51:521302 EXPECT_EQ(SiteInfo::CreateForTesting(
Aaron Colwell5fb878042020-12-17 19:48:441303 current_instance->GetIsolationContext(), kUrlSameSiteAs2),
Aaron Colwell91e32b12021-02-17 01:40:561304 related_instance->GetSiteInfo());
Sharon Yang02279222025-01-15 19:09:191305 } else {
1306 ASSERT_TRUE(related_instance->IsDefaultSiteInstance());
Aaron Colwellddeccbdb2019-03-08 01:11:031307 }
carlosk078298a82015-04-07 10:33:201308 }
1309
1310 // 5) Convert a descriptor of an unrelated instance with the same site as the
1311 // current one, several times, with and without candidate sites.
1312 {
Arthur Hemery2e1d149b2020-08-21 14:23:541313 SiteInstanceDescriptor descriptor(
W. James MacLean46cf26212020-10-01 16:43:371314 UrlInfo::CreateForTesting(kUrlSameSiteAs1),
Arthur Hemery821fa5d2021-08-30 13:32:421315 SiteInstanceRelation::UNRELATED);
Aaron Colwell91e32b12021-02-17 01:40:561316 scoped_refptr<SiteInstanceImpl> converted_instance_1 =
carlosk078298a82015-04-07 10:33:201317 ConvertToSiteInstance(rfhm, descriptor, nullptr);
1318 // Should return a new instance, unrelated to the current one, set to the
1319 // provided site URL.
1320 EXPECT_FALSE(
1321 current_instance->IsRelatedSiteInstance(converted_instance_1.get()));
1322 EXPECT_NE(current_instance, converted_instance_1.get());
1323 EXPECT_NE(unrelated_instance.get(), converted_instance_1.get());
Aaron Colwell91e32b12021-02-17 01:40:561324 EXPECT_EQ(CreateExpectedSiteInfo(kUrlSameSiteAs1),
1325 converted_instance_1->GetSiteInfo());
carlosk078298a82015-04-07 10:33:201326
1327 // Does the same but this time using unrelated_instance as a candidate,
1328 // which has a different site.
Aaron Colwell91e32b12021-02-17 01:40:561329 scoped_refptr<SiteInstanceImpl> converted_instance_2 =
carlosk078298a82015-04-07 10:33:201330 ConvertToSiteInstance(rfhm, descriptor, unrelated_instance.get());
1331 // Should return yet another new instance, unrelated to the current one, set
1332 // to the same site URL.
1333 EXPECT_FALSE(
1334 current_instance->IsRelatedSiteInstance(converted_instance_2.get()));
1335 EXPECT_NE(current_instance, converted_instance_2.get());
1336 EXPECT_NE(unrelated_instance.get(), converted_instance_2.get());
1337 EXPECT_NE(converted_instance_1.get(), converted_instance_2.get());
Aaron Colwell91e32b12021-02-17 01:40:561338 EXPECT_EQ(CreateExpectedSiteInfo(kUrlSameSiteAs1),
1339 converted_instance_1->GetSiteInfo());
carlosk078298a82015-04-07 10:33:201340
1341 // Converts once more but with |converted_instance_1| as a candidate.
dchengbccd6b82016-03-30 16:24:191342 scoped_refptr<SiteInstance> converted_instance_3 =
carlosk078298a82015-04-07 10:33:201343 ConvertToSiteInstance(rfhm, descriptor, converted_instance_1.get());
1344 // Should return |converted_instance_1| because its site matches and it is
1345 // unrelated to the current SiteInstance.
1346 EXPECT_EQ(converted_instance_1.get(), converted_instance_3);
1347 }
1348
1349 // 6) Convert a descriptor of an unrelated instance with the same site of
1350 // related_instance and using it as a candidate.
1351 {
Arthur Hemery2e1d149b2020-08-21 14:23:541352 SiteInstanceDescriptor descriptor(
W. James MacLean46cf26212020-10-01 16:43:371353 UrlInfo::CreateForTesting(kUrlSameSiteAs2),
Arthur Hemery821fa5d2021-08-30 13:32:421354 SiteInstanceRelation::UNRELATED);
Aaron Colwell91e32b12021-02-17 01:40:561355 scoped_refptr<SiteInstanceImpl> converted_instance_1 =
carlosk078298a82015-04-07 10:33:201356 ConvertToSiteInstance(rfhm, descriptor, related_instance.get());
1357 // Should return a new instance, unrelated to the current, set to the
1358 // provided site URL.
1359 EXPECT_FALSE(
1360 current_instance->IsRelatedSiteInstance(converted_instance_1.get()));
1361 EXPECT_NE(related_instance.get(), converted_instance_1.get());
1362 EXPECT_NE(unrelated_instance.get(), converted_instance_1.get());
Aaron Colwellf45e3a852019-06-06 00:48:271363
Sharon Yang47453bb2025-04-25 14:48:091364 if (AreStrictSiteInstancesEnabled()) {
Aaron Colwell91e32b12021-02-17 01:40:561365 EXPECT_EQ(CreateExpectedSiteInfo(kUrlSameSiteAs2),
1366 converted_instance_1->GetSiteInfo());
Sharon Yang02279222025-01-15 19:09:191367 } else {
1368 EXPECT_TRUE(converted_instance_1->IsDefaultSiteInstance());
Aaron Colwellf45e3a852019-06-06 00:48:271369 }
carlosk078298a82015-04-07 10:33:201370
dchengbccd6b82016-03-30 16:24:191371 scoped_refptr<SiteInstance> converted_instance_2 =
carlosk078298a82015-04-07 10:33:201372 ConvertToSiteInstance(rfhm, descriptor, unrelated_instance.get());
1373 // Should return |unrelated_instance| because its site matches and it is
1374 // unrelated to the current SiteInstance.
1375 EXPECT_EQ(unrelated_instance.get(), converted_instance_2);
1376 }
1377}
1378
gzobqq8be1ff12016-03-01 17:12:011379// A renderer process might try and claim that a cross site navigation was
Balazs Engedya40712f2017-09-15 15:01:111380// within the same document by setting was_within_same_document = true in
arthursonzogni73fe3212020-11-17 13:24:071381// DidCommitProvisionalLoadParams. Such case should be detected on the browser
1382// side and the renderer process should be killed.
Camille Lamy07c49cdf2019-03-11 15:53:571383TEST_F(NavigatorTest, CrossSiteClaimWithinPage) {
gzobqq8be1ff12016-03-01 17:12:011384 const GURL kUrl1("http://www.chromium.org/");
1385 const GURL kUrl2("http://www.google.com/");
1386
Arthur Hemery7b0ae492018-02-05 16:04:451387 NavigationSimulator::NavigateAndCommitFromBrowser(contents(), kUrl1);
gzobqq8be1ff12016-03-01 17:12:011388
Arthur Hemery7b0ae492018-02-05 16:04:451389 // Navigate to a different site and claim that the navigation was within same
1390 // page.
gzobqq8be1ff12016-03-01 17:12:011391 int bad_msg_count = process()->bad_msg_count();
Arthur Hemery7b0ae492018-02-05 16:04:451392 auto simulator =
1393 NavigationSimulator::CreateRendererInitiated(kUrl2, main_test_rfh());
1394 simulator->CommitSameDocument();
gzobqq8be1ff12016-03-01 17:12:011395 EXPECT_EQ(process()->bad_msg_count(), bad_msg_count + 1);
1396}
1397
Charlie Hu5130d25e2021-03-05 21:53:391398// Permissions Policy: Test that the permissions policy is reset when navigating
1399// pages within a site.
Charlie Hubb5943d2021-03-09 19:46:121400TEST_F(NavigatorTest, PermissionsPolicySameSiteNavigation) {
iclellandf46f88a2017-03-04 14:01:441401 const GURL kUrl1("http://www.chromium.org/");
1402 const GURL kUrl2("http://www.chromium.org/Home");
1403
1404 contents()->NavigateAndCommit(kUrl1);
1405
Charlie Hu5130d25e2021-03-05 21:53:391406 // Check the permissions policy before navigation.
Sandor Major07aa8b062025-02-28 17:24:351407 const network::PermissionsPolicy* original_permissions_policy =
Sandor Majord1bbf7752025-01-09 22:49:301408 main_test_rfh()->GetPermissionsPolicy();
Charlie Hue20fe2f2021-03-07 03:39:591409 ASSERT_TRUE(original_permissions_policy);
iclellandf46f88a2017-03-04 14:01:441410
1411 // Navigate to the new URL.
1412 contents()->NavigateAndCommit(kUrl2);
1413
Charlie Hu5130d25e2021-03-05 21:53:391414 // Check the permissions policy after navigation.
Sandor Major07aa8b062025-02-28 17:24:351415 const network::PermissionsPolicy* final_permissions_policy =
Sandor Majord1bbf7752025-01-09 22:49:301416 main_test_rfh()->GetPermissionsPolicy();
Charlie Hue20fe2f2021-03-07 03:39:591417 ASSERT_TRUE(final_permissions_policy);
1418 ASSERT_NE(original_permissions_policy, final_permissions_policy);
iclellandf46f88a2017-03-04 14:01:441419}
1420
Charlie Hu5130d25e2021-03-05 21:53:391421// Permissions Policy: Test that the permissions policy is not reset when
1422// navigating within a page.
Charlie Hubb5943d2021-03-09 19:46:121423TEST_F(NavigatorTest, PermissionsPolicyFragmentNavigation) {
iclellandf46f88a2017-03-04 14:01:441424 const GURL kUrl1("http://www.chromium.org/");
1425 const GURL kUrl2("http://www.chromium.org/#Home");
1426
1427 contents()->NavigateAndCommit(kUrl1);
1428
Charlie Hu5130d25e2021-03-05 21:53:391429 // Check the permissions policy before navigation.
Sandor Major07aa8b062025-02-28 17:24:351430 const network::PermissionsPolicy* original_permissions_policy =
Sandor Majord1bbf7752025-01-09 22:49:301431 main_test_rfh()->GetPermissionsPolicy();
Charlie Hue20fe2f2021-03-07 03:39:591432 ASSERT_TRUE(original_permissions_policy);
iclellandf46f88a2017-03-04 14:01:441433
1434 // Navigate to the new URL.
1435 contents()->NavigateAndCommit(kUrl2);
1436
Charlie Hu5130d25e2021-03-05 21:53:391437 // Check the permissions policy after navigation.
Sandor Major07aa8b062025-02-28 17:24:351438 const network::PermissionsPolicy* final_permissions_policy =
Sandor Majord1bbf7752025-01-09 22:49:301439 main_test_rfh()->GetPermissionsPolicy();
Charlie Hue20fe2f2021-03-07 03:39:591440 ASSERT_EQ(original_permissions_policy, final_permissions_policy);
iclellandf46f88a2017-03-04 14:01:441441}
1442
Charlie Hu5130d25e2021-03-05 21:53:391443// Permissions Policy: Test that the permissions policy is set correctly when
1444// inserting a new child frame.
Charlie Hubb5943d2021-03-09 19:46:121445TEST_F(NavigatorTest, PermissionsPolicyNewChild) {
Ian Clelland784f56a92017-04-24 17:25:031446 const GURL kUrl1("http://www.chromium.org/");
1447 const GURL kUrl2("http://www.chromium.org/Home");
1448
1449 contents()->NavigateAndCommit(kUrl1);
1450
Camille Lamyb8155002019-03-13 13:46:391451 // Simulate the navigation triggered by inserting a child frame into a page.
Ian Clelland784f56a92017-04-24 17:25:031452 TestRenderFrameHost* subframe_rfh =
Dave Tapuska327c06c92022-06-13 20:31:511453 contents()->GetPrimaryMainFrame()->AppendChild("child");
Camille Lamyb8155002019-03-13 13:46:391454 NavigationSimulator::NavigateAndCommitFromDocument(kUrl2, subframe_rfh);
Ian Clelland784f56a92017-04-24 17:25:031455
Sandor Major07aa8b062025-02-28 17:24:351456 const network::PermissionsPolicy* subframe_permissions_policy =
Sandor Majord1bbf7752025-01-09 22:49:301457 subframe_rfh->GetPermissionsPolicy();
Charlie Hue20fe2f2021-03-07 03:39:591458 ASSERT_TRUE(subframe_permissions_policy);
1459 ASSERT_FALSE(subframe_permissions_policy->GetOriginForTest().opaque());
Ian Clelland784f56a92017-04-24 17:25:031460}
1461
Camille Lamy07c49cdf2019-03-11 15:53:571462TEST_F(NavigatorTest, TwoNavigationsRacingCommit) {
clamyd3bfdb02018-07-12 13:52:181463 const GURL kUrl1("http://www.chromium.org/");
1464 const GURL kUrl2("http://www.chromium.org/Home");
1465
Dave Tapuska327c06c92022-06-13 20:31:511466 EXPECT_EQ(0u, contents()->GetPrimaryMainFrame()->navigation_requests_.size());
clamyd3bfdb02018-07-12 13:52:181467
1468 // Have the first navigation reach ReadyToCommit.
1469 auto first_navigation =
1470 NavigationSimulator::CreateBrowserInitiated(kUrl1, contents());
1471 first_navigation->ReadyToCommit();
Dave Tapuska327c06c92022-06-13 20:31:511472 EXPECT_EQ(1u, contents()->GetPrimaryMainFrame()->navigation_requests_.size());
clamyd3bfdb02018-07-12 13:52:181473
Rakina Zata Amnidfcab2e52023-08-26 07:11:591474 // A second navigation starts.
clamyd3bfdb02018-07-12 13:52:181475 auto second_navigation =
1476 NavigationSimulator::CreateBrowserInitiated(kUrl1, contents());
Rakina Zata Amnidfcab2e52023-08-26 07:11:591477 second_navigation->Start();
1478 EXPECT_EQ(1u, contents()->GetPrimaryMainFrame()->navigation_requests_.size());
clamyd3bfdb02018-07-12 13:52:181479
1480 // The first navigation commits.
1481 first_navigation->Commit();
Rakina Zata Amnidfcab2e52023-08-26 07:11:591482 EXPECT_EQ(0u, contents()->GetPrimaryMainFrame()->navigation_requests_.size());
clamyd3bfdb02018-07-12 13:52:181483
1484 // The second navigation commits.
1485 second_navigation->Commit();
Dave Tapuska327c06c92022-06-13 20:31:511486 EXPECT_EQ(0u, contents()->GetPrimaryMainFrame()->navigation_requests_.size());
clamyd3bfdb02018-07-12 13:52:181487}
1488
clamy71a42ec2014-10-02 18:43:221489} // namespace content