blob: 44753eb4e1159b9cc4e582535a6431e34f3585d5 [file] [log] [blame]
Avi Drissman4e1b7bc32022-09-15 14:03:501// Copyright 2017 The Chromium Authors
John Abd-El-Malekdeec0082017-12-20 20:47:472// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
John Abd-El-Malek984dc002019-05-29 01:26:595#include "content/browser/network_service_instance_impl.h"
John Abd-El-Malekdeec0082017-12-20 20:47:476
Dan McArdle0c085b22024-07-12 14:15:237#include <stdint.h>
8
Lukasz Anforowiczce4487b72018-10-23 18:05:539#include <memory>
10#include <string>
Md Hasibul Hasana963a9342024-04-03 10:15:1411#include <string_view>
Lukasz Anforowiczce4487b72018-10-23 18:05:5312#include <utility>
13
Felipe Andradea9174c62022-08-16 18:35:1114#include "base/base_paths.h"
Matthew Denton095b6972023-11-02 21:56:1715#include "base/callback_list.h"
Matt Muellere6df72cb2023-04-12 22:08:3716#include "base/check.h"
Gabriel Charettef3851332022-04-28 23:39:1817#include "base/command_line.h"
Doug Turner08512342018-09-24 20:54:1918#include "base/environment.h"
John Abd-El-Malekdeec0082017-12-20 20:47:4719#include "base/feature_list.h"
Matt Menke04db81d2020-07-29 21:54:5820#include "base/files/file.h"
Will Harrisdac11fb2021-09-08 02:21:4121#include "base/files/file_util.h"
Avi Drissmanadac21992023-01-11 23:46:3922#include "base/functional/bind.h"
Matthew Denton542c43c2023-08-18 07:32:1723#include "base/functional/callback_forward.h"
Matthew Denton402a99002023-06-20 08:19:3824#include "base/location.h"
Ken Rockot91216c0f2019-10-11 20:38:1125#include "base/message_loop/message_pump_type.h"
Will Harrisdac11fb2021-09-08 02:21:4126#include "base/metrics/histogram_functions.h"
Clark DuVall984239a2019-08-08 23:38:3327#include "base/metrics/histogram_macros.h"
Lukasz Anforowiczce4487b72018-10-23 18:05:5328#include "base/no_destructor.h"
Dan McArdle0c085b22024-07-12 14:15:2329#include "base/numerics/safe_conversions.h"
Dheeraj Pannala98969a2f2025-04-17 01:15:0830#include "base/strings/string_number_conversions.h"
Doug Turner08512342018-09-24 20:54:1931#include "base/strings/string_util.h"
32#include "base/strings/utf_string_conversions.h"
Robbie McElrath8dc3acc2019-08-15 20:43:0433#include "base/synchronization/waitable_event.h"
Patrick Monette643cdf62021-10-15 19:13:4234#include "base/task/sequenced_task_runner.h"
Sean Mahere672a662023-01-09 21:42:2835#include "base/task/single_thread_task_runner.h"
Matthew Denton402a99002023-06-20 08:19:3836#include "base/task/task_traits.h"
Will Harrisdac11fb2021-09-08 02:21:4137#include "base/task/thread_pool.h"
John Abd-El-Malek984dc002019-05-29 01:26:5938#include "base/threading/sequence_local_storage_slot.h"
Ken Rockot91216c0f2019-10-11 20:38:1139#include "base/threading/thread.h"
Matt Menke04db81d2020-07-29 21:54:5840#include "base/threading/thread_restrictions.h"
Dheeraj Pannala98969a2f2025-04-17 01:15:0841#include "base/time/time.h"
Egor Pasko75389f12022-03-22 16:09:1142#include "base/trace_event/trace_event.h"
Yoichi Osatoccb08372023-10-02 08:34:3743#include "build/build_config.h"
Robbie McElrath995a2bf2018-11-19 23:21:5944#include "content/browser/browser_main_loop.h"
Shuran Huang103981502022-03-28 21:52:1845#include "content/browser/first_party_sets/first_party_sets_handler_impl.h"
Takashi Toyoshimabfc3b2812022-10-07 23:51:3746#include "content/browser/network/http_cache_backend_file_operations_factory.h"
47#include "content/browser/network/socket_broker_impl.h"
Egor Pasko75389f12022-03-22 16:09:1148#include "content/browser/network_sandbox_grant_result.h"
John Abd-El-Malekdeec0082017-12-20 20:47:4749#include "content/browser/network_service_client.h"
Eric Seckler8652dcd52018-09-20 10:42:2850#include "content/public/browser/browser_task_traits.h"
John Abd-El-Malekdeec0082017-12-20 20:47:4751#include "content/public/browser/browser_thread.h"
52#include "content/public/browser/content_browser_client.h"
John Abd-El-Malek984dc002019-05-29 01:26:5953#include "content/public/browser/network_service_instance.h"
Yoichi Osatoe0400142023-05-30 19:35:4054#include "content/public/browser/network_service_util.h"
Ken Rockot91216c0f2019-10-11 20:38:1155#include "content/public/browser/service_process_host.h"
Hans Wennborg5ffd1392019-10-16 11:00:0256#include "content/public/common/content_client.h"
Yutaka Hirano92bdfa22022-06-01 15:51:3357#include "content/public/common/content_features.h"
Will Harris66b7f8a2025-07-18 17:56:4358#include "content/public/common/content_switches.h"
Ken Rockot91216c0f2019-10-11 20:38:1159#include "mojo/public/cpp/bindings/pending_receiver.h"
Julie Jeongeun Kima3471c62019-10-15 07:09:2460#include "mojo/public/cpp/bindings/remote.h"
Yutaka Hiranode9868f2022-04-27 02:48:4461#include "mojo/public/cpp/bindings/self_owned_receiver.h"
62#include "net/base/features.h"
Matthew Denton1ca2b3d2023-04-20 03:17:5663#include "net/base/network_change_notifier.h"
Chris Fredrickson0cad3722022-09-30 14:50:3164#include "net/first_party_sets/global_first_party_sets.h"
sbingler072b97842023-07-26 20:29:0565#include "net/log/file_net_log_observer.h"
Matt Menke38662e22018-08-07 12:18:1166#include "net/log/net_log_util.h"
Liza Burakova27070602022-07-01 05:27:4067#include "sandbox/policy/features.h"
Matthew Denton03c45a22020-06-01 23:40:4868#include "services/cert_verifier/cert_verifier_service_factory.h"
Matthew Denton1d7839c2020-11-27 04:59:2369#include "services/cert_verifier/public/mojom/cert_verifier_service_factory.mojom.h"
John Abd-El-Malek8e82a322018-01-31 20:30:4770#include "services/network/network_service.h"
Yutaka Hiranod8789f92018-01-30 09:59:5171#include "services/network/public/cpp/features.h"
Matt Menke38662e22018-08-07 12:18:1172#include "services/network/public/cpp/network_switches.h"
Hayato Ito743f0662025-07-17 01:05:4973#include "services/network/public/cpp/sequence_manager_configurator.h"
Matt Menke55a16f02018-10-09 23:07:5374#include "services/network/public/mojom/net_log.mojom.h"
Robbie McElrathf572f5272018-08-17 21:21:4275#include "services/network/public/mojom/network_change_manager.mojom.h"
Hans Wennborg78b52182021-06-15 13:42:1576#include "services/network/public/mojom/network_context.mojom.h"
Matthew Dentone4eac432023-04-21 04:58:3277#include "services/network/public/mojom/network_interface_change_listener.mojom.h"
Etienne Pierre-doray0df4474a2019-10-16 14:56:3978#include "services/network/public/mojom/network_service.mojom.h"
Ken Rockot91216c0f2019-10-11 20:38:1179#include "services/network/public/mojom/network_service_test.mojom.h"
Liza Burakova27070602022-07-01 05:27:4080#include "services/network/public/mojom/socket_broker.mojom.h"
John Abd-El-Malekdeec0082017-12-20 20:47:4781
Egor Pasko75389f12022-03-22 16:09:1182#if !BUILDFLAG(IS_ANDROID)
83#include "content/browser/network_sandbox.h"
84#endif
Will Harris1967f8442021-02-05 20:34:2285
Will Harrisf26ad342022-09-06 02:03:2886#if BUILDFLAG(IS_WIN)
Takashi Toyoshimabfc3b2812022-10-07 23:51:3787#include "content/browser/network/network_service_process_tracker_win.h"
Will Harrisf26ad342022-09-06 02:03:2888#endif
89
Matthew Dentona9b37702022-10-28 22:23:2090#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
91#include "content/browser/system_dns_resolution/system_dns_resolver.h"
92#include "services/network/public/mojom/system_dns_resolution.mojom-forward.h"
93#endif
94
Matthew Denton1ca2b3d2023-04-20 03:17:5695#if BUILDFLAG(IS_LINUX)
96#include "net/base/address_map_linux.h"
97#include "net/base/address_tracker_linux.h"
98#include "services/network/public/mojom/network_interface_change_listener.mojom.h"
99#endif
100
John Abd-El-Malekdeec0082017-12-20 20:47:47101namespace content {
102
103namespace {
104
Xiaohan Wang1ecfd002022-01-19 22:33:10105#if BUILDFLAG(IS_POSIX)
Felipe Andradefc9bc632023-10-26 20:26:07106// Environment variable pointing to Kerberos credential cache file.
Robbie McElrathfa25a7c2019-03-13 17:54:36107constexpr char kKrb5CCEnvName[] = "KRB5CCNAME";
108// Environment variable pointing to Kerberos config file.
109constexpr char kKrb5ConfEnvName[] = "KRB5_CONFIG";
110#endif
111
Matthew Denton850436d2023-10-23 22:29:29112#if BUILDFLAG(IS_CHROMEOS)
Felipe Andradefc9bc632023-10-26 20:26:07113// File paths to the Kerberos credentials cache and configuration. The `FILE:`
114// prefix describes the type of credentials cache used. The `/home/chronos/user`
115// subpath corresponds to a bind mount of the active user.
116constexpr char kKrb5CCFilePath[] = "FILE:/home/chronos/user/kerberos/krb5cc";
117constexpr char kKrb5ConfFilePath[] = "/home/chronos/user/kerberos/krb5.conf";
Matthew Denton850436d2023-10-23 22:29:29118#endif // BUILDFLAG(IS_CHROMEOS)
Felipe Andradea9174c62022-08-16 18:35:11119
John Abd-El-Malek984dc002019-05-29 01:26:59120bool g_force_create_network_service_directly = false;
Will Harris66b7f8a2025-07-18 17:56:43121bool g_network_service_crashes_on_next_startup = false;
Julie Jeongeun Kima3471c62019-10-15 07:09:24122mojo::Remote<network::mojom::NetworkService>* g_network_service_remote =
123 nullptr;
Robbie McElrathf961dc52018-08-08 21:29:26124network::NetworkConnectionTracker* g_network_connection_tracker;
Clark DuVallb026e582019-07-31 19:50:38125bool g_network_service_is_responding = false;
John Abd-El-Malek984dc002019-05-29 01:26:59126
John Abd-El-Malek984dc002019-05-29 01:26:59127std::unique_ptr<network::NetworkService>& GetLocalNetworkService() {
Avi Drissmanded77172021-07-02 18:23:00128 static base::SequenceLocalStorageSlot<
129 std::unique_ptr<network::NetworkService>>
John Abd-El-Malek984dc002019-05-29 01:26:59130 service;
Avi Drissmanded77172021-07-02 18:23:00131 return service.GetOrCreateValue();
John Abd-El-Malek984dc002019-05-29 01:26:59132}
John Abd-El-Malekdeec0082017-12-20 20:47:47133
Ken Rockot91216c0f2019-10-11 20:38:11134base::Thread& GetNetworkServiceDedicatedThread() {
135 static base::NoDestructor<base::Thread> thread{"NetworkService"};
John Abd-El-Maleka5fe84b2022-03-18 01:05:29136 DCHECK(base::FeatureList::IsEnabled(kNetworkServiceDedicatedThread));
Ken Rockot91216c0f2019-10-11 20:38:11137 return *thread;
138}
139
Ken Rockot7ff141d2019-11-01 21:09:44140// The instance NetworkService used when hosting the service in-process. This is
141// set up by |CreateInProcessNetworkServiceOnThread()| and destroyed by
142// |ShutDownNetworkService()|.
143network::NetworkService* g_in_process_instance = nullptr;
144
Dave Tapuska69f89252021-03-10 17:11:37145static NetworkServiceClient* g_client = nullptr;
146
Ken Rockot91216c0f2019-10-11 20:38:11147void CreateInProcessNetworkServiceOnThread(
148 mojo::PendingReceiver<network::mojom::NetworkService> receiver) {
Scott Sheehan8e1d03c2019-11-05 16:11:15149 g_in_process_instance = new network::NetworkService(
Matthew Denton09b7b4b52023-03-28 09:02:49150 nullptr /* registry */, std::move(receiver),
Scott Sheehan8e1d03c2019-11-05 16:11:15151 true /* delay_initialization_until_set_client */);
Ken Rockot91216c0f2019-10-11 20:38:11152}
153
Will Harris3d6f9e4c2021-09-17 19:11:16154// A utility function to make it clear what behavior is expected by the network
155// context instance depending on the various errors that can happen during data
156// migration.
157//
Kevin Marshall4bdfa5df2022-03-21 22:33:27158// If this function returns 'true' then the `data_directory` should be used (if
Will Harris3d6f9e4c2021-09-17 19:11:16159// specified in the network context params). If this function returns 'false'
160// then the `unsandboxed_data_path` should be used.
161bool IsSafeToUseDataPath(SandboxGrantResult result) {
162 switch (result) {
163 case SandboxGrantResult::kSuccess:
164 // A migration occurred, and it was successful.
165 return true;
166 case SandboxGrantResult::kFailedToGrantSandboxAccessToCache:
167 case SandboxGrantResult::kFailedToCreateCacheDirectory:
168 // A failure to grant create or grant access to the cache dir does not
Kevin Marshall4bdfa5df2022-03-21 22:33:27169 // affect the providence of the data contained in `data_directory` as the
Will Harris3d6f9e4c2021-09-17 19:11:16170 // migration could have still occurred.
171 //
172 // These cases are handled internally and so this case should never be
173 // hit. It is undefined behavior to proceed in this case so CHECK here.
Peter Boström25c6ec72022-11-02 23:25:19174 base::ImmediateCrash();
Will Harris3d6f9e4c2021-09-17 19:11:16175 case SandboxGrantResult::kFailedToCreateDataDirectory:
Kevin Marshall4bdfa5df2022-03-21 22:33:27176 // A failure to create the `data_directory` is fatal, and the
Will Harris3d6f9e4c2021-09-17 19:11:16177 // `unsandboxed_data_path` should be used.
178 return false;
179 case SandboxGrantResult::kFailedToCopyData:
180 // A failure to copy the data from `unsandboxed_data_path` to the
Kevin Marshall4bdfa5df2022-03-21 22:33:27181 // `data_directory` is fatal, and the `unsandboxed_data_path` should be
182 // used.
Will Harris3d6f9e4c2021-09-17 19:11:16183 return false;
184 case SandboxGrantResult::kFailedToDeleteOldData:
185 // This is not fatal, as the new data has been correctly migrated, and the
186 // deletion will be retried at a later time.
187 return true;
188 case SandboxGrantResult::kFailedToGrantSandboxAccessToData:
189 // If the sandbox could not be granted access to the new data dir, then
190 // don't attempt to migrate. This means that the old
191 // `unsandboxed_data_path` should be used.
192 return false;
193 case SandboxGrantResult::kDidNotAttemptToGrantSandboxAccess:
194 // No migration was attempted either because of platform constraints or
195 // because the network context had no valid data paths (e.g. in-memory or
Kevin Marshall4bdfa5df2022-03-21 22:33:27196 // incognito), or `unsandboxed_data_path` was not specified.
197 // `data_directory` should be used in this case (if present).
Will Harris3d6f9e4c2021-09-17 19:11:16198 return true;
199 case SandboxGrantResult::kFailedToCreateCheckpointFile:
200 // This is fatal, as a failure to create the checkpoint file means that
201 // the next time the same network context is used, the data in
Kevin Marshall4bdfa5df2022-03-21 22:33:27202 // `unsandboxed_data_path` will be re-copied to the new `data_directory`
203 // and thus any changes to the data will be discarded. So in this case,
Will Harris3d6f9e4c2021-09-17 19:11:16204 // `unsandboxed_data_path` should be used.
205 return false;
206 case SandboxGrantResult::kNoMigrationRequested:
207 // The caller supplied an `unsandboxed_data_path` but did not trigger a
208 // migration so the data should be read from the `unsandboxed_data_path`.
209 return false;
210 case SandboxGrantResult::kMigrationAlreadySucceeded:
Kevin Marshall4bdfa5df2022-03-21 22:33:27211 // Migration has already taken place, so `data_directory` contains the
212 // valid data.
Will Harris3d6f9e4c2021-09-17 19:11:16213 return true;
214 case SandboxGrantResult::kMigrationAlreadySucceededWithNoAccess:
215 // If the sandbox could not be granted access to the new data dir, but the
Kevin Marshall4bdfa5df2022-03-21 22:33:27216 // migration has already happened to `data_directory`. This means that the
217 // sandbox might not have access to the data but `data_directory` should
218 // still be used because it's been migrated.
Will Harris3d6f9e4c2021-09-17 19:11:16219 return true;
220 }
221}
222
Will Harrisdac11fb2021-09-08 02:21:41223void CreateNetworkContextInternal(
224 mojo::PendingReceiver<network::mojom::NetworkContext> context,
225 network::mojom::NetworkContextParamsPtr params,
226 SandboxGrantResult grant_access_result) {
Egor Pasko75389f12022-03-22 16:09:11227 TRACE_EVENT0("loading", "CreateNetworkContextInternal");
Will Harris3d6f9e4c2021-09-17 19:11:16228 // These two histograms are logged from elsewhere, so don't log them twice.
229 DCHECK(grant_access_result !=
230 SandboxGrantResult::kFailedToCreateCacheDirectory);
231 DCHECK(grant_access_result !=
232 SandboxGrantResult::kFailedToGrantSandboxAccessToCache);
Will Harrisdac11fb2021-09-08 02:21:41233 base::UmaHistogramEnumeration("NetworkService.GrantSandboxResult",
234 grant_access_result);
Will Harris3d6f9e4c2021-09-17 19:11:16235
236 if (grant_access_result != SandboxGrantResult::kSuccess &&
237 grant_access_result !=
238 SandboxGrantResult::kDidNotAttemptToGrantSandboxAccess &&
239 grant_access_result != SandboxGrantResult::kNoMigrationRequested &&
240 grant_access_result != SandboxGrantResult::kMigrationAlreadySucceeded) {
241 PLOG(ERROR) << "Encountered error while migrating network context data or "
242 "granting sandbox access for "
Kevin Marshalleece67f2022-03-30 20:30:04243 << (params->file_paths
244 ? params->file_paths->data_directory.path()
245 : base::FilePath())
Will Harris3d6f9e4c2021-09-17 19:11:16246 << ". Result: " << static_cast<int>(grant_access_result);
247 }
248
249 if (!IsSafeToUseDataPath(grant_access_result)) {
Kevin Marshall4bdfa5df2022-03-21 22:33:27250 // Unsafe to use new `data_directory`. This means that a migration was
251 // attempted, and `unsandboxed_data_path` contains the still-valid set of
252 // data. Swap the parameters to instruct the network service to use this
253 // path for the network context. This of course will mean that if the
254 // network service is running sandboxed then this data might not be
255 // accessible, but does provide a pathway to user recovery, as the sandbox
256 // can just be disabled in this case.
Will Harris3d6f9e4c2021-09-17 19:11:16257 DCHECK(params->file_paths->unsandboxed_data_path.has_value());
Kevin Marshall4bdfa5df2022-03-21 22:33:27258 params->file_paths->data_directory =
259 *params->file_paths->unsandboxed_data_path;
Will Harrisdac11fb2021-09-08 02:21:41260 }
Kevin Marshalleece67f2022-03-30 20:30:04261
262 if (network::TransferableDirectory::IsOpenForTransferRequired()) {
263 if (params->file_paths) {
Liza Burakovad009fdd2023-06-23 18:43:23264 if (params->file_paths->http_cache_directory) {
265 params->file_paths->http_cache_directory->OpenForTransfer();
266 }
267 if (params->file_paths->shared_dictionary_directory) {
268 params->file_paths->shared_dictionary_directory->OpenForTransfer();
269 }
Kevin Marshalleece67f2022-03-30 20:30:04270 params->file_paths->data_directory.OpenForTransfer();
271 }
Will Harrisb246f672021-10-28 06:47:13272 }
Kevin Marshalleece67f2022-03-30 20:30:04273
Will Harris78ccb552022-09-08 05:40:48274 // This might recreate g_client if the network service needed to be restarted.
275 auto* network_service = GetNetworkService();
276
Liza Burakova1595a7812023-09-27 15:03:32277#if BUILDFLAG(IS_WIN)
Will Harrisec9cd862022-10-05 05:09:25278 // If the browser has started shutting down, it is possible that either a)
279 // `g_client` was never created if shutdown started before the network service
280 // was created, or b) the network service might have crashed meaning
281 // `g_client` is the client for the already-crashed Network Service, and a new
282 // network service never started. It's not safe to bind the socket broker in
283 // either of these cases so skip the binding since the browser is shutting
284 // down anyway.
285 if (!GetContentClient()->browser()->IsShuttingDown() &&
286 GetContentClient()->browser()->ShouldSandboxNetworkService() &&
Liza Burakovaf7b8fe52023-11-08 22:37:27287 !params->socket_brokers) {
288 params->socket_brokers = network::mojom::SocketBrokerRemotes::New();
289 params->socket_brokers->client = g_client->BindSocketBroker();
290 params->socket_brokers->server = g_client->BindSocketBroker();
Will Harris78ccb552022-09-08 05:40:48291 }
Liza Burakova1595a7812023-09-27 15:03:32292#endif // BUILDFLAG(IS_WIN)
Will Harris78ccb552022-09-08 05:40:48293
294 network_service->CreateNetworkContext(std::move(context), std::move(params));
Will Harrisdac11fb2021-09-08 02:21:41295}
296
Alexander Timin7ab3ed82020-01-13 20:00:13297scoped_refptr<base::SequencedTaskRunner>& GetNetworkTaskRunnerStorage() {
298 static base::NoDestructor<scoped_refptr<base::SequencedTaskRunner>> storage;
299 return *storage;
300}
301
Ken Rockot91216c0f2019-10-11 20:38:11302void CreateInProcessNetworkService(
303 mojo::PendingReceiver<network::mojom::NetworkService> receiver) {
Egor Pasko75389f12022-03-22 16:09:11304 TRACE_EVENT0("loading", "CreateInProcessNetworkService");
Ken Rockot91216c0f2019-10-11 20:38:11305 scoped_refptr<base::SingleThreadTaskRunner> task_runner;
John Abd-El-Maleka5fe84b2022-03-18 01:05:29306 if (base::FeatureList::IsEnabled(kNetworkServiceDedicatedThread)) {
Ken Rockot91216c0f2019-10-11 20:38:11307 base::Thread::Options options(base::MessagePumpType::IO, 0);
Hayato Ito743f0662025-07-17 01:05:49308 if (base::FeatureList::IsEnabled(
309 network::features::kNetworkServiceTaskScheduler)) {
310 network::ConfigureSequenceManager(options);
311 }
Olivier Li89911c42021-07-02 21:27:02312 GetNetworkServiceDedicatedThread().StartWithOptions(std::move(options));
Ken Rockot91216c0f2019-10-11 20:38:11313 task_runner = GetNetworkServiceDedicatedThread().task_runner();
Michael Thiessendd70b612024-08-17 18:25:25314 task_runner->PostTask(
315 FROM_HERE, base::BindOnce([]() {
316 mojo::InterfaceEndpointClient::SetThreadNameSuffixForMetrics(
317 "NetworkService");
318 }));
Ken Rockot91216c0f2019-10-11 20:38:11319 } else {
Gabriel Charettee7cdc5cd2020-05-27 23:35:05320 task_runner = GetIOThreadTaskRunner({});
Ken Rockot91216c0f2019-10-11 20:38:11321 }
322
Alexander Timin7ab3ed82020-01-13 20:00:13323 GetNetworkTaskRunnerStorage() = std::move(task_runner);
324
325 GetNetworkTaskRunner()->PostTask(
326 FROM_HERE, base::BindOnce(&CreateInProcessNetworkServiceOnThread,
327 std::move(receiver)));
Ken Rockot91216c0f2019-10-11 20:38:11328}
329
Matthew Dentone4976262023-06-20 09:18:32330#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX)
Matthew Denton402a99002023-06-20 08:19:38331// Runs a self-owned SystemDnsResolverMojoImpl. This is meant to run on a
332// high-priority thread pool.
333void RunSystemDnsResolverOnThreadPool(
334 mojo::PendingReceiver<network::mojom::SystemDnsResolver> dns_receiver) {
335 mojo::MakeSelfOwnedReceiver(
336 std::make_unique<content::SystemDnsResolverMojoImpl>(),
337 std::move(dns_receiver));
338}
Matt Mueller53e75c92025-05-22 18:07:54339#endif // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX)
Matthew Denton402a99002023-06-20 08:19:38340
John Abd-El-Malekd1e2a1c2019-02-28 20:01:03341network::mojom::NetworkServiceParamsPtr CreateNetworkServiceParams() {
342 network::mojom::NetworkServiceParamsPtr network_service_params =
343 network::mojom::NetworkServiceParams::New();
344 network_service_params->initial_connection_type =
345 network::mojom::ConnectionType(
346 net::NetworkChangeNotifier::GetConnectionType());
347 network_service_params->initial_connection_subtype =
348 network::mojom::ConnectionSubtype(
349 net::NetworkChangeNotifier::GetConnectionSubtype());
Dave Tapuska69f89252021-03-10 17:11:37350 network_service_params->default_observer =
351 g_client->BindURLLoaderNetworkServiceObserver();
Kirubel Aklilu60d316f2021-12-16 01:55:33352 network_service_params->first_party_sets_enabled =
353 GetContentClient()->browser()->IsFirstPartySetsEnabled();
354
Matthew Denton1ca2b3d2023-04-20 03:17:56355#if BUILDFLAG(IS_LINUX)
356 if (base::FeatureList::IsEnabled(
357 net::features::kAddressTrackerLinuxIsProxied) &&
358 IsOutOfProcessNetworkService()) {
Matthew Dentone4eac432023-04-21 04:58:32359 auto [address_map, online_links] =
360 net::NetworkChangeNotifier::GetAddressMapOwner()
361 ->GetAddressTrackerLinux()
362 ->GetInitialDataAndStartRecordingDiffs();
Matthew Denton1ca2b3d2023-04-20 03:17:56363 network_service_params->initial_address_map =
Matthew Dentone4eac432023-04-21 04:58:32364 network::mojom::InitialAddressMap::New(std::move(address_map),
365 std::move(online_links));
Matthew Denton1ca2b3d2023-04-20 03:17:56366 }
367#endif // BUILDFLAG(IS_LINUX)
368
Matthew Denton850436d2023-10-23 22:29:29369#if BUILDFLAG(IS_CHROMEOS)
Felipe Andradefc9bc632023-10-26 20:26:07370 // On ChromeOS, the network service is always out of process (unless
371 // --single-process is set on the command-line). In any case, we set Kerberos
372 // environment variables during the service initialization.
373 network_service_params->environment.push_back(
374 network::mojom::EnvironmentVariable::New(kKrb5CCEnvName,
375 kKrb5CCFilePath));
376 network_service_params->environment.push_back(
377 network::mojom::EnvironmentVariable::New(kKrb5ConfEnvName,
378 kKrb5ConfFilePath));
379#elif BUILDFLAG(IS_POSIX)
380 // Send Kerberos environment variables to the network service, if it's running
381 // in another process.
382 if (IsOutOfProcessNetworkService()) {
Robbie McElrathfa25a7c2019-03-13 17:54:36383 std::unique_ptr<base::Environment> env(base::Environment::Create());
Helmut Januschkab9667282025-04-03 15:04:37384 std::optional<std::string> value = env->GetVar(kKrb5CCEnvName);
385 if (value.has_value()) {
Robbie McElrathfa25a7c2019-03-13 17:54:36386 network_service_params->environment.push_back(
Helmut Januschkab9667282025-04-03 15:04:37387 network::mojom::EnvironmentVariable::New(kKrb5CCEnvName, *value));
Robbie McElrathfa25a7c2019-03-13 17:54:36388 }
Helmut Januschkab9667282025-04-03 15:04:37389 value = env->GetVar(kKrb5ConfEnvName);
390 if (value.has_value()) {
Robbie McElrathfa25a7c2019-03-13 17:54:36391 network_service_params->environment.push_back(
Helmut Januschkab9667282025-04-03 15:04:37392 network::mojom::EnvironmentVariable::New(kKrb5ConfEnvName, *value));
Robbie McElrathfa25a7c2019-03-13 17:54:36393 }
394 }
Felipe Andradea9174c62022-08-16 18:35:11395#endif // BUILDFLAG(IS_POSIX)
Matthew Dentona9b37702022-10-28 22:23:20396
Matthew Dentone4976262023-06-20 09:18:32397#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX)
Matthew Denton98b91482023-01-25 01:19:54398 if (GetContentClient()
399 ->browser()
400 ->ShouldRunOutOfProcessSystemDnsResolution() &&
Matthew Denton09b7b4b52023-03-28 09:02:49401 IsOutOfProcessNetworkService()) {
Matthew Dentona9b37702022-10-28 22:23:20402 mojo::PendingRemote<network::mojom::SystemDnsResolver> dns_remote;
Matthew Denton402a99002023-06-20 08:19:38403 scoped_refptr<base::SequencedTaskRunner> thread_pool_task_runner =
404 base::ThreadPool::CreateSequencedTaskRunner(
405 {base::TaskPriority::USER_BLOCKING});
406 thread_pool_task_runner->PostTask(
407 FROM_HERE, base::BindOnce(RunSystemDnsResolverOnThreadPool,
408 dns_remote.InitWithNewPipeAndPassReceiver()));
Matthew Dentona9b37702022-10-28 22:23:20409 network_service_params->system_dns_resolver = std::move(dns_remote);
410 }
Matthew Dentone4976262023-06-20 09:18:32411#endif // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX)
Matthew Dentona9b37702022-10-28 22:23:20412
Abhijith Nair7c7be7662023-11-14 16:25:37413 network_service_params->ip_protection_proxy_bypass_policy =
414 GetContentClient()->browser()->GetIpProtectionProxyBypassPolicy();
John Abd-El-Malekd1e2a1c2019-02-28 20:01:03415 return network_service_params;
416}
417
Robbie McElrath8dc3acc2019-08-15 20:43:04418void CreateNetworkServiceOnIOForTesting(
Julie Jeongeun Kima3471c62019-10-15 07:09:24419 mojo::PendingReceiver<network::mojom::NetworkService> receiver,
Robbie McElrath8dc3acc2019-08-15 20:43:04420 base::WaitableEvent* completion_event) {
John Abd-El-Malek984dc002019-05-29 01:26:59421 if (GetLocalNetworkService()) {
Julie Jeongeun Kima3471c62019-10-15 07:09:24422 GetLocalNetworkService()->Bind(std::move(receiver));
John Abd-El-Malekdeec0082017-12-20 20:47:47423 return;
424 }
425
Etienne Pierre-doray0df4474a2019-10-16 14:56:39426 GetLocalNetworkService() = std::make_unique<network::NetworkService>(
427 nullptr /* registry */, std::move(receiver),
428 true /* delay_initialization_until_set_client */);
429 GetLocalNetworkService()->Initialize(
430 network::mojom::NetworkServiceParams::New(),
431 true /* mock_network_change_notifier */);
Robbie McElrath8dc3acc2019-08-15 20:43:04432 if (completion_event)
433 completion_event->Signal();
John Abd-El-Malekdeec0082017-12-20 20:47:47434}
435
Gyuyoung Kim5f3bd4202019-09-27 01:59:49436void BindNetworkChangeManagerReceiver(
437 mojo::PendingReceiver<network::mojom::NetworkChangeManager> receiver) {
438 GetNetworkService()->GetNetworkChangeManager(std::move(receiver));
Robbie McElrathf572f5272018-08-17 21:21:42439}
440
Matthew Denton095b6972023-11-02 21:56:17441base::RepeatingCallbackList<void(bool)>& GetProcessGoneHandlersList() {
442 static base::NoDestructor<base::RepeatingCallbackList<void(bool)>> s_list;
Lukasz Anforowiczc195e912018-10-30 16:20:54443 return *s_list;
Lukasz Anforowiczce4487b72018-10-23 18:05:53444}
445
Matthew Denton095b6972023-11-02 21:56:17446void OnNetworkServiceProcessGone(bool crashed) {
Lukasz Anforowiczce4487b72018-10-23 18:05:53447 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
Julie Jeongeun Kima3471c62019-10-15 07:09:24448 DCHECK(g_network_service_remote);
449 DCHECK(g_network_service_remote->is_bound());
Matthew Denton095b6972023-11-02 21:56:17450 DCHECK(!crashed || !g_network_service_remote->is_connected());
451 GetProcessGoneHandlersList().Notify(crashed);
Lukasz Anforowiczce4487b72018-10-23 18:05:53452}
453
Eric Romanc03b62622019-06-25 02:13:22454// Parses the desired granularity of NetLog capturing specified by the command
455// line.
456net::NetLogCaptureMode GetNetCaptureModeFromCommandLine(
457 const base::CommandLine& command_line) {
Md Hasibul Hasana963a9342024-04-03 10:15:14458 std::string_view switch_name = network::switches::kNetLogCaptureMode;
Eric Romanc03b62622019-06-25 02:13:22459
460 if (command_line.HasSwitch(switch_name)) {
461 std::string value = command_line.GetSwitchValueASCII(switch_name);
462
Etienne Dechampsf568a412025-04-22 15:54:56463 if (value == "HeavilyRedacted") {
464 return net::NetLogCaptureMode::kHeavilyRedacted;
465 }
Eric Romanc03b62622019-06-25 02:13:22466 if (value == "Default")
Eric Roman3124cde2019-07-10 22:26:15467 return net::NetLogCaptureMode::kDefault;
468 if (value == "IncludeSensitive")
469 return net::NetLogCaptureMode::kIncludeSensitive;
470 if (value == "Everything")
471 return net::NetLogCaptureMode::kEverything;
472
473 // Warn when using the old command line switches.
474 if (value == "IncludeCookiesAndCredentials") {
475 LOG(ERROR) << "Deprecated value for --" << switch_name
476 << ". Use IncludeSensitive instead";
477 return net::NetLogCaptureMode::kIncludeSensitive;
478 }
479 if (value == "IncludeSocketBytes") {
480 LOG(ERROR) << "Deprecated value for --" << switch_name
481 << ". Use Everything instead";
482 return net::NetLogCaptureMode::kEverything;
483 }
Eric Romanc03b62622019-06-25 02:13:22484
485 LOG(ERROR) << "Unrecognized value for --" << switch_name;
486 }
487
Eric Roman3124cde2019-07-10 22:26:15488 return net::NetLogCaptureMode::kDefault;
Eric Romanc03b62622019-06-25 02:13:22489}
490
Dheeraj Pannala98969a2f2025-04-17 01:15:08491std::optional<base::TimeDelta> GetNetLogDurationFromCommandLine(
492 const base::CommandLine& command_line) {
493 std::string_view switch_name = network::switches::kLogNetLogDuration;
494
495 if (!command_line.HasSwitch(switch_name)) {
496 return std::nullopt;
497 }
498
499 std::string duration_str = command_line.GetSwitchValueASCII(switch_name);
500 int duration_sec = 0;
501 if (base::StringToInt(duration_str, &duration_sec) && duration_sec > 0) {
502 return base::Seconds(duration_sec);
503 }
504
505 return std::nullopt;
506}
sbingler072b97842023-07-26 20:29:05507// Parse the maximum file size for the NetLog, if one was specified.
508// kNoLimit indicates no, valid, maximum size was specified.
Dan McArdle0c085b22024-07-12 14:15:23509base::StrictNumeric<uint64_t> GetNetLogMaximumFileSizeFromCommandLine(
sbingler072b97842023-07-26 20:29:05510 const base::CommandLine& command_line) {
Md Hasibul Hasana963a9342024-04-03 10:15:14511 std::string_view switch_name = network::switches::kNetLogMaxSizeMb;
sbingler072b97842023-07-26 20:29:05512
513 if (!command_line.HasSwitch(switch_name)) {
514 return net::FileNetLogObserver::kNoLimit;
515 }
516
517 std::string value = command_line.GetSwitchValueASCII(switch_name);
518
519 if (value.empty()) {
520 return net::FileNetLogObserver::kNoLimit;
521 }
522
523 // 32 bits for the input is fine, a max size of ~2 PB ought to be enough for
524 // anybody.
525 uint32_t max_size_megabytes;
526 bool valid = base::StringToUint(value, &max_size_megabytes);
527
528 if (!valid) {
529 return net::FileNetLogObserver::kNoLimit;
530 }
531
532 // Value is currently in megabytes, convert to bytes. 1024*1024 == 2^20 ==
533 // left shift by 20 bits
Dan McArdle0c085b22024-07-12 14:15:23534 uint64_t max_size_bytes = uint64_t{max_size_megabytes} << 20;
sbingler072b97842023-07-26 20:29:05535 return max_size_bytes;
536}
537
John Abd-El-Malekdeec0082017-12-20 20:47:47538} // namespace
539
Thiabaud Engelbrechtfc9998642025-07-08 15:09:06540// If this feature is enabled, the Network Service will run on its own thread
541// when running in-process; otherwise it will run on the IO thread.
542BASE_FEATURE(kNetworkServiceDedicatedThread,
543 "NetworkServiceDedicatedThread",
544 base::FEATURE_ENABLED_BY_DEFAULT);
545
Dan McArdle0c085b22024-07-12 14:15:23546uint64_t GetNetLogMaximumFileSizeFromCommandLineForTesting( // IN-TEST
547 const base::CommandLine& command_line) {
548 return GetNetLogMaximumFileSizeFromCommandLine(command_line);
549}
550
Matt Menke04db81d2020-07-29 21:54:58551class NetworkServiceInstancePrivate {
552 public:
553 // Opens the specified file, blocking until the file is open. Used to open
554 // files specified by network::switches::kLogNetLog or
555 // network::switches::kSSLKeyLogFile. Since these arguments can be used to
556 // debug startup behavior, asynchronously opening the file on another thread
557 // would result in losing data, hence the need for blocking open operations.
558 // |file_flags| specifies the flags passed to the base::File constructor call.
559 //
560 // ThreadRestrictions needs to be able to friend the class/method to allow
561 // blocking, but can't friend CONTENT_EXPORT methods, so have it friend
562 // NetworkServiceInstancePrivate instead of GetNetworkService().
563 static base::File BlockingOpenFile(const base::FilePath& path,
564 int file_flags) {
565 base::ScopedAllowBlocking allow_blocking;
566 return base::File(path, file_flags);
567 }
568};
569
John Abd-El-Malek53670dd2018-01-18 22:07:21570network::mojom::NetworkService* GetNetworkService() {
Julie Jeongeun Kima3471c62019-10-15 07:09:24571 if (!g_network_service_remote)
572 g_network_service_remote = new mojo::Remote<network::mojom::NetworkService>;
Julie Jeongeun Kima3471c62019-10-15 07:09:24573 if (!g_network_service_remote->is_bound() ||
574 !g_network_service_remote->is_connected()) {
Matt Menke080a9172020-01-31 10:44:08575 bool service_was_bound = g_network_service_remote->is_bound();
Julie Jeongeun Kima3471c62019-10-15 07:09:24576 g_network_service_remote->reset();
John Abd-El-Malek1ae9dbb2019-03-04 23:40:47577 if (GetContentClient()->browser()->IsShuttingDown()) {
578 // This happens at system shutdown, since in other scenarios the network
579 // process would only be torn down once the message loop stopped running.
Oleh Lamzin0e228572019-12-06 16:46:09580 // We don't want to start the network service again so just create message
581 // pipe that's not bound to stop consumers from requesting creation of the
582 // service.
Julie Jeongeun Kima3471c62019-10-15 07:09:24583 auto receiver = g_network_service_remote->BindNewPipeAndPassReceiver();
584 auto leaked_pipe = receiver.PassPipe().release();
John Abd-El-Malekdeec0082017-12-20 20:47:47585 } else {
Ken Rockot91216c0f2019-10-11 20:38:11586 if (!g_force_create_network_service_directly) {
587 mojo::PendingReceiver<network::mojom::NetworkService> receiver =
Julie Jeongeun Kima3471c62019-10-15 07:09:24588 g_network_service_remote->BindNewPipeAndPassReceiver();
589 g_network_service_remote->set_disconnect_handler(
Matthew Denton095b6972023-11-02 21:56:17590 base::BindOnce(&OnNetworkServiceProcessGone, /*crashed=*/true));
Ken Rockot91216c0f2019-10-11 20:38:11591 if (IsInProcessNetworkService()) {
592 CreateInProcessNetworkService(std::move(receiver));
593 } else {
Matt Menke080a9172020-01-31 10:44:08594 if (service_was_bound)
595 LOG(ERROR) << "Network service crashed, restarting service.";
Will Harris66b7f8a2025-07-18 17:56:43596 ServiceProcessHost::Options options;
597 options.WithDisplayName(u"Network Service");
598 if (g_network_service_crashes_on_next_startup) {
599 g_network_service_crashes_on_next_startup = false;
600 options.WithExtraCommandLineSwitches(
601 {switches::kUtilityImmediateCrashForTesting});
602 }
603 ServiceProcessHost::Launch(std::move(receiver), std::move(options));
Ken Rockot91216c0f2019-10-11 20:38:11604 }
John Abd-El-Malek1ae9dbb2019-03-04 23:40:47605 } else {
Matthew Denton09b7b4b52023-03-28 09:02:49606 DCHECK(IsInProcessNetworkService())
607 << "If the network service is created directly, the test must not "
608 "request an out of process network service.";
Robbie McElrath8dc3acc2019-08-15 20:43:04609 // This should only be reached in unit tests.
610 if (BrowserThread::CurrentlyOn(BrowserThread::IO)) {
611 CreateNetworkServiceOnIOForTesting(
Julie Jeongeun Kima3471c62019-10-15 07:09:24612 g_network_service_remote->BindNewPipeAndPassReceiver(),
Robbie McElrath8dc3acc2019-08-15 20:43:04613 /*completion_event=*/nullptr);
614 } else {
615 base::WaitableEvent event;
Gabriel Charettee7cdc5cd2020-05-27 23:35:05616 GetIOThreadTaskRunner({})->PostTask(
617 FROM_HERE,
Julie Jeongeun Kima3471c62019-10-15 07:09:24618 base::BindOnce(
619 CreateNetworkServiceOnIOForTesting,
620 g_network_service_remote->BindNewPipeAndPassReceiver(),
621 base::Unretained(&event)));
Robbie McElrath8dc3acc2019-08-15 20:43:04622 event.Wait();
623 }
John Abd-El-Malek1ae9dbb2019-03-04 23:40:47624 }
John Abd-El-Malekdeec0082017-12-20 20:47:47625
Dave Tapuska69f89252021-03-10 17:11:37626 delete g_client; // In case we're recreating the network service.
627 g_client = new NetworkServiceClient();
628
Dave Tapuska69f89252021-03-10 17:11:37629 (*g_network_service_remote)->SetParams(CreateNetworkServiceParams());
Yutaka Hirano136bd912022-01-31 16:26:11630 g_client->OnNetworkServiceInitialized(g_network_service_remote->get());
631
Clark DuVallb026e582019-07-31 19:50:38632 g_network_service_is_responding = false;
Jan Wilken Dörrie8c74db022020-04-20 09:05:00633 g_network_service_remote->QueryVersion(base::BindOnce(
Ari Chivukula10f65362023-03-06 05:51:19634 [](uint32_t) { g_network_service_is_responding = true; }));
John Abd-El-Malekd1e2a1c2019-02-28 20:01:03635
Robbie McElrath35ef9672019-02-13 22:01:59636 const base::CommandLine* command_line =
637 base::CommandLine::ForCurrentProcess();
John Abd-El-Malekc134dd82019-07-31 20:51:44638 if (command_line->HasSwitch(network::switches::kLogNetLog)) {
639 base::FilePath log_path =
640 command_line->GetSwitchValuePath(network::switches::kLogNetLog);
Cheng Yu6e46b4d2021-09-02 06:43:08641 if (log_path.empty()) {
642 log_path = GetContentClient()->browser()->GetNetLogDefaultDirectory();
643 if (!log_path.empty())
644 log_path = log_path.Append(FILE_PATH_LITERAL("netlog.json"));
645 }
Doug Turner08512342018-09-24 20:54:19646
Matt Menke04db81d2020-07-29 21:54:58647 base::File file = NetworkServiceInstancePrivate::BlockingOpenFile(
John Abd-El-Malekc134dd82019-07-31 20:51:44648 log_path, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
649 if (!file.IsValid()) {
650 LOG(ERROR) << "Failed opening NetLog: " << log_path.value();
651 } else {
Julie Jeongeun Kima3471c62019-10-15 07:09:24652 (*g_network_service_remote)
Matt Menke04db81d2020-07-29 21:54:58653 ->StartNetLog(
Dan McArdle0c085b22024-07-12 14:15:23654 std::move(file),
655 GetNetLogMaximumFileSizeFromCommandLine(*command_line),
Matt Menke04db81d2020-07-29 21:54:58656 GetNetCaptureModeFromCommandLine(*command_line),
Dheeraj Pannala98969a2f2025-04-17 01:15:08657 GetContentClient()->browser()->GetNetLogConstants(),
658 GetNetLogDurationFromCommandLine(*command_line));
Robbie McElrath35ef9672019-02-13 22:01:59659 }
Robbie McElrathd063ed02019-02-13 21:59:30660 }
Robbie McElrathd063ed02019-02-13 21:59:30661
David Benjamin887153852019-08-07 23:19:55662 base::FilePath ssl_key_log_path;
Robbie McElrath35ef9672019-02-13 22:01:59663 if (command_line->HasSwitch(network::switches::kSSLKeyLogFile)) {
Christopher Thompson2a4c69e92019-08-21 16:29:11664 UMA_HISTOGRAM_ENUMERATION(kSSLKeyLogFileHistogram,
665 SSLKeyLogFileAction::kSwitchFound);
David Benjamin887153852019-08-07 23:19:55666 ssl_key_log_path =
Robbie McElrath35ef9672019-02-13 22:01:59667 command_line->GetSwitchValuePath(network::switches::kSSLKeyLogFile);
David Benjamin887153852019-08-07 23:19:55668 LOG_IF(WARNING, ssl_key_log_path.empty())
Robbie McElrath35ef9672019-02-13 22:01:59669 << "ssl-key-log-file argument missing";
David Benjamin887153852019-08-07 23:19:55670 } else {
671 std::unique_ptr<base::Environment> env(base::Environment::Create());
Helmut Januschkab9667282025-04-03 15:04:37672 std::optional<std::string> env_str = env->GetVar("SSLKEYLOGFILE");
673 if (env_str.has_value()) {
Christopher Thompson2a4c69e92019-08-21 16:29:11674 UMA_HISTOGRAM_ENUMERATION(kSSLKeyLogFileHistogram,
675 SSLKeyLogFileAction::kEnvVarFound);
Xiaohan Wang1ecfd002022-01-19 22:33:10676#if BUILDFLAG(IS_WIN)
David Benjamin887153852019-08-07 23:19:55677 // base::Environment returns environment variables in UTF-8 on
678 // Windows.
Helmut Januschkab9667282025-04-03 15:04:37679 ssl_key_log_path = base::FilePath(base::UTF8ToWide(*env_str));
David Benjamin887153852019-08-07 23:19:55680#else
Helmut Januschkab9667282025-04-03 15:04:37681 ssl_key_log_path = base::FilePath(*env_str);
David Benjamin887153852019-08-07 23:19:55682#endif
683 }
Robbie McElrath35ef9672019-02-13 22:01:59684 }
Robbie McElrathd063ed02019-02-13 21:59:30685
David Benjamin887153852019-08-07 23:19:55686 if (!ssl_key_log_path.empty()) {
Matt Menke04db81d2020-07-29 21:54:58687 base::File file = NetworkServiceInstancePrivate::BlockingOpenFile(
688 ssl_key_log_path,
689 base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_APPEND);
David Benjamin887153852019-08-07 23:19:55690 if (!file.IsValid()) {
691 LOG(ERROR) << "Failed opening SSL key log file: "
692 << ssl_key_log_path.value();
693 } else {
Christopher Thompson2a4c69e92019-08-21 16:29:11694 UMA_HISTOGRAM_ENUMERATION(kSSLKeyLogFileHistogram,
695 SSLKeyLogFileAction::kLogFileEnabled);
Julie Jeongeun Kima3471c62019-10-15 07:09:24696 (*g_network_service_remote)->SetSSLKeyLogFile(std::move(file));
David Benjamin887153852019-08-07 23:19:55697 }
Robbie McElrath35ef9672019-02-13 22:01:59698 }
Doug Turner08512342018-09-24 20:54:19699
Chris Fredricksona2092c9b2022-05-09 21:54:12700 if (FirstPartySetsHandlerImpl::GetInstance()->IsEnabled()) {
Arthur Sonzognic686e8f2024-01-11 08:36:37701 if (std::optional<net::GlobalFirstPartySets> sets =
Chris Fredricksona2092c9b2022-05-09 21:54:12702 FirstPartySetsHandlerImpl::GetInstance()->GetSets(
Chris Fredrickson0cad3722022-09-30 14:50:31703 base::BindOnce([](net::GlobalFirstPartySets sets) {
Chris Fredrickson878d06b2022-09-08 15:20:37704 GetNetworkService()->SetFirstPartySets(std::move(sets));
705 }));
Chris Fredricksona2092c9b2022-05-09 21:54:12706 sets.has_value()) {
707 g_network_service_remote->get()->SetFirstPartySets(
708 std::move(sets.value()));
709 }
cfredric763290422022-03-31 23:00:33710 }
Shuran Huang103981502022-03-28 21:52:18711
Robbie McElrath35ef9672019-02-13 22:01:59712 GetContentClient()->browser()->OnNetworkServiceCreated(
Julie Jeongeun Kima3471c62019-10-15 07:09:24713 g_network_service_remote->get());
John Abd-El-Malek1ae9dbb2019-03-04 23:40:47714 }
John Abd-El-Malekdeec0082017-12-20 20:47:47715 }
Julie Jeongeun Kima3471c62019-10-15 07:09:24716 return g_network_service_remote->get();
John Abd-El-Malekdeec0082017-12-20 20:47:47717}
718
Matthew Denton095b6972023-11-02 21:56:17719base::CallbackListSubscription RegisterNetworkServiceProcessGoneHandler(
720 NetworkServiceProcessGoneHandler handler) {
Lukasz Anforowiczce4487b72018-10-23 18:05:53721 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
722 DCHECK(!handler.is_null());
723
Matthew Denton095b6972023-11-02 21:56:17724 return GetProcessGoneHandlersList().Add(std::move(handler));
John Abd-El-Malekdeec0082017-12-20 20:47:47725}
726
Eriko Kurimoto64656462022-07-21 01:07:49727#if BUILDFLAG(IS_CHROMEOS)
Robbie McElrath995a2bf2018-11-19 23:21:59728net::NetworkChangeNotifier* GetNetworkChangeNotifier() {
729 return BrowserMainLoop::GetInstance()->network_change_notifier();
730}
John Abd-El-Malek03438952019-05-16 22:53:51731#endif
Robbie McElrath995a2bf2018-11-19 23:21:59732
John Abd-El-Malekdeec0082017-12-20 20:47:47733void FlushNetworkServiceInstanceForTesting() {
734 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
John Abd-El-Malekdeec0082017-12-20 20:47:47735
Julie Jeongeun Kima3471c62019-10-15 07:09:24736 if (g_network_service_remote)
737 g_network_service_remote->FlushForTesting();
John Abd-El-Malekdeec0082017-12-20 20:47:47738}
739
Robbie McElrathf961dc52018-08-08 21:29:26740network::NetworkConnectionTracker* GetNetworkConnectionTracker() {
Andrew Paseltiner82a1f89f2022-02-28 21:59:36741 DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
742 BrowserThread::CurrentlyOn(BrowserThread::UI));
Robbie McElrathf961dc52018-08-08 21:29:26743 if (!g_network_connection_tracker) {
744 g_network_connection_tracker = new network::NetworkConnectionTracker(
Gyuyoung Kim5f3bd4202019-09-27 01:59:49745 base::BindRepeating(&BindNetworkChangeManagerReceiver));
Robbie McElrathf961dc52018-08-08 21:29:26746 }
747 return g_network_connection_tracker;
748}
749
Robbie McElrathf633990e2018-10-02 21:44:48750void GetNetworkConnectionTrackerFromUIThread(
751 base::OnceCallback<void(network::NetworkConnectionTracker*)> callback) {
Gabriel Charettee7cdc5cd2020-05-27 23:35:05752 GetUIThreadTaskRunner({base::TaskPriority::BEST_EFFORT})
753 ->PostTaskAndReplyWithResult(FROM_HERE,
754 base::BindOnce(&GetNetworkConnectionTracker),
755 std::move(callback));
Robbie McElrathf633990e2018-10-02 21:44:48756}
757
Jun Cai597752e42018-11-15 19:54:25758network::NetworkConnectionTrackerAsyncGetter
759CreateNetworkConnectionTrackerAsyncGetter() {
760 return base::BindRepeating(&content::GetNetworkConnectionTrackerFromUIThread);
761}
762
Robbie McElrathf961dc52018-08-08 21:29:26763void SetNetworkConnectionTrackerForTesting(
764 network::NetworkConnectionTracker* network_connection_tracker) {
Andrew Paseltiner82a1f89f2022-02-28 21:59:36765 DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
766 BrowserThread::CurrentlyOn(BrowserThread::UI));
Robbie McElrathdb12d8e2018-09-18 21:20:40767 if (g_network_connection_tracker != network_connection_tracker) {
768 DCHECK(!g_network_connection_tracker || !network_connection_tracker);
769 g_network_connection_tracker = network_connection_tracker;
770 }
Robbie McElrathf961dc52018-08-08 21:29:26771}
772
Alexander Timin7ab3ed82020-01-13 20:00:13773const scoped_refptr<base::SequencedTaskRunner>& GetNetworkTaskRunner() {
Clark DuVallb9924e92018-12-10 23:36:33774 DCHECK(IsInProcessNetworkService());
Alexander Timin7ab3ed82020-01-13 20:00:13775 return GetNetworkTaskRunnerStorage();
Clark DuVallb9924e92018-12-10 23:36:33776}
777
John Abd-El-Malek984dc002019-05-29 01:26:59778void ForceCreateNetworkServiceDirectlyForTesting() {
Yoichi Osato55a287f22023-06-01 22:16:27779 ForceInProcessNetworkService();
John Abd-El-Malek984dc002019-05-29 01:26:59780 g_force_create_network_service_directly = true;
781}
782
Will Harris66b7f8a2025-07-18 17:56:43783void SetNetworkServiceCrashOnNextStartupImplForTesting() {
784 g_network_service_crashes_on_next_startup = true;
785}
786
John Abd-El-Malek984dc002019-05-29 01:26:59787void ResetNetworkServiceForTesting() {
Ken Rockot91216c0f2019-10-11 20:38:11788 ShutDownNetworkService();
789}
790
791void ShutDownNetworkService() {
Julie Jeongeun Kima3471c62019-10-15 07:09:24792 delete g_network_service_remote;
793 g_network_service_remote = nullptr;
Sebastien Marchand0d68f75a2020-07-20 15:39:27794 delete g_client;
795 g_client = nullptr;
Ken Rockot7ff141d2019-11-01 21:09:44796 if (g_in_process_instance) {
797 GetNetworkTaskRunner()->DeleteSoon(FROM_HERE, g_in_process_instance);
798 g_in_process_instance = nullptr;
799 }
Ken Rockot91216c0f2019-10-11 20:38:11800 GetNetworkTaskRunnerStorage().reset();
John Abd-El-Malek984dc002019-05-29 01:26:59801}
802
Matthew Denton542c43c2023-08-18 07:32:17803void RestartNetworkService() {
804 ShutDownNetworkService();
805 GetNetworkService();
Matthew Denton095b6972023-11-02 21:56:17806 OnNetworkServiceProcessGone(/*crashed=*/false);
Matthew Denton542c43c2023-08-18 07:32:17807}
808
Matthew Denton03c45a22020-06-01 23:40:48809namespace {
810
Matthew Denton1d7839c2020-11-27 04:59:23811cert_verifier::mojom::CertVerifierServiceFactory*
812 g_cert_verifier_service_factory_for_testing = nullptr;
813
Matt Mueller47a15272023-12-12 01:44:16814std::unique_ptr<cert_verifier::CertVerifierServiceFactoryImpl>&
815GetCertVerifierServiceFactoryImplStorage() {
Matthew Denton1d7839c2020-11-27 04:59:23816 DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
817 BrowserThread::CurrentlyOn(BrowserThread::UI));
Avi Drissmanded77172021-07-02 18:23:00818 static base::SequenceLocalStorageSlot<
819 std::unique_ptr<cert_verifier::CertVerifierServiceFactoryImpl>>
Matthew Denton1d7839c2020-11-27 04:59:23820 service_factory_slot;
Matt Mueller47a15272023-12-12 01:44:16821 return service_factory_slot.GetOrCreateValue();
822}
823
824void RunInProcessCertVerifierServiceFactory(
825 mojo::PendingReceiver<cert_verifier::mojom::CertVerifierServiceFactory>
826 receiver) {
827 GetCertVerifierServiceFactoryImplStorage() =
Matthew Denton1d7839c2020-11-27 04:59:23828 std::make_unique<cert_verifier::CertVerifierServiceFactoryImpl>(
Matt Muellere6df72cb2023-04-12 22:08:37829 std::move(receiver));
Matthew Dentonb6730bf2020-06-25 04:54:11830}
831
Matthew Denton03c45a22020-06-01 23:40:48832// Owns the CertVerifierServiceFactory used by the browser.
833// Lives on the UI thread.
Matthew Denton1d7839c2020-11-27 04:59:23834mojo::Remote<cert_verifier::mojom::CertVerifierServiceFactory>&
835GetCertVerifierServiceFactoryRemoteStorage() {
Avi Drissmanded77172021-07-02 18:23:00836 static base::SequenceLocalStorageSlot<
837 mojo::Remote<cert_verifier::mojom::CertVerifierServiceFactory>>
Matthew Denton1d7839c2020-11-27 04:59:23838 cert_verifier_service_factory_remote;
Avi Drissmanded77172021-07-02 18:23:00839 return cert_verifier_service_factory_remote.GetOrCreateValue();
Matthew Denton1d7839c2020-11-27 04:59:23840}
Matthew Denton03c45a22020-06-01 23:40:48841
Hubert Chao2a000d72022-04-25 19:43:30842} // namespace
843
Matthew Denton1d7839c2020-11-27 04:59:23844// Returns a pointer to a CertVerifierServiceFactory usable on the UI thread.
845cert_verifier::mojom::CertVerifierServiceFactory*
846GetCertVerifierServiceFactory() {
Hubert Chao2a000d72022-04-25 19:43:30847 DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
848 BrowserThread::CurrentlyOn(BrowserThread::UI));
Matthew Denton1d7839c2020-11-27 04:59:23849 if (g_cert_verifier_service_factory_for_testing)
850 return g_cert_verifier_service_factory_for_testing;
Yuki Yamada709edde2020-11-24 05:47:21851
Matthew Denton1d7839c2020-11-27 04:59:23852 mojo::Remote<cert_verifier::mojom::CertVerifierServiceFactory>&
853 factory_remote_storage = GetCertVerifierServiceFactoryRemoteStorage();
854 if (!factory_remote_storage.is_bound() ||
855 !factory_remote_storage.is_connected()) {
856 factory_remote_storage.reset();
Matthew Denton1d7839c2020-11-27 04:59:23857 RunInProcessCertVerifierServiceFactory(
858 factory_remote_storage.BindNewPipeAndPassReceiver());
Yuki Yamada709edde2020-11-24 05:47:21859 }
Matthew Denton1d7839c2020-11-27 04:59:23860 return factory_remote_storage.get();
861}
Matthew Denton03c45a22020-06-01 23:40:48862
Matt Muellere6df72cb2023-04-12 22:08:37863mojo::Remote<cert_verifier::mojom::CertVerifierServiceFactory>&
864GetCertVerifierServiceFactoryRemoteForTesting() {
865 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
866
867 // The Remote isn't used if g_cert_verifier_service_factory_for_testing is
868 // registered, so any test trying to do both is doing something wrong.
869 CHECK(!g_cert_verifier_service_factory_for_testing);
870
871 return GetCertVerifierServiceFactoryRemoteStorage();
872}
Matt Mueller47a15272023-12-12 01:44:16873
874cert_verifier::CertVerifierServiceFactoryImpl*
875GetCertVerifierServiceFactoryForTesting() {
876 // The same comment about CHECK(!g_cert_verifier_service_factory_for_testing)
877 // from GetCertVerifierServiceFactoryRemoteForTesting() applies here, but
878 // since this method could be called on the IO thread, it is not CHECKed here.
879
Alison Gale81f4f2c72024-04-22 19:33:31880 // TODO(crbug.com/40693524): This depends on the cert verifier service
Matt Mueller47a15272023-12-12 01:44:16881 // and the network service both being in the same process as the unit test.
882 // The network service is taken care of by `UnitTestTestSuite` calling
883 // `ForceCreateNetworkServiceDirectlyForTesting()`, but if the cert verifier
884 // service is moved to a separate process as well, something similar will
885 // need to be done for that to be testable.
886 return GetCertVerifierServiceFactoryImplStorage().get();
887}
888
Matthew Denton82c211f2021-02-06 01:58:54889network::mojom::CertVerifierServiceRemoteParamsPtr GetCertVerifierParams(
Matthew Denton6f6ca6ac2021-02-18 09:00:35890 cert_verifier::mojom::CertVerifierCreationParamsPtr
Matthew Denton03c45a22020-06-01 23:40:48891 cert_verifier_creation_params) {
Matt Muellerf7839622023-11-13 20:23:15892 return GetCertVerifierParamsWithUpdater(
893 std::move(cert_verifier_creation_params), mojo::NullReceiver());
894}
895
896network::mojom::CertVerifierServiceRemoteParamsPtr
897GetCertVerifierParamsWithUpdater(
898 cert_verifier::mojom::CertVerifierCreationParamsPtr
899 cert_verifier_creation_params,
900 mojo::PendingReceiver<cert_verifier::mojom::CertVerifierServiceUpdater>
901 cert_verifier_updater_remote) {
Matt Mueller4924f222023-04-07 21:47:57902 mojo::PendingRemote<cert_verifier::mojom::CertVerifierService>
903 cert_verifier_remote;
904 mojo::PendingReceiver<cert_verifier::mojom::CertVerifierServiceClient>
905 cert_verifier_client;
906
907 GetCertVerifierServiceFactory()->GetNewCertVerifier(
908 cert_verifier_remote.InitWithNewPipeAndPassReceiver(),
Matt Muellerf7839622023-11-13 20:23:15909 std::move(cert_verifier_updater_remote),
Matt Mueller4924f222023-04-07 21:47:57910 cert_verifier_client.InitWithNewPipeAndPassRemote(),
911 std::move(cert_verifier_creation_params));
912
Matthew Denton82c211f2021-02-06 01:58:54913 return network::mojom::CertVerifierServiceRemoteParams::New(
Matt Mueller4924f222023-04-07 21:47:57914 std::move(cert_verifier_remote), std::move(cert_verifier_client));
Matthew Denton03c45a22020-06-01 23:40:48915}
916
917void SetCertVerifierServiceFactoryForTesting(
918 cert_verifier::mojom::CertVerifierServiceFactory* service_factory) {
Matthew Denton1d7839c2020-11-27 04:59:23919 g_cert_verifier_service_factory_for_testing = service_factory;
Matthew Denton03c45a22020-06-01 23:40:48920}
921
Will Harrisa6a750b2021-07-14 03:12:02922void CreateNetworkContextInNetworkService(
923 mojo::PendingReceiver<network::mojom::NetworkContext> context,
924 network::mojom::NetworkContextParamsPtr params) {
Egor Pasko75389f12022-03-22 16:09:11925 TRACE_EVENT0("loading", "CreateNetworkContextInNetworkService");
Will Harrise06ce8722023-08-03 23:11:47926 DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
927 BrowserThread::CurrentlyOn(BrowserThread::UI));
Kevin Marshalleece67f2022-03-30 20:30:04928
Chris Davis08351ce2025-03-04 21:19:33929 if (params->http_cache_enabled && params->file_paths &&
930 params->file_paths->http_cache_directory) {
Adam Riceb26f3f32025-08-04 09:37:18931 if (!params->file_paths->no_vary_search_directory.has_value()) {
932 static constexpr base::FilePath::CharType kNoVarySearchDirectoryName[] =
933 FILE_PATH_LITERAL("No_Vary_Search");
934
935 params->file_paths->no_vary_search_directory =
936 params->file_paths->http_cache_directory->path().Append(
937 kNoVarySearchDirectoryName);
938 }
Chris Davis08351ce2025-03-04 21:19:33939 params->file_paths->http_cache_directory =
940 params->file_paths->http_cache_directory->path().Append(
941 kCacheDataDirectoryName);
942 }
Kevin Marshalleece67f2022-03-30 20:30:04943
Yutaka Hirano92bdfa22022-06-01 15:51:33944 const bool has_valid_http_cache_path =
Liza Burakovad009fdd2023-06-23 18:43:23945 params->http_cache_enabled && params->file_paths &&
946 params->file_paths->http_cache_directory &&
947 !params->file_paths->http_cache_directory->path().empty();
Yutaka Hirano92bdfa22022-06-01 15:51:33948 const bool brokering_is_enabled =
949 IsOutOfProcessNetworkService() &&
950 base::FeatureList::IsEnabled(
951 features::kBrokerFileOperationsOnDiskCacheInNetworkService);
952 if (has_valid_http_cache_path && brokering_is_enabled) {
Yutaka Hiranode9868f2022-04-27 02:48:44953 mojo::MakeSelfOwnedReceiver(
954 std::make_unique<HttpCacheBackendFileOperationsFactory>(
Liza Burakovad009fdd2023-06-23 18:43:23955 params->file_paths->http_cache_directory->path()),
Yutaka Hiranode9868f2022-04-27 02:48:44956 params->http_cache_file_operations_factory
957 .InitWithNewPipeAndPassReceiver());
958 }
959
Will Harris7bcc5282022-07-29 00:51:03960#if BUILDFLAG(IS_ANDROID)
Will Harrisb57cfc562022-05-27 19:51:51961 // On Android, if a cookie_manager pending receiver was passed then migration
962 // should not be attempted as the cookie file is already being accessed by the
963 // browser instance.
964 if (params->cookie_manager) {
965 if (params->file_paths) {
966 // No migration should ever be attempted under this configuration.
967 DCHECK(!params->file_paths->unsandboxed_data_path);
968 }
969 CreateNetworkContextInternal(
970 std::move(context), std::move(params),
971 SandboxGrantResult::kDidNotAttemptToGrantSandboxAccess);
972 return;
973 }
974
975 // Note: This logic is duplicated from MaybeGrantAccessToDataPath to this fast
976 // path. This should be kept in sync if there are any changes to the logic.
977 SandboxGrantResult grant_result = SandboxGrantResult::kNoMigrationRequested;
978 if (!params->file_paths) {
979 // No file paths (e.g. in-memory context) so nothing to do.
980 grant_result = SandboxGrantResult::kDidNotAttemptToGrantSandboxAccess;
981 } else {
982 // If no `unsandboxed_data_path` is supplied, it means this is network
983 // context has been created by Android Webview, which does not understand
984 // the concept of `unsandboxed_data_path`. In this case, `data_directory`
985 // should always be used, if present.
986 if (!params->file_paths->unsandboxed_data_path)
987 grant_result = SandboxGrantResult::kDidNotAttemptToGrantSandboxAccess;
988 }
Egor Pasko75389f12022-03-22 16:09:11989 // Create network context immediately without thread hops.
Will Harrisb57cfc562022-05-27 19:51:51990 CreateNetworkContextInternal(std::move(context), std::move(params),
991 grant_result);
Egor Pasko75389f12022-03-22 16:09:11992#else
993 // Restrict disk access to a certain path (on another thread) and continue
994 // with network context creation.
995 GrantSandboxAccessOnThreadPool(
996 std::move(params),
997 base::BindOnce(&CreateNetworkContextInternal, std::move(context)));
Xiaohan Wang1ecfd002022-01-19 22:33:10998#endif // BUILDFLAG(IS_ANDROID)
Will Harrisa6a750b2021-07-14 03:12:02999}
1000
John Abd-El-Malekdeec0082017-12-20 20:47:471001} // namespace content