blob: 47d0e3b8a439ee9148ffdcd83daf1ebbb6d59109 [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
Dmitrii Kuraginb7f90da2022-11-02 22:09:3087 void TearDown() override { RenderViewHostImplTestHarness::TearDown(); }
clamy49678312015-10-22 21:59:0088
Charles Harrison4f2bf1a2017-07-18 20:21:2189 void CancelDeferredNavigation(
90 NavigationThrottle::ThrottleCheckResult result) {
Hiroki Nakagawaadcffc502021-06-16 10:47:5191 GetNavigationRequest()->CancelDeferredNavigationInternal(result);
Charles Harrison4f2bf1a2017-07-18 20:21:2192 }
93
clamy49678312015-10-22 21:59:0094 // Helper function to call WillStartRequest on |handle|. If this function
95 // returns DEFER, |callback_result_| will be set to the actual result of
96 // the throttle checks when they are finished.
97 void SimulateWillStartRequest() {
98 was_callback_called_ = false;
99 callback_result_ = NavigationThrottle::DEFER;
100
Mohamed Abdelhalim7e9e9c12019-11-26 13:48:44101 // It's safe to use base::Unretained since the NavigationRequest is owned by
Mohamed Abdelhalim1e8c5822019-08-02 11:45:43102 // the NavigationRequestTest.
Hiroki Nakagawaadcffc502021-06-16 10:47:51103 GetNavigationRequest()->set_complete_callback_for_testing(
Makoto Shimazud2aa2202019-10-09 13:57:18104 base::BindOnce(&NavigationRequestTest::UpdateThrottleCheckResult,
105 base::Unretained(this)));
Mohamed Abdelhalim7e9e9c12019-11-26 13:48:44106
Hiroki Nakagawaadcffc502021-06-16 10:47:51107 GetNavigationRequest()->WillStartRequest();
clamy49678312015-10-22 21:59:00108 }
109
110 // Helper function to call WillRedirectRequest on |handle|. If this function
111 // returns DEFER, |callback_result_| will be set to the actual result of the
112 // throttle checks when they are finished.
clamye88533842015-11-18 12:48:57113 // TODO(clamy): this should also simulate that WillStartRequest was called if
114 // it has not been called before.
clamy49678312015-10-22 21:59:00115 void SimulateWillRedirectRequest() {
116 was_callback_called_ = false;
117 callback_result_ = NavigationThrottle::DEFER;
118
Mohamed Abdelhalim7e9e9c12019-11-26 13:48:44119 // It's safe to use base::Unretained since the NavigationRequest is owned by
Mohamed Abdelhalim1e8c5822019-08-02 11:45:43120 // the NavigationRequestTest.
Hiroki Nakagawaadcffc502021-06-16 10:47:51121 GetNavigationRequest()->set_complete_callback_for_testing(
Makoto Shimazud2aa2202019-10-09 13:57:18122 base::BindOnce(&NavigationRequestTest::UpdateThrottleCheckResult,
123 base::Unretained(this)));
Mohamed Abdelhalim7e9e9c12019-11-26 13:48:44124
Hiroki Nakagawaadcffc502021-06-16 10:47:51125 GetNavigationRequest()->WillRedirectRequest(
Arthur Hemery3a991c092021-12-22 12:04:24126 GURL(), nullptr /* post_redirect_process */);
clamy49678312015-10-22 21:59:00127 }
128
Lucas Garron0cedd962017-10-17 07:23:33129 // Helper function to call WillFailRequest on |handle|. If this function
130 // returns DEFER, |callback_result_| will be set to the actual result of the
131 // throttle checks when they are finished.
Lucas Garronc1edb5ab2017-11-08 03:31:13132 void SimulateWillFailRequest(
133 net::Error net_error_code,
Anton Bikineevf62d1bf2021-05-15 17:56:07134 const absl::optional<net::SSLInfo> ssl_info = absl::nullopt) {
Lucas Garron0cedd962017-10-17 07:23:33135 was_callback_called_ = false;
136 callback_result_ = NavigationThrottle::DEFER;
Hiroki Nakagawaadcffc502021-06-16 10:47:51137 GetNavigationRequest()->set_net_error(net_error_code);
Lucas Garron0cedd962017-10-17 07:23:33138
Mohamed Abdelhalim7e9e9c12019-11-26 13:48:44139 // It's safe to use base::Unretained since the NavigationRequest is owned by
Mohamed Abdelhalim1e8c5822019-08-02 11:45:43140 // the NavigationRequestTest.
Hiroki Nakagawaadcffc502021-06-16 10:47:51141 GetNavigationRequest()->set_complete_callback_for_testing(
Makoto Shimazud2aa2202019-10-09 13:57:18142 base::BindOnce(&NavigationRequestTest::UpdateThrottleCheckResult,
143 base::Unretained(this)));
Mohamed Abdelhalim7e9e9c12019-11-26 13:48:44144
Hiroki Nakagawaadcffc502021-06-16 10:47:51145 GetNavigationRequest()->WillFailRequest();
Lucas Garron0cedd962017-10-17 07:23:33146 }
147
clamy49678312015-10-22 21:59:00148 // Whether the callback was called.
149 bool was_callback_called() const { return was_callback_called_; }
150
151 // Returns the callback_result.
152 NavigationThrottle::ThrottleCheckResult callback_result() const {
153 return callback_result_;
154 }
155
Hiroki Nakagawaadcffc502021-06-16 10:47:51156 NavigationRequest::NavigationState state() {
157 return GetNavigationRequest()->state();
158 }
Mohamed Abdelhalimccd149af2019-10-31 14:48:53159
Lucas Garron0cedd962017-10-17 07:23:33160 bool call_counts_match(TestNavigationThrottle* throttle,
161 int start,
162 int redirect,
163 int failure,
164 int process) {
165 return start == throttle->GetCallCount(
166 TestNavigationThrottle::WILL_START_REQUEST) &&
167 redirect == throttle->GetCallCount(
168 TestNavigationThrottle::WILL_REDIRECT_REQUEST) &&
169 failure == throttle->GetCallCount(
170 TestNavigationThrottle::WILL_FAIL_REQUEST) &&
171 process == throttle->GetCallCount(
172 TestNavigationThrottle::WILL_PROCESS_RESPONSE);
173 }
174
175 // Creates, register and returns a TestNavigationThrottle that will
176 // synchronously return |result| on checks by default.
clamy49678312015-10-22 21:59:00177 TestNavigationThrottle* CreateTestNavigationThrottle(
178 NavigationThrottle::ThrottleCheckResult result) {
179 TestNavigationThrottle* test_throttle =
Hiroki Nakagawaadcffc502021-06-16 10:47:51180 new TestNavigationThrottle(GetNavigationRequest());
Lucas Garron79e1a972017-10-04 22:25:06181 test_throttle->SetResponseForAllMethods(TestNavigationThrottle::SYNCHRONOUS,
182 result);
Hiroki Nakagawaadcffc502021-06-16 10:47:51183 GetNavigationRequest()->RegisterThrottleForTesting(
dcheng9bfa5162016-04-09 01:00:57184 std::unique_ptr<TestNavigationThrottle>(test_throttle));
clamy49678312015-10-22 21:59:00185 return test_throttle;
186 }
187
Lucas Garron0cedd962017-10-17 07:23:33188 // Creates, register and returns a TestNavigationThrottle that will
189 // synchronously return |result| on check for the given |method|, and
190 // NavigationThrottle::PROCEED otherwise.
191 TestNavigationThrottle* CreateTestNavigationThrottle(
192 TestNavigationThrottle::ThrottleMethod method,
193 NavigationThrottle::ThrottleCheckResult result) {
194 TestNavigationThrottle* test_throttle =
195 CreateTestNavigationThrottle(NavigationThrottle::PROCEED);
196 test_throttle->SetResponse(method, TestNavigationThrottle::SYNCHRONOUS,
197 result);
198 return test_throttle;
199 }
200
Mohamed Abdelhalim9ef43fc2019-04-05 13:09:43201 // TODO(zetamoo): Use NavigationSimulator instead of creating
202 // NavigationRequest and NavigationHandleImpl.
clamy1d4e78fd2017-07-11 12:59:19203 void CreateNavigationHandle() {
Minggang Wanga13c796e2021-07-02 05:54:43204 auto common_params = blink::CreateCommonNavigationParams();
Lucas Furukawa Gadanief8290a2019-07-29 20:27:51205 common_params->initiator_origin =
Lukasz Anforowicz435bcb582019-07-12 20:50:06206 url::Origin::Create(GURL("https://initiator.example.com"));
Minggang Wanga13c796e2021-07-02 05:54:43207 auto commit_params = blink::CreateCommitNavigationParams();
arthursonzogni70ac7302020-05-28 08:49:05208 commit_params->frame_policy =
209 main_test_rfh()->frame_tree_node()->pending_frame_policy();
Hiroki Nakagawaadcffc502021-06-16 10:47:51210 auto request = NavigationRequest::CreateBrowserInitiated(
Lucas Furukawa Gadanief8290a2019-07-29 20:27:51211 main_test_rfh()->frame_tree_node(), std::move(common_params),
arthursonzogni70ac7302020-05-28 08:49:05212 std::move(commit_params), false /* browser-initiated */,
Takashi Toyoshimae87b7be2021-01-22 11:51:08213 false /* was_opener_suppressed */, nullptr /* initiator_frame_token */,
Antonio Sartori9a82f6f32020-12-14 09:22:45214 ChildProcessHost::kInvalidUniqueID /* initiator_process_id */,
John Delaney50425f82020-04-07 16:26:21215 std::string() /* extra_headers */, nullptr /* frame_entry */,
jongdeok.kim5de823b32022-06-14 04:37:50216 nullptr /* entry */, false /* is_form_submission */,
Daniel Hosseinianf0fbfb42021-09-08 02:20:47217 nullptr /* navigation_ui_data */, absl::nullopt /* impression */,
218 false /* is_pdf */);
Hiroki Nakagawaadcffc502021-06-16 10:47:51219 main_test_rfh()->frame_tree_node()->CreatedNavigationRequest(
220 std::move(request));
221 GetNavigationRequest()->StartNavigation();
clamy1d4e78fd2017-07-11 12:59:19222 }
223
Yao Xiao6e1f7d32022-01-07 03:28:40224 FrameTreeNode* AddFrame(FrameTree& frame_tree,
225 RenderFrameHostImpl* parent,
226 int process_id,
227 int new_routing_id,
228 const blink::FramePolicy& frame_policy,
229 blink::FrameOwnerElementType owner_type) {
230 return frame_tree.AddFrame(
231 parent, process_id, new_routing_id,
232 TestRenderFrameHost::CreateStubFrameRemote(),
233 TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
234 TestRenderFrameHost::CreateStubPolicyContainerBindParams(),
Dominic Farolino12e06d72022-08-05 02:29:49235 TestRenderFrameHost::CreateStubAssociatedInterfaceProviderReceiver(),
Yao Xiao6e1f7d32022-01-07 03:28:40236 blink::mojom::TreeScopeType::kDocument, std::string(), "uniqueName0",
237 false, blink::LocalFrameToken(), base::UnguessableToken::Create(),
Daniel Cheng284c38942022-09-22 23:30:34238 blink::DocumentToken(), frame_policy,
239 blink::mojom::FrameOwnerProperties(), false, owner_type,
Yao Xiao6e1f7d32022-01-07 03:28:40240 /*is_dummy_frame_for_inner_tree=*/false);
241 }
242
clamy49678312015-10-22 21:59:00243 private:
Mohamed Abdelhalimf03d4a22019-10-01 13:34:31244 // The callback provided to NavigationRequest::WillStartRequest,
245 // NavigationRequest::WillRedirectRequest, and
246 // NavigationRequest::WillFailRequest during the tests.
Mohamed Abdelhalim7e9e9c12019-11-26 13:48:44247 bool UpdateThrottleCheckResult(
clamy49678312015-10-22 21:59:00248 NavigationThrottle::ThrottleCheckResult result) {
249 callback_result_ = result;
250 was_callback_called_ = true;
Mohamed Abdelhalim7e9e9c12019-11-26 13:48:44251 return true;
clamy49678312015-10-22 21:59:00252 }
253
Hiroki Nakagawaadcffc502021-06-16 10:47:51254 // This must be called after CreateNavigationHandle().
255 NavigationRequest* GetNavigationRequest() {
256 return main_test_rfh()->frame_tree_node()->navigation_request();
257 }
258
Fergal Dalya1d569972021-03-16 03:24:53259 bool was_callback_called_ = false;
clamy49678312015-10-22 21:59:00260 NavigationThrottle::ThrottleCheckResult callback_result_;
261};
262
carlosk489d9e22016-07-25 14:25:43263// Checks that the request_context_type is properly set.
264// Note: can be extended to cover more internal members.
Mohamed Abdelhalim1e8c5822019-08-02 11:45:43265TEST_F(NavigationRequestTest, SimpleDataChecksRedirectAndProcess) {
Camille Lamy62b826012019-02-26 09:15:47266 const GURL kUrl1 = GURL("http://chromium.org");
267 const GURL kUrl2 = GURL("http://google.com");
268 auto navigation =
269 NavigationSimulatorImpl::CreateRendererInitiated(kUrl1, main_rfh());
270 navigation->Start();
Harkiran Bolariaa2c9f79a2021-07-02 09:25:40271 EXPECT_EQ(blink::mojom::RequestContextType::LOCATION,
Mohamed Abdelhalim40c35d22019-09-19 15:59:05272 NavigationRequest::From(navigation->GetNavigationHandle())
273 ->request_context_type());
jkarlinbb150112016-11-02 17:55:11274 EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN,
Camille Lamy62b826012019-02-26 09:15:47275 navigation->GetNavigationHandle()->GetConnectionInfo());
carlosk489d9e22016-07-25 14:25:43276
Camille Lamy62b826012019-02-26 09:15:47277 navigation->set_http_connection_info(
278 net::HttpResponseInfo::CONNECTION_INFO_HTTP1_1);
279 navigation->Redirect(kUrl2);
Harkiran Bolariaa2c9f79a2021-07-02 09:25:40280 EXPECT_EQ(blink::mojom::RequestContextType::LOCATION,
Mohamed Abdelhalim40c35d22019-09-19 15:59:05281 NavigationRequest::From(navigation->GetNavigationHandle())
282 ->request_context_type());
jkarlinbb150112016-11-02 17:55:11283 EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_HTTP1_1,
Camille Lamy62b826012019-02-26 09:15:47284 navigation->GetNavigationHandle()->GetConnectionInfo());
carlosk489d9e22016-07-25 14:25:43285
Camille Lamy62b826012019-02-26 09:15:47286 navigation->set_http_connection_info(
287 net::HttpResponseInfo::CONNECTION_INFO_QUIC_35);
288 navigation->ReadyToCommit();
Harkiran Bolariaa2c9f79a2021-07-02 09:25:40289 EXPECT_EQ(blink::mojom::RequestContextType::LOCATION,
Mohamed Abdelhalim40c35d22019-09-19 15:59:05290 NavigationRequest::From(navigation->GetNavigationHandle())
291 ->request_context_type());
bnc90be5dd782016-11-09 16:28:44292 EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_QUIC_35,
Camille Lamy62b826012019-02-26 09:15:47293 navigation->GetNavigationHandle()->GetConnectionInfo());
jkarlinbb150112016-11-02 17:55:11294}
295
Mohamed Abdelhalim1e8c5822019-08-02 11:45:43296TEST_F(NavigationRequestTest, SimpleDataCheckNoRedirect) {
Camille Lamy62b826012019-02-26 09:15:47297 const GURL kUrl = GURL("http://chromium.org");
298 auto navigation =
299 NavigationSimulatorImpl::CreateRendererInitiated(kUrl, main_rfh());
300 navigation->Start();
jkarlinbb150112016-11-02 17:55:11301 EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN,
Camille Lamy62b826012019-02-26 09:15:47302 navigation->GetNavigationHandle()->GetConnectionInfo());
jkarlinbb150112016-11-02 17:55:11303
Camille Lamy62b826012019-02-26 09:15:47304 navigation->set_http_connection_info(
305 net::HttpResponseInfo::CONNECTION_INFO_QUIC_35);
306 navigation->ReadyToCommit();
bnc90be5dd782016-11-09 16:28:44307 EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_QUIC_35,
Camille Lamy62b826012019-02-26 09:15:47308 navigation->GetNavigationHandle()->GetConnectionInfo());
carlosk489d9e22016-07-25 14:25:43309}
310
Mohamed Abdelhalim1e8c5822019-08-02 11:45:43311TEST_F(NavigationRequestTest, SimpleDataChecksFailure) {
Camille Lamy62b826012019-02-26 09:15:47312 const GURL kUrl = GURL("http://chromium.org");
313 auto navigation =
314 NavigationSimulatorImpl::CreateRendererInitiated(kUrl, main_rfh());
315 navigation->Start();
Harkiran Bolariaa2c9f79a2021-07-02 09:25:40316 EXPECT_EQ(blink::mojom::RequestContextType::LOCATION,
Mohamed Abdelhalim40c35d22019-09-19 15:59:05317 NavigationRequest::From(navigation->GetNavigationHandle())
318 ->request_context_type());
Lucas Garron0cedd962017-10-17 07:23:33319 EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN,
Camille Lamy62b826012019-02-26 09:15:47320 navigation->GetNavigationHandle()->GetConnectionInfo());
Lucas Garron0cedd962017-10-17 07:23:33321
Camille Lamy62b826012019-02-26 09:15:47322 navigation->Fail(net::ERR_CERT_DATE_INVALID);
Harkiran Bolariaa2c9f79a2021-07-02 09:25:40323 EXPECT_EQ(blink::mojom::RequestContextType::LOCATION,
Mohamed Abdelhalim40c35d22019-09-19 15:59:05324 NavigationRequest::From(navigation->GetNavigationHandle())
325 ->request_context_type());
Camille Lamy62b826012019-02-26 09:15:47326 EXPECT_EQ(net::ERR_CERT_DATE_INVALID,
327 navigation->GetNavigationHandle()->GetNetErrorCode());
Lucas Garron0cedd962017-10-17 07:23:33328}
329
clamye88533842015-11-18 12:48:57330// Checks that a navigation deferred during WillStartRequest can be properly
331// cancelled.
Mohamed Abdelhalimba020672019-10-31 16:18:53332TEST_F(NavigationRequestTest, CancelDeferredWillStart) {
clamye88533842015-11-18 12:48:57333 TestNavigationThrottle* test_throttle =
334 CreateTestNavigationThrottle(NavigationThrottle::DEFER);
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19335 EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, state());
Lucas Garron0cedd962017-10-17 07:23:33336 EXPECT_TRUE(call_counts_match(test_throttle, 0, 0, 0, 0));
clamye88533842015-11-18 12:48:57337
338 // Simulate WillStartRequest. The request should be deferred. The callback
339 // should not have been called.
340 SimulateWillStartRequest();
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19341 EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, state());
clamye88533842015-11-18 12:48:57342 EXPECT_FALSE(was_callback_called());
Lucas Garron0cedd962017-10-17 07:23:33343 EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 0, 0));
clamye88533842015-11-18 12:48:57344
345 // Cancel the request. The callback should have been called.
Charles Harrison4f2bf1a2017-07-18 20:21:21346 CancelDeferredNavigation(NavigationThrottle::CANCEL_AND_IGNORE);
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19347 EXPECT_EQ(NavigationRequest::CANCELING, state());
clamye88533842015-11-18 12:48:57348 EXPECT_TRUE(was_callback_called());
349 EXPECT_EQ(NavigationThrottle::CANCEL_AND_IGNORE, callback_result());
Lucas Garron0cedd962017-10-17 07:23:33350 EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 0, 0));
clamye88533842015-11-18 12:48:57351}
352
353// Checks that a navigation deferred during WillRedirectRequest can be properly
354// cancelled.
Mohamed Abdelhalimba020672019-10-31 16:18:53355TEST_F(NavigationRequestTest, CancelDeferredWillRedirect) {
clamye88533842015-11-18 12:48:57356 TestNavigationThrottle* test_throttle =
357 CreateTestNavigationThrottle(NavigationThrottle::DEFER);
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19358 EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, state());
Lucas Garron0cedd962017-10-17 07:23:33359 EXPECT_TRUE(call_counts_match(test_throttle, 0, 0, 0, 0));
clamye88533842015-11-18 12:48:57360
361 // Simulate WillRedirectRequest. The request should be deferred. The callback
362 // should not have been called.
363 SimulateWillRedirectRequest();
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19364 EXPECT_EQ(NavigationRequest::WILL_REDIRECT_REQUEST, state());
clamye88533842015-11-18 12:48:57365 EXPECT_FALSE(was_callback_called());
Lucas Garron0cedd962017-10-17 07:23:33366 EXPECT_TRUE(call_counts_match(test_throttle, 0, 1, 0, 0));
clamye88533842015-11-18 12:48:57367
368 // Cancel the request. The callback should have been called.
Charles Harrison4f2bf1a2017-07-18 20:21:21369 CancelDeferredNavigation(NavigationThrottle::CANCEL_AND_IGNORE);
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19370 EXPECT_EQ(NavigationRequest::CANCELING, state());
clamye88533842015-11-18 12:48:57371 EXPECT_TRUE(was_callback_called());
372 EXPECT_EQ(NavigationThrottle::CANCEL_AND_IGNORE, callback_result());
Lucas Garron0cedd962017-10-17 07:23:33373 EXPECT_TRUE(call_counts_match(test_throttle, 0, 1, 0, 0));
374}
375
376// Checks that a navigation deferred during WillFailRequest can be properly
377// cancelled.
Mohamed Abdelhalimba020672019-10-31 16:18:53378TEST_F(NavigationRequestTest, CancelDeferredWillFail) {
Lucas Garron0cedd962017-10-17 07:23:33379 TestNavigationThrottle* test_throttle = CreateTestNavigationThrottle(
380 TestNavigationThrottle::WILL_FAIL_REQUEST, NavigationThrottle::DEFER);
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19381 EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, state());
Lucas Garron0cedd962017-10-17 07:23:33382 EXPECT_TRUE(call_counts_match(test_throttle, 0, 0, 0, 0));
383
384 // Simulate WillStartRequest.
385 SimulateWillStartRequest();
386 EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 0, 0));
387
388 // Simulate WillFailRequest. The request should be deferred. The callback
389 // should not have been called.
390 SimulateWillFailRequest(net::ERR_CERT_DATE_INVALID);
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19391 EXPECT_EQ(NavigationRequest::WILL_FAIL_REQUEST, state());
Lucas Garron0cedd962017-10-17 07:23:33392 EXPECT_FALSE(was_callback_called());
393 EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 1, 0));
394
395 // Cancel the request. The callback should have been called.
396 CancelDeferredNavigation(NavigationThrottle::CANCEL_AND_IGNORE);
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19397 EXPECT_EQ(NavigationRequest::CANCELING, state());
Lucas Garron0cedd962017-10-17 07:23:33398 EXPECT_TRUE(was_callback_called());
399 EXPECT_EQ(NavigationThrottle::CANCEL_AND_IGNORE, callback_result());
400 EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 1, 0));
clamye88533842015-11-18 12:48:57401}
402
403// Checks that a navigation deferred can be canceled and not ignored.
Mohamed Abdelhalimba020672019-10-31 16:18:53404TEST_F(NavigationRequestTest, CancelDeferredWillRedirectNoIgnore) {
clamye88533842015-11-18 12:48:57405 TestNavigationThrottle* test_throttle =
406 CreateTestNavigationThrottle(NavigationThrottle::DEFER);
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19407 EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, state());
Lucas Garron0cedd962017-10-17 07:23:33408 EXPECT_TRUE(call_counts_match(test_throttle, 0, 0, 0, 0));
clamye88533842015-11-18 12:48:57409
Lucas Garron0cedd962017-10-17 07:23:33410 // Simulate WillStartRequest. The request should be deferred. The callback
clamye88533842015-11-18 12:48:57411 // should not have been called.
412 SimulateWillStartRequest();
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19413 EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, state());
Lucas Garron0cedd962017-10-17 07:23:33414 EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 0, 0));
clamye88533842015-11-18 12:48:57415
416 // Cancel the request. The callback should have been called with CANCEL, and
417 // not CANCEL_AND_IGNORE.
Charles Harrison4f2bf1a2017-07-18 20:21:21418 CancelDeferredNavigation(NavigationThrottle::CANCEL);
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19419 EXPECT_EQ(NavigationRequest::CANCELING, state());
clamye88533842015-11-18 12:48:57420 EXPECT_TRUE(was_callback_called());
421 EXPECT_EQ(NavigationThrottle::CANCEL, callback_result());
Lucas Garron0cedd962017-10-17 07:23:33422 EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 0, 0));
clamye88533842015-11-18 12:48:57423}
424
Lucas Garron0cedd962017-10-17 07:23:33425// Checks that a navigation deferred by WillFailRequest can be canceled and not
426// ignored.
Mohamed Abdelhalimba020672019-10-31 16:18:53427TEST_F(NavigationRequestTest, CancelDeferredWillFailNoIgnore) {
Lucas Garron0cedd962017-10-17 07:23:33428 TestNavigationThrottle* test_throttle = CreateTestNavigationThrottle(
429 TestNavigationThrottle::WILL_FAIL_REQUEST, NavigationThrottle::DEFER);
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19430 EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, state());
Lucas Garron0cedd962017-10-17 07:23:33431 EXPECT_TRUE(call_counts_match(test_throttle, 0, 0, 0, 0));
432
433 // Simulate WillStartRequest.
434 SimulateWillStartRequest();
435 EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 0, 0));
436
437 // Simulate WillFailRequest. The request should be deferred. The callback
438 // should not have been called.
439 SimulateWillFailRequest(net::ERR_CERT_DATE_INVALID);
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19440 EXPECT_EQ(NavigationRequest::WILL_FAIL_REQUEST, state());
Lucas Garron0cedd962017-10-17 07:23:33441 EXPECT_FALSE(was_callback_called());
442 EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 1, 0));
443
444 // Cancel the request. The callback should have been called with CANCEL, and
445 // not CANCEL_AND_IGNORE.
446 CancelDeferredNavigation(NavigationThrottle::CANCEL);
Mohamed Abdelhalimb6f9f702019-11-06 17:23:19447 EXPECT_EQ(NavigationRequest::CANCELING, state());
Lucas Garron0cedd962017-10-17 07:23:33448 EXPECT_TRUE(was_callback_called());
449 EXPECT_EQ(NavigationThrottle::CANCEL, callback_result());
450 EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 1, 0));
451}
452
Lucas Garronc1edb5ab2017-11-08 03:31:13453// Checks that data from the SSLInfo passed into SimulateWillStartRequest() is
John Abd-El-Malekf36e05f2017-11-30 16:17:52454// stored on the handle.
Mohamed Abdelhalim1e8c5822019-08-02 11:45:43455TEST_F(NavigationRequestTest, WillFailRequestSetsSSLInfo) {
Lucas Garronc1edb5ab2017-11-08 03:31:13456 uint16_t cipher_suite = 0xc02f; // TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
457 int connection_status = 0;
458 net::SSLConnectionStatusSetCipherSuite(cipher_suite, &connection_status);
459
460 // Set some test values.
461 net::SSLInfo ssl_info;
462 ssl_info.cert_status = net::CERT_STATUS_AUTHORITY_INVALID;
463 ssl_info.connection_status = connection_status;
464
Camille Lamy62b826012019-02-26 09:15:47465 const GURL kUrl = GURL("https://chromium.org");
466 auto navigation =
467 NavigationSimulatorImpl::CreateRendererInitiated(kUrl, main_rfh());
Emily Starkfd6978ad12019-04-30 21:20:07468 navigation->SetSSLInfo(ssl_info);
Camille Lamy62b826012019-02-26 09:15:47469 navigation->Fail(net::ERR_CERT_DATE_INVALID);
Lucas Garronc1edb5ab2017-11-08 03:31:13470
471 EXPECT_EQ(net::CERT_STATUS_AUTHORITY_INVALID,
Camille Lamy62b826012019-02-26 09:15:47472 navigation->GetNavigationHandle()->GetSSLInfo()->cert_status);
473 EXPECT_EQ(connection_status,
474 navigation->GetNavigationHandle()->GetSSLInfo()->connection_status);
Lucas Garronc1edb5ab2017-11-08 03:31:13475}
476
Camille Lamy62b826012019-02-26 09:15:47477namespace {
478
Alex Moshchuk1a66b1d2018-05-15 21:18:26479// Helper throttle which checks that it can access NavigationHandle's
480// RenderFrameHost in WillFailRequest() and then defers the failure.
481class GetRenderFrameHostOnFailureNavigationThrottle
482 : public NavigationThrottle {
483 public:
Fergal Dalya1d569972021-03-16 03:24:53484 explicit GetRenderFrameHostOnFailureNavigationThrottle(
485 NavigationHandle* handle)
Alex Moshchuk1a66b1d2018-05-15 21:18:26486 : NavigationThrottle(handle) {}
Peter Boström828b9022021-09-21 02:28:43487
488 GetRenderFrameHostOnFailureNavigationThrottle(
489 const GetRenderFrameHostOnFailureNavigationThrottle&) = delete;
490 GetRenderFrameHostOnFailureNavigationThrottle& operator=(
491 const GetRenderFrameHostOnFailureNavigationThrottle&) = delete;
492
Fergal Dalya1d569972021-03-16 03:24:53493 ~GetRenderFrameHostOnFailureNavigationThrottle() override = default;
Alex Moshchuk1a66b1d2018-05-15 21:18:26494
495 NavigationThrottle::ThrottleCheckResult WillFailRequest() override {
496 EXPECT_TRUE(navigation_handle()->GetRenderFrameHost());
497 return NavigationThrottle::DEFER;
498 }
499
500 const char* GetNameForLogging() override {
501 return "GetRenderFrameHostOnFailureNavigationThrottle";
502 }
Alex Moshchuk1a66b1d2018-05-15 21:18:26503};
504
Camille Lamy62b826012019-02-26 09:15:47505class ThrottleTestContentBrowserClient : public ContentBrowserClient {
506 std::vector<std::unique_ptr<NavigationThrottle>> CreateThrottlesForNavigation(
507 NavigationHandle* navigation_handle) override {
508 std::vector<std::unique_ptr<NavigationThrottle>> throttle;
509 throttle.push_back(
510 std::make_unique<GetRenderFrameHostOnFailureNavigationThrottle>(
511 navigation_handle));
512 return throttle;
513 }
514};
515
516} // namespace
517
Alex Moshchuk1a66b1d2018-05-15 21:18:26518// Verify that the NavigationHandle::GetRenderFrameHost() can be retrieved by a
519// throttle in WillFailRequest(), as well as after deferring the failure. This
520// is allowed, since at that point the final RenderFrameHost will have already
521// been chosen. See https://crbug.com/817881.
Mohamed Abdelhalimba020672019-10-31 16:18:53522TEST_F(NavigationRequestTest, WillFailRequestCanAccessRenderFrameHost) {
Camille Lamy62b826012019-02-26 09:15:47523 std::unique_ptr<ContentBrowserClient> client(
524 new ThrottleTestContentBrowserClient);
525 ContentBrowserClient* old_browser_client =
526 SetBrowserClientForTesting(client.get());
527
528 const GURL kUrl = GURL("http://chromium.org");
529 auto navigation =
530 NavigationSimulatorImpl::CreateRendererInitiated(kUrl, main_rfh());
531 navigation->SetAutoAdvance(false);
532 navigation->Start();
533 navigation->Fail(net::ERR_CERT_DATE_INVALID);
Mohamed Abdelhalim3b235272019-11-05 15:06:07534 EXPECT_EQ(
535 NavigationRequest::WILL_FAIL_REQUEST,
536 NavigationRequest::From(navigation->GetNavigationHandle())->state());
Camille Lamy62b826012019-02-26 09:15:47537 EXPECT_TRUE(navigation->GetNavigationHandle()->GetRenderFrameHost());
Mohamed Abdelhalim40c35d22019-09-19 15:59:05538 NavigationRequest::From(navigation->GetNavigationHandle())
danakjf26536bf2020-09-10 00:46:13539 ->GetNavigationThrottleRunnerForTesting()
Mohamed Abdelhalim40c35d22019-09-19 15:59:05540 ->CallResumeForTesting();
Camille Lamy62b826012019-02-26 09:15:47541 EXPECT_TRUE(navigation->GetNavigationHandle()->GetRenderFrameHost());
542
543 SetBrowserClientForTesting(old_browser_client);
Alex Moshchuk1a66b1d2018-05-15 21:18:26544}
545
Antonio Sartori3cfa3b62020-10-09 10:42:40546TEST_F(NavigationRequestTest, PolicyContainerInheritance) {
547 struct TestCase {
548 const char* url;
549 bool expect_inherit;
550 } cases[]{{"about:blank", true},
551 {"data:text/plain,hello", true},
552 {"file://local", false},
553 {"http://chromium.org", false}};
554
555 const GURL kUrl1 = GURL("http://chromium.org");
556 auto navigation =
557 NavigationSimulatorImpl::CreateRendererInitiated(kUrl1, main_rfh());
558 navigation->Commit();
559
560 for (auto test : cases) {
561 // We navigate child frames because the BlockedSchemeNavigationThrottle
562 // restricts navigations in the main frame.
563 auto* child_frame = static_cast<TestRenderFrameHost*>(
564 content::RenderFrameHostTester::For(main_rfh())->AppendChild("child"));
565
566 // We set the referrer policy of the frame to "always". We then create a new
567 // navigation, set as initiator the frame itself, start the navigation, and
568 // change the referrer policy of the frame to "never". After we commit the
569 // navigation:
570 // - If navigating to a local scheme, the target frame should have inherited
571 // the referrer policy of the initiator ("always").
572 // - If navigating to a non-local scheme, the target frame should have a new
573 // policy container (hence referrer policy set to "default").
574 const GURL kUrl = GURL(test.url);
Peter Kastingeb8c3ce2021-08-20 04:39:35575 navigation =
Antonio Sartori3cfa3b62020-10-09 10:42:40576 NavigationSimulatorImpl::CreateRendererInitiated(kUrl, child_frame);
Antonio Sartori5b2f8042020-10-23 18:13:26577 static_cast<blink::mojom::PolicyContainerHost*>(
Antonio Sartori9290b6b2020-11-09 10:09:33578 child_frame->policy_container_host())
Antonio Sartori5b2f8042020-10-23 18:13:26579 ->SetReferrerPolicy(network::mojom::ReferrerPolicy::kAlways);
Antonio Sartori3cfa3b62020-10-09 10:42:40580 navigation->SetInitiatorFrame(child_frame);
581 navigation->Start();
Antonio Sartori5b2f8042020-10-23 18:13:26582 static_cast<blink::mojom::PolicyContainerHost*>(
Antonio Sartori9290b6b2020-11-09 10:09:33583 child_frame->policy_container_host())
Antonio Sartori5b2f8042020-10-23 18:13:26584 ->SetReferrerPolicy(network::mojom::ReferrerPolicy::kNever);
Antonio Sartori3cfa3b62020-10-09 10:42:40585 navigation->Commit();
586 EXPECT_EQ(
587 test.expect_inherit ? network::mojom::ReferrerPolicy::kAlways
588 : network::mojom::ReferrerPolicy::kDefault,
589 static_cast<RenderFrameHostImpl*>(navigation->GetFinalRenderFrameHost())
Antonio Sartori9290b6b2020-11-09 10:09:33590 ->policy_container_host()
Antonio Sartori3cfa3b62020-10-09 10:42:40591 ->referrer_policy());
592 }
593}
594
Cammie Smith Barnesa0da2cf2021-01-11 22:09:37595TEST_F(NavigationRequestTest, DnsAliasesCanBeAccessed) {
596 // Create simulated NavigationRequest for the URL, which has aliases.
597 const GURL kUrl = GURL("http://chromium.org");
598 auto navigation =
599 NavigationSimulatorImpl::CreateRendererInitiated(kUrl, main_rfh());
600 std::vector<std::string> dns_aliases({"alias1", "alias2"});
601 navigation->SetResponseDnsAliases(std::move(dns_aliases));
602
603 // Start the navigation.
604 navigation->Start();
605 EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN,
606 navigation->GetNavigationHandle()->GetConnectionInfo());
607
608 // Commit the navigation.
609 navigation->set_http_connection_info(
610 net::HttpResponseInfo::CONNECTION_INFO_QUIC_35);
611 navigation->ReadyToCommit();
612 EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_QUIC_35,
613 navigation->GetNavigationHandle()->GetConnectionInfo());
614
615 // Verify that the aliases are accessible from the NavigationRequest.
616 EXPECT_THAT(navigation->GetNavigationHandle()->GetDnsAliases(),
617 testing::ElementsAre("alias1", "alias2"));
618}
619
620TEST_F(NavigationRequestTest, NoDnsAliases) {
621 // Create simulated NavigationRequest for the URL, which does not
622 // have aliases. (Note the empty alias list.)
623 const GURL kUrl = GURL("http://chromium.org");
624 auto navigation =
625 NavigationSimulatorImpl::CreateRendererInitiated(kUrl, main_rfh());
626 std::vector<std::string> dns_aliases;
627 navigation->SetResponseDnsAliases(std::move(dns_aliases));
628
629 // Start the navigation.
630 navigation->Start();
631 EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN,
632 navigation->GetNavigationHandle()->GetConnectionInfo());
633
634 // Commit the navigation.
635 navigation->set_http_connection_info(
636 net::HttpResponseInfo::CONNECTION_INFO_QUIC_35);
637 navigation->ReadyToCommit();
638 EXPECT_EQ(net::HttpResponseInfo::CONNECTION_INFO_QUIC_35,
639 navigation->GetNavigationHandle()->GetConnectionInfo());
640
641 // Verify that there are no aliases in the NavigationRequest.
642 EXPECT_TRUE(navigation->GetNavigationHandle()->GetDnsAliases().empty());
643}
644
Antonio Sartori3e8de6d2021-07-26 10:28:41645TEST_F(NavigationRequestTest, StorageKeyToCommit) {
646 TestRenderFrameHost* child_document = static_cast<TestRenderFrameHost*>(
647 content::RenderFrameHostTester::For(main_rfh())->AppendChild(""));
Yuzu Saijo03dbf9b2022-07-22 04:29:45648 auto attributes = child_document->frame_tree_node()->attributes_->Clone();
649 // Set |anonymous| to true.
650 attributes->anonymous = true;
651 child_document->frame_tree_node()->SetAttributes(std::move(attributes));
Antonio Sartori3e8de6d2021-07-26 10:28:41652
653 const GURL kUrl = GURL("http://chromium.org");
654 auto navigation =
655 NavigationSimulatorImpl::CreateRendererInitiated(kUrl, child_document);
656 navigation->ReadyToCommit();
657 NavigationRequest* request =
658 NavigationRequest::From(navigation->GetNavigationHandle());
659 EXPECT_TRUE(request->commit_params().storage_key.nonce().has_value());
Ali Hijazi78de14c2022-07-21 11:32:19660 EXPECT_EQ(child_document->GetMainFrame()->anonymous_iframes_nonce(),
Antonio Sartori3e8de6d2021-07-26 10:28:41661 request->commit_params().storage_key.nonce().value());
662
663 navigation->Commit();
664 child_document =
665 static_cast<TestRenderFrameHost*>(navigation->GetFinalRenderFrameHost());
Arthur Sonzognie41678a2022-06-16 15:51:19666 EXPECT_TRUE(child_document->IsAnonymous());
Ali Hijazi78de14c2022-07-21 11:32:19667 EXPECT_EQ(blink::StorageKey::CreateWithNonce(
668 url::Origin::Create(kUrl),
669 child_document->GetMainFrame()->anonymous_iframes_nonce()),
670 child_document->storage_key());
Antonio Sartori3e8de6d2021-07-26 10:28:41671}
672
Antonio Sartoribf27cc442021-08-25 13:08:23673TEST_F(NavigationRequestTest,
674 NavigationToAnonymousDocumentNetworkIsolationInfo) {
675 auto* child_frame = static_cast<TestRenderFrameHost*>(
676 content::RenderFrameHostTester::For(main_test_rfh())
677 ->AppendChild("child"));
Yuzu Saijo03dbf9b2022-07-22 04:29:45678 auto attributes = child_frame->frame_tree_node()->attributes_->Clone();
679 // Set |anonymous| to true.
680 attributes->anonymous = true;
681 child_frame->frame_tree_node()->SetAttributes(std::move(attributes));
Antonio Sartoribf27cc442021-08-25 13:08:23682
683 std::unique_ptr<NavigationSimulator> navigation =
684 NavigationSimulator::CreateRendererInitiated(
685 GURL("https://example.com/navigation.html"), child_frame);
686 navigation->ReadyToCommit();
687
Ali Hijazi78de14c2022-07-21 11:32:19688 EXPECT_EQ(main_test_rfh()->anonymous_iframes_nonce(),
Antonio Sartoribf27cc442021-08-25 13:08:23689 static_cast<NavigationRequest*>(navigation->GetNavigationHandle())
690 ->isolation_info_for_subresources()
691 .network_isolation_key()
692 .GetNonce());
Ali Hijazi78de14c2022-07-21 11:32:19693 EXPECT_EQ(main_test_rfh()->anonymous_iframes_nonce(),
Antonio Sartoribf27cc442021-08-25 13:08:23694 static_cast<NavigationRequest*>(navigation->GetNavigationHandle())
695 ->GetIsolationInfo()
696 .network_isolation_key()
697 .GetNonce());
698}
699
Robbie McElrath5641d572022-05-20 17:15:29700class ScopedIsolatedAppBrowserClient : public ContentBrowserClient {
701 public:
702 ScopedIsolatedAppBrowserClient()
703 : old_client_(SetBrowserClientForTesting(this)) {}
704
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 {
713 return origin_matches_flag;
Robbie McElrath5641d572022-05-20 17:15:29714 }
715
716 private:
717 raw_ptr<ContentBrowserClient> old_client_;
718};
719
720TEST_F(NavigationRequestTest, IsolatedAppPolicyInjection) {
721 const GURL kUrl = GURL("https://chromium.org");
722 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
723 switches::kIsolatedAppOrigins, kUrl.spec());
724 // Disable flag caching so the --isolated-app-origins value takes effect.
725 SiteIsolationPolicy::DisableFlagCachingForTesting();
726 ScopedIsolatedAppBrowserClient client;
727
728 auto navigation =
729 NavigationSimulatorImpl::CreateRendererInitiated(kUrl, main_rfh());
730 navigation->ReadyToCommit();
731
732 // Validate the COOP/COEP headers.
733 const PolicyContainerPolicies& policies =
734 navigation->GetNavigationHandle()->GetPolicyContainerPolicies();
735 EXPECT_EQ(network::mojom::CrossOriginOpenerPolicyValue::kSameOriginPlusCoep,
736 policies.cross_origin_opener_policy.value);
737 EXPECT_EQ(network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp,
738 policies.cross_origin_embedder_policy.value);
739
740 // Validate CSP.
741 EXPECT_EQ(1UL, policies.content_security_policies.size());
742 const auto& csp = policies.content_security_policies[0];
Ovidio Ruiz-Henríquezadd3f402022-10-17 19:10:31743 EXPECT_EQ(10UL, csp->raw_directives.size());
Robbie McElrath5641d572022-05-20 17:15:29744 using Directive = network::mojom::CSPDirectiveName;
745 EXPECT_EQ("'none'", csp->raw_directives[Directive::BaseURI]);
746 EXPECT_EQ("'none'", csp->raw_directives[Directive::ObjectSrc]);
747 EXPECT_EQ("'self'", csp->raw_directives[Directive::DefaultSrc]);
748 EXPECT_EQ("'self' https:", csp->raw_directives[Directive::FrameSrc]);
749 EXPECT_EQ("'self' https:", csp->raw_directives[Directive::ConnectSrc]);
Robbie McElrathb062f3d2022-08-09 17:48:44750 EXPECT_EQ("'self' 'wasm-unsafe-eval'",
751 csp->raw_directives[Directive::ScriptSrc]);
Ovidio Ruiz-Henríquezadd3f402022-10-17 19:10:31752 EXPECT_EQ("'self' data:", csp->raw_directives[Directive::ImgSrc]);
753 EXPECT_EQ("'self' data:", csp->raw_directives[Directive::MediaSrc]);
754 EXPECT_EQ("'self' data:", csp->raw_directives[Directive::FontSrc]);
Robbie McElrath5641d572022-05-20 17:15:29755 EXPECT_EQ("'script'", csp->raw_directives[Directive::RequireTrustedTypesFor]);
756}
757
arthursonzogni898dcda52021-01-21 08:50:10758// Test that the required CSP of every frame is computed/inherited correctly and
759// that the Sec-Required-CSP header is set.
760class CSPEmbeddedEnforcementUnitTest : public NavigationRequestTest {
761 protected:
762 TestRenderFrameHost* main_rfh() {
763 return static_cast<TestRenderFrameHost*>(NavigationRequestTest::main_rfh());
764 }
765
766 // Simulate the |csp| attribute being set in |rfh|'s frame. Then navigate it.
767 // Returns the request's Sec-Required-CSP header.
768 std::string NavigateWithRequiredCSP(TestRenderFrameHost** rfh,
769 std::string required_csp) {
770 TestRenderFrameHost* document = *rfh;
771
772 if (!required_csp.empty()) {
773 auto headers =
774 base::MakeRefCounted<net::HttpResponseHeaders>("HTTP/1.1 200 OK");
775 headers->SetHeader("Content-Security-Policy", required_csp);
776 std::vector<network::mojom::ContentSecurityPolicyPtr> policies;
777 network::AddContentSecurityPolicyFromHeaders(
778 *headers, GURL("https://example.com/"), &policies);
Yuzu Saijo03dbf9b2022-07-22 04:29:45779 auto attributes = document->frame_tree_node()->attributes_->Clone();
780 // Set csp value.
781 attributes->parsed_csp_attribute = std::move(policies[0]);
782 document->frame_tree_node()->SetAttributes(std::move(attributes));
arthursonzogni898dcda52021-01-21 08:50:10783 }
784
785 // Chrome blocks a document navigating to a URL if more than one of its
786 // ancestors have the same URL. Use a different URL every time, to
787 // avoid blocking navigation of the grandchild frame.
788 static int nonce = 0;
789 GURL url("https://www.example.com" + base::NumberToString(nonce++));
790
791 auto navigation =
792 content::NavigationSimulator::CreateRendererInitiated(url, *rfh);
793 navigation->Start();
794 NavigationRequest* request =
795 NavigationRequest::From(navigation->GetNavigationHandle());
796 std::string sec_required_csp;
797 request->GetRequestHeaders().GetHeader("sec-required-csp",
798 &sec_required_csp);
799
800 // Complete the navigation so that the required csp is stored in the
801 // RenderFrameHost, so that when we will add children to this document they
802 // will be able to get the parent's required csp (and hence also test that
803 // the whole logic works).
804 auto response_headers =
805 base::MakeRefCounted<net::HttpResponseHeaders>("HTTP/1.1 200 OK");
806 response_headers->SetHeader("Allow-CSP-From", "*");
807 navigation->SetResponseHeaders(response_headers);
808 navigation->Commit();
809
810 *rfh = static_cast<TestRenderFrameHost*>(
811 navigation->GetFinalRenderFrameHost());
812
813 return sec_required_csp;
814 }
815
816 TestRenderFrameHost* AddChild(TestRenderFrameHost* parent) {
817 return static_cast<TestRenderFrameHost*>(
818 content::RenderFrameHostTester::For(parent)->AppendChild(""));
819 }
820};
821
822TEST_F(CSPEmbeddedEnforcementUnitTest, TopLevel) {
823 TestRenderFrameHost* top_document = main_rfh();
824 std::string sec_required_csp = NavigateWithRequiredCSP(&top_document, "");
825 EXPECT_EQ("", sec_required_csp);
826 EXPECT_FALSE(top_document->required_csp());
827}
828
829TEST_F(CSPEmbeddedEnforcementUnitTest, ChildNoCSP) {
830 TestRenderFrameHost* top_document = main_rfh();
831 TestRenderFrameHost* child_document = AddChild(top_document);
832 std::string sec_required_csp = NavigateWithRequiredCSP(&child_document, "");
833 EXPECT_EQ("", sec_required_csp);
834 EXPECT_FALSE(child_document->required_csp());
835}
836
837TEST_F(CSPEmbeddedEnforcementUnitTest, ChildWithCSP) {
838 TestRenderFrameHost* top_document = main_rfh();
839 TestRenderFrameHost* child_document = AddChild(top_document);
840 std::string sec_required_csp =
841 NavigateWithRequiredCSP(&child_document, "script-src 'none'");
842 EXPECT_EQ("script-src 'none'", sec_required_csp);
843 EXPECT_TRUE(child_document->required_csp());
844 EXPECT_EQ("script-src 'none'",
845 child_document->required_csp()->header->header_value);
846}
847
848TEST_F(CSPEmbeddedEnforcementUnitTest, ChildSiblingNoCSP) {
849 TestRenderFrameHost* top_document = main_rfh();
850 TestRenderFrameHost* child_document = AddChild(top_document);
851 NavigateWithRequiredCSP(&child_document, "script-src 'none'");
852 TestRenderFrameHost* sibling_document = AddChild(top_document);
853 std::string sec_required_csp = NavigateWithRequiredCSP(&sibling_document, "");
854 EXPECT_FALSE(sibling_document->required_csp());
855}
856
857TEST_F(CSPEmbeddedEnforcementUnitTest, ChildSiblingCSP) {
858 TestRenderFrameHost* top_document = main_rfh();
859 TestRenderFrameHost* child_document = AddChild(top_document);
860 NavigateWithRequiredCSP(&child_document, "script-src 'none'");
861 TestRenderFrameHost* sibling_document = AddChild(top_document);
862 std::string sec_required_csp =
863 NavigateWithRequiredCSP(&sibling_document, "script-src 'none'");
864 EXPECT_EQ("script-src 'none'", sec_required_csp);
865 EXPECT_TRUE(sibling_document->required_csp());
866 EXPECT_EQ("script-src 'none'",
867 sibling_document->required_csp()->header->header_value);
868}
869
870TEST_F(CSPEmbeddedEnforcementUnitTest, GrandChildNoCSP) {
871 TestRenderFrameHost* top_document = main_rfh();
872 TestRenderFrameHost* child_document = AddChild(top_document);
873 NavigateWithRequiredCSP(&child_document, "script-src 'none'");
874 TestRenderFrameHost* grand_child_document = AddChild(child_document);
875 std::string sec_required_csp =
876 NavigateWithRequiredCSP(&grand_child_document, "");
877 EXPECT_EQ("script-src 'none'", sec_required_csp);
878 EXPECT_TRUE(grand_child_document->required_csp());
879 EXPECT_EQ("script-src 'none'",
880 grand_child_document->required_csp()->header->header_value);
881}
882
883TEST_F(CSPEmbeddedEnforcementUnitTest, GrandChildSameCSP) {
884 TestRenderFrameHost* top_document = main_rfh();
885 TestRenderFrameHost* child_document = AddChild(top_document);
886 NavigateWithRequiredCSP(&child_document, "script-src 'none'");
887 TestRenderFrameHost* grand_child_document = AddChild(child_document);
888 std::string sec_required_csp =
889 NavigateWithRequiredCSP(&grand_child_document, "script-src 'none'");
890 EXPECT_EQ("script-src 'none'", sec_required_csp);
891 EXPECT_TRUE(grand_child_document->required_csp());
892 EXPECT_EQ("script-src 'none'",
893 grand_child_document->required_csp()->header->header_value);
894}
895
896TEST_F(CSPEmbeddedEnforcementUnitTest, GrandChildDifferentCSP) {
897 TestRenderFrameHost* top_document = main_rfh();
898 TestRenderFrameHost* child_document = AddChild(top_document);
899 NavigateWithRequiredCSP(&child_document, "script-src 'none'");
900 TestRenderFrameHost* grand_child_document = AddChild(child_document);
901 std::string sec_required_csp =
902 NavigateWithRequiredCSP(&grand_child_document, "img-src 'none'");
903
904 // This seems weird, but it is the intended behaviour according to the spec.
905 // The problem is that "script-src 'none'" does not subsume "img-src 'none'",
906 // so "img-src 'none'" on the grandchild is an invalid csp attribute, and we
907 // just discard it in favour of the parent's csp attribute.
908 //
909 // This should probably be fixed in the specification:
910 // https://github.com/w3c/webappsec-cspee/pull/11
911 EXPECT_EQ("script-src 'none'", sec_required_csp);
912 EXPECT_TRUE(grand_child_document->required_csp());
913 EXPECT_EQ("script-src 'none'",
914 grand_child_document->required_csp()->header->header_value);
915}
916
917TEST_F(CSPEmbeddedEnforcementUnitTest, InvalidCSP) {
918 TestRenderFrameHost* top_document = main_rfh();
919 TestRenderFrameHost* child_document = AddChild(top_document);
920 std::string sec_required_csp =
921 NavigateWithRequiredCSP(&child_document, "report-to group");
922 EXPECT_EQ("", sec_required_csp);
923 EXPECT_FALSE(child_document->required_csp());
924}
925
926TEST_F(CSPEmbeddedEnforcementUnitTest, InvalidCspAndInheritFromParent) {
927 TestRenderFrameHost* top_document = main_rfh();
928 TestRenderFrameHost* child_document = AddChild(top_document);
929 NavigateWithRequiredCSP(&child_document, "script-src 'none'");
930 TestRenderFrameHost* grand_child_document = AddChild(child_document);
931 std::string sec_required_csp =
Antonio Sartori4231e932021-02-04 12:01:14932 NavigateWithRequiredCSP(&grand_child_document, "report-to group");
arthursonzogni898dcda52021-01-21 08:50:10933 EXPECT_EQ("script-src 'none'", sec_required_csp);
934 EXPECT_TRUE(grand_child_document->required_csp());
935 EXPECT_EQ("script-src 'none'",
936 grand_child_document->required_csp()->header->header_value);
937}
938
939TEST_F(CSPEmbeddedEnforcementUnitTest,
940 SemiInvalidCspAndInheritSameCspFromParent) {
941 TestRenderFrameHost* top_document = main_rfh();
942 TestRenderFrameHost* child_document = AddChild(top_document);
943 NavigateWithRequiredCSP(&child_document, "script-src 'none'");
944 TestRenderFrameHost* grand_child_document = AddChild(child_document);
945 std::string sec_required_csp = NavigateWithRequiredCSP(
Antonio Sartori4231e932021-02-04 12:01:14946 &grand_child_document, "script-src 'none'; report-to group");
arthursonzogni898dcda52021-01-21 08:50:10947 EXPECT_EQ("script-src 'none'", sec_required_csp);
948 EXPECT_TRUE(grand_child_document->required_csp());
949 EXPECT_EQ("script-src 'none'",
950 grand_child_document->required_csp()->header->header_value);
951}
952
953TEST_F(CSPEmbeddedEnforcementUnitTest,
954 SemiInvalidCspAndInheritDifferentCspFromParent) {
955 TestRenderFrameHost* top_document = main_rfh();
956 TestRenderFrameHost* child_document = AddChild(top_document);
957 NavigateWithRequiredCSP(&child_document, "script-src 'none'");
958 TestRenderFrameHost* grand_child_document = AddChild(child_document);
959 std::string sec_required_csp = NavigateWithRequiredCSP(
Antonio Sartori4231e932021-02-04 12:01:14960 &grand_child_document, "sandbox; report-to group");
arthursonzogni898dcda52021-01-21 08:50:10961 EXPECT_EQ("script-src 'none'", sec_required_csp);
962 EXPECT_TRUE(grand_child_document->required_csp());
963 EXPECT_EQ("script-src 'none'",
964 grand_child_document->required_csp()->header->header_value);
965}
966
Peter Birk Pakkenberg73e07b62022-09-21 11:20:30967namespace {
968
969// Mock that allows us to avoid depending on the origin_trials component.
970class OriginTrialsControllerDelegateMock
971 : public OriginTrialsControllerDelegate {
972 public:
973 ~OriginTrialsControllerDelegateMock() override = default;
974
975 void PersistTrialsFromTokens(
976 const url::Origin& origin,
977 const base::span<const std::string> header_tokens,
978 const base::Time current_time) override {
979 persisted_tokens_[origin] =
980 std::vector<std::string>(header_tokens.begin(), header_tokens.end());
981 }
982 bool IsTrialPersistedForOrigin(const url::Origin& origin,
983 const base::StringPiece trial_name,
984 const base::Time current_time) override {
985 DCHECK(false) << "Method not implemented for test.";
986 return false;
987 }
988
Peter Birk Pakkenberg4c1bb272022-09-27 10:51:29989 base::flat_set<std::string> GetPersistedTrialsForOrigin(
990 const url::Origin& origin,
991 base::Time current_time) override {
992 DCHECK(false) << "Method not implemented for test.";
993 return base::flat_set<std::string>();
994 }
995
Peter Birk Pakkenbergd74c6f82022-11-08 17:44:38996 void ClearPersistedTokens() override { persisted_tokens_.clear(); }
997
Peter Birk Pakkenberg73e07b62022-09-21 11:20:30998 base::flat_map<url::Origin, std::vector<std::string>> persisted_tokens_;
999};
1000
1001} // namespace
1002
1003class PersistentOriginTrialNavigationRequestTest
1004 : public NavigationRequestTest {
1005 public:
1006 PersistentOriginTrialNavigationRequestTest()
1007 : delegate_mock_(std::make_unique<OriginTrialsControllerDelegateMock>()) {
1008
1009 }
1010 ~PersistentOriginTrialNavigationRequestTest() override = default;
1011
1012 std::vector<std::string> GetPersistedTokens(const url::Origin& origin) {
1013 return delegate_mock_->persisted_tokens_[origin];
1014 }
1015
1016 protected:
1017 std::unique_ptr<BrowserContext> CreateBrowserContext() override {
1018 std::unique_ptr<TestBrowserContext> context =
1019 std::make_unique<TestBrowserContext>();
1020 context->SetOriginTrialsControllerDelegate(delegate_mock_.get());
1021 return context;
1022 }
1023
1024 private:
1025 std::unique_ptr<OriginTrialsControllerDelegateMock> delegate_mock_;
1026};
1027
1028// Ensure that navigations with a valid Origin-Trial header with a persistent
1029// origin trial token results in the trial being marked as enabled.
1030// Then check that subsequent navigations without headers trigger an update
1031// that clears out stored trials.
1032TEST_F(PersistentOriginTrialNavigationRequestTest,
1033 NavigationCommitsPersistentOriginTrials) {
1034 // Generated with:
1035 // tools/origin_trials/generate_token.py https://example.com
1036 // FrobulatePersistent
1037 // --expire-timestamp=2000000000
1038 const char kPersistentOriginTrialToken[] =
1039 "AzZfd1vKZ0SSGRGk/"
1040 "8nIszQSlHYjbuYVE3jwaNZG3X4t11zRhzPWWJwTZ+JJDS3JJsyEZcpz+y20pAP6/"
1041 "6upOQ4AAABdeyJvcmlnaW4iOiAiaHR0cHM6Ly9leGFtcGxlLmNvbTo0NDMiLCAiZmVhdHVyZ"
1042 "SI"
1043 "6ICJGcm9idWxhdGVQZXJzaXN0ZW50IiwgImV4cGlyeSI6IDIwMDAwMDAwMDB9";
1044
1045 base::test::ScopedFeatureList scoped_feature_list;
1046 scoped_feature_list.InitAndEnableFeature(features::kPersistentOriginTrials);
1047 blink::ScopedTestOriginTrialPolicy origin_trial_policy_;
1048
1049 const GURL kUrl = GURL("https://example.com");
1050 auto navigation =
1051 NavigationSimulatorImpl::CreateRendererInitiated(kUrl, main_rfh());
1052
1053 auto response_headers =
1054 base::MakeRefCounted<net::HttpResponseHeaders>("HTTP/1.1 200 OK");
1055 response_headers->SetHeader("Origin-Trial", kPersistentOriginTrialToken);
1056 navigation->SetResponseHeaders(response_headers);
1057
1058 navigation->Commit();
1059
1060 url::Origin origin = url::Origin::Create(kUrl);
1061 EXPECT_EQ(std::vector<std::string>{kPersistentOriginTrialToken},
1062 GetPersistedTokens(origin));
1063
1064 // Navigate again without response headers to assert the trial information is
1065 // still updated and cleared.
1066 NavigationSimulatorImpl::CreateRendererInitiated(kUrl, main_rfh())->Commit();
1067 EXPECT_EQ(std::vector<std::string>(), GetPersistedTokens(origin));
1068}
1069
clamy49678312015-10-22 21:59:001070} // namespace content