blob: b169c1a31e3594230f3f26011a3ab106f5441929 [file] [log] [blame]
Avi Drissman4e1b7bc32022-09-15 14:03:501// Copyright 2014 The Chromium Authors
davidben6b77cd72014-10-29 21:13:452// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Chris Fredrickson9ffdf5b2024-07-09 20:05:095#include "content/browser/loader/navigation_url_loader.h"
6
dcheng40ce7b382016-04-08 23:46:137#include <memory>
dcheng36b6aec92015-12-26 06:16:368#include <utility>
9
davidben6b77cd72014-10-29 21:13:4510#include "base/command_line.h"
Avi Drissmanadac21992023-01-11 23:46:3911#include "base/functional/bind.h"
davidben6b77cd72014-10-29 21:13:4512#include "base/memory/ref_counted.h"
davidben6b77cd72014-10-29 21:13:4513#include "base/run_loop.h"
Tsuyoshi Horo32b51f12018-05-09 17:58:4614#include "base/unguessable_token.h"
Kevin McNee8f0543b2021-03-12 16:13:3515#include "content/browser/renderer_host/frame_tree_node.h"
danakj10f32372020-09-15 22:25:1616#include "content/browser/renderer_host/navigation_request_info.h"
Tsuyoshi Horo0e20a6e2019-06-04 09:48:3017#include "content/browser/web_package/prefetched_signed_exchange_cache.h"
davidben6b77cd72014-10-29 21:13:4518#include "content/public/browser/browser_context.h"
clamy1e5574e92016-09-29 16:48:4419#include "content/public/browser/navigation_ui_data.h"
John Abd-El-Malek8e05be72019-05-28 16:35:1720#include "content/public/browser/storage_partition.h"
davidben6b77cd72014-10-29 21:13:4521#include "content/public/common/content_switches.h"
Gabriel Charettec7108742019-08-23 03:31:4022#include "content/public/test/browser_task_environment.h"
Alexander Timind975f4aa2022-03-10 01:47:2123#include "content/public/test/navigation_simulator.h"
davidben6b77cd72014-10-29 21:13:4524#include "content/public/test/test_browser_context.h"
clamy9fb38cd2016-04-11 12:57:4825#include "content/test/test_navigation_url_loader_delegate.h"
Alexander Timind975f4aa2022-03-10 01:47:2126#include "content/test/test_web_contents.h"
clamy0ab288e2015-02-05 17:39:1427#include "net/base/load_flags.h"
davidben6b77cd72014-10-29 21:13:4528#include "net/base/net_errors.h"
Lucas Garron0efab6d2017-08-30 22:28:5129#include "net/cert/cert_status_flags.h"
davidben6b77cd72014-10-29 21:13:4530#include "net/http/http_response_headers.h"
Chris Fredrickson9ffdf5b2024-07-09 20:05:0931#include "net/storage_access_api/status.h"
Lucas Garron0efab6d2017-08-30 22:28:5132#include "net/test/embedded_test_server/embedded_test_server.h"
rhalavatia20efdbc2017-04-20 12:28:2733#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
davidben6b77cd72014-10-29 21:13:4534#include "net/url_request/redirect_info.h"
John Abd-El-Malek8e05be72019-05-28 16:35:1735#include "services/network/public/cpp/features.h"
Nan Lind91c8152021-10-21 16:22:3736#include "services/network/public/mojom/fetch_api.mojom.h"
John Abd-El-Malek8e05be72019-05-28 16:35:1737#include "services/network/public/mojom/network_context.mojom.h"
davidben6b77cd72014-10-29 21:13:4538#include "testing/gtest/include/gtest/gtest.h"
Minggang Wanga13c796e2021-07-02 05:54:4339#include "third_party/blink/public/common/navigation/navigation_params.h"
Henrique Ferreiro621b3ad2021-02-15 12:51:4140#include "third_party/blink/public/mojom/loader/mixed_content.mojom.h"
mkwst202534e32016-01-15 16:07:1541#include "url/origin.h"
davidben6b77cd72014-10-29 21:13:4542
43namespace content {
44
davidben6b77cd72014-10-29 21:13:4545class NavigationURLLoaderTest : public testing::Test {
46 public:
47 NavigationURLLoaderTest()
Gabriel Charette798fde72019-08-20 22:24:0448 : task_environment_(BrowserTaskEnvironment::IO_MAINLOOP),
Kinuko Yasuda48c475862019-07-29 15:08:2649 browser_context_(new TestBrowserContext) {
davidben6b77cd72014-10-29 21:13:4550 base::RunLoop().RunUntilIdle();
davidben6b77cd72014-10-29 21:13:4551 }
52
Alexander Timind975f4aa2022-03-10 01:47:2153 void SetUp() override {
54 // Do not create TestNavigationURLLoaderFactory as this tests creates
55 // NavigationURLLoaders explicitly and TestNavigationURLLoaderFactory
56 // interferes with that.
57 rvh_test_enabler_ = std::make_unique<RenderViewHostTestEnabler>(
58 RenderViewHostTestEnabler::NavigationURLLoaderFactoryType::kNone);
59 web_contents_ = TestWebContents::Create(
60 browser_context_.get(),
61 SiteInstanceImpl::Create(browser_context_.get()));
62 // NavigationURLLoader assumes that the corresponding FrameTreeNode has an
63 // associated NavigationRequest.
64 pending_navigation_ = NavigationSimulator::CreateBrowserInitiated(
65 GURL("https://example.com"), web_contents_.get());
66 pending_navigation_->Start();
67 }
68
69 void TearDown() override {
70 pending_navigation_.reset();
71 web_contents_.reset();
72 }
73
dcheng40ce7b382016-04-08 23:46:1374 std::unique_ptr<NavigationURLLoader> MakeTestLoader(
davidben6b77cd72014-10-29 21:13:4575 const GURL& url,
76 NavigationURLLoaderDelegate* delegate) {
arthursonzognie37f76e52018-02-01 16:36:3777 return CreateTestLoader(url, delegate);
Min Qin37db5102017-09-13 21:21:2578 }
79
80 std::unique_ptr<NavigationURLLoader> CreateTestLoader(
81 const GURL& url,
arthursonzognie37f76e52018-02-01 16:36:3782 NavigationURLLoaderDelegate* delegate) {
Minggang Wangb9f3fa92021-07-01 15:30:3183 blink::mojom::BeginNavigationParamsPtr begin_params =
84 blink::mojom::BeginNavigationParams::New(
Arthur Sonzognic686e8f2024-01-11 08:36:3785 std::nullopt /* initiator_frame_token */,
Arthur Hemery7b67a972017-12-01 15:24:4986 std::string() /* headers */, net::LOAD_NORMAL,
Richard Li01f040322018-09-19 07:45:5987 false /* skip_service_worker */,
88 blink::mojom::RequestContextType::LOCATION,
Henrique Ferreiro621b3ad2021-02-15 12:51:4189 blink::mojom::MixedContentContextType::kBlockable,
Vadym Doroshenko910bddb2019-06-13 15:43:3790 false /* is_form_submission */,
91 false /* was_initiated_by_link_click */,
Nate Chapindf6356e2023-02-01 01:11:4292 blink::mojom::ForceHistoryPush::kNo,
Vadym Doroshenko910bddb2019-06-13 15:43:3793 GURL() /* searchable_form_url */,
Arthur Hemery7b67a972017-12-01 15:24:4994 std::string() /* searchable_form_encoding */,
Nasko Oskov93e7c55c2018-12-19 01:59:2995 GURL() /* client_side_redirect_url */,
Arthur Sonzognic686e8f2024-01-11 08:36:3796 std::nullopt /* devtools_initiator_info */,
97 nullptr /* trust_token_params */, std::nullopt /* impression */,
Katie Dilloneb6c69812020-07-10 23:29:2098 base::TimeTicks() /* renderer_before_unload_start */,
Kunihiko Sakamoto7d9429d72021-02-01 07:07:4199 base::TimeTicks() /* renderer_before_unload_end */,
Yao Xiao720ef9d62022-12-09 05:18:29100 blink::mojom::NavigationInitiatorActivationAndAdStatus::
Sergey Poromovdd557c12023-03-01 11:28:45101 kDidNotStartWithTransientActivation,
Chris Fredrickson9ffdf5b2024-07-09 20:05:09102 false /* is_container_initiated */,
103 net::StorageAccessApiStatus::kNone, false /* has_rel_opener */);
Minggang Wanga13c796e2021-07-02 05:54:43104 auto common_params = blink::CreateCommonNavigationParams();
Lucas Furukawa Gadanief8290a2019-07-29 20:27:51105 common_params->url = url;
106 common_params->initiator_origin = url::Origin::Create(url);
Nan Lind91c8152021-10-21 16:22:37107 common_params->request_destination =
108 network::mojom::RequestDestination::kDocument;
Lucas Garron0efab6d2017-08-30 22:28:51109
Dave Tapuskacb5cbcb2021-02-09 19:10:45110 StoragePartition* storage_partition =
Lukasz Anforowiczb9a969a2021-04-29 15:26:25111 browser_context_->GetDefaultStoragePartition();
Dave Tapuskacb5cbcb2021-02-09 19:10:45112
Avi Drissman580a3da62024-09-04 16:16:56113 FrameTreeNodeId frame_tree_node_id =
Dave Tapuska327c06c92022-06-13 20:31:51114 web_contents_->GetPrimaryMainFrame()->GetFrameTreeNodeId();
Alexander Timind975f4aa2022-03-10 01:47:21115
Shivani Sharma8ae506c2019-07-21 21:08:27116 url::Origin origin = url::Origin::Create(url);
dcheng40ce7b382016-04-08 23:46:13117 std::unique_ptr<NavigationRequestInfo> request_info(
Kevin McNee8f0543b2021-03-12 16:13:35118 std::make_unique<NavigationRequestInfo>(
Maks Orlovichab27e242020-01-07 18:10:39119 std::move(common_params), std::move(begin_params),
Arthur Sonzogni038f0de2021-10-07 13:51:34120 network::mojom::WebSandboxFlags::kNone,
Matt Menkea56c5992020-04-10 20:53:56121 net::IsolationInfo::Create(
shivanigithub4e78015f592020-10-21 13:26:23122 net::IsolationInfo::RequestType::kMainFrame, origin, origin,
123 net::SiteForCookies::FromUrl(url)),
David Bokan98aabfe92022-04-14 02:10:12124 true /* is_primary_main_frame */,
125 true /* is_outermost_main_frame */, true /* is_main_frame */,
Alexander Timind975f4aa2022-03-10 01:47:21126 false /* are_ancestors_secure */, frame_tree_node_id,
Hiroki Nakagawa0d975a42021-04-14 02:25:18127 false /* report_raw_headers */, false /* upgrade_if_insecure */,
Andy Paicud669835e2019-08-13 14:41:33128 nullptr /* blob_url_loader_factory */,
129 base::UnguessableToken::Create() /* devtools_navigation_token */,
130 base::UnguessableToken::Create() /* devtools_frame_token */,
Kevin McNee8f0543b2021-03-12 16:13:35131 net::HttpRequestHeaders() /* cors_exempt_headers */,
Alex Rudenko0e632e472021-03-24 09:57:40132 nullptr /* client_security_state */,
Arthur Sonzognic686e8f2024-01-11 08:36:37133 std::nullopt /* devtools_accepted_stream_types */,
Jeremy Roman04ad4e3f2021-12-22 18:54:54134 false /* is_pdf */,
Hiroshige Hayashizaki2df45292023-10-10 22:59:03135 ChildProcessHost::kInvalidUniqueID /* initiator_process_id */,
Arthur Sonzognic686e8f2024-01-11 08:36:37136 std::nullopt /* initiator_document_token */,
Hiroshige Hayashizaki6e9a1892023-04-17 06:47:38137 GlobalRenderFrameHostId() /* previous_render_frame_host_id */,
Hiroshige Hayashizaki6a2bc752023-10-31 19:08:11138 nullptr /* serving_page_metrics_container */,
Camillia Smith Barnes6d2966c82023-08-23 21:16:18139 false /* allow_cookies_from_browser */, 0 /* navigation_id */,
Mustafa Emre Acer1001b3d2024-07-09 23:10:43140 false /* shared_storage_writable */, false /* is_ad_tagged */,
141 false /* force_no_https_upgrade */));
jam0f396ee2017-03-01 01:34:11142 return NavigationURLLoader::Create(
Dave Tapuskacb5cbcb2021-02-09 19:10:45143 browser_context_.get(), storage_partition, std::move(request_info),
Adrienne Walker5b98d1ee2021-10-19 16:57:41144 nullptr, nullptr, nullptr, delegate,
Dave Tapuskacb5cbcb2021-02-09 19:10:45145 NavigationURLLoader::LoaderType::kRegular, mojo::NullRemote(),
Steven Valdeza06f680c2023-03-21 19:00:10146 /* trust_token_observer=*/mojo::NullRemote(),
Tsuyoshi Horobcd0b9f62023-06-28 11:35:32147 /* shared_dictionary_observer=*/mojo::NullRemote(),
Julie Jeongeun Kim4a5fef22022-04-02 02:08:38148 /* url_loader_network_observer */ mojo::NullRemote(),
Daniel Rubery6420d74302024-11-19 01:42:40149 /*devtools_observer=*/mojo::NullRemote(),
150 /*device_bound_session_observer=*/mojo::NullRemote());
davidben6b77cd72014-10-29 21:13:45151 }
152
davidben6b77cd72014-10-29 21:13:45153 protected:
Gabriel Charette798fde72019-08-20 22:24:04154 BrowserTaskEnvironment task_environment_;
dcheng40ce7b382016-04-08 23:46:13155 std::unique_ptr<TestBrowserContext> browser_context_;
Alexander Timind975f4aa2022-03-10 01:47:21156 std::unique_ptr<RenderViewHostTestEnabler> rvh_test_enabler_;
157 std::unique_ptr<TestWebContents> web_contents_;
158 // NavigationURLLoaderImpl relies on the existence of the
159 // |frame_tree_node->navigation_request()|.
160 std::unique_ptr<NavigationSimulator> pending_navigation_;
davidben6b77cd72014-10-29 21:13:45161};
162
davidben6b77cd72014-10-29 21:13:45163// Tests that request failures are propagated correctly.
Lucas Garron0efab6d2017-08-30 22:28:51164TEST_F(NavigationURLLoaderTest, RequestFailedNoCertError) {
davidben6b77cd72014-10-29 21:13:45165 TestNavigationURLLoaderDelegate delegate;
dcheng40ce7b382016-04-08 23:46:13166 std::unique_ptr<NavigationURLLoader> loader =
davidben6b77cd72014-10-29 21:13:45167 MakeTestLoader(GURL("bogus:bogus"), &delegate);
Hiroki Nakagawa6d377e4a2021-07-08 23:29:11168 loader->Start();
davidben6b77cd72014-10-29 21:13:45169
170 // Wait for the request to fail as expected.
171 delegate.WaitForRequestFailed();
John Abd-El-Maleka67add82018-03-09 18:22:01172 EXPECT_EQ(net::ERR_ABORTED, delegate.net_error());
John Abd-El-Malekf36e05f2017-11-30 16:17:52173 EXPECT_FALSE(delegate.ssl_info().is_valid());
Lucas Garron0efab6d2017-08-30 22:28:51174 EXPECT_EQ(1, delegate.on_request_handled_counter());
175}
176
177// Tests that request failures are propagated correctly for a (non-fatal) cert
178// error:
179// - |ssl_info| has the expected values.
Lucas Garron0efab6d2017-08-30 22:28:51180TEST_F(NavigationURLLoaderTest, RequestFailedCertError) {
181 net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
182 https_server.SetSSLConfig(net::EmbeddedTestServer::CERT_MISMATCHED_NAME);
183 ASSERT_TRUE(https_server.Start());
184
185 TestNavigationURLLoaderDelegate delegate;
186 std::unique_ptr<NavigationURLLoader> loader =
187 MakeTestLoader(https_server.GetURL("/"), &delegate);
Hiroki Nakagawa6d377e4a2021-07-08 23:29:11188 loader->Start();
Lucas Garron0efab6d2017-08-30 22:28:51189
190 // Wait for the request to fail as expected.
191 delegate.WaitForRequestFailed();
Alexander Timind975f4aa2022-03-10 01:47:21192 EXPECT_EQ(net::ERR_CERT_COMMON_NAME_INVALID, delegate.net_error());
John Abd-El-Malekf36e05f2017-11-30 16:17:52193 net::SSLInfo ssl_info = delegate.ssl_info();
194 EXPECT_TRUE(ssl_info.is_valid());
Matt Mueller294998d2018-04-17 03:04:53195 EXPECT_TRUE(
196 https_server.GetCertificate()->EqualsExcludingChain(ssl_info.cert.get()));
Lucas Garron0efab6d2017-08-30 22:28:51197 EXPECT_EQ(net::ERR_CERT_COMMON_NAME_INVALID,
198 net::MapCertStatusToNetError(ssl_info.cert_status));
Carlos IL81133382017-12-06 17:18:45199 EXPECT_FALSE(ssl_info.is_fatal_cert_error);
Lucas Garron0efab6d2017-08-30 22:28:51200 EXPECT_EQ(1, delegate.on_request_handled_counter());
201}
202
203// Tests that request failures are propagated correctly for a fatal cert error:
204// - |ssl_info| has the expected values.
Lucas Garron0efab6d2017-08-30 22:28:51205TEST_F(NavigationURLLoaderTest, RequestFailedCertErrorFatal) {
206 net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
207 https_server.SetSSLConfig(net::EmbeddedTestServer::CERT_MISMATCHED_NAME);
208 ASSERT_TRUE(https_server.Start());
209 GURL url = https_server.GetURL("/");
210
211 // Set HSTS for the test domain in order to make SSL errors fatal.
Peter Kastinge5a38ed2021-10-02 03:06:35212 base::Time expiry = base::Time::Now() + base::Days(1000);
Lucas Garron0efab6d2017-08-30 22:28:51213 bool include_subdomains = false;
Lukasz Anforowiczb9a969a2021-04-29 15:26:25214 auto* storage_partition = browser_context_->GetDefaultStoragePartition();
Kinuko Yasuda48c475862019-07-29 15:08:26215 base::RunLoop run_loop;
216 storage_partition->GetNetworkContext()->AddHSTS(
217 url.host(), expiry, include_subdomains, run_loop.QuitClosure());
218 run_loop.Run();
Lucas Garron0efab6d2017-08-30 22:28:51219
220 TestNavigationURLLoaderDelegate delegate;
221 std::unique_ptr<NavigationURLLoader> loader = MakeTestLoader(url, &delegate);
Hiroki Nakagawa6d377e4a2021-07-08 23:29:11222 loader->Start();
Lucas Garron0efab6d2017-08-30 22:28:51223
224 // Wait for the request to fail as expected.
225 delegate.WaitForRequestFailed();
Sigurd Schneider71d7ed82019-12-11 09:05:17226 ASSERT_EQ(net::ERR_CERT_COMMON_NAME_INVALID, delegate.net_error());
John Abd-El-Malekf36e05f2017-11-30 16:17:52227 net::SSLInfo ssl_info = delegate.ssl_info();
228 EXPECT_TRUE(ssl_info.is_valid());
Matt Mueller294998d2018-04-17 03:04:53229 EXPECT_TRUE(
230 https_server.GetCertificate()->EqualsExcludingChain(ssl_info.cert.get()));
Lucas Garron0efab6d2017-08-30 22:28:51231 EXPECT_EQ(net::ERR_CERT_COMMON_NAME_INVALID,
232 net::MapCertStatusToNetError(ssl_info.cert_status));
Carlos IL81133382017-12-06 17:18:45233 EXPECT_TRUE(ssl_info.is_fatal_cert_error);
carlosk947ebfb62015-02-04 11:53:59234 EXPECT_EQ(1, delegate.on_request_handled_counter());
davidben6b77cd72014-10-29 21:13:45235}
236
davidben6b77cd72014-10-29 21:13:45237} // namespace content