blob: 9caa0c0ff4b3e3a0fa4145484c371d113b563203 [file] [log] [blame]
Avi Drissman4e1b7bc32022-09-15 14:03:501// Copyright 2015 The Chromium Authors
clamy49678312015-10-22 21:59:002// 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/navigation_request.h"
Cammie Smith Barnesa0da2cf2021-01-11 22:09:376
7#include <string>
8#include <vector>
9
Sebastien Marchandf8cbfab2019-01-25 16:02:3010#include "base/bind.h"
Peter Birk Pakkenberg73e07b62022-09-21 11:20:3011#include "base/containers/flat_map.h"
arthursonzogni898dcda52021-01-21 08:50:1012#include "base/i18n/number_formatting.h"
Yao Xiao6e1f7d32022-01-07 03:28:4013#include "base/test/scoped_feature_list.h"
Becky Zhou9898cb6e2019-06-05 00:35:3014#include "build/build_config.h"
clamy49678312015-10-22 21:59:0015#include "content/public/browser/navigation_throttle.h"
Peter Birk Pakkenberg73e07b62022-09-21 11:20:3016#include "content/public/browser/origin_trials_controller_delegate.h"
Robbie McElrath5641d572022-05-20 17:15:2917#include "content/public/browser/site_isolation_policy.h"
jam6d47c3452016-09-09 18:51:0118#include "content/public/browser/ssl_status.h"
Hans Wennborg5ffd1392019-10-16 11:00:0219#include "content/public/common/content_client.h"
Peter Birk Pakkenberg73e07b62022-09-21 11:20:3020#include "content/public/common/content_features.h"
Robbie McElrath5641d572022-05-20 17:15:2921#include "content/public/common/content_switches.h"
Charles Harrison860f7ef2017-06-28 15:31:4122#include "content/public/common/url_constants.h"
Peter Birk Pakkenberg73e07b62022-09-21 11:20:3023#include "content/public/test/test_browser_context.h"
Lucas Garron79e1a972017-10-04 22:25:0624#include "content/public/test/test_navigation_throttle.h"
Yao Xiao1099e4c2022-03-24 22:40:3725#include "content/test/fenced_frame_test_utils.h"
Camille Lamy62b826012019-02-26 09:15:4726#include "content/test/navigation_simulator_impl.h"
Charles Harrison860f7ef2017-06-28 15:31:4127#include "content/test/test_content_browser_client.h"
clamy49678312015-10-22 21:59:0028#include "content/test/test_render_frame_host.h"
scottmg276753cf2016-10-27 18:25:2229#include "content/test/test_web_contents.h"
Lucas Garronc1edb5ab2017-11-08 03:31:1330#include "net/ssl/ssl_connection_status_flags.h"
arthursonzogni898dcda52021-01-21 08:50:1031#include "services/network/public/cpp/content_security_policy/content_security_policy.h"
Cammie Smith Barnesa0da2cf2021-01-11 22:09:3732#include "testing/gmock/include/gmock/gmock.h"
Anton Bikineevf62d1bf2021-05-15 17:56:0733#include "third_party/abseil-cpp/absl/types/optional.h"
Minggang Wanga13c796e2021-07-02 05:54:4334#include "third_party/blink/public/common/navigation/navigation_params.h"
Peter Birk Pakkenberg73e07b62022-09-21 11:20:3035#include "third_party/blink/public/common/origin_trials/scoped_test_origin_trial_policy.h"
Richard Lie6899952018-11-30 08:42:0036#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h"
clamy49678312015-10-22 21:59:0037
38namespace content {
39
clamy1d4e78fd2017-07-11 12:59:1940// Test version of a NavigationThrottle that will execute a callback when
41// called.
Lucas Garron79e1a972017-10-04 22:25:0642class DeletingNavigationThrottle : public NavigationThrottle {
clamy1d4e78fd2017-07-11 12:59:1943 public:
Lucas Garron79e1a972017-10-04 22:25:0644 DeletingNavigationThrottle(NavigationHandle* handle,
45 const base::RepeatingClosure& deletion_callback)
46 : NavigationThrottle(handle), deletion_callback_(deletion_callback) {}
Fergal Dalya1d569972021-03-16 03:24:5347 ~DeletingNavigationThrottle() override = default;
clamy1d4e78fd2017-07-11 12:59:1948
49 NavigationThrottle::ThrottleCheckResult WillStartRequest() override {
Lucas Garron79e1a972017-10-04 22:25:0650 deletion_callback_.Run();
clamy1d4e78fd2017-07-11 12:59:1951 return NavigationThrottle::PROCEED;
52 }
53
54 NavigationThrottle::ThrottleCheckResult WillRedirectRequest() override {
Lucas Garron79e1a972017-10-04 22:25:0655 deletion_callback_.Run();
clamy1d4e78fd2017-07-11 12:59:1956 return NavigationThrottle::PROCEED;
57 }
58
Lucas Garron0cedd962017-10-17 07:23:3359 NavigationThrottle::ThrottleCheckResult WillFailRequest() override {
60 deletion_callback_.Run();
61 return NavigationThrottle::PROCEED;
62 }
63
clamy1d4e78fd2017-07-11 12:59:1964 NavigationThrottle::ThrottleCheckResult WillProcessResponse() override {
Lucas Garron79e1a972017-10-04 22:25:0665 deletion_callback_.Run();
clamy1d4e78fd2017-07-11 12:59:1966 return NavigationThrottle::PROCEED;
67 }
68
69 const char* GetNameForLogging() override {
Lucas Garron79e1a972017-10-04 22:25:0670 return "DeletingNavigationThrottle";
clamy1d4e78fd2017-07-11 12:59:1971 }
72
73 private:
Lucas Garron79e1a972017-10-04 22:25:0674 base::RepeatingClosure deletion_callback_;
clamy1d4e78fd2017-07-11 12:59:1975};
76
Mohamed Abdelhalim1e8c5822019-08-02 11:45:4377class NavigationRequestTest : public RenderViewHostImplTestHarness {
clamy49678312015-10-22 21:59:0078 public:
Fergal Dalya1d569972021-03-16 03:24:5379 NavigationRequestTest() : callback_result_(NavigationThrottle::DEFER) {}
clamy49678312015-10-22 21:59:0080
81 void SetUp() override {
82 RenderViewHostImplTestHarness::SetUp();
clamy1d4e78fd2017-07-11 12:59:1983 CreateNavigationHandle();
Dave Tapuska327c06c92022-06-13 20:31:5184 contents()->GetPrimaryMainFrame()->InitializeRenderFrameIfNeeded();
clamy49678312015-10-22 21:59:0085 }
86
87 void TearDown() override {
clamy49678312015-10-22 21:59:0088 RenderViewHostImplTestHarness::TearDown();
89 }
90
Charles Harrison4f2bf1a2017-07-18 20:21:2191 void CancelDeferredNavigation(
92 NavigationThrottle::ThrottleCheckResult result) {
Hiroki Nakagawaadcffc502021-06-16 10:47:5193 GetNavigationRequest()->CancelDeferredNavigationInternal(result);
Charles Harrison4f2bf1a2017-07-18 20:21:2194 }
95
clamy49678312015-10-22 21:59:0096 // Helper function to call WillStartRequest on |handle|. If this function
97 // returns DEFER, |callback_result_| will be set to the actual result of
98 // the throttle checks when they are finished.
99 void SimulateWillStartRequest() {
100 was_callback_called_ = false;
101 callback_result_ = NavigationThrottle::DEFER;
102
Mohamed Abdelhalim7e9e9c12019-11-26 13:48:44103 // It's safe to use base::Unretained since the NavigationRequest is owned by
Mohamed Abdelhalim1e8c5822019-08-02 11:45:43104 // the NavigationRequestTest.
Hiroki Nakagawaadcffc502021-06-16 10:47:51105 GetNavigationRequest()->set_complete_callback_for_testing(
Makoto Shimazud2aa2202019-10-09 13:57:18106 base::BindOnce(&NavigationRequestTest::UpdateThrottleCheckResult,
107 base::Unretained(this)));
Mohamed Abdelhalim7e9e9c12019-11-26 13:48:44108
Hiroki Nakagawaadcffc502021-06-16 10:47:51109 GetNavigationRequest()->WillStartRequest();
clamy49678312015-10-22 21:59:00110 }
111
112 // Helper function to call WillRedirectRequest on |handle|. If this function
113 // returns DEFER, |callback_result_| will be set to the actual result of the
114 // throttle checks when they are finished.
clamye88533842015-11-18 12:48:57115 // TODO(clamy): this should also simulate that WillStartRequest was called if
116 // it has not been called before.
clamy49678312015-10-22 21:59:00117 void SimulateWillRedirectRequest() {
118 was_callback_called_ = false;
119 callback_result_ = NavigationThrottle::DEFER;
120
Mohamed Abdelhalim7e9e9c12019-11-26 13:48:44121 // It's safe to use base::Unretained since the NavigationRequest is owned by
Mohamed Abdelhalim1e8c5822019-08-02 11:45:43122 // the NavigationRequestTest.
Hiroki Nakagawaadcffc502021-06-16 10:47:51123 GetNavigationRequest()->set_complete_callback_for_testing(
Makoto Shimazud2aa2202019-10-09 13:57:18124 base::BindOnce(&NavigationRequestTest::UpdateThrottleCheckResult,
125 base::Unretained(this)));
Mohamed Abdelhalim7e9e9c12019-11-26 13:48:44126
Hiroki Nakagawaadcffc502021-06-16 10:47:51127 GetNavigationRequest()->WillRedirectRequest(
Arthur Hemery3a991c092021-12-22 12:04:24128 GURL(), nullptr /* post_redirect_process */);
clamy49678312015-10-22 21:59:00129 }
130
Lucas Garron0cedd962017-10-17 07:23:33131 // Helper function to call WillFailRequest on |handle|. If this function
132 // returns DEFER, |callback_result_| will be set to the actual result of the
133 // throttle checks when they are finished.
Lucas Garronc1edb5ab2017-11-08 03:31:13134 void SimulateWillFailRequest(
135 net::Error net_error_code,
Anton Bikineevf62d1bf2021-05-15 17:56:07136 const absl::optional<net::SSLInfo> ssl_info = absl::nullopt) {
Lucas Garron0cedd962017-10-17 07:23:33137 was_callback_called_ = false;
138 callback_result_ = NavigationThrottle::DEFER;
Hiroki Nakagawaadcffc502021-06-16 10:47:51139 GetNavigationRequest()->set_net_error(net_error_code);
Lucas Garron0cedd962017-10-17 07:23:33140
Mohamed Abdelhalim7e9e9c12019-11-26 13:48:44141 // It's safe to use base::Unretained since the NavigationRequest is owned by
Mohamed Abdelhalim1e8c5822019-08-02 11:45:43142 // the NavigationRequestTest.
Hiroki Nakagawaadcffc502021-06-16 10:47:51143 GetNavigationRequest()->set_complete_callback_for_testing(
Makoto Shimazud2aa2202019-10-09 13:57:18144 base::BindOnce(&NavigationRequestTest::UpdateThrottleCheckResult,
145 base::Unretained(this)));
Mohamed Abdelhalim7e9e9c12019-11-26 13:48:44146
Hiroki Nakagawaadcffc502021-06-16 10:47:51147 GetNavigationRequest()->WillFailRequest();
Lucas Garron0cedd962017-10-17 07:23:33148 }
149
clamy49678312015-10-22 21:59:00150 // Whether the callback was called.
151 bool was_callback_called() const { return was_callback_called_; }
152
153 // Returns the callback_result.
154 NavigationThrottle::ThrottleCheckResult callback_result() const {
155 return callback_result_;
156 }
157
Hiroki Nakagawaadcffc502021-06-16 10:47:51158 NavigationRequest::NavigationState state() {
159 return GetNavigationRequest()->state();
160 }
Mohamed Abdelhalimccd149af2019-10-31 14:48:53161
Lucas Garron0cedd962017-10-17 07:23:33162 bool call_counts_match(TestNavigationThrottle* throttle,
163 int start,
164 int redirect,
165 int failure,
166 int process) {
167 return start == throttle->GetCallCount(
168 TestNavigationThrottle::WILL_START_REQUEST) &&
169 redirect == throttle->GetCallCount(
170 TestNavigationThrottle::WILL_REDIRECT_REQUEST) &&
171 failure == throttle->GetCallCount(
172 TestNavigationThrottle::WILL_FAIL_REQUEST) &&
173 process == throttle->GetCallCount(
174 TestNavigationThrottle::WILL_PROCESS_RESPONSE);
175 }
176
177 // Creates, register and returns a TestNavigationThrottle that will
178 // synchronously return |result| on checks by default.
clamy49678312015-10-22 21:59:00179 TestNavigationThrottle* CreateTestNavigationThrottle(
180 NavigationThrottle::ThrottleCheckResult result) {
181 TestNavigationThrottle* test_throttle =
Hiroki Nakagawaadcffc502021-06-16 10:47:51182 new TestNavigationThrottle(GetNavigationRequest());
Lucas Garron79e1a972017-10-04 22:25:06183 test_throttle->SetResponseForAllMethods(TestNavigationThrottle::SYNCHRONOUS,
184 result);
Hiroki Nakagawaadcffc502021-06-16 10:47:51185 GetNavigationRequest()->RegisterThrottleForTesting(
dcheng9bfa5162016-04-09 01:00:57186 std::unique_ptr<TestNavigationThrottle>(test_throttle));
clamy49678312015-10-22 21:59:00187 return test_throttle;
188 }
189
Lucas Garron0cedd962017-10-17 07:23:33190 // Creates, register and returns a TestNavigationThrottle that will
191 // synchronously return |result| on check for the given |method|, and
192 // NavigationThrottle::PROCEED otherwise.
193 TestNavigationThrottle* CreateTestNavigationThrottle(
194 TestNavigationThrottle::ThrottleMethod method,
195 NavigationThrottle::ThrottleCheckResult result) {
196 TestNavigationThrottle* test_throttle =
197 CreateTestNavigationThrottle(NavigationThrottle::PROCEED);
198 test_throttle->SetResponse(method, TestNavigationThrottle::SYNCHRONOUS,
199 result);
200 return test_throttle;
201 }
202
Mohamed Abdelhalim9ef43fc2019-04-05 13:09:43203 // TODO(zetamoo): Use NavigationSimulator instead of creating
204 // NavigationRequest and NavigationHandleImpl.
clamy1d4e78fd2017-07-11 12:59:19205 void CreateNavigationHandle() {
Minggang Wanga13c796e2021-07-02 05:54:43206 auto common_params = blink::CreateCommonNavigationParams();
Lucas Furukawa Gadanief8290a2019-07-29 20:27:51207 common_params->initiator_origin =
Lukasz Anforowicz435bcb582019-07-12 20:50:06208 url::Origin::Create(GURL("https://initiator.example.com"));
Minggang Wanga13c796e2021-07-02 05:54:43209 auto commit_params = blink::CreateCommitNavigationParams();
arthursonzogni70ac7302020-05-28 08:49:05210 commit_params->frame_policy =
211 main_test_rfh()->frame_tree_node()->pending_frame_policy();
Hiroki Nakagawaadcffc502021-06-16 10:47:51212 auto request = NavigationRequest::CreateBrowserInitiated(
Lucas Furukawa Gadanief8290a2019-07-29 20:27:51213 main_test_rfh()->frame_tree_node(), std::move(common_params),
arthursonzogni70ac7302020-05-28 08:49:05214 std::move(commit_params), false /* browser-initiated */,
Takashi Toyoshimae87b7be2021-01-22 11:51:08215 false /* was_opener_suppressed */, nullptr /* initiator_frame_token */,
Antonio Sartori9a82f6f32020-12-14 09:22:45216 ChildProcessHost::kInvalidUniqueID /* initiator_process_id */,
John Delaney50425f82020-04-07 16:26:21217 std::string() /* extra_headers */, nullptr /* frame_entry */,
jongdeok.kim5de823b32022-06-14 04:37:50218 nullptr /* entry */, false /* is_form_submission */,
Daniel Hosseinianf0fbfb42021-09-08 02:20:47219 nullptr /* navigation_ui_data */, absl::nullopt /* impression */,
220 false /* is_pdf */);
Hiroki Nakagawaadcffc502021-06-16 10:47:51221 main_test_rfh()->frame_tree_node()->CreatedNavigationRequest(
222 std::move(request));
223 GetNavigationRequest()->StartNavigation();
clamy1d4e78fd2017-07-11 12:59:19224 }
225
Yao Xiao6e1f7d32022-01-07 03:28:40226 FrameTreeNode* AddFrame(FrameTree& frame_tree,
227 RenderFrameHostImpl* parent,
228 int process_id,
229 int new_routing_id,
230 const blink::FramePolicy& frame_policy,
231 blink::FrameOwnerElementType owner_type) {
232 return frame_tree.AddFrame(
233 parent, process_id, new_routing_id,
234 TestRenderFrameHost::CreateStubFrameRemote(),
235 TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
236 TestRenderFrameHost::CreateStubPolicyContainerBindParams(),
Dominic Farolino12e06d72022-08-05 02:29:49237 TestRenderFrameHost::CreateStubAssociatedInterfaceProviderReceiver(),
Yao Xiao6e1f7d32022-01-07 03:28:40238 blink::mojom::TreeScopeType::kDocument, std::string(), "uniqueName0",
239 false, blink::LocalFrameToken(), base::UnguessableToken::Create(),
Daniel Cheng284c38942022-09-22 23:30:34240 blink::DocumentToken(), frame_policy,
241 blink::mojom::FrameOwnerProperties(), false, owner_type,
Yao Xiao6e1f7d32022-01-07 03:28:40242 /*is_dummy_frame_for_inner_tree=*/false);
243 }
244
clamy49678312015-10-22 21:59:00245 private:
Mohamed Abdelhalimf03d4a22019-10-01 13:34:31246 // The callback provided to NavigationRequest::WillStartRequest,
247 // NavigationRequest::WillRedirectRequest, and
248 // NavigationRequest::WillFailRequest during the tests.
Mohamed Abdelhalim7e9e9c12019-11-26 13:48:44249 bool UpdateThrottleCheckResult(
clamy49678312015-10-22 21:59:00250 NavigationThrottle::ThrottleCheckResult result) {
251 callback_result_ = result;
252 was_callback_called_ = true;
Mohamed Abdelhalim7e9e9c12019-11-26 13:48:44253 return true;
clamy49678312015-10-22 21:59:00254 }
255
Hiroki Nakagawaadcffc502021-06-16 10:47:51256 // This must be called after CreateNavigationHandle().
257 NavigationRequest* GetNavigationRequest() {
258 return main_test_rfh()->frame_tree_node()->navigation_request();
259 }
260
Fergal Dalya1d569972021-03-16 03:24:53261 bool was_callback_called_ = false;
clamy49678312015-10-22 21:59:00262 NavigationThrottle::ThrottleCheckResult callback_result_;
263};
264
carlosk489d9e22016-07-25 14:25:43265// Checks that the request_context_type is properly set.
266// Note: can be extended to cover more internal members.
Mohamed Abdelhalim1e8c5822019-08-02 11:45:43267TEST_F(NavigationRequestTest, SimpleDataChecksRedirectAndProcess) {
Camille Lamy62b826012019-02-26 09:15:47268 const GURL kUrl1 = GURL("http://chromium.org");
269 const GURL kUrl2 = GURL("http://google.com");
270 auto navigation =
271 NavigationSimulatorImpl::CreateRendererInitiated(kUrl1, main_rfh());
272 navigation->Start();
Harkiran Bolariaa2c9f79a2021-07-02 09:25:40273 EXPECT_EQ(blink::mojom::RequestContextType::LOCATION,
Mohamed Abdelhalim40c35d22019-09-19 15:59:05274 NavigationRequest::From(navigation->GetNavigationHandle())
275 ->request_context_type());
jkarlinbb150112016-11-02 17:55:11276 EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN,
Camille Lamy62b826012019-02-26 09:15:47277 navigation->GetNavigationHandle()->GetConnectionInfo());
carlosk489d9e22016-07-25 14:25:43278
Camille Lamy62b826012019-02-26 09:15:47279 navigation->set_http_connection_info(
280 net::HttpResponseInfo::CONNECTION_INFO_HTTP1_1);
281 navigation->Redirect(kUrl2);
Harkiran Bolariaa2c9f79a2021-07-02 09:25:40282 EXPECT_EQ(blink::mojom::RequestContextType::LOCATION,
Mohamed Abdelhalim40c35d22019-09-19 15:59:05283 NavigationRequest::From(navigation->GetNavigationHandle())
284 ->request_context_type());
jkarlinbb150112016-11-02 17:55:11285 EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_HTTP1_1,
Camille Lamy62b826012019-02-26 09:15:47286 navigation->GetNavigationHandle()->GetConnectionInfo());
carlosk489d9e22016-07-25 14:25:43287
Camille Lamy62b826012019-02-26 09:15:47288 navigation->set_http_connection_info(
289 net::HttpResponseInfo::CONNECTION_INFO_QUIC_35);
290 navigation->ReadyToCommit();
Harkiran Bolariaa2c9f79a2021-07-02 09:25:40291 EXPECT_EQ(blink::mojom::RequestContextType::LOCATION,
Mohamed Abdelhalim40c35d22019-09-19 15:59:05292 NavigationRequest::From(navigation->GetNavigationHandle())
293 ->request_context_type());
bnc90be5dd782016-11-09 16:28:44294 EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_QUIC_35,
Camille Lamy62b826012019-02-26 09:15:47295 navigation->GetNavigationHandle()->GetConnectionInfo());
jkarlinbb150112016-11-02 17:55:11296}
297
Mohamed Abdelhalim1e8c5822019-08-02 11:45:43298TEST_F(NavigationRequestTest, SimpleDataCheckNoRedirect) {
Camille Lamy62b826012019-02-26 09:15:47299 const GURL kUrl = GURL("http://chromium.org");
300 auto navigation =
301 NavigationSimulatorImpl::CreateRendererInitiated(kUrl, main_rfh());
302 navigation->Start();
jkarlinbb150112016-11-02 17:55:11303 EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN,
Camille Lamy62b826012019-02-26 09:15:47304 navigation->GetNavigationHandle()->GetConnectionInfo());
jkarlinbb150112016-11-02 17:55:11305
Camille Lamy62b826012019-02-26 09:15:47306 navigation->set_http_connection_info(
307 net::HttpResponseInfo::CONNECTION_INFO_QUIC_35);
308 navigation->ReadyToCommit();
bnc90be5dd782016-11-09 16:28:44309 EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_QUIC_35,
Camille Lamy62b826012019-02-26 09:15:47310 navigation->GetNavigationHandle()->GetConnectionInfo());
carlosk489d9e22016-07-25 14:25:43311}
312
Mohamed Abdelhalim1e8c5822019-08-02 11:45:43313TEST_F(NavigationRequestTest, SimpleDataChecksFailure) {
Camille Lamy62b826012019-02-26 09:15:47314 const GURL kUrl = GURL("http://chromium.org");
315 auto navigation =
316 NavigationSimulatorImpl::CreateRendererInitiated(kUrl, main_rfh());
317 navigation->Start();
Harkiran Bolariaa2c9f79a2021-07-02 09:25:40318 EXPECT_EQ(blink::mojom::RequestContextType::LOCATION,
Mohamed Abdelhalim40c35d22019-09-19 15:59:05319 NavigationRequest::From(navigation->GetNavigationHandle())
320 ->request_context_type());
Lucas Garron0cedd962017-10-17 07:23:33321 EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN,
Camille Lamy62b826012019-02-26 09:15:47322 navigation->GetNavigationHandle()->GetConnectionInfo());
Lucas Garron0cedd962017-10-17 07:23:33323
Camille Lamy62b826012019-02-26 09:15:47324 navigation->Fail(net::ERR_CERT_DATE_INVALID);
Harkiran Bolariaa2c9f79a2021-07-02 09:25:40325 EXPECT_EQ(blink::mojom::RequestContextType::LOCATION,
Mohamed Abdelhalim40c35d22019-09-19 15:59:05326 NavigationRequest::From(navigation->GetNavigationHandle())
327 ->request_context_type());
Camille Lamy62b826012019-02-26 09:15:47328 EXPECT_EQ(net::ERR_CERT_DATE_INVALID,
329 navigation->GetNavigationHandle()->GetNetErrorCode());
Lucas Garron0cedd962017-10-17 07:23:33330}
331
Yao Xiao6e1f7d32022-01-07 03:28:40332TEST_F(NavigationRequestTest, FencedFrameNavigationToPendingMappedURN) {
333 // Note that we only run this test for the ShadowDOM implementation of fenced
334 // frames, due to how they add subframes in a way that is very specific to the
335 // ShadowDOM implementation, and not suitable for the MPArch implementation.
336 base::test::ScopedFeatureList scoped_feature_list;
337 scoped_feature_list.InitAndEnableFeatureWithParameters(
338 blink::features::kFencedFrames, {{"implementation_type", "shadow_dom"}});
339
340 FrameTree& frame_tree = contents()->GetPrimaryFrameTree();
341 FrameTreeNode* root = frame_tree.root();
342 int process_id = root->current_frame_host()->GetProcess()->GetID();
343
344 // Add a fenced frame.
345 constexpr auto kFencedframeOwnerType =
346 blink::FrameOwnerElementType::kFencedframe;
347 blink::FramePolicy policy;
348 policy.is_fenced = true;
349 AddFrame(frame_tree, root->current_frame_host(), process_id, 15, policy,
350 kFencedframeOwnerType);
351
352 FrameTreeNode* fenced_frame_tree_node = root->child_at(0);
353 EXPECT_TRUE(fenced_frame_tree_node->IsFencedFrameRoot());
354 EXPECT_TRUE(fenced_frame_tree_node->IsInFencedFrameTree());
355
356 FencedFrameURLMapping& fenced_frame_urls_map =
357 main_test_rfh()->GetPage().fenced_frame_urls_map();
358
Xiaochen Zhouc2f3dd52022-09-27 15:40:29359 auto pending_urn_uuid = fenced_frame_urls_map.GeneratePendingMappedURN();
360 EXPECT_TRUE(pending_urn_uuid.has_value());
361 GURL urn_uuid = pending_urn_uuid.value();
Dominic Farolinoe724b5332022-04-26 05:00:06362 const GURL mapped_url = GURL("https://chromium.org");
Yao Xiao6e1f7d32022-01-07 03:28:40363
364 auto navigation_simulator = NavigationSimulatorImpl::CreateRendererInitiated(
365 urn_uuid, fenced_frame_tree_node->current_frame_host());
366
367 auto response_headers =
368 base::MakeRefCounted<net::HttpResponseHeaders>("HTTP/1.1 200 OK");
369 response_headers->SetHeader("Supports-Loading-Mode", "fenced-frame");
370
371 navigation_simulator->SetAutoAdvance(false);
372 navigation_simulator->SetResponseHeaders(response_headers);
373 navigation_simulator->SetTransition(ui::PAGE_TRANSITION_AUTO_SUBFRAME);
374
375 navigation_simulator->Start();
376
377 EXPECT_EQ(navigation_simulator->GetNavigationHandle()->GetURL(), urn_uuid);
378
Yao Xiao1099e4c2022-03-24 22:40:37379 SimulateSharedStorageURNMappingComplete(
380 fenced_frame_urls_map, urn_uuid, mapped_url,
381 /*shared_storage_origin=*/url::Origin::Create(GURL("https://bar.com")),
382 /*budget_to_charge=*/2.0);
Yao Xiao6e1f7d32022-01-07 03:28:40383
384 // Expect that the url in the NavigationRequest is already mapped.
385 EXPECT_EQ(navigation_simulator->GetNavigationHandle()->GetURL(), mapped_url);
386
387 navigation_simulator->Wait();
388
389 navigation_simulator->SetAutoAdvance(true);
390 navigation_simulator->ReadyToCommit();
391 navigation_simulator->Commit();
392
393 EXPECT_EQ(fenced_frame_tree_node->current_url(), mapped_url);
394}
395
clamye88533842015-11-18 12:48:57396// Checks that a navigation deferred during WillStartRequest can be properly
397// cancelled.
Mohamed Abdelhalimba020672019-10-31 16:18:53398TEST_F(NavigationRequestTest, CancelDeferredWillStart) {
clamye88533842015-11-18 12:48:57399 TestNavigationThrottle* test_throttle =
400 CreateTestNavigationThrottle(NavigationThrottle::DEFER);
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19401 EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, state());
Lucas Garron0cedd962017-10-17 07:23:33402 EXPECT_TRUE(call_counts_match(test_throttle, 0, 0, 0, 0));
clamye88533842015-11-18 12:48:57403
404 // Simulate WillStartRequest. The request should be deferred. The callback
405 // should not have been called.
406 SimulateWillStartRequest();
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19407 EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, state());
clamye88533842015-11-18 12:48:57408 EXPECT_FALSE(was_callback_called());
Lucas Garron0cedd962017-10-17 07:23:33409 EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 0, 0));
clamye88533842015-11-18 12:48:57410
411 // Cancel the request. The callback should have been called.
Charles Harrison4f2bf1a2017-07-18 20:21:21412 CancelDeferredNavigation(NavigationThrottle::CANCEL_AND_IGNORE);
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19413 EXPECT_EQ(NavigationRequest::CANCELING, state());
clamye88533842015-11-18 12:48:57414 EXPECT_TRUE(was_callback_called());
415 EXPECT_EQ(NavigationThrottle::CANCEL_AND_IGNORE, callback_result());
Lucas Garron0cedd962017-10-17 07:23:33416 EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 0, 0));
clamye88533842015-11-18 12:48:57417}
418
419// Checks that a navigation deferred during WillRedirectRequest can be properly
420// cancelled.
Mohamed Abdelhalimba020672019-10-31 16:18:53421TEST_F(NavigationRequestTest, CancelDeferredWillRedirect) {
clamye88533842015-11-18 12:48:57422 TestNavigationThrottle* test_throttle =
423 CreateTestNavigationThrottle(NavigationThrottle::DEFER);
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19424 EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, state());
Lucas Garron0cedd962017-10-17 07:23:33425 EXPECT_TRUE(call_counts_match(test_throttle, 0, 0, 0, 0));
clamye88533842015-11-18 12:48:57426
427 // Simulate WillRedirectRequest. The request should be deferred. The callback
428 // should not have been called.
429 SimulateWillRedirectRequest();
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19430 EXPECT_EQ(NavigationRequest::WILL_REDIRECT_REQUEST, state());
clamye88533842015-11-18 12:48:57431 EXPECT_FALSE(was_callback_called());
Lucas Garron0cedd962017-10-17 07:23:33432 EXPECT_TRUE(call_counts_match(test_throttle, 0, 1, 0, 0));
clamye88533842015-11-18 12:48:57433
434 // Cancel the request. The callback should have been called.
Charles Harrison4f2bf1a2017-07-18 20:21:21435 CancelDeferredNavigation(NavigationThrottle::CANCEL_AND_IGNORE);
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19436 EXPECT_EQ(NavigationRequest::CANCELING, state());
clamye88533842015-11-18 12:48:57437 EXPECT_TRUE(was_callback_called());
438 EXPECT_EQ(NavigationThrottle::CANCEL_AND_IGNORE, callback_result());
Lucas Garron0cedd962017-10-17 07:23:33439 EXPECT_TRUE(call_counts_match(test_throttle, 0, 1, 0, 0));
440}
441
442// Checks that a navigation deferred during WillFailRequest can be properly
443// cancelled.
Mohamed Abdelhalimba020672019-10-31 16:18:53444TEST_F(NavigationRequestTest, CancelDeferredWillFail) {
Lucas Garron0cedd962017-10-17 07:23:33445 TestNavigationThrottle* test_throttle = CreateTestNavigationThrottle(
446 TestNavigationThrottle::WILL_FAIL_REQUEST, NavigationThrottle::DEFER);
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19447 EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, state());
Lucas Garron0cedd962017-10-17 07:23:33448 EXPECT_TRUE(call_counts_match(test_throttle, 0, 0, 0, 0));
449
450 // Simulate WillStartRequest.
451 SimulateWillStartRequest();
452 EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 0, 0));
453
454 // Simulate WillFailRequest. The request should be deferred. The callback
455 // should not have been called.
456 SimulateWillFailRequest(net::ERR_CERT_DATE_INVALID);
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19457 EXPECT_EQ(NavigationRequest::WILL_FAIL_REQUEST, state());
Lucas Garron0cedd962017-10-17 07:23:33458 EXPECT_FALSE(was_callback_called());
459 EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 1, 0));
460
461 // Cancel the request. The callback should have been called.
462 CancelDeferredNavigation(NavigationThrottle::CANCEL_AND_IGNORE);
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19463 EXPECT_EQ(NavigationRequest::CANCELING, state());
Lucas Garron0cedd962017-10-17 07:23:33464 EXPECT_TRUE(was_callback_called());
465 EXPECT_EQ(NavigationThrottle::CANCEL_AND_IGNORE, callback_result());
466 EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 1, 0));
clamye88533842015-11-18 12:48:57467}
468
469// Checks that a navigation deferred can be canceled and not ignored.
Mohamed Abdelhalimba020672019-10-31 16:18:53470TEST_F(NavigationRequestTest, CancelDeferredWillRedirectNoIgnore) {
clamye88533842015-11-18 12:48:57471 TestNavigationThrottle* test_throttle =
472 CreateTestNavigationThrottle(NavigationThrottle::DEFER);
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19473 EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, state());
Lucas Garron0cedd962017-10-17 07:23:33474 EXPECT_TRUE(call_counts_match(test_throttle, 0, 0, 0, 0));
clamye88533842015-11-18 12:48:57475
Lucas Garron0cedd962017-10-17 07:23:33476 // Simulate WillStartRequest. The request should be deferred. The callback
clamye88533842015-11-18 12:48:57477 // should not have been called.
478 SimulateWillStartRequest();
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19479 EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, state());
Lucas Garron0cedd962017-10-17 07:23:33480 EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 0, 0));
clamye88533842015-11-18 12:48:57481
482 // Cancel the request. The callback should have been called with CANCEL, and
483 // not CANCEL_AND_IGNORE.
Charles Harrison4f2bf1a2017-07-18 20:21:21484 CancelDeferredNavigation(NavigationThrottle::CANCEL);
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19485 EXPECT_EQ(NavigationRequest::CANCELING, state());
clamye88533842015-11-18 12:48:57486 EXPECT_TRUE(was_callback_called());
487 EXPECT_EQ(NavigationThrottle::CANCEL, callback_result());
Lucas Garron0cedd962017-10-17 07:23:33488 EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 0, 0));
clamye88533842015-11-18 12:48:57489}
490
Lucas Garron0cedd962017-10-17 07:23:33491// Checks that a navigation deferred by WillFailRequest can be canceled and not
492// ignored.
Mohamed Abdelhalimba020672019-10-31 16:18:53493TEST_F(NavigationRequestTest, CancelDeferredWillFailNoIgnore) {
Lucas Garron0cedd962017-10-17 07:23:33494 TestNavigationThrottle* test_throttle = CreateTestNavigationThrottle(
495 TestNavigationThrottle::WILL_FAIL_REQUEST, NavigationThrottle::DEFER);
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19496 EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, state());
Lucas Garron0cedd962017-10-17 07:23:33497 EXPECT_TRUE(call_counts_match(test_throttle, 0, 0, 0, 0));
498
499 // Simulate WillStartRequest.
500 SimulateWillStartRequest();
501 EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 0, 0));
502
503 // Simulate WillFailRequest. The request should be deferred. The callback
504 // should not have been called.
505 SimulateWillFailRequest(net::ERR_CERT_DATE_INVALID);
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19506 EXPECT_EQ(NavigationRequest::WILL_FAIL_REQUEST, state());
Lucas Garron0cedd962017-10-17 07:23:33507 EXPECT_FALSE(was_callback_called());
508 EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 1, 0));
509
510 // Cancel the request. The callback should have been called with CANCEL, and
511 // not CANCEL_AND_IGNORE.
512 CancelDeferredNavigation(NavigationThrottle::CANCEL);
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19513 EXPECT_EQ(NavigationRequest::CANCELING, state());
Lucas Garron0cedd962017-10-17 07:23:33514 EXPECT_TRUE(was_callback_called());
515 EXPECT_EQ(NavigationThrottle::CANCEL, callback_result());
516 EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 1, 0));
517}
518
Lucas Garronc1edb5ab2017-11-08 03:31:13519// Checks that data from the SSLInfo passed into SimulateWillStartRequest() is
John Abd-El-Malekf36e05f2017-11-30 16:17:52520// stored on the handle.
Mohamed Abdelhalim1e8c5822019-08-02 11:45:43521TEST_F(NavigationRequestTest, WillFailRequestSetsSSLInfo) {
Lucas Garronc1edb5ab2017-11-08 03:31:13522 uint16_t cipher_suite = 0xc02f; // TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
523 int connection_status = 0;
524 net::SSLConnectionStatusSetCipherSuite(cipher_suite, &connection_status);
525
526 // Set some test values.
527 net::SSLInfo ssl_info;
528 ssl_info.cert_status = net::CERT_STATUS_AUTHORITY_INVALID;
529 ssl_info.connection_status = connection_status;
530
Camille Lamy62b826012019-02-26 09:15:47531 const GURL kUrl = GURL("https://chromium.org");
532 auto navigation =
533 NavigationSimulatorImpl::CreateRendererInitiated(kUrl, main_rfh());
Emily Starkfd6978ad12019-04-30 21:20:07534 navigation->SetSSLInfo(ssl_info);
Camille Lamy62b826012019-02-26 09:15:47535 navigation->Fail(net::ERR_CERT_DATE_INVALID);
Lucas Garronc1edb5ab2017-11-08 03:31:13536
537 EXPECT_EQ(net::CERT_STATUS_AUTHORITY_INVALID,
Camille Lamy62b826012019-02-26 09:15:47538 navigation->GetNavigationHandle()->GetSSLInfo()->cert_status);
539 EXPECT_EQ(connection_status,
540 navigation->GetNavigationHandle()->GetSSLInfo()->connection_status);
Lucas Garronc1edb5ab2017-11-08 03:31:13541}
542
Camille Lamy62b826012019-02-26 09:15:47543namespace {
544
Alex Moshchuk1a66b1d2018-05-15 21:18:26545// Helper throttle which checks that it can access NavigationHandle's
546// RenderFrameHost in WillFailRequest() and then defers the failure.
547class GetRenderFrameHostOnFailureNavigationThrottle
548 : public NavigationThrottle {
549 public:
Fergal Dalya1d569972021-03-16 03:24:53550 explicit GetRenderFrameHostOnFailureNavigationThrottle(
551 NavigationHandle* handle)
Alex Moshchuk1a66b1d2018-05-15 21:18:26552 : NavigationThrottle(handle) {}
Peter Boström828b9022021-09-21 02:28:43553
554 GetRenderFrameHostOnFailureNavigationThrottle(
555 const GetRenderFrameHostOnFailureNavigationThrottle&) = delete;
556 GetRenderFrameHostOnFailureNavigationThrottle& operator=(
557 const GetRenderFrameHostOnFailureNavigationThrottle&) = delete;
558
Fergal Dalya1d569972021-03-16 03:24:53559 ~GetRenderFrameHostOnFailureNavigationThrottle() override = default;
Alex Moshchuk1a66b1d2018-05-15 21:18:26560
561 NavigationThrottle::ThrottleCheckResult WillFailRequest() override {
562 EXPECT_TRUE(navigation_handle()->GetRenderFrameHost());
563 return NavigationThrottle::DEFER;
564 }
565
566 const char* GetNameForLogging() override {
567 return "GetRenderFrameHostOnFailureNavigationThrottle";
568 }
Alex Moshchuk1a66b1d2018-05-15 21:18:26569};
570
Camille Lamy62b826012019-02-26 09:15:47571class ThrottleTestContentBrowserClient : public ContentBrowserClient {
572 std::vector<std::unique_ptr<NavigationThrottle>> CreateThrottlesForNavigation(
573 NavigationHandle* navigation_handle) override {
574 std::vector<std::unique_ptr<NavigationThrottle>> throttle;
575 throttle.push_back(
576 std::make_unique<GetRenderFrameHostOnFailureNavigationThrottle>(
577 navigation_handle));
578 return throttle;
579 }
580};
581
582} // namespace
583
Alex Moshchuk1a66b1d2018-05-15 21:18:26584// Verify that the NavigationHandle::GetRenderFrameHost() can be retrieved by a
585// throttle in WillFailRequest(), as well as after deferring the failure. This
586// is allowed, since at that point the final RenderFrameHost will have already
587// been chosen. See https://crbug.com/817881.
Mohamed Abdelhalimba020672019-10-31 16:18:53588TEST_F(NavigationRequestTest, WillFailRequestCanAccessRenderFrameHost) {
Camille Lamy62b826012019-02-26 09:15:47589 std::unique_ptr<ContentBrowserClient> client(
590 new ThrottleTestContentBrowserClient);
591 ContentBrowserClient* old_browser_client =
592 SetBrowserClientForTesting(client.get());
593
594 const GURL kUrl = GURL("http://chromium.org");
595 auto navigation =
596 NavigationSimulatorImpl::CreateRendererInitiated(kUrl, main_rfh());
597 navigation->SetAutoAdvance(false);
598 navigation->Start();
599 navigation->Fail(net::ERR_CERT_DATE_INVALID);
Mohamed Abdelhalim3b235272019-11-05 15:06:07600 EXPECT_EQ(
601 NavigationRequest::WILL_FAIL_REQUEST,
602 NavigationRequest::From(navigation->GetNavigationHandle())->state());
Camille Lamy62b826012019-02-26 09:15:47603 EXPECT_TRUE(navigation->GetNavigationHandle()->GetRenderFrameHost());
Mohamed Abdelhalim40c35d22019-09-19 15:59:05604 NavigationRequest::From(navigation->GetNavigationHandle())
danakjf26536bf2020-09-10 00:46:13605 ->GetNavigationThrottleRunnerForTesting()
Mohamed Abdelhalim40c35d22019-09-19 15:59:05606 ->CallResumeForTesting();
Camille Lamy62b826012019-02-26 09:15:47607 EXPECT_TRUE(navigation->GetNavigationHandle()->GetRenderFrameHost());
608
609 SetBrowserClientForTesting(old_browser_client);
Alex Moshchuk1a66b1d2018-05-15 21:18:26610}
611
Antonio Sartori3cfa3b62020-10-09 10:42:40612TEST_F(NavigationRequestTest, PolicyContainerInheritance) {
613 struct TestCase {
614 const char* url;
615 bool expect_inherit;
616 } cases[]{{"about:blank", true},
617 {"data:text/plain,hello", true},
618 {"file://local", false},
619 {"http://chromium.org", false}};
620
621 const GURL kUrl1 = GURL("http://chromium.org");
622 auto navigation =
623 NavigationSimulatorImpl::CreateRendererInitiated(kUrl1, main_rfh());
624 navigation->Commit();
625
626 for (auto test : cases) {
627 // We navigate child frames because the BlockedSchemeNavigationThrottle
628 // restricts navigations in the main frame.
629 auto* child_frame = static_cast<TestRenderFrameHost*>(
630 content::RenderFrameHostTester::For(main_rfh())->AppendChild("child"));
631
632 // We set the referrer policy of the frame to "always". We then create a new
633 // navigation, set as initiator the frame itself, start the navigation, and
634 // change the referrer policy of the frame to "never". After we commit the
635 // navigation:
636 // - If navigating to a local scheme, the target frame should have inherited
637 // the referrer policy of the initiator ("always").
638 // - If navigating to a non-local scheme, the target frame should have a new
639 // policy container (hence referrer policy set to "default").
640 const GURL kUrl = GURL(test.url);
Peter Kastingeb8c3ce2021-08-20 04:39:35641 navigation =
Antonio Sartori3cfa3b62020-10-09 10:42:40642 NavigationSimulatorImpl::CreateRendererInitiated(kUrl, child_frame);
Antonio Sartori5b2f8042020-10-23 18:13:26643 static_cast<blink::mojom::PolicyContainerHost*>(
Antonio Sartori9290b6b2020-11-09 10:09:33644 child_frame->policy_container_host())
Antonio Sartori5b2f8042020-10-23 18:13:26645 ->SetReferrerPolicy(network::mojom::ReferrerPolicy::kAlways);
Antonio Sartori3cfa3b62020-10-09 10:42:40646 navigation->SetInitiatorFrame(child_frame);
647 navigation->Start();
Antonio Sartori5b2f8042020-10-23 18:13:26648 static_cast<blink::mojom::PolicyContainerHost*>(
Antonio Sartori9290b6b2020-11-09 10:09:33649 child_frame->policy_container_host())
Antonio Sartori5b2f8042020-10-23 18:13:26650 ->SetReferrerPolicy(network::mojom::ReferrerPolicy::kNever);
Antonio Sartori3cfa3b62020-10-09 10:42:40651 navigation->Commit();
652 EXPECT_EQ(
653 test.expect_inherit ? network::mojom::ReferrerPolicy::kAlways
654 : network::mojom::ReferrerPolicy::kDefault,
655 static_cast<RenderFrameHostImpl*>(navigation->GetFinalRenderFrameHost())
Antonio Sartori9290b6b2020-11-09 10:09:33656 ->policy_container_host()
Antonio Sartori3cfa3b62020-10-09 10:42:40657 ->referrer_policy());
658 }
659}
660
Cammie Smith Barnesa0da2cf2021-01-11 22:09:37661TEST_F(NavigationRequestTest, DnsAliasesCanBeAccessed) {
662 // Create simulated NavigationRequest for the URL, which has aliases.
663 const GURL kUrl = GURL("http://chromium.org");
664 auto navigation =
665 NavigationSimulatorImpl::CreateRendererInitiated(kUrl, main_rfh());
666 std::vector<std::string> dns_aliases({"alias1", "alias2"});
667 navigation->SetResponseDnsAliases(std::move(dns_aliases));
668
669 // Start the navigation.
670 navigation->Start();
671 EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN,
672 navigation->GetNavigationHandle()->GetConnectionInfo());
673
674 // Commit the navigation.
675 navigation->set_http_connection_info(
676 net::HttpResponseInfo::CONNECTION_INFO_QUIC_35);
677 navigation->ReadyToCommit();
678 EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_QUIC_35,
679 navigation->GetNavigationHandle()->GetConnectionInfo());
680
681 // Verify that the aliases are accessible from the NavigationRequest.
682 EXPECT_THAT(navigation->GetNavigationHandle()->GetDnsAliases(),
683 testing::ElementsAre("alias1", "alias2"));
684}
685
686TEST_F(NavigationRequestTest, NoDnsAliases) {
687 // Create simulated NavigationRequest for the URL, which does not
688 // have aliases. (Note the empty alias list.)
689 const GURL kUrl = GURL("http://chromium.org");
690 auto navigation =
691 NavigationSimulatorImpl::CreateRendererInitiated(kUrl, main_rfh());
692 std::vector<std::string> dns_aliases;
693 navigation->SetResponseDnsAliases(std::move(dns_aliases));
694
695 // Start the navigation.
696 navigation->Start();
697 EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN,
698 navigation->GetNavigationHandle()->GetConnectionInfo());
699
700 // Commit the navigation.
701 navigation->set_http_connection_info(
702 net::HttpResponseInfo::CONNECTION_INFO_QUIC_35);
703 navigation->ReadyToCommit();
704 EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_QUIC_35,
705 navigation->GetNavigationHandle()->GetConnectionInfo());
706
707 // Verify that there are no aliases in the NavigationRequest.
708 EXPECT_TRUE(navigation->GetNavigationHandle()->GetDnsAliases().empty());
709}
710
Antonio Sartori3e8de6d2021-07-26 10:28:41711TEST_F(NavigationRequestTest, StorageKeyToCommit) {
712 TestRenderFrameHost* child_document = static_cast<TestRenderFrameHost*>(
713 content::RenderFrameHostTester::For(main_rfh())->AppendChild(""));
Yuzu Saijo03dbf9b2022-07-22 04:29:45714 auto attributes = child_document->frame_tree_node()->attributes_->Clone();
715 // Set |anonymous| to true.
716 attributes->anonymous = true;
717 child_document->frame_tree_node()->SetAttributes(std::move(attributes));
Antonio Sartori3e8de6d2021-07-26 10:28:41718
719 const GURL kUrl = GURL("http://chromium.org");
720 auto navigation =
721 NavigationSimulatorImpl::CreateRendererInitiated(kUrl, child_document);
722 navigation->ReadyToCommit();
723 NavigationRequest* request =
724 NavigationRequest::From(navigation->GetNavigationHandle());
725 EXPECT_TRUE(request->commit_params().storage_key.nonce().has_value());
Ali Hijazi78de14c2022-07-21 11:32:19726 EXPECT_EQ(child_document->GetMainFrame()->anonymous_iframes_nonce(),
Antonio Sartori3e8de6d2021-07-26 10:28:41727 request->commit_params().storage_key.nonce().value());
728
729 navigation->Commit();
730 child_document =
731 static_cast<TestRenderFrameHost*>(navigation->GetFinalRenderFrameHost());
Arthur Sonzognie41678a2022-06-16 15:51:19732 EXPECT_TRUE(child_document->IsAnonymous());
Ali Hijazi78de14c2022-07-21 11:32:19733 EXPECT_EQ(blink::StorageKey::CreateWithNonce(
734 url::Origin::Create(kUrl),
735 child_document->GetMainFrame()->anonymous_iframes_nonce()),
736 child_document->storage_key());
Antonio Sartori3e8de6d2021-07-26 10:28:41737}
738
Antonio Sartoribf27cc442021-08-25 13:08:23739TEST_F(NavigationRequestTest,
740 NavigationToAnonymousDocumentNetworkIsolationInfo) {
741 auto* child_frame = static_cast<TestRenderFrameHost*>(
742 content::RenderFrameHostTester::For(main_test_rfh())
743 ->AppendChild("child"));
Yuzu Saijo03dbf9b2022-07-22 04:29:45744 auto attributes = child_frame->frame_tree_node()->attributes_->Clone();
745 // Set |anonymous| to true.
746 attributes->anonymous = true;
747 child_frame->frame_tree_node()->SetAttributes(std::move(attributes));
Antonio Sartoribf27cc442021-08-25 13:08:23748
749 std::unique_ptr<NavigationSimulator> navigation =
750 NavigationSimulator::CreateRendererInitiated(
751 GURL("https://example.com/navigation.html"), child_frame);
752 navigation->ReadyToCommit();
753
Ali Hijazi78de14c2022-07-21 11:32:19754 EXPECT_EQ(main_test_rfh()->anonymous_iframes_nonce(),
Antonio Sartoribf27cc442021-08-25 13:08:23755 static_cast<NavigationRequest*>(navigation->GetNavigationHandle())
756 ->isolation_info_for_subresources()
757 .network_isolation_key()
758 .GetNonce());
Ali Hijazi78de14c2022-07-21 11:32:19759 EXPECT_EQ(main_test_rfh()->anonymous_iframes_nonce(),
Antonio Sartoribf27cc442021-08-25 13:08:23760 static_cast<NavigationRequest*>(navigation->GetNavigationHandle())
761 ->GetIsolationInfo()
762 .network_isolation_key()
763 .GetNonce());
764}
765
Robbie McElrath5641d572022-05-20 17:15:29766class ScopedIsolatedAppBrowserClient : public ContentBrowserClient {
767 public:
768 ScopedIsolatedAppBrowserClient()
769 : old_client_(SetBrowserClientForTesting(this)) {}
770
771 ~ScopedIsolatedAppBrowserClient() override {
772 SetBrowserClientForTesting(old_client_);
773 }
774
775 bool ShouldUrlUseApplicationIsolationLevel(BrowserContext* browser_context,
776 const GURL& url) override {
777 return true;
778 }
779
780 private:
781 raw_ptr<ContentBrowserClient> old_client_;
782};
783
784TEST_F(NavigationRequestTest, IsolatedAppPolicyInjection) {
785 const GURL kUrl = GURL("https://chromium.org");
786 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
787 switches::kIsolatedAppOrigins, kUrl.spec());
788 // Disable flag caching so the --isolated-app-origins value takes effect.
789 SiteIsolationPolicy::DisableFlagCachingForTesting();
790 ScopedIsolatedAppBrowserClient client;
791
792 auto navigation =
793 NavigationSimulatorImpl::CreateRendererInitiated(kUrl, main_rfh());
794 navigation->ReadyToCommit();
795
796 // Validate the COOP/COEP headers.
797 const PolicyContainerPolicies& policies =
798 navigation->GetNavigationHandle()->GetPolicyContainerPolicies();
799 EXPECT_EQ(network::mojom::CrossOriginOpenerPolicyValue::kSameOriginPlusCoep,
800 policies.cross_origin_opener_policy.value);
801 EXPECT_EQ(network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp,
802 policies.cross_origin_embedder_policy.value);
803
804 // Validate CSP.
805 EXPECT_EQ(1UL, policies.content_security_policies.size());
806 const auto& csp = policies.content_security_policies[0];
Ovidio Ruiz-Henríquezadd3f402022-10-17 19:10:31807 EXPECT_EQ(10UL, csp->raw_directives.size());
Robbie McElrath5641d572022-05-20 17:15:29808 using Directive = network::mojom::CSPDirectiveName;
809 EXPECT_EQ("'none'", csp->raw_directives[Directive::BaseURI]);
810 EXPECT_EQ("'none'", csp->raw_directives[Directive::ObjectSrc]);
811 EXPECT_EQ("'self'", csp->raw_directives[Directive::DefaultSrc]);
812 EXPECT_EQ("'self' https:", csp->raw_directives[Directive::FrameSrc]);
813 EXPECT_EQ("'self' https:", csp->raw_directives[Directive::ConnectSrc]);
Robbie McElrathb062f3d2022-08-09 17:48:44814 EXPECT_EQ("'self' 'wasm-unsafe-eval'",
815 csp->raw_directives[Directive::ScriptSrc]);
Ovidio Ruiz-Henríquezadd3f402022-10-17 19:10:31816 EXPECT_EQ("'self' data:", csp->raw_directives[Directive::ImgSrc]);
817 EXPECT_EQ("'self' data:", csp->raw_directives[Directive::MediaSrc]);
818 EXPECT_EQ("'self' data:", csp->raw_directives[Directive::FontSrc]);
Robbie McElrath5641d572022-05-20 17:15:29819 EXPECT_EQ("'script'", csp->raw_directives[Directive::RequireTrustedTypesFor]);
820}
821
arthursonzogni898dcda52021-01-21 08:50:10822// Test that the required CSP of every frame is computed/inherited correctly and
823// that the Sec-Required-CSP header is set.
824class CSPEmbeddedEnforcementUnitTest : public NavigationRequestTest {
825 protected:
826 TestRenderFrameHost* main_rfh() {
827 return static_cast<TestRenderFrameHost*>(NavigationRequestTest::main_rfh());
828 }
829
830 // Simulate the |csp| attribute being set in |rfh|'s frame. Then navigate it.
831 // Returns the request's Sec-Required-CSP header.
832 std::string NavigateWithRequiredCSP(TestRenderFrameHost** rfh,
833 std::string required_csp) {
834 TestRenderFrameHost* document = *rfh;
835
836 if (!required_csp.empty()) {
837 auto headers =
838 base::MakeRefCounted<net::HttpResponseHeaders>("HTTP/1.1 200 OK");
839 headers->SetHeader("Content-Security-Policy", required_csp);
840 std::vector<network::mojom::ContentSecurityPolicyPtr> policies;
841 network::AddContentSecurityPolicyFromHeaders(
842 *headers, GURL("https://example.com/"), &policies);
Yuzu Saijo03dbf9b2022-07-22 04:29:45843 auto attributes = document->frame_tree_node()->attributes_->Clone();
844 // Set csp value.
845 attributes->parsed_csp_attribute = std::move(policies[0]);
846 document->frame_tree_node()->SetAttributes(std::move(attributes));
arthursonzogni898dcda52021-01-21 08:50:10847 }
848
849 // Chrome blocks a document navigating to a URL if more than one of its
850 // ancestors have the same URL. Use a different URL every time, to
851 // avoid blocking navigation of the grandchild frame.
852 static int nonce = 0;
853 GURL url("https://www.example.com" + base::NumberToString(nonce++));
854
855 auto navigation =
856 content::NavigationSimulator::CreateRendererInitiated(url, *rfh);
857 navigation->Start();
858 NavigationRequest* request =
859 NavigationRequest::From(navigation->GetNavigationHandle());
860 std::string sec_required_csp;
861 request->GetRequestHeaders().GetHeader("sec-required-csp",
862 &sec_required_csp);
863
864 // Complete the navigation so that the required csp is stored in the
865 // RenderFrameHost, so that when we will add children to this document they
866 // will be able to get the parent's required csp (and hence also test that
867 // the whole logic works).
868 auto response_headers =
869 base::MakeRefCounted<net::HttpResponseHeaders>("HTTP/1.1 200 OK");
870 response_headers->SetHeader("Allow-CSP-From", "*");
871 navigation->SetResponseHeaders(response_headers);
872 navigation->Commit();
873
874 *rfh = static_cast<TestRenderFrameHost*>(
875 navigation->GetFinalRenderFrameHost());
876
877 return sec_required_csp;
878 }
879
880 TestRenderFrameHost* AddChild(TestRenderFrameHost* parent) {
881 return static_cast<TestRenderFrameHost*>(
882 content::RenderFrameHostTester::For(parent)->AppendChild(""));
883 }
884};
885
886TEST_F(CSPEmbeddedEnforcementUnitTest, TopLevel) {
887 TestRenderFrameHost* top_document = main_rfh();
888 std::string sec_required_csp = NavigateWithRequiredCSP(&top_document, "");
889 EXPECT_EQ("", sec_required_csp);
890 EXPECT_FALSE(top_document->required_csp());
891}
892
893TEST_F(CSPEmbeddedEnforcementUnitTest, ChildNoCSP) {
894 TestRenderFrameHost* top_document = main_rfh();
895 TestRenderFrameHost* child_document = AddChild(top_document);
896 std::string sec_required_csp = NavigateWithRequiredCSP(&child_document, "");
897 EXPECT_EQ("", sec_required_csp);
898 EXPECT_FALSE(child_document->required_csp());
899}
900
901TEST_F(CSPEmbeddedEnforcementUnitTest, ChildWithCSP) {
902 TestRenderFrameHost* top_document = main_rfh();
903 TestRenderFrameHost* child_document = AddChild(top_document);
904 std::string sec_required_csp =
905 NavigateWithRequiredCSP(&child_document, "script-src 'none'");
906 EXPECT_EQ("script-src 'none'", sec_required_csp);
907 EXPECT_TRUE(child_document->required_csp());
908 EXPECT_EQ("script-src 'none'",
909 child_document->required_csp()->header->header_value);
910}
911
912TEST_F(CSPEmbeddedEnforcementUnitTest, ChildSiblingNoCSP) {
913 TestRenderFrameHost* top_document = main_rfh();
914 TestRenderFrameHost* child_document = AddChild(top_document);
915 NavigateWithRequiredCSP(&child_document, "script-src 'none'");
916 TestRenderFrameHost* sibling_document = AddChild(top_document);
917 std::string sec_required_csp = NavigateWithRequiredCSP(&sibling_document, "");
918 EXPECT_FALSE(sibling_document->required_csp());
919}
920
921TEST_F(CSPEmbeddedEnforcementUnitTest, ChildSiblingCSP) {
922 TestRenderFrameHost* top_document = main_rfh();
923 TestRenderFrameHost* child_document = AddChild(top_document);
924 NavigateWithRequiredCSP(&child_document, "script-src 'none'");
925 TestRenderFrameHost* sibling_document = AddChild(top_document);
926 std::string sec_required_csp =
927 NavigateWithRequiredCSP(&sibling_document, "script-src 'none'");
928 EXPECT_EQ("script-src 'none'", sec_required_csp);
929 EXPECT_TRUE(sibling_document->required_csp());
930 EXPECT_EQ("script-src 'none'",
931 sibling_document->required_csp()->header->header_value);
932}
933
934TEST_F(CSPEmbeddedEnforcementUnitTest, GrandChildNoCSP) {
935 TestRenderFrameHost* top_document = main_rfh();
936 TestRenderFrameHost* child_document = AddChild(top_document);
937 NavigateWithRequiredCSP(&child_document, "script-src 'none'");
938 TestRenderFrameHost* grand_child_document = AddChild(child_document);
939 std::string sec_required_csp =
940 NavigateWithRequiredCSP(&grand_child_document, "");
941 EXPECT_EQ("script-src 'none'", sec_required_csp);
942 EXPECT_TRUE(grand_child_document->required_csp());
943 EXPECT_EQ("script-src 'none'",
944 grand_child_document->required_csp()->header->header_value);
945}
946
947TEST_F(CSPEmbeddedEnforcementUnitTest, GrandChildSameCSP) {
948 TestRenderFrameHost* top_document = main_rfh();
949 TestRenderFrameHost* child_document = AddChild(top_document);
950 NavigateWithRequiredCSP(&child_document, "script-src 'none'");
951 TestRenderFrameHost* grand_child_document = AddChild(child_document);
952 std::string sec_required_csp =
953 NavigateWithRequiredCSP(&grand_child_document, "script-src 'none'");
954 EXPECT_EQ("script-src 'none'", sec_required_csp);
955 EXPECT_TRUE(grand_child_document->required_csp());
956 EXPECT_EQ("script-src 'none'",
957 grand_child_document->required_csp()->header->header_value);
958}
959
960TEST_F(CSPEmbeddedEnforcementUnitTest, GrandChildDifferentCSP) {
961 TestRenderFrameHost* top_document = main_rfh();
962 TestRenderFrameHost* child_document = AddChild(top_document);
963 NavigateWithRequiredCSP(&child_document, "script-src 'none'");
964 TestRenderFrameHost* grand_child_document = AddChild(child_document);
965 std::string sec_required_csp =
966 NavigateWithRequiredCSP(&grand_child_document, "img-src 'none'");
967
968 // This seems weird, but it is the intended behaviour according to the spec.
969 // The problem is that "script-src 'none'" does not subsume "img-src 'none'",
970 // so "img-src 'none'" on the grandchild is an invalid csp attribute, and we
971 // just discard it in favour of the parent's csp attribute.
972 //
973 // This should probably be fixed in the specification:
974 // https://github.com/w3c/webappsec-cspee/pull/11
975 EXPECT_EQ("script-src 'none'", sec_required_csp);
976 EXPECT_TRUE(grand_child_document->required_csp());
977 EXPECT_EQ("script-src 'none'",
978 grand_child_document->required_csp()->header->header_value);
979}
980
981TEST_F(CSPEmbeddedEnforcementUnitTest, InvalidCSP) {
982 TestRenderFrameHost* top_document = main_rfh();
983 TestRenderFrameHost* child_document = AddChild(top_document);
984 std::string sec_required_csp =
985 NavigateWithRequiredCSP(&child_document, "report-to group");
986 EXPECT_EQ("", sec_required_csp);
987 EXPECT_FALSE(child_document->required_csp());
988}
989
990TEST_F(CSPEmbeddedEnforcementUnitTest, InvalidCspAndInheritFromParent) {
991 TestRenderFrameHost* top_document = main_rfh();
992 TestRenderFrameHost* child_document = AddChild(top_document);
993 NavigateWithRequiredCSP(&child_document, "script-src 'none'");
994 TestRenderFrameHost* grand_child_document = AddChild(child_document);
995 std::string sec_required_csp =
Antonio Sartori4231e932021-02-04 12:01:14996 NavigateWithRequiredCSP(&grand_child_document, "report-to group");
arthursonzogni898dcda52021-01-21 08:50:10997 EXPECT_EQ("script-src 'none'", sec_required_csp);
998 EXPECT_TRUE(grand_child_document->required_csp());
999 EXPECT_EQ("script-src 'none'",
1000 grand_child_document->required_csp()->header->header_value);
1001}
1002
1003TEST_F(CSPEmbeddedEnforcementUnitTest,
1004 SemiInvalidCspAndInheritSameCspFromParent) {
1005 TestRenderFrameHost* top_document = main_rfh();
1006 TestRenderFrameHost* child_document = AddChild(top_document);
1007 NavigateWithRequiredCSP(&child_document, "script-src 'none'");
1008 TestRenderFrameHost* grand_child_document = AddChild(child_document);
1009 std::string sec_required_csp = NavigateWithRequiredCSP(
Antonio Sartori4231e932021-02-04 12:01:141010 &grand_child_document, "script-src 'none'; report-to group");
arthursonzogni898dcda52021-01-21 08:50:101011 EXPECT_EQ("script-src 'none'", sec_required_csp);
1012 EXPECT_TRUE(grand_child_document->required_csp());
1013 EXPECT_EQ("script-src 'none'",
1014 grand_child_document->required_csp()->header->header_value);
1015}
1016
1017TEST_F(CSPEmbeddedEnforcementUnitTest,
1018 SemiInvalidCspAndInheritDifferentCspFromParent) {
1019 TestRenderFrameHost* top_document = main_rfh();
1020 TestRenderFrameHost* child_document = AddChild(top_document);
1021 NavigateWithRequiredCSP(&child_document, "script-src 'none'");
1022 TestRenderFrameHost* grand_child_document = AddChild(child_document);
1023 std::string sec_required_csp = NavigateWithRequiredCSP(
Antonio Sartori4231e932021-02-04 12:01:141024 &grand_child_document, "sandbox; report-to group");
arthursonzogni898dcda52021-01-21 08:50:101025 EXPECT_EQ("script-src 'none'", sec_required_csp);
1026 EXPECT_TRUE(grand_child_document->required_csp());
1027 EXPECT_EQ("script-src 'none'",
1028 grand_child_document->required_csp()->header->header_value);
1029}
1030
Peter Birk Pakkenberg73e07b62022-09-21 11:20:301031namespace {
1032
1033// Mock that allows us to avoid depending on the origin_trials component.
1034class OriginTrialsControllerDelegateMock
1035 : public OriginTrialsControllerDelegate {
1036 public:
1037 ~OriginTrialsControllerDelegateMock() override = default;
1038
1039 void PersistTrialsFromTokens(
1040 const url::Origin& origin,
1041 const base::span<const std::string> header_tokens,
1042 const base::Time current_time) override {
1043 persisted_tokens_[origin] =
1044 std::vector<std::string>(header_tokens.begin(), header_tokens.end());
1045 }
1046 bool IsTrialPersistedForOrigin(const url::Origin& origin,
1047 const base::StringPiece trial_name,
1048 const base::Time current_time) override {
1049 DCHECK(false) << "Method not implemented for test.";
1050 return false;
1051 }
1052
Peter Birk Pakkenberg4c1bb272022-09-27 10:51:291053 base::flat_set<std::string> GetPersistedTrialsForOrigin(
1054 const url::Origin& origin,
1055 base::Time current_time) override {
1056 DCHECK(false) << "Method not implemented for test.";
1057 return base::flat_set<std::string>();
1058 }
1059
Peter Birk Pakkenberg73e07b62022-09-21 11:20:301060 base::flat_map<url::Origin, std::vector<std::string>> persisted_tokens_;
1061};
1062
1063} // namespace
1064
1065class PersistentOriginTrialNavigationRequestTest
1066 : public NavigationRequestTest {
1067 public:
1068 PersistentOriginTrialNavigationRequestTest()
1069 : delegate_mock_(std::make_unique<OriginTrialsControllerDelegateMock>()) {
1070
1071 }
1072 ~PersistentOriginTrialNavigationRequestTest() override = default;
1073
1074 std::vector<std::string> GetPersistedTokens(const url::Origin& origin) {
1075 return delegate_mock_->persisted_tokens_[origin];
1076 }
1077
1078 protected:
1079 std::unique_ptr<BrowserContext> CreateBrowserContext() override {
1080 std::unique_ptr<TestBrowserContext> context =
1081 std::make_unique<TestBrowserContext>();
1082 context->SetOriginTrialsControllerDelegate(delegate_mock_.get());
1083 return context;
1084 }
1085
1086 private:
1087 std::unique_ptr<OriginTrialsControllerDelegateMock> delegate_mock_;
1088};
1089
1090// Ensure that navigations with a valid Origin-Trial header with a persistent
1091// origin trial token results in the trial being marked as enabled.
1092// Then check that subsequent navigations without headers trigger an update
1093// that clears out stored trials.
1094TEST_F(PersistentOriginTrialNavigationRequestTest,
1095 NavigationCommitsPersistentOriginTrials) {
1096 // Generated with:
1097 // tools/origin_trials/generate_token.py https://example.com
1098 // FrobulatePersistent
1099 // --expire-timestamp=2000000000
1100 const char kPersistentOriginTrialToken[] =
1101 "AzZfd1vKZ0SSGRGk/"
1102 "8nIszQSlHYjbuYVE3jwaNZG3X4t11zRhzPWWJwTZ+JJDS3JJsyEZcpz+y20pAP6/"
1103 "6upOQ4AAABdeyJvcmlnaW4iOiAiaHR0cHM6Ly9leGFtcGxlLmNvbTo0NDMiLCAiZmVhdHVyZ"
1104 "SI"
1105 "6ICJGcm9idWxhdGVQZXJzaXN0ZW50IiwgImV4cGlyeSI6IDIwMDAwMDAwMDB9";
1106
1107 base::test::ScopedFeatureList scoped_feature_list;
1108 scoped_feature_list.InitAndEnableFeature(features::kPersistentOriginTrials);
1109 blink::ScopedTestOriginTrialPolicy origin_trial_policy_;
1110
1111 const GURL kUrl = GURL("https://example.com");
1112 auto navigation =
1113 NavigationSimulatorImpl::CreateRendererInitiated(kUrl, main_rfh());
1114
1115 auto response_headers =
1116 base::MakeRefCounted<net::HttpResponseHeaders>("HTTP/1.1 200 OK");
1117 response_headers->SetHeader("Origin-Trial", kPersistentOriginTrialToken);
1118 navigation->SetResponseHeaders(response_headers);
1119
1120 navigation->Commit();
1121
1122 url::Origin origin = url::Origin::Create(kUrl);
1123 EXPECT_EQ(std::vector<std::string>{kPersistentOriginTrialToken},
1124 GetPersistedTokens(origin));
1125
1126 // Navigate again without response headers to assert the trial information is
1127 // still updated and cleared.
1128 NavigationSimulatorImpl::CreateRendererInitiated(kUrl, main_rfh())->Commit();
1129 EXPECT_EQ(std::vector<std::string>(), GetPersistedTokens(origin));
1130}
1131
clamy49678312015-10-22 21:59:001132} // namespace content