blob: 19214dd1fe06bc35d3d6770f587099a39495e757 [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"
jam6d47c3452016-09-09 18:51:0117#include "content/public/browser/ssl_status.h"
Hans Wennborg5ffd1392019-10-16 11:00:0218#include "content/public/common/content_client.h"
Peter Birk Pakkenberg73e07b62022-09-21 11:20:3019#include "content/public/common/content_features.h"
Robbie McElrath5641d572022-05-20 17:15:2920#include "content/public/common/content_switches.h"
Charles Harrison860f7ef2017-06-28 15:31:4121#include "content/public/common/url_constants.h"
Peter Birk Pakkenberg73e07b62022-09-21 11:20:3022#include "content/public/test/test_browser_context.h"
Lucas Garron79e1a972017-10-04 22:25:0623#include "content/public/test/test_navigation_throttle.h"
Yao Xiao1099e4c2022-03-24 22:40:3724#include "content/test/fenced_frame_test_utils.h"
Camille Lamy62b826012019-02-26 09:15:4725#include "content/test/navigation_simulator_impl.h"
Charles Harrison860f7ef2017-06-28 15:31:4126#include "content/test/test_content_browser_client.h"
clamy49678312015-10-22 21:59:0027#include "content/test/test_render_frame_host.h"
scottmg276753cf2016-10-27 18:25:2228#include "content/test/test_web_contents.h"
Lucas Garronc1edb5ab2017-11-08 03:31:1329#include "net/ssl/ssl_connection_status_flags.h"
arthursonzogni898dcda52021-01-21 08:50:1030#include "services/network/public/cpp/content_security_policy/content_security_policy.h"
Cammie Smith Barnesa0da2cf2021-01-11 22:09:3731#include "testing/gmock/include/gmock/gmock.h"
Anton Bikineevf62d1bf2021-05-15 17:56:0732#include "third_party/abseil-cpp/absl/types/optional.h"
Minggang Wanga13c796e2021-07-02 05:54:4333#include "third_party/blink/public/common/navigation/navigation_params.h"
Peter Birk Pakkenberg73e07b62022-09-21 11:20:3034#include "third_party/blink/public/common/origin_trials/scoped_test_origin_trial_policy.h"
Richard Lie6899952018-11-30 08:42:0035#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h"
clamy49678312015-10-22 21:59:0036
37namespace content {
38
clamy1d4e78fd2017-07-11 12:59:1939// Test version of a NavigationThrottle that will execute a callback when
40// called.
Lucas Garron79e1a972017-10-04 22:25:0641class DeletingNavigationThrottle : public NavigationThrottle {
clamy1d4e78fd2017-07-11 12:59:1942 public:
Lucas Garron79e1a972017-10-04 22:25:0643 DeletingNavigationThrottle(NavigationHandle* handle,
44 const base::RepeatingClosure& deletion_callback)
45 : NavigationThrottle(handle), deletion_callback_(deletion_callback) {}
Fergal Dalya1d569972021-03-16 03:24:5346 ~DeletingNavigationThrottle() override = default;
clamy1d4e78fd2017-07-11 12:59:1947
48 NavigationThrottle::ThrottleCheckResult WillStartRequest() override {
Lucas Garron79e1a972017-10-04 22:25:0649 deletion_callback_.Run();
clamy1d4e78fd2017-07-11 12:59:1950 return NavigationThrottle::PROCEED;
51 }
52
53 NavigationThrottle::ThrottleCheckResult WillRedirectRequest() override {
Lucas Garron79e1a972017-10-04 22:25:0654 deletion_callback_.Run();
clamy1d4e78fd2017-07-11 12:59:1955 return NavigationThrottle::PROCEED;
56 }
57
Lucas Garron0cedd962017-10-17 07:23:3358 NavigationThrottle::ThrottleCheckResult WillFailRequest() override {
59 deletion_callback_.Run();
60 return NavigationThrottle::PROCEED;
61 }
62
clamy1d4e78fd2017-07-11 12:59:1963 NavigationThrottle::ThrottleCheckResult WillProcessResponse() override {
Lucas Garron79e1a972017-10-04 22:25:0664 deletion_callback_.Run();
clamy1d4e78fd2017-07-11 12:59:1965 return NavigationThrottle::PROCEED;
66 }
67
68 const char* GetNameForLogging() override {
Lucas Garron79e1a972017-10-04 22:25:0669 return "DeletingNavigationThrottle";
clamy1d4e78fd2017-07-11 12:59:1970 }
71
72 private:
Lucas Garron79e1a972017-10-04 22:25:0673 base::RepeatingClosure deletion_callback_;
clamy1d4e78fd2017-07-11 12:59:1974};
75
Mohamed Abdelhalim1e8c5822019-08-02 11:45:4376class NavigationRequestTest : public RenderViewHostImplTestHarness {
clamy49678312015-10-22 21:59:0077 public:
Fergal Dalya1d569972021-03-16 03:24:5378 NavigationRequestTest() : callback_result_(NavigationThrottle::DEFER) {}
clamy49678312015-10-22 21:59:0079
80 void SetUp() override {
81 RenderViewHostImplTestHarness::SetUp();
clamy1d4e78fd2017-07-11 12:59:1982 CreateNavigationHandle();
Dave Tapuska327c06c92022-06-13 20:31:5183 contents()->GetPrimaryMainFrame()->InitializeRenderFrameIfNeeded();
clamy49678312015-10-22 21:59:0084 }
85
Dmitrii Kuraginb7f90da2022-11-02 22:09:3086 void TearDown() override { RenderViewHostImplTestHarness::TearDown(); }
clamy49678312015-10-22 21:59:0087
Charles Harrison4f2bf1a2017-07-18 20:21:2188 void CancelDeferredNavigation(
89 NavigationThrottle::ThrottleCheckResult result) {
Hiroki Nakagawaadcffc502021-06-16 10:47:5190 GetNavigationRequest()->CancelDeferredNavigationInternal(result);
Charles Harrison4f2bf1a2017-07-18 20:21:2191 }
92
clamy49678312015-10-22 21:59:0093 // Helper function to call WillStartRequest on |handle|. If this function
94 // returns DEFER, |callback_result_| will be set to the actual result of
95 // the throttle checks when they are finished.
96 void SimulateWillStartRequest() {
97 was_callback_called_ = false;
98 callback_result_ = NavigationThrottle::DEFER;
99
Mohamed Abdelhalim7e9e9c12019-11-26 13:48:44100 // It's safe to use base::Unretained since the NavigationRequest is owned by
Mohamed Abdelhalim1e8c5822019-08-02 11:45:43101 // the NavigationRequestTest.
Hiroki Nakagawaadcffc502021-06-16 10:47:51102 GetNavigationRequest()->set_complete_callback_for_testing(
Makoto Shimazud2aa2202019-10-09 13:57:18103 base::BindOnce(&NavigationRequestTest::UpdateThrottleCheckResult,
104 base::Unretained(this)));
Mohamed Abdelhalim7e9e9c12019-11-26 13:48:44105
Hiroki Nakagawaadcffc502021-06-16 10:47:51106 GetNavigationRequest()->WillStartRequest();
clamy49678312015-10-22 21:59:00107 }
108
109 // Helper function to call WillRedirectRequest on |handle|. If this function
110 // returns DEFER, |callback_result_| will be set to the actual result of the
111 // throttle checks when they are finished.
clamye88533842015-11-18 12:48:57112 // TODO(clamy): this should also simulate that WillStartRequest was called if
113 // it has not been called before.
clamy49678312015-10-22 21:59:00114 void SimulateWillRedirectRequest() {
115 was_callback_called_ = false;
116 callback_result_ = NavigationThrottle::DEFER;
117
Mohamed Abdelhalim7e9e9c12019-11-26 13:48:44118 // It's safe to use base::Unretained since the NavigationRequest is owned by
Mohamed Abdelhalim1e8c5822019-08-02 11:45:43119 // the NavigationRequestTest.
Hiroki Nakagawaadcffc502021-06-16 10:47:51120 GetNavigationRequest()->set_complete_callback_for_testing(
Makoto Shimazud2aa2202019-10-09 13:57:18121 base::BindOnce(&NavigationRequestTest::UpdateThrottleCheckResult,
122 base::Unretained(this)));
Mohamed Abdelhalim7e9e9c12019-11-26 13:48:44123
Hiroki Nakagawaadcffc502021-06-16 10:47:51124 GetNavigationRequest()->WillRedirectRequest(
Arthur Hemery3a991c092021-12-22 12:04:24125 GURL(), nullptr /* post_redirect_process */);
clamy49678312015-10-22 21:59:00126 }
127
Lucas Garron0cedd962017-10-17 07:23:33128 // Helper function to call WillFailRequest on |handle|. If this function
129 // returns DEFER, |callback_result_| will be set to the actual result of the
130 // throttle checks when they are finished.
Lucas Garronc1edb5ab2017-11-08 03:31:13131 void SimulateWillFailRequest(
132 net::Error net_error_code,
Anton Bikineevf62d1bf2021-05-15 17:56:07133 const absl::optional<net::SSLInfo> ssl_info = absl::nullopt) {
Lucas Garron0cedd962017-10-17 07:23:33134 was_callback_called_ = false;
135 callback_result_ = NavigationThrottle::DEFER;
Hiroki Nakagawaadcffc502021-06-16 10:47:51136 GetNavigationRequest()->set_net_error(net_error_code);
Lucas Garron0cedd962017-10-17 07:23:33137
Mohamed Abdelhalim7e9e9c12019-11-26 13:48:44138 // It's safe to use base::Unretained since the NavigationRequest is owned by
Mohamed Abdelhalim1e8c5822019-08-02 11:45:43139 // the NavigationRequestTest.
Hiroki Nakagawaadcffc502021-06-16 10:47:51140 GetNavigationRequest()->set_complete_callback_for_testing(
Makoto Shimazud2aa2202019-10-09 13:57:18141 base::BindOnce(&NavigationRequestTest::UpdateThrottleCheckResult,
142 base::Unretained(this)));
Mohamed Abdelhalim7e9e9c12019-11-26 13:48:44143
Hiroki Nakagawaadcffc502021-06-16 10:47:51144 GetNavigationRequest()->WillFailRequest();
Lucas Garron0cedd962017-10-17 07:23:33145 }
146
clamy49678312015-10-22 21:59:00147 // Whether the callback was called.
148 bool was_callback_called() const { return was_callback_called_; }
149
150 // Returns the callback_result.
151 NavigationThrottle::ThrottleCheckResult callback_result() const {
152 return callback_result_;
153 }
154
Hiroki Nakagawaadcffc502021-06-16 10:47:51155 NavigationRequest::NavigationState state() {
156 return GetNavigationRequest()->state();
157 }
Mohamed Abdelhalimccd149af2019-10-31 14:48:53158
Lucas Garron0cedd962017-10-17 07:23:33159 bool call_counts_match(TestNavigationThrottle* throttle,
160 int start,
161 int redirect,
162 int failure,
163 int process) {
164 return start == throttle->GetCallCount(
165 TestNavigationThrottle::WILL_START_REQUEST) &&
166 redirect == throttle->GetCallCount(
167 TestNavigationThrottle::WILL_REDIRECT_REQUEST) &&
168 failure == throttle->GetCallCount(
169 TestNavigationThrottle::WILL_FAIL_REQUEST) &&
170 process == throttle->GetCallCount(
171 TestNavigationThrottle::WILL_PROCESS_RESPONSE);
172 }
173
174 // Creates, register and returns a TestNavigationThrottle that will
175 // synchronously return |result| on checks by default.
clamy49678312015-10-22 21:59:00176 TestNavigationThrottle* CreateTestNavigationThrottle(
177 NavigationThrottle::ThrottleCheckResult result) {
178 TestNavigationThrottle* test_throttle =
Hiroki Nakagawaadcffc502021-06-16 10:47:51179 new TestNavigationThrottle(GetNavigationRequest());
Lucas Garron79e1a972017-10-04 22:25:06180 test_throttle->SetResponseForAllMethods(TestNavigationThrottle::SYNCHRONOUS,
181 result);
Hiroki Nakagawaadcffc502021-06-16 10:47:51182 GetNavigationRequest()->RegisterThrottleForTesting(
dcheng9bfa5162016-04-09 01:00:57183 std::unique_ptr<TestNavigationThrottle>(test_throttle));
clamy49678312015-10-22 21:59:00184 return test_throttle;
185 }
186
Lucas Garron0cedd962017-10-17 07:23:33187 // Creates, register and returns a TestNavigationThrottle that will
188 // synchronously return |result| on check for the given |method|, and
189 // NavigationThrottle::PROCEED otherwise.
190 TestNavigationThrottle* CreateTestNavigationThrottle(
191 TestNavigationThrottle::ThrottleMethod method,
192 NavigationThrottle::ThrottleCheckResult result) {
193 TestNavigationThrottle* test_throttle =
194 CreateTestNavigationThrottle(NavigationThrottle::PROCEED);
195 test_throttle->SetResponse(method, TestNavigationThrottle::SYNCHRONOUS,
196 result);
197 return test_throttle;
198 }
199
Mohamed Abdelhalim9ef43fc2019-04-05 13:09:43200 // TODO(zetamoo): Use NavigationSimulator instead of creating
201 // NavigationRequest and NavigationHandleImpl.
clamy1d4e78fd2017-07-11 12:59:19202 void CreateNavigationHandle() {
Minggang Wanga13c796e2021-07-02 05:54:43203 auto common_params = blink::CreateCommonNavigationParams();
Lucas Furukawa Gadanief8290a2019-07-29 20:27:51204 common_params->initiator_origin =
Lukasz Anforowicz435bcb582019-07-12 20:50:06205 url::Origin::Create(GURL("https://initiator.example.com"));
Minggang Wanga13c796e2021-07-02 05:54:43206 auto commit_params = blink::CreateCommitNavigationParams();
arthursonzogni70ac7302020-05-28 08:49:05207 commit_params->frame_policy =
208 main_test_rfh()->frame_tree_node()->pending_frame_policy();
Hiroki Nakagawaadcffc502021-06-16 10:47:51209 auto request = NavigationRequest::CreateBrowserInitiated(
Lucas Furukawa Gadanief8290a2019-07-29 20:27:51210 main_test_rfh()->frame_tree_node(), std::move(common_params),
arthursonzogni70ac7302020-05-28 08:49:05211 std::move(commit_params), false /* browser-initiated */,
Takashi Toyoshimae87b7be2021-01-22 11:51:08212 false /* was_opener_suppressed */, nullptr /* initiator_frame_token */,
Antonio Sartori9a82f6f32020-12-14 09:22:45213 ChildProcessHost::kInvalidUniqueID /* initiator_process_id */,
John Delaney50425f82020-04-07 16:26:21214 std::string() /* extra_headers */, nullptr /* frame_entry */,
jongdeok.kim5de823b32022-06-14 04:37:50215 nullptr /* entry */, false /* is_form_submission */,
Daniel Hosseinianf0fbfb42021-09-08 02:20:47216 nullptr /* navigation_ui_data */, absl::nullopt /* impression */,
217 false /* is_pdf */);
Hiroki Nakagawaadcffc502021-06-16 10:47:51218 main_test_rfh()->frame_tree_node()->CreatedNavigationRequest(
219 std::move(request));
220 GetNavigationRequest()->StartNavigation();
clamy1d4e78fd2017-07-11 12:59:19221 }
222
Yao Xiao6e1f7d32022-01-07 03:28:40223 FrameTreeNode* AddFrame(FrameTree& frame_tree,
224 RenderFrameHostImpl* parent,
225 int process_id,
226 int new_routing_id,
227 const blink::FramePolicy& frame_policy,
228 blink::FrameOwnerElementType owner_type) {
229 return frame_tree.AddFrame(
230 parent, process_id, new_routing_id,
231 TestRenderFrameHost::CreateStubFrameRemote(),
232 TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
233 TestRenderFrameHost::CreateStubPolicyContainerBindParams(),
Dominic Farolino12e06d72022-08-05 02:29:49234 TestRenderFrameHost::CreateStubAssociatedInterfaceProviderReceiver(),
Yao Xiao6e1f7d32022-01-07 03:28:40235 blink::mojom::TreeScopeType::kDocument, std::string(), "uniqueName0",
236 false, blink::LocalFrameToken(), base::UnguessableToken::Create(),
Daniel Cheng284c38942022-09-22 23:30:34237 blink::DocumentToken(), frame_policy,
238 blink::mojom::FrameOwnerProperties(), false, owner_type,
Yao Xiao6e1f7d32022-01-07 03:28:40239 /*is_dummy_frame_for_inner_tree=*/false);
240 }
241
clamy49678312015-10-22 21:59:00242 private:
Mohamed Abdelhalimf03d4a22019-10-01 13:34:31243 // The callback provided to NavigationRequest::WillStartRequest,
244 // NavigationRequest::WillRedirectRequest, and
245 // NavigationRequest::WillFailRequest during the tests.
Mohamed Abdelhalim7e9e9c12019-11-26 13:48:44246 bool UpdateThrottleCheckResult(
clamy49678312015-10-22 21:59:00247 NavigationThrottle::ThrottleCheckResult result) {
248 callback_result_ = result;
249 was_callback_called_ = true;
Mohamed Abdelhalim7e9e9c12019-11-26 13:48:44250 return true;
clamy49678312015-10-22 21:59:00251 }
252
Hiroki Nakagawaadcffc502021-06-16 10:47:51253 // This must be called after CreateNavigationHandle().
254 NavigationRequest* GetNavigationRequest() {
255 return main_test_rfh()->frame_tree_node()->navigation_request();
256 }
257
Fergal Dalya1d569972021-03-16 03:24:53258 bool was_callback_called_ = false;
clamy49678312015-10-22 21:59:00259 NavigationThrottle::ThrottleCheckResult callback_result_;
260};
261
carlosk489d9e22016-07-25 14:25:43262// Checks that the request_context_type is properly set.
263// Note: can be extended to cover more internal members.
Mohamed Abdelhalim1e8c5822019-08-02 11:45:43264TEST_F(NavigationRequestTest, SimpleDataChecksRedirectAndProcess) {
Camille Lamy62b826012019-02-26 09:15:47265 const GURL kUrl1 = GURL("http://chromium.org");
266 const GURL kUrl2 = GURL("http://google.com");
267 auto navigation =
268 NavigationSimulatorImpl::CreateRendererInitiated(kUrl1, main_rfh());
269 navigation->Start();
Harkiran Bolariaa2c9f79a2021-07-02 09:25:40270 EXPECT_EQ(blink::mojom::RequestContextType::LOCATION,
Mohamed Abdelhalim40c35d22019-09-19 15:59:05271 NavigationRequest::From(navigation->GetNavigationHandle())
272 ->request_context_type());
jkarlinbb150112016-11-02 17:55:11273 EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN,
Camille Lamy62b826012019-02-26 09:15:47274 navigation->GetNavigationHandle()->GetConnectionInfo());
carlosk489d9e22016-07-25 14:25:43275
Camille Lamy62b826012019-02-26 09:15:47276 navigation->set_http_connection_info(
277 net::HttpResponseInfo::CONNECTION_INFO_HTTP1_1);
278 navigation->Redirect(kUrl2);
Harkiran Bolariaa2c9f79a2021-07-02 09:25:40279 EXPECT_EQ(blink::mojom::RequestContextType::LOCATION,
Mohamed Abdelhalim40c35d22019-09-19 15:59:05280 NavigationRequest::From(navigation->GetNavigationHandle())
281 ->request_context_type());
jkarlinbb150112016-11-02 17:55:11282 EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_HTTP1_1,
Camille Lamy62b826012019-02-26 09:15:47283 navigation->GetNavigationHandle()->GetConnectionInfo());
carlosk489d9e22016-07-25 14:25:43284
Camille Lamy62b826012019-02-26 09:15:47285 navigation->set_http_connection_info(
286 net::HttpResponseInfo::CONNECTION_INFO_QUIC_35);
287 navigation->ReadyToCommit();
Harkiran Bolariaa2c9f79a2021-07-02 09:25:40288 EXPECT_EQ(blink::mojom::RequestContextType::LOCATION,
Mohamed Abdelhalim40c35d22019-09-19 15:59:05289 NavigationRequest::From(navigation->GetNavigationHandle())
290 ->request_context_type());
bnc90be5dd782016-11-09 16:28:44291 EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_QUIC_35,
Camille Lamy62b826012019-02-26 09:15:47292 navigation->GetNavigationHandle()->GetConnectionInfo());
jkarlinbb150112016-11-02 17:55:11293}
294
Mohamed Abdelhalim1e8c5822019-08-02 11:45:43295TEST_F(NavigationRequestTest, SimpleDataCheckNoRedirect) {
Camille Lamy62b826012019-02-26 09:15:47296 const GURL kUrl = GURL("http://chromium.org");
297 auto navigation =
298 NavigationSimulatorImpl::CreateRendererInitiated(kUrl, main_rfh());
299 navigation->Start();
jkarlinbb150112016-11-02 17:55:11300 EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN,
Camille Lamy62b826012019-02-26 09:15:47301 navigation->GetNavigationHandle()->GetConnectionInfo());
jkarlinbb150112016-11-02 17:55:11302
Camille Lamy62b826012019-02-26 09:15:47303 navigation->set_http_connection_info(
304 net::HttpResponseInfo::CONNECTION_INFO_QUIC_35);
305 navigation->ReadyToCommit();
bnc90be5dd782016-11-09 16:28:44306 EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_QUIC_35,
Camille Lamy62b826012019-02-26 09:15:47307 navigation->GetNavigationHandle()->GetConnectionInfo());
carlosk489d9e22016-07-25 14:25:43308}
309
Mohamed Abdelhalim1e8c5822019-08-02 11:45:43310TEST_F(NavigationRequestTest, SimpleDataChecksFailure) {
Camille Lamy62b826012019-02-26 09:15:47311 const GURL kUrl = GURL("http://chromium.org");
312 auto navigation =
313 NavigationSimulatorImpl::CreateRendererInitiated(kUrl, main_rfh());
314 navigation->Start();
Harkiran Bolariaa2c9f79a2021-07-02 09:25:40315 EXPECT_EQ(blink::mojom::RequestContextType::LOCATION,
Mohamed Abdelhalim40c35d22019-09-19 15:59:05316 NavigationRequest::From(navigation->GetNavigationHandle())
317 ->request_context_type());
Lucas Garron0cedd962017-10-17 07:23:33318 EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN,
Camille Lamy62b826012019-02-26 09:15:47319 navigation->GetNavigationHandle()->GetConnectionInfo());
Lucas Garron0cedd962017-10-17 07:23:33320
Camille Lamy62b826012019-02-26 09:15:47321 navigation->Fail(net::ERR_CERT_DATE_INVALID);
Harkiran Bolariaa2c9f79a2021-07-02 09:25:40322 EXPECT_EQ(blink::mojom::RequestContextType::LOCATION,
Mohamed Abdelhalim40c35d22019-09-19 15:59:05323 NavigationRequest::From(navigation->GetNavigationHandle())
324 ->request_context_type());
Camille Lamy62b826012019-02-26 09:15:47325 EXPECT_EQ(net::ERR_CERT_DATE_INVALID,
326 navigation->GetNavigationHandle()->GetNetErrorCode());
Lucas Garron0cedd962017-10-17 07:23:33327}
328
clamye88533842015-11-18 12:48:57329// Checks that a navigation deferred during WillStartRequest can be properly
330// cancelled.
Mohamed Abdelhalimba020672019-10-31 16:18:53331TEST_F(NavigationRequestTest, CancelDeferredWillStart) {
clamye88533842015-11-18 12:48:57332 TestNavigationThrottle* test_throttle =
333 CreateTestNavigationThrottle(NavigationThrottle::DEFER);
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19334 EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, state());
Lucas Garron0cedd962017-10-17 07:23:33335 EXPECT_TRUE(call_counts_match(test_throttle, 0, 0, 0, 0));
clamye88533842015-11-18 12:48:57336
337 // Simulate WillStartRequest. The request should be deferred. The callback
338 // should not have been called.
339 SimulateWillStartRequest();
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19340 EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, state());
clamye88533842015-11-18 12:48:57341 EXPECT_FALSE(was_callback_called());
Lucas Garron0cedd962017-10-17 07:23:33342 EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 0, 0));
clamye88533842015-11-18 12:48:57343
344 // Cancel the request. The callback should have been called.
Charles Harrison4f2bf1a2017-07-18 20:21:21345 CancelDeferredNavigation(NavigationThrottle::CANCEL_AND_IGNORE);
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19346 EXPECT_EQ(NavigationRequest::CANCELING, state());
clamye88533842015-11-18 12:48:57347 EXPECT_TRUE(was_callback_called());
348 EXPECT_EQ(NavigationThrottle::CANCEL_AND_IGNORE, callback_result());
Lucas Garron0cedd962017-10-17 07:23:33349 EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 0, 0));
clamye88533842015-11-18 12:48:57350}
351
352// Checks that a navigation deferred during WillRedirectRequest can be properly
353// cancelled.
Mohamed Abdelhalimba020672019-10-31 16:18:53354TEST_F(NavigationRequestTest, CancelDeferredWillRedirect) {
clamye88533842015-11-18 12:48:57355 TestNavigationThrottle* test_throttle =
356 CreateTestNavigationThrottle(NavigationThrottle::DEFER);
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19357 EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, state());
Lucas Garron0cedd962017-10-17 07:23:33358 EXPECT_TRUE(call_counts_match(test_throttle, 0, 0, 0, 0));
clamye88533842015-11-18 12:48:57359
360 // Simulate WillRedirectRequest. The request should be deferred. The callback
361 // should not have been called.
362 SimulateWillRedirectRequest();
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19363 EXPECT_EQ(NavigationRequest::WILL_REDIRECT_REQUEST, state());
clamye88533842015-11-18 12:48:57364 EXPECT_FALSE(was_callback_called());
Lucas Garron0cedd962017-10-17 07:23:33365 EXPECT_TRUE(call_counts_match(test_throttle, 0, 1, 0, 0));
clamye88533842015-11-18 12:48:57366
367 // Cancel the request. The callback should have been called.
Charles Harrison4f2bf1a2017-07-18 20:21:21368 CancelDeferredNavigation(NavigationThrottle::CANCEL_AND_IGNORE);
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19369 EXPECT_EQ(NavigationRequest::CANCELING, state());
clamye88533842015-11-18 12:48:57370 EXPECT_TRUE(was_callback_called());
371 EXPECT_EQ(NavigationThrottle::CANCEL_AND_IGNORE, callback_result());
Lucas Garron0cedd962017-10-17 07:23:33372 EXPECT_TRUE(call_counts_match(test_throttle, 0, 1, 0, 0));
373}
374
375// Checks that a navigation deferred during WillFailRequest can be properly
376// cancelled.
Mohamed Abdelhalimba020672019-10-31 16:18:53377TEST_F(NavigationRequestTest, CancelDeferredWillFail) {
Lucas Garron0cedd962017-10-17 07:23:33378 TestNavigationThrottle* test_throttle = CreateTestNavigationThrottle(
379 TestNavigationThrottle::WILL_FAIL_REQUEST, NavigationThrottle::DEFER);
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19380 EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, state());
Lucas Garron0cedd962017-10-17 07:23:33381 EXPECT_TRUE(call_counts_match(test_throttle, 0, 0, 0, 0));
382
383 // Simulate WillStartRequest.
384 SimulateWillStartRequest();
385 EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 0, 0));
386
387 // Simulate WillFailRequest. The request should be deferred. The callback
388 // should not have been called.
389 SimulateWillFailRequest(net::ERR_CERT_DATE_INVALID);
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19390 EXPECT_EQ(NavigationRequest::WILL_FAIL_REQUEST, state());
Lucas Garron0cedd962017-10-17 07:23:33391 EXPECT_FALSE(was_callback_called());
392 EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 1, 0));
393
394 // Cancel the request. The callback should have been called.
395 CancelDeferredNavigation(NavigationThrottle::CANCEL_AND_IGNORE);
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19396 EXPECT_EQ(NavigationRequest::CANCELING, state());
Lucas Garron0cedd962017-10-17 07:23:33397 EXPECT_TRUE(was_callback_called());
398 EXPECT_EQ(NavigationThrottle::CANCEL_AND_IGNORE, callback_result());
399 EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 1, 0));
clamye88533842015-11-18 12:48:57400}
401
402// Checks that a navigation deferred can be canceled and not ignored.
Mohamed Abdelhalimba020672019-10-31 16:18:53403TEST_F(NavigationRequestTest, CancelDeferredWillRedirectNoIgnore) {
clamye88533842015-11-18 12:48:57404 TestNavigationThrottle* test_throttle =
405 CreateTestNavigationThrottle(NavigationThrottle::DEFER);
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19406 EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, state());
Lucas Garron0cedd962017-10-17 07:23:33407 EXPECT_TRUE(call_counts_match(test_throttle, 0, 0, 0, 0));
clamye88533842015-11-18 12:48:57408
Lucas Garron0cedd962017-10-17 07:23:33409 // Simulate WillStartRequest. The request should be deferred. The callback
clamye88533842015-11-18 12:48:57410 // should not have been called.
411 SimulateWillStartRequest();
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19412 EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, state());
Lucas Garron0cedd962017-10-17 07:23:33413 EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 0, 0));
clamye88533842015-11-18 12:48:57414
415 // Cancel the request. The callback should have been called with CANCEL, and
416 // not CANCEL_AND_IGNORE.
Charles Harrison4f2bf1a2017-07-18 20:21:21417 CancelDeferredNavigation(NavigationThrottle::CANCEL);
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19418 EXPECT_EQ(NavigationRequest::CANCELING, state());
clamye88533842015-11-18 12:48:57419 EXPECT_TRUE(was_callback_called());
420 EXPECT_EQ(NavigationThrottle::CANCEL, callback_result());
Lucas Garron0cedd962017-10-17 07:23:33421 EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 0, 0));
clamye88533842015-11-18 12:48:57422}
423
Lucas Garron0cedd962017-10-17 07:23:33424// Checks that a navigation deferred by WillFailRequest can be canceled and not
425// ignored.
Mohamed Abdelhalimba020672019-10-31 16:18:53426TEST_F(NavigationRequestTest, CancelDeferredWillFailNoIgnore) {
Lucas Garron0cedd962017-10-17 07:23:33427 TestNavigationThrottle* test_throttle = CreateTestNavigationThrottle(
428 TestNavigationThrottle::WILL_FAIL_REQUEST, NavigationThrottle::DEFER);
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19429 EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, state());
Lucas Garron0cedd962017-10-17 07:23:33430 EXPECT_TRUE(call_counts_match(test_throttle, 0, 0, 0, 0));
431
432 // Simulate WillStartRequest.
433 SimulateWillStartRequest();
434 EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 0, 0));
435
436 // Simulate WillFailRequest. The request should be deferred. The callback
437 // should not have been called.
438 SimulateWillFailRequest(net::ERR_CERT_DATE_INVALID);
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19439 EXPECT_EQ(NavigationRequest::WILL_FAIL_REQUEST, state());
Lucas Garron0cedd962017-10-17 07:23:33440 EXPECT_FALSE(was_callback_called());
441 EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 1, 0));
442
443 // Cancel the request. The callback should have been called with CANCEL, and
444 // not CANCEL_AND_IGNORE.
445 CancelDeferredNavigation(NavigationThrottle::CANCEL);
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19446 EXPECT_EQ(NavigationRequest::CANCELING, state());
Lucas Garron0cedd962017-10-17 07:23:33447 EXPECT_TRUE(was_callback_called());
448 EXPECT_EQ(NavigationThrottle::CANCEL, callback_result());
449 EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 1, 0));
450}
451
Lucas Garronc1edb5ab2017-11-08 03:31:13452// Checks that data from the SSLInfo passed into SimulateWillStartRequest() is
John Abd-El-Malekf36e05f2017-11-30 16:17:52453// stored on the handle.
Mohamed Abdelhalim1e8c5822019-08-02 11:45:43454TEST_F(NavigationRequestTest, WillFailRequestSetsSSLInfo) {
Lucas Garronc1edb5ab2017-11-08 03:31:13455 uint16_t cipher_suite = 0xc02f; // TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
456 int connection_status = 0;
457 net::SSLConnectionStatusSetCipherSuite(cipher_suite, &connection_status);
458
459 // Set some test values.
460 net::SSLInfo ssl_info;
461 ssl_info.cert_status = net::CERT_STATUS_AUTHORITY_INVALID;
462 ssl_info.connection_status = connection_status;
463
Camille Lamy62b826012019-02-26 09:15:47464 const GURL kUrl = GURL("https://chromium.org");
465 auto navigation =
466 NavigationSimulatorImpl::CreateRendererInitiated(kUrl, main_rfh());
Emily Starkfd6978ad12019-04-30 21:20:07467 navigation->SetSSLInfo(ssl_info);
Camille Lamy62b826012019-02-26 09:15:47468 navigation->Fail(net::ERR_CERT_DATE_INVALID);
Lucas Garronc1edb5ab2017-11-08 03:31:13469
470 EXPECT_EQ(net::CERT_STATUS_AUTHORITY_INVALID,
Camille Lamy62b826012019-02-26 09:15:47471 navigation->GetNavigationHandle()->GetSSLInfo()->cert_status);
472 EXPECT_EQ(connection_status,
473 navigation->GetNavigationHandle()->GetSSLInfo()->connection_status);
Lucas Garronc1edb5ab2017-11-08 03:31:13474}
475
Camille Lamy62b826012019-02-26 09:15:47476namespace {
477
Alex Moshchuk1a66b1d2018-05-15 21:18:26478// Helper throttle which checks that it can access NavigationHandle's
479// RenderFrameHost in WillFailRequest() and then defers the failure.
480class GetRenderFrameHostOnFailureNavigationThrottle
481 : public NavigationThrottle {
482 public:
Fergal Dalya1d569972021-03-16 03:24:53483 explicit GetRenderFrameHostOnFailureNavigationThrottle(
484 NavigationHandle* handle)
Alex Moshchuk1a66b1d2018-05-15 21:18:26485 : NavigationThrottle(handle) {}
Peter Boström828b9022021-09-21 02:28:43486
487 GetRenderFrameHostOnFailureNavigationThrottle(
488 const GetRenderFrameHostOnFailureNavigationThrottle&) = delete;
489 GetRenderFrameHostOnFailureNavigationThrottle& operator=(
490 const GetRenderFrameHostOnFailureNavigationThrottle&) = delete;
491
Fergal Dalya1d569972021-03-16 03:24:53492 ~GetRenderFrameHostOnFailureNavigationThrottle() override = default;
Alex Moshchuk1a66b1d2018-05-15 21:18:26493
494 NavigationThrottle::ThrottleCheckResult WillFailRequest() override {
495 EXPECT_TRUE(navigation_handle()->GetRenderFrameHost());
496 return NavigationThrottle::DEFER;
497 }
498
499 const char* GetNameForLogging() override {
500 return "GetRenderFrameHostOnFailureNavigationThrottle";
501 }
Alex Moshchuk1a66b1d2018-05-15 21:18:26502};
503
Camille Lamy62b826012019-02-26 09:15:47504class ThrottleTestContentBrowserClient : public ContentBrowserClient {
505 std::vector<std::unique_ptr<NavigationThrottle>> CreateThrottlesForNavigation(
506 NavigationHandle* navigation_handle) override {
507 std::vector<std::unique_ptr<NavigationThrottle>> throttle;
508 throttle.push_back(
509 std::make_unique<GetRenderFrameHostOnFailureNavigationThrottle>(
510 navigation_handle));
511 return throttle;
512 }
513};
514
515} // namespace
516
Alex Moshchuk1a66b1d2018-05-15 21:18:26517// Verify that the NavigationHandle::GetRenderFrameHost() can be retrieved by a
518// throttle in WillFailRequest(), as well as after deferring the failure. This
519// is allowed, since at that point the final RenderFrameHost will have already
520// been chosen. See https://crbug.com/817881.
Mohamed Abdelhalimba020672019-10-31 16:18:53521TEST_F(NavigationRequestTest, WillFailRequestCanAccessRenderFrameHost) {
Camille Lamy62b826012019-02-26 09:15:47522 std::unique_ptr<ContentBrowserClient> client(
523 new ThrottleTestContentBrowserClient);
524 ContentBrowserClient* old_browser_client =
525 SetBrowserClientForTesting(client.get());
526
527 const GURL kUrl = GURL("http://chromium.org");
528 auto navigation =
529 NavigationSimulatorImpl::CreateRendererInitiated(kUrl, main_rfh());
530 navigation->SetAutoAdvance(false);
531 navigation->Start();
532 navigation->Fail(net::ERR_CERT_DATE_INVALID);
Mohamed Abdelhalim3b235272019-11-05 15:06:07533 EXPECT_EQ(
534 NavigationRequest::WILL_FAIL_REQUEST,
535 NavigationRequest::From(navigation->GetNavigationHandle())->state());
Camille Lamy62b826012019-02-26 09:15:47536 EXPECT_TRUE(navigation->GetNavigationHandle()->GetRenderFrameHost());
Mohamed Abdelhalim40c35d22019-09-19 15:59:05537 NavigationRequest::From(navigation->GetNavigationHandle())
danakjf26536bf2020-09-10 00:46:13538 ->GetNavigationThrottleRunnerForTesting()
Mohamed Abdelhalim40c35d22019-09-19 15:59:05539 ->CallResumeForTesting();
Camille Lamy62b826012019-02-26 09:15:47540 EXPECT_TRUE(navigation->GetNavigationHandle()->GetRenderFrameHost());
541
542 SetBrowserClientForTesting(old_browser_client);
Alex Moshchuk1a66b1d2018-05-15 21:18:26543}
544
Antonio Sartori3cfa3b62020-10-09 10:42:40545TEST_F(NavigationRequestTest, PolicyContainerInheritance) {
546 struct TestCase {
547 const char* url;
548 bool expect_inherit;
549 } cases[]{{"about:blank", true},
550 {"data:text/plain,hello", true},
551 {"file://local", false},
552 {"http://chromium.org", false}};
553
554 const GURL kUrl1 = GURL("http://chromium.org");
555 auto navigation =
556 NavigationSimulatorImpl::CreateRendererInitiated(kUrl1, main_rfh());
557 navigation->Commit();
558
559 for (auto test : cases) {
560 // We navigate child frames because the BlockedSchemeNavigationThrottle
561 // restricts navigations in the main frame.
562 auto* child_frame = static_cast<TestRenderFrameHost*>(
563 content::RenderFrameHostTester::For(main_rfh())->AppendChild("child"));
564
565 // We set the referrer policy of the frame to "always". We then create a new
566 // navigation, set as initiator the frame itself, start the navigation, and
567 // change the referrer policy of the frame to "never". After we commit the
568 // navigation:
569 // - If navigating to a local scheme, the target frame should have inherited
570 // the referrer policy of the initiator ("always").
571 // - If navigating to a non-local scheme, the target frame should have a new
572 // policy container (hence referrer policy set to "default").
573 const GURL kUrl = GURL(test.url);
Peter Kastingeb8c3ce2021-08-20 04:39:35574 navigation =
Antonio Sartori3cfa3b62020-10-09 10:42:40575 NavigationSimulatorImpl::CreateRendererInitiated(kUrl, child_frame);
Antonio Sartori5b2f8042020-10-23 18:13:26576 static_cast<blink::mojom::PolicyContainerHost*>(
Antonio Sartori9290b6b2020-11-09 10:09:33577 child_frame->policy_container_host())
Antonio Sartori5b2f8042020-10-23 18:13:26578 ->SetReferrerPolicy(network::mojom::ReferrerPolicy::kAlways);
Antonio Sartori3cfa3b62020-10-09 10:42:40579 navigation->SetInitiatorFrame(child_frame);
580 navigation->Start();
Antonio Sartori5b2f8042020-10-23 18:13:26581 static_cast<blink::mojom::PolicyContainerHost*>(
Antonio Sartori9290b6b2020-11-09 10:09:33582 child_frame->policy_container_host())
Antonio Sartori5b2f8042020-10-23 18:13:26583 ->SetReferrerPolicy(network::mojom::ReferrerPolicy::kNever);
Antonio Sartori3cfa3b62020-10-09 10:42:40584 navigation->Commit();
585 EXPECT_EQ(
586 test.expect_inherit ? network::mojom::ReferrerPolicy::kAlways
587 : network::mojom::ReferrerPolicy::kDefault,
588 static_cast<RenderFrameHostImpl*>(navigation->GetFinalRenderFrameHost())
Antonio Sartori9290b6b2020-11-09 10:09:33589 ->policy_container_host()
Antonio Sartori3cfa3b62020-10-09 10:42:40590 ->referrer_policy());
591 }
592}
593
Cammie Smith Barnesa0da2cf2021-01-11 22:09:37594TEST_F(NavigationRequestTest, DnsAliasesCanBeAccessed) {
595 // Create simulated NavigationRequest for the URL, which has aliases.
596 const GURL kUrl = GURL("http://chromium.org");
597 auto navigation =
598 NavigationSimulatorImpl::CreateRendererInitiated(kUrl, main_rfh());
599 std::vector<std::string> dns_aliases({"alias1", "alias2"});
600 navigation->SetResponseDnsAliases(std::move(dns_aliases));
601
602 // Start the navigation.
603 navigation->Start();
604 EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN,
605 navigation->GetNavigationHandle()->GetConnectionInfo());
606
607 // Commit the navigation.
608 navigation->set_http_connection_info(
609 net::HttpResponseInfo::CONNECTION_INFO_QUIC_35);
610 navigation->ReadyToCommit();
611 EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_QUIC_35,
612 navigation->GetNavigationHandle()->GetConnectionInfo());
613
614 // Verify that the aliases are accessible from the NavigationRequest.
615 EXPECT_THAT(navigation->GetNavigationHandle()->GetDnsAliases(),
616 testing::ElementsAre("alias1", "alias2"));
617}
618
619TEST_F(NavigationRequestTest, NoDnsAliases) {
620 // Create simulated NavigationRequest for the URL, which does not
621 // have aliases. (Note the empty alias list.)
622 const GURL kUrl = GURL("http://chromium.org");
623 auto navigation =
624 NavigationSimulatorImpl::CreateRendererInitiated(kUrl, main_rfh());
625 std::vector<std::string> dns_aliases;
626 navigation->SetResponseDnsAliases(std::move(dns_aliases));
627
628 // Start the navigation.
629 navigation->Start();
630 EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN,
631 navigation->GetNavigationHandle()->GetConnectionInfo());
632
633 // Commit the navigation.
634 navigation->set_http_connection_info(
635 net::HttpResponseInfo::CONNECTION_INFO_QUIC_35);
636 navigation->ReadyToCommit();
637 EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_QUIC_35,
638 navigation->GetNavigationHandle()->GetConnectionInfo());
639
640 // Verify that there are no aliases in the NavigationRequest.
641 EXPECT_TRUE(navigation->GetNavigationHandle()->GetDnsAliases().empty());
642}
643
Antonio Sartori3e8de6d2021-07-26 10:28:41644TEST_F(NavigationRequestTest, StorageKeyToCommit) {
645 TestRenderFrameHost* child_document = static_cast<TestRenderFrameHost*>(
646 content::RenderFrameHostTester::For(main_rfh())->AppendChild(""));
Yuzu Saijo03dbf9b2022-07-22 04:29:45647 auto attributes = child_document->frame_tree_node()->attributes_->Clone();
648 // Set |anonymous| to true.
649 attributes->anonymous = true;
650 child_document->frame_tree_node()->SetAttributes(std::move(attributes));
Antonio Sartori3e8de6d2021-07-26 10:28:41651
652 const GURL kUrl = GURL("http://chromium.org");
653 auto navigation =
654 NavigationSimulatorImpl::CreateRendererInitiated(kUrl, child_document);
655 navigation->ReadyToCommit();
656 NavigationRequest* request =
657 NavigationRequest::From(navigation->GetNavigationHandle());
658 EXPECT_TRUE(request->commit_params().storage_key.nonce().has_value());
Ali Hijazi78de14c2022-07-21 11:32:19659 EXPECT_EQ(child_document->GetMainFrame()->anonymous_iframes_nonce(),
Antonio Sartori3e8de6d2021-07-26 10:28:41660 request->commit_params().storage_key.nonce().value());
661
662 navigation->Commit();
663 child_document =
664 static_cast<TestRenderFrameHost*>(navigation->GetFinalRenderFrameHost());
Arthur Sonzognie41678a2022-06-16 15:51:19665 EXPECT_TRUE(child_document->IsAnonymous());
Ali Hijazi78de14c2022-07-21 11:32:19666 EXPECT_EQ(blink::StorageKey::CreateWithNonce(
667 url::Origin::Create(kUrl),
668 child_document->GetMainFrame()->anonymous_iframes_nonce()),
669 child_document->storage_key());
Antonio Sartori3e8de6d2021-07-26 10:28:41670}
671
Antonio Sartoribf27cc442021-08-25 13:08:23672TEST_F(NavigationRequestTest,
673 NavigationToAnonymousDocumentNetworkIsolationInfo) {
674 auto* child_frame = static_cast<TestRenderFrameHost*>(
675 content::RenderFrameHostTester::For(main_test_rfh())
676 ->AppendChild("child"));
Yuzu Saijo03dbf9b2022-07-22 04:29:45677 auto attributes = child_frame->frame_tree_node()->attributes_->Clone();
678 // Set |anonymous| to true.
679 attributes->anonymous = true;
680 child_frame->frame_tree_node()->SetAttributes(std::move(attributes));
Antonio Sartoribf27cc442021-08-25 13:08:23681
682 std::unique_ptr<NavigationSimulator> navigation =
683 NavigationSimulator::CreateRendererInitiated(
684 GURL("https://example.com/navigation.html"), child_frame);
685 navigation->ReadyToCommit();
686
Ali Hijazi78de14c2022-07-21 11:32:19687 EXPECT_EQ(main_test_rfh()->anonymous_iframes_nonce(),
Antonio Sartoribf27cc442021-08-25 13:08:23688 static_cast<NavigationRequest*>(navigation->GetNavigationHandle())
689 ->isolation_info_for_subresources()
690 .network_isolation_key()
691 .GetNonce());
Ali Hijazi78de14c2022-07-21 11:32:19692 EXPECT_EQ(main_test_rfh()->anonymous_iframes_nonce(),
Antonio Sartoribf27cc442021-08-25 13:08:23693 static_cast<NavigationRequest*>(navigation->GetNavigationHandle())
694 ->GetIsolationInfo()
695 .network_isolation_key()
696 .GetNonce());
697}
698
Robbie McElrath5641d572022-05-20 17:15:29699class ScopedIsolatedAppBrowserClient : public ContentBrowserClient {
700 public:
Robbie McElrathc91ce362022-11-18 18:08:12701 explicit ScopedIsolatedAppBrowserClient(const GURL& isolated_url)
702 : isolated_host_(isolated_url.host()),
703 old_client_(SetBrowserClientForTesting(this)) {}
Robbie McElrath5641d572022-05-20 17:15:29704
705 ~ScopedIsolatedAppBrowserClient() override {
706 SetBrowserClientForTesting(old_client_);
707 }
708
Dmitrii Kuraginb7f90da2022-11-02 22:09:30709 bool ShouldUrlUseApplicationIsolationLevel(
710 BrowserContext* browser_context,
711 const GURL& url,
712 bool origin_matches_flag) override {
Robbie McElrathc91ce362022-11-18 18:08:12713 return url.host() == isolated_host_;
Robbie McElrath5641d572022-05-20 17:15:29714 }
715
716 private:
Robbie McElrathc91ce362022-11-18 18:08:12717 std::string isolated_host_;
Robbie McElrath5641d572022-05-20 17:15:29718 raw_ptr<ContentBrowserClient> old_client_;
719};
720
721TEST_F(NavigationRequestTest, IsolatedAppPolicyInjection) {
722 const GURL kUrl = GURL("https://chromium.org");
Robbie McElrathc91ce362022-11-18 18:08:12723 ScopedIsolatedAppBrowserClient client(kUrl);
Robbie McElrath5641d572022-05-20 17:15:29724
725 auto navigation =
726 NavigationSimulatorImpl::CreateRendererInitiated(kUrl, main_rfh());
727 navigation->ReadyToCommit();
728
729 // Validate the COOP/COEP headers.
730 const PolicyContainerPolicies& policies =
731 navigation->GetNavigationHandle()->GetPolicyContainerPolicies();
732 EXPECT_EQ(network::mojom::CrossOriginOpenerPolicyValue::kSameOriginPlusCoep,
733 policies.cross_origin_opener_policy.value);
734 EXPECT_EQ(network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp,
735 policies.cross_origin_embedder_policy.value);
736
737 // Validate CSP.
738 EXPECT_EQ(1UL, policies.content_security_policies.size());
739 const auto& csp = policies.content_security_policies[0];
Ovidio Ruiz-Henríquezadd3f402022-10-17 19:10:31740 EXPECT_EQ(10UL, csp->raw_directives.size());
Robbie McElrath5641d572022-05-20 17:15:29741 using Directive = network::mojom::CSPDirectiveName;
742 EXPECT_EQ("'none'", csp->raw_directives[Directive::BaseURI]);
743 EXPECT_EQ("'none'", csp->raw_directives[Directive::ObjectSrc]);
744 EXPECT_EQ("'self'", csp->raw_directives[Directive::DefaultSrc]);
745 EXPECT_EQ("'self' https:", csp->raw_directives[Directive::FrameSrc]);
746 EXPECT_EQ("'self' https:", csp->raw_directives[Directive::ConnectSrc]);
Robbie McElrathb062f3d2022-08-09 17:48:44747 EXPECT_EQ("'self' 'wasm-unsafe-eval'",
748 csp->raw_directives[Directive::ScriptSrc]);
Ovidio Ruiz-Henríquezadd3f402022-10-17 19:10:31749 EXPECT_EQ("'self' data:", csp->raw_directives[Directive::ImgSrc]);
750 EXPECT_EQ("'self' data:", csp->raw_directives[Directive::MediaSrc]);
751 EXPECT_EQ("'self' data:", csp->raw_directives[Directive::FontSrc]);
Robbie McElrath5641d572022-05-20 17:15:29752 EXPECT_EQ("'script'", csp->raw_directives[Directive::RequireTrustedTypesFor]);
753}
754
arthursonzogni898dcda52021-01-21 08:50:10755// Test that the required CSP of every frame is computed/inherited correctly and
756// that the Sec-Required-CSP header is set.
757class CSPEmbeddedEnforcementUnitTest : public NavigationRequestTest {
758 protected:
759 TestRenderFrameHost* main_rfh() {
760 return static_cast<TestRenderFrameHost*>(NavigationRequestTest::main_rfh());
761 }
762
763 // Simulate the |csp| attribute being set in |rfh|'s frame. Then navigate it.
764 // Returns the request's Sec-Required-CSP header.
765 std::string NavigateWithRequiredCSP(TestRenderFrameHost** rfh,
766 std::string required_csp) {
767 TestRenderFrameHost* document = *rfh;
768
769 if (!required_csp.empty()) {
770 auto headers =
771 base::MakeRefCounted<net::HttpResponseHeaders>("HTTP/1.1 200 OK");
772 headers->SetHeader("Content-Security-Policy", required_csp);
773 std::vector<network::mojom::ContentSecurityPolicyPtr> policies;
774 network::AddContentSecurityPolicyFromHeaders(
775 *headers, GURL("https://example.com/"), &policies);
Yuzu Saijo03dbf9b2022-07-22 04:29:45776 auto attributes = document->frame_tree_node()->attributes_->Clone();
777 // Set csp value.
778 attributes->parsed_csp_attribute = std::move(policies[0]);
779 document->frame_tree_node()->SetAttributes(std::move(attributes));
arthursonzogni898dcda52021-01-21 08:50:10780 }
781
782 // Chrome blocks a document navigating to a URL if more than one of its
783 // ancestors have the same URL. Use a different URL every time, to
784 // avoid blocking navigation of the grandchild frame.
785 static int nonce = 0;
786 GURL url("https://www.example.com" + base::NumberToString(nonce++));
787
788 auto navigation =
789 content::NavigationSimulator::CreateRendererInitiated(url, *rfh);
790 navigation->Start();
791 NavigationRequest* request =
792 NavigationRequest::From(navigation->GetNavigationHandle());
793 std::string sec_required_csp;
794 request->GetRequestHeaders().GetHeader("sec-required-csp",
795 &sec_required_csp);
796
797 // Complete the navigation so that the required csp is stored in the
798 // RenderFrameHost, so that when we will add children to this document they
799 // will be able to get the parent's required csp (and hence also test that
800 // the whole logic works).
801 auto response_headers =
802 base::MakeRefCounted<net::HttpResponseHeaders>("HTTP/1.1 200 OK");
803 response_headers->SetHeader("Allow-CSP-From", "*");
804 navigation->SetResponseHeaders(response_headers);
805 navigation->Commit();
806
807 *rfh = static_cast<TestRenderFrameHost*>(
808 navigation->GetFinalRenderFrameHost());
809
810 return sec_required_csp;
811 }
812
813 TestRenderFrameHost* AddChild(TestRenderFrameHost* parent) {
814 return static_cast<TestRenderFrameHost*>(
815 content::RenderFrameHostTester::For(parent)->AppendChild(""));
816 }
817};
818
819TEST_F(CSPEmbeddedEnforcementUnitTest, TopLevel) {
820 TestRenderFrameHost* top_document = main_rfh();
821 std::string sec_required_csp = NavigateWithRequiredCSP(&top_document, "");
822 EXPECT_EQ("", sec_required_csp);
823 EXPECT_FALSE(top_document->required_csp());
824}
825
826TEST_F(CSPEmbeddedEnforcementUnitTest, ChildNoCSP) {
827 TestRenderFrameHost* top_document = main_rfh();
828 TestRenderFrameHost* child_document = AddChild(top_document);
829 std::string sec_required_csp = NavigateWithRequiredCSP(&child_document, "");
830 EXPECT_EQ("", sec_required_csp);
831 EXPECT_FALSE(child_document->required_csp());
832}
833
834TEST_F(CSPEmbeddedEnforcementUnitTest, ChildWithCSP) {
835 TestRenderFrameHost* top_document = main_rfh();
836 TestRenderFrameHost* child_document = AddChild(top_document);
837 std::string sec_required_csp =
838 NavigateWithRequiredCSP(&child_document, "script-src 'none'");
839 EXPECT_EQ("script-src 'none'", sec_required_csp);
840 EXPECT_TRUE(child_document->required_csp());
841 EXPECT_EQ("script-src 'none'",
842 child_document->required_csp()->header->header_value);
843}
844
845TEST_F(CSPEmbeddedEnforcementUnitTest, ChildSiblingNoCSP) {
846 TestRenderFrameHost* top_document = main_rfh();
847 TestRenderFrameHost* child_document = AddChild(top_document);
848 NavigateWithRequiredCSP(&child_document, "script-src 'none'");
849 TestRenderFrameHost* sibling_document = AddChild(top_document);
850 std::string sec_required_csp = NavigateWithRequiredCSP(&sibling_document, "");
851 EXPECT_FALSE(sibling_document->required_csp());
852}
853
854TEST_F(CSPEmbeddedEnforcementUnitTest, ChildSiblingCSP) {
855 TestRenderFrameHost* top_document = main_rfh();
856 TestRenderFrameHost* child_document = AddChild(top_document);
857 NavigateWithRequiredCSP(&child_document, "script-src 'none'");
858 TestRenderFrameHost* sibling_document = AddChild(top_document);
859 std::string sec_required_csp =
860 NavigateWithRequiredCSP(&sibling_document, "script-src 'none'");
861 EXPECT_EQ("script-src 'none'", sec_required_csp);
862 EXPECT_TRUE(sibling_document->required_csp());
863 EXPECT_EQ("script-src 'none'",
864 sibling_document->required_csp()->header->header_value);
865}
866
867TEST_F(CSPEmbeddedEnforcementUnitTest, GrandChildNoCSP) {
868 TestRenderFrameHost* top_document = main_rfh();
869 TestRenderFrameHost* child_document = AddChild(top_document);
870 NavigateWithRequiredCSP(&child_document, "script-src 'none'");
871 TestRenderFrameHost* grand_child_document = AddChild(child_document);
872 std::string sec_required_csp =
873 NavigateWithRequiredCSP(&grand_child_document, "");
874 EXPECT_EQ("script-src 'none'", sec_required_csp);
875 EXPECT_TRUE(grand_child_document->required_csp());
876 EXPECT_EQ("script-src 'none'",
877 grand_child_document->required_csp()->header->header_value);
878}
879
880TEST_F(CSPEmbeddedEnforcementUnitTest, GrandChildSameCSP) {
881 TestRenderFrameHost* top_document = main_rfh();
882 TestRenderFrameHost* child_document = AddChild(top_document);
883 NavigateWithRequiredCSP(&child_document, "script-src 'none'");
884 TestRenderFrameHost* grand_child_document = AddChild(child_document);
885 std::string sec_required_csp =
886 NavigateWithRequiredCSP(&grand_child_document, "script-src 'none'");
887 EXPECT_EQ("script-src 'none'", sec_required_csp);
888 EXPECT_TRUE(grand_child_document->required_csp());
889 EXPECT_EQ("script-src 'none'",
890 grand_child_document->required_csp()->header->header_value);
891}
892
893TEST_F(CSPEmbeddedEnforcementUnitTest, GrandChildDifferentCSP) {
894 TestRenderFrameHost* top_document = main_rfh();
895 TestRenderFrameHost* child_document = AddChild(top_document);
896 NavigateWithRequiredCSP(&child_document, "script-src 'none'");
897 TestRenderFrameHost* grand_child_document = AddChild(child_document);
898 std::string sec_required_csp =
899 NavigateWithRequiredCSP(&grand_child_document, "img-src 'none'");
900
901 // This seems weird, but it is the intended behaviour according to the spec.
902 // The problem is that "script-src 'none'" does not subsume "img-src 'none'",
903 // so "img-src 'none'" on the grandchild is an invalid csp attribute, and we
904 // just discard it in favour of the parent's csp attribute.
905 //
906 // This should probably be fixed in the specification:
907 // https://github.com/w3c/webappsec-cspee/pull/11
908 EXPECT_EQ("script-src 'none'", sec_required_csp);
909 EXPECT_TRUE(grand_child_document->required_csp());
910 EXPECT_EQ("script-src 'none'",
911 grand_child_document->required_csp()->header->header_value);
912}
913
914TEST_F(CSPEmbeddedEnforcementUnitTest, InvalidCSP) {
915 TestRenderFrameHost* top_document = main_rfh();
916 TestRenderFrameHost* child_document = AddChild(top_document);
917 std::string sec_required_csp =
918 NavigateWithRequiredCSP(&child_document, "report-to group");
919 EXPECT_EQ("", sec_required_csp);
920 EXPECT_FALSE(child_document->required_csp());
921}
922
923TEST_F(CSPEmbeddedEnforcementUnitTest, InvalidCspAndInheritFromParent) {
924 TestRenderFrameHost* top_document = main_rfh();
925 TestRenderFrameHost* child_document = AddChild(top_document);
926 NavigateWithRequiredCSP(&child_document, "script-src 'none'");
927 TestRenderFrameHost* grand_child_document = AddChild(child_document);
928 std::string sec_required_csp =
Antonio Sartori4231e932021-02-04 12:01:14929 NavigateWithRequiredCSP(&grand_child_document, "report-to group");
arthursonzogni898dcda52021-01-21 08:50:10930 EXPECT_EQ("script-src 'none'", sec_required_csp);
931 EXPECT_TRUE(grand_child_document->required_csp());
932 EXPECT_EQ("script-src 'none'",
933 grand_child_document->required_csp()->header->header_value);
934}
935
936TEST_F(CSPEmbeddedEnforcementUnitTest,
937 SemiInvalidCspAndInheritSameCspFromParent) {
938 TestRenderFrameHost* top_document = main_rfh();
939 TestRenderFrameHost* child_document = AddChild(top_document);
940 NavigateWithRequiredCSP(&child_document, "script-src 'none'");
941 TestRenderFrameHost* grand_child_document = AddChild(child_document);
942 std::string sec_required_csp = NavigateWithRequiredCSP(
Antonio Sartori4231e932021-02-04 12:01:14943 &grand_child_document, "script-src 'none'; report-to group");
arthursonzogni898dcda52021-01-21 08:50:10944 EXPECT_EQ("script-src 'none'", sec_required_csp);
945 EXPECT_TRUE(grand_child_document->required_csp());
946 EXPECT_EQ("script-src 'none'",
947 grand_child_document->required_csp()->header->header_value);
948}
949
950TEST_F(CSPEmbeddedEnforcementUnitTest,
951 SemiInvalidCspAndInheritDifferentCspFromParent) {
952 TestRenderFrameHost* top_document = main_rfh();
953 TestRenderFrameHost* child_document = AddChild(top_document);
954 NavigateWithRequiredCSP(&child_document, "script-src 'none'");
955 TestRenderFrameHost* grand_child_document = AddChild(child_document);
956 std::string sec_required_csp = NavigateWithRequiredCSP(
Antonio Sartori4231e932021-02-04 12:01:14957 &grand_child_document, "sandbox; report-to group");
arthursonzogni898dcda52021-01-21 08:50:10958 EXPECT_EQ("script-src 'none'", sec_required_csp);
959 EXPECT_TRUE(grand_child_document->required_csp());
960 EXPECT_EQ("script-src 'none'",
961 grand_child_document->required_csp()->header->header_value);
962}
963
Peter Birk Pakkenberg73e07b62022-09-21 11:20:30964namespace {
965
966// Mock that allows us to avoid depending on the origin_trials component.
967class OriginTrialsControllerDelegateMock
968 : public OriginTrialsControllerDelegate {
969 public:
970 ~OriginTrialsControllerDelegateMock() override = default;
971
972 void PersistTrialsFromTokens(
973 const url::Origin& origin,
974 const base::span<const std::string> header_tokens,
975 const base::Time current_time) override {
976 persisted_tokens_[origin] =
977 std::vector<std::string>(header_tokens.begin(), header_tokens.end());
978 }
979 bool IsTrialPersistedForOrigin(const url::Origin& origin,
980 const base::StringPiece trial_name,
981 const base::Time current_time) override {
982 DCHECK(false) << "Method not implemented for test.";
983 return false;
984 }
985
Peter Birk Pakkenberg4c1bb272022-09-27 10:51:29986 base::flat_set<std::string> GetPersistedTrialsForOrigin(
987 const url::Origin& origin,
988 base::Time current_time) override {
989 DCHECK(false) << "Method not implemented for test.";
990 return base::flat_set<std::string>();
991 }
992
Peter Birk Pakkenbergd74c6f82022-11-08 17:44:38993 void ClearPersistedTokens() override { persisted_tokens_.clear(); }
994
Peter Birk Pakkenberg73e07b62022-09-21 11:20:30995 base::flat_map<url::Origin, std::vector<std::string>> persisted_tokens_;
996};
997
998} // namespace
999
1000class PersistentOriginTrialNavigationRequestTest
1001 : public NavigationRequestTest {
1002 public:
1003 PersistentOriginTrialNavigationRequestTest()
1004 : delegate_mock_(std::make_unique<OriginTrialsControllerDelegateMock>()) {
1005
1006 }
1007 ~PersistentOriginTrialNavigationRequestTest() override = default;
1008
1009 std::vector<std::string> GetPersistedTokens(const url::Origin& origin) {
1010 return delegate_mock_->persisted_tokens_[origin];
1011 }
1012
1013 protected:
1014 std::unique_ptr<BrowserContext> CreateBrowserContext() override {
1015 std::unique_ptr<TestBrowserContext> context =
1016 std::make_unique<TestBrowserContext>();
1017 context->SetOriginTrialsControllerDelegate(delegate_mock_.get());
1018 return context;
1019 }
1020
1021 private:
1022 std::unique_ptr<OriginTrialsControllerDelegateMock> delegate_mock_;
1023};
1024
1025// Ensure that navigations with a valid Origin-Trial header with a persistent
1026// origin trial token results in the trial being marked as enabled.
1027// Then check that subsequent navigations without headers trigger an update
1028// that clears out stored trials.
1029TEST_F(PersistentOriginTrialNavigationRequestTest,
1030 NavigationCommitsPersistentOriginTrials) {
1031 // Generated with:
1032 // tools/origin_trials/generate_token.py https://example.com
1033 // FrobulatePersistent
1034 // --expire-timestamp=2000000000
1035 const char kPersistentOriginTrialToken[] =
1036 "AzZfd1vKZ0SSGRGk/"
1037 "8nIszQSlHYjbuYVE3jwaNZG3X4t11zRhzPWWJwTZ+JJDS3JJsyEZcpz+y20pAP6/"
1038 "6upOQ4AAABdeyJvcmlnaW4iOiAiaHR0cHM6Ly9leGFtcGxlLmNvbTo0NDMiLCAiZmVhdHVyZ"
1039 "SI"
1040 "6ICJGcm9idWxhdGVQZXJzaXN0ZW50IiwgImV4cGlyeSI6IDIwMDAwMDAwMDB9";
1041
1042 base::test::ScopedFeatureList scoped_feature_list;
1043 scoped_feature_list.InitAndEnableFeature(features::kPersistentOriginTrials);
1044 blink::ScopedTestOriginTrialPolicy origin_trial_policy_;
1045
1046 const GURL kUrl = GURL("https://example.com");
1047 auto navigation =
1048 NavigationSimulatorImpl::CreateRendererInitiated(kUrl, main_rfh());
1049
1050 auto response_headers =
1051 base::MakeRefCounted<net::HttpResponseHeaders>("HTTP/1.1 200 OK");
1052 response_headers->SetHeader("Origin-Trial", kPersistentOriginTrialToken);
1053 navigation->SetResponseHeaders(response_headers);
1054
1055 navigation->Commit();
1056
1057 url::Origin origin = url::Origin::Create(kUrl);
1058 EXPECT_EQ(std::vector<std::string>{kPersistentOriginTrialToken},
1059 GetPersistedTokens(origin));
1060
1061 // Navigate again without response headers to assert the trial information is
1062 // still updated and cleared.
1063 NavigationSimulatorImpl::CreateRendererInitiated(kUrl, main_rfh())->Commit();
1064 EXPECT_EQ(std::vector<std::string>(), GetPersistedTokens(origin));
1065}
1066
clamy49678312015-10-22 21:59:001067} // namespace content