blob: 804a0ceb35d61b71047f9e58ef9a699b616eb8ba [file] [log] [blame]
John Abd-El-Malekdeec0082017-12-20 20:47:471// Copyright 2017 The Chromium Authors. All rights reserved.
2// 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
Lukasz Anforowiczce4487b72018-10-23 18:05:537#include <memory>
8#include <string>
9#include <utility>
10
Felipe Andradea9174c62022-08-16 18:35:1111#include "base/base_paths.h"
Sebastien Marchandf8cbfab2019-01-25 16:02:3012#include "base/bind.h"
Gabriel Charettef3851332022-04-28 23:39:1813#include "base/command_line.h"
Doug Turner08512342018-09-24 20:54:1914#include "base/environment.h"
John Abd-El-Malekdeec0082017-12-20 20:47:4715#include "base/feature_list.h"
Matt Menke04db81d2020-07-29 21:54:5816#include "base/files/file.h"
Will Harrisb246f672021-10-28 06:47:1317#include "base/files/file_enumerator.h"
Will Harrisdac11fb2021-09-08 02:21:4118#include "base/files/file_util.h"
Ken Rockot91216c0f2019-10-11 20:38:1119#include "base/message_loop/message_pump_type.h"
Will Harrisdac11fb2021-09-08 02:21:4120#include "base/metrics/histogram_functions.h"
Clark DuVall984239a2019-08-08 23:38:3321#include "base/metrics/histogram_macros.h"
Lukasz Anforowiczce4487b72018-10-23 18:05:5322#include "base/no_destructor.h"
Felipe Andradea9174c62022-08-16 18:35:1123#include "base/path_service.h"
Doug Turner08512342018-09-24 20:54:1924#include "base/strings/string_util.h"
25#include "base/strings/utf_string_conversions.h"
Robbie McElrath8dc3acc2019-08-15 20:43:0426#include "base/synchronization/waitable_event.h"
Patrick Monette643cdf62021-10-15 19:13:4227#include "base/task/sequenced_task_runner.h"
Will Harrisdac11fb2021-09-08 02:21:4128#include "base/task/thread_pool.h"
John Abd-El-Malek984dc002019-05-29 01:26:5929#include "base/threading/sequence_local_storage_slot.h"
Ken Rockot91216c0f2019-10-11 20:38:1130#include "base/threading/thread.h"
Matt Menke04db81d2020-07-29 21:54:5831#include "base/threading/thread_restrictions.h"
Gabriel Charetted87f10f2022-03-31 00:44:2232#include "base/time/time.h"
Egor Pasko75389f12022-03-22 16:09:1133#include "base/trace_event/trace_event.h"
Doug Turner08512342018-09-24 20:54:1934#include "build/build_config.h"
Yuta Hijikatad0a8b6b2020-11-20 16:36:1535#include "build/chromeos_buildflags.h"
Robbie McElrath995a2bf2018-11-19 23:21:5936#include "content/browser/browser_main_loop.h"
Will Harris7bcc5282022-07-29 00:51:0337#include "content/browser/buildflags.h"
Shuran Huang103981502022-03-28 21:52:1838#include "content/browser/first_party_sets/first_party_sets_handler_impl.h"
Yutaka Hiranode9868f2022-04-27 02:48:4439#include "content/browser/net/http_cache_backend_file_operations_factory.h"
Liza Burakova27070602022-07-01 05:27:4040#include "content/browser/net/socket_broker_impl.h"
Egor Pasko75389f12022-03-22 16:09:1141#include "content/browser/network_sandbox_grant_result.h"
John Abd-El-Malekdeec0082017-12-20 20:47:4742#include "content/browser/network_service_client.h"
Eric Seckler8652dcd52018-09-20 10:42:2843#include "content/public/browser/browser_task_traits.h"
John Abd-El-Malekdeec0082017-12-20 20:47:4744#include "content/public/browser/browser_thread.h"
45#include "content/public/browser/content_browser_client.h"
John Abd-El-Malek984dc002019-05-29 01:26:5946#include "content/public/browser/network_service_instance.h"
Ken Rockot91216c0f2019-10-11 20:38:1147#include "content/public/browser/service_process_host.h"
Hans Wennborg5ffd1392019-10-16 11:00:0248#include "content/public/common/content_client.h"
Yutaka Hirano92bdfa22022-06-01 15:51:3349#include "content/public/common/content_features.h"
Clark DuVallb9924e92018-12-10 23:36:3350#include "content/public/common/network_service_util.h"
Ken Rockot91216c0f2019-10-11 20:38:1151#include "mojo/public/cpp/bindings/pending_receiver.h"
Julie Jeongeun Kima3471c62019-10-15 07:09:2452#include "mojo/public/cpp/bindings/remote.h"
Yutaka Hiranode9868f2022-04-27 02:48:4453#include "mojo/public/cpp/bindings/self_owned_receiver.h"
54#include "net/base/features.h"
Matt Menke38662e22018-08-07 12:18:1155#include "net/log/net_log_util.h"
Liza Burakova27070602022-07-01 05:27:4056#include "sandbox/policy/features.h"
Matthew Denton03c45a22020-06-01 23:40:4857#include "services/cert_verifier/cert_verifier_service_factory.h"
Matthew Denton1d7839c2020-11-27 04:59:2358#include "services/cert_verifier/public/mojom/cert_verifier_service_factory.mojom.h"
John Abd-El-Malek8e82a322018-01-31 20:30:4759#include "services/network/network_service.h"
Yutaka Hiranod8789f92018-01-30 09:59:5160#include "services/network/public/cpp/features.h"
Matt Menke38662e22018-08-07 12:18:1161#include "services/network/public/cpp/network_switches.h"
Matt Menke55a16f02018-10-09 23:07:5362#include "services/network/public/mojom/net_log.mojom.h"
Robbie McElrathf572f5272018-08-17 21:21:4263#include "services/network/public/mojom/network_change_manager.mojom.h"
Hans Wennborg78b52182021-06-15 13:42:1564#include "services/network/public/mojom/network_context.mojom.h"
Etienne Pierre-doray0df4474a2019-10-16 14:56:3965#include "services/network/public/mojom/network_service.mojom.h"
Ken Rockot91216c0f2019-10-11 20:38:1166#include "services/network/public/mojom/network_service_test.mojom.h"
Liza Burakova27070602022-07-01 05:27:4067#include "services/network/public/mojom/socket_broker.mojom.h"
John Abd-El-Malekdeec0082017-12-20 20:47:4768
Egor Pasko75389f12022-03-22 16:09:1169#if !BUILDFLAG(IS_ANDROID)
70#include "content/browser/network_sandbox.h"
71#endif
Will Harris1967f8442021-02-05 20:34:2272
Will Harrisf26ad342022-09-06 02:03:2873#if BUILDFLAG(IS_WIN)
74#include "content/browser/net/network_service_process_tracker_win.h"
75#endif
76
John Abd-El-Malekdeec0082017-12-20 20:47:4777namespace content {
78
79namespace {
80
Xiaohan Wang1ecfd002022-01-19 22:33:1081#if BUILDFLAG(IS_POSIX)
Robbie McElrathfa25a7c2019-03-13 17:54:3682// Environment variable pointing to credential cache file.
83constexpr char kKrb5CCEnvName[] = "KRB5CCNAME";
84// Environment variable pointing to Kerberos config file.
85constexpr char kKrb5ConfEnvName[] = "KRB5_CONFIG";
86#endif
87
Felipe Andradea9174c62022-08-16 18:35:1188#if BUILDFLAG(IS_CHROMEOS_LACROS)
89constexpr char kKrb5CCFilePrefix[] = "FILE:";
90constexpr char kKrb5Directory[] = "kerberos";
91constexpr char kKrb5CCFile[] = "krb5cc";
92constexpr char kKrb5ConfFile[] = "krb5.conf";
93#endif // BUILDFLAG(IS_CHROMEOS_LACROS)
94
John Abd-El-Malek984dc002019-05-29 01:26:5995bool g_force_create_network_service_directly = false;
Julie Jeongeun Kima3471c62019-10-15 07:09:2496mojo::Remote<network::mojom::NetworkService>* g_network_service_remote =
97 nullptr;
Robbie McElrathf961dc52018-08-08 21:29:2698network::NetworkConnectionTracker* g_network_connection_tracker;
Clark DuVallb026e582019-07-31 19:50:3899bool g_network_service_is_responding = false;
100base::Time g_last_network_service_crash;
John Abd-El-Malek984dc002019-05-29 01:26:59101
Will Harrisb246f672021-10-28 06:47:13102// A directory name that is created below the http cache path and passed to the
103// network context when creating a network context with cache enabled.
104// This must be a directory below the main cache path so operations such as
105// resetting the cache via HttpCacheParams.reset_cache can function correctly
106// as they rely on having access to the parent directory of the cache.
107const base::FilePath::CharType kCacheDataDirectoryName[] =
108 FILE_PATH_LITERAL("Cache_Data");
109
John Abd-El-Malek984dc002019-05-29 01:26:59110std::unique_ptr<network::NetworkService>& GetLocalNetworkService() {
Avi Drissmanded77172021-07-02 18:23:00111 static base::SequenceLocalStorageSlot<
112 std::unique_ptr<network::NetworkService>>
John Abd-El-Malek984dc002019-05-29 01:26:59113 service;
Avi Drissmanded77172021-07-02 18:23:00114 return service.GetOrCreateValue();
John Abd-El-Malek984dc002019-05-29 01:26:59115}
John Abd-El-Malekdeec0082017-12-20 20:47:47116
Ken Rockot91216c0f2019-10-11 20:38:11117// If this feature is enabled, the Network Service will run on its own thread
118// when running in-process; otherwise it will run on the IO thread.
119//
120// On Chrome OS, the Network Service must run on the IO thread because
121// ProfileIOData and NetworkContext both try to set up NSS, which has to be
122// called from the IO thread.
123const base::Feature kNetworkServiceDedicatedThread {
124 "NetworkServiceDedicatedThread",
Michael Ershovcbdb8202022-02-21 19:17:01125#if BUILDFLAG(IS_CHROMEOS)
Ken Rockot91216c0f2019-10-11 20:38:11126 base::FEATURE_DISABLED_BY_DEFAULT
127#else
128 base::FEATURE_ENABLED_BY_DEFAULT
129#endif
130};
131
132base::Thread& GetNetworkServiceDedicatedThread() {
133 static base::NoDestructor<base::Thread> thread{"NetworkService"};
John Abd-El-Maleka5fe84b2022-03-18 01:05:29134 DCHECK(base::FeatureList::IsEnabled(kNetworkServiceDedicatedThread));
Ken Rockot91216c0f2019-10-11 20:38:11135 return *thread;
136}
137
Ken Rockot7ff141d2019-11-01 21:09:44138// The instance NetworkService used when hosting the service in-process. This is
139// set up by |CreateInProcessNetworkServiceOnThread()| and destroyed by
140// |ShutDownNetworkService()|.
141network::NetworkService* g_in_process_instance = nullptr;
142
Dave Tapuska69f89252021-03-10 17:11:37143static NetworkServiceClient* g_client = nullptr;
144
Ken Rockot91216c0f2019-10-11 20:38:11145void CreateInProcessNetworkServiceOnThread(
146 mojo::PendingReceiver<network::mojom::NetworkService> receiver) {
147 // The test interface doesn't need to be implemented in the in-process case.
148 auto registry = std::make_unique<service_manager::BinderRegistry>();
Daniel Chengb7b2f5b2021-09-25 21:37:19149 registry->AddInterface(base::BindRepeating(
150 [](mojo::PendingReceiver<network::mojom::NetworkServiceTest>) {}));
Scott Sheehan8e1d03ce2019-11-05 16:11:15151 g_in_process_instance = new network::NetworkService(
152 std::move(registry), std::move(receiver),
153 true /* delay_initialization_until_set_client */);
Ken Rockot91216c0f2019-10-11 20:38:11154}
155
Will Harris3d6f9e4c2021-09-17 19:11:16156// A utility function to make it clear what behavior is expected by the network
157// context instance depending on the various errors that can happen during data
158// migration.
159//
Kevin Marshall4bdfa5df2022-03-21 22:33:27160// If this function returns 'true' then the `data_directory` should be used (if
Will Harris3d6f9e4c2021-09-17 19:11:16161// specified in the network context params). If this function returns 'false'
162// then the `unsandboxed_data_path` should be used.
163bool IsSafeToUseDataPath(SandboxGrantResult result) {
164 switch (result) {
165 case SandboxGrantResult::kSuccess:
166 // A migration occurred, and it was successful.
167 return true;
168 case SandboxGrantResult::kFailedToGrantSandboxAccessToCache:
169 case SandboxGrantResult::kFailedToCreateCacheDirectory:
170 // A failure to grant create or grant access to the cache dir does not
Kevin Marshall4bdfa5df2022-03-21 22:33:27171 // affect the providence of the data contained in `data_directory` as the
Will Harris3d6f9e4c2021-09-17 19:11:16172 // migration could have still occurred.
173 //
174 // These cases are handled internally and so this case should never be
175 // hit. It is undefined behavior to proceed in this case so CHECK here.
176 IMMEDIATE_CRASH();
177 return false;
178 case SandboxGrantResult::kFailedToCreateDataDirectory:
Kevin Marshall4bdfa5df2022-03-21 22:33:27179 // A failure to create the `data_directory` is fatal, and the
Will Harris3d6f9e4c2021-09-17 19:11:16180 // `unsandboxed_data_path` should be used.
181 return false;
182 case SandboxGrantResult::kFailedToCopyData:
183 // A failure to copy the data from `unsandboxed_data_path` to the
Kevin Marshall4bdfa5df2022-03-21 22:33:27184 // `data_directory` is fatal, and the `unsandboxed_data_path` should be
185 // used.
Will Harris3d6f9e4c2021-09-17 19:11:16186 return false;
187 case SandboxGrantResult::kFailedToDeleteOldData:
188 // This is not fatal, as the new data has been correctly migrated, and the
189 // deletion will be retried at a later time.
190 return true;
191 case SandboxGrantResult::kFailedToGrantSandboxAccessToData:
192 // If the sandbox could not be granted access to the new data dir, then
193 // don't attempt to migrate. This means that the old
194 // `unsandboxed_data_path` should be used.
195 return false;
196 case SandboxGrantResult::kDidNotAttemptToGrantSandboxAccess:
197 // No migration was attempted either because of platform constraints or
198 // because the network context had no valid data paths (e.g. in-memory or
Kevin Marshall4bdfa5df2022-03-21 22:33:27199 // incognito), or `unsandboxed_data_path` was not specified.
200 // `data_directory` should be used in this case (if present).
Will Harris3d6f9e4c2021-09-17 19:11:16201 return true;
202 case SandboxGrantResult::kFailedToCreateCheckpointFile:
203 // This is fatal, as a failure to create the checkpoint file means that
204 // the next time the same network context is used, the data in
Kevin Marshall4bdfa5df2022-03-21 22:33:27205 // `unsandboxed_data_path` will be re-copied to the new `data_directory`
206 // and thus any changes to the data will be discarded. So in this case,
Will Harris3d6f9e4c2021-09-17 19:11:16207 // `unsandboxed_data_path` should be used.
208 return false;
209 case SandboxGrantResult::kNoMigrationRequested:
210 // The caller supplied an `unsandboxed_data_path` but did not trigger a
211 // migration so the data should be read from the `unsandboxed_data_path`.
212 return false;
213 case SandboxGrantResult::kMigrationAlreadySucceeded:
Kevin Marshall4bdfa5df2022-03-21 22:33:27214 // Migration has already taken place, so `data_directory` contains the
215 // valid data.
Will Harris3d6f9e4c2021-09-17 19:11:16216 return true;
217 case SandboxGrantResult::kMigrationAlreadySucceededWithNoAccess:
218 // If the sandbox could not be granted access to the new data dir, but the
Kevin Marshall4bdfa5df2022-03-21 22:33:27219 // migration has already happened to `data_directory`. This means that the
220 // sandbox might not have access to the data but `data_directory` should
221 // still be used because it's been migrated.
Will Harris3d6f9e4c2021-09-17 19:11:16222 return true;
223 }
224}
225
Will Harrisb246f672021-10-28 06:47:13226// Takes a cache dir and deletes all files in it except those in 'Cache_Data'
227// directory. This can be removed once all caches have been moved to the new
228// sub-directory, around M99.
229void MaybeDeleteOldCache(const base::FilePath& cache_dir) {
230 bool deleted_old_files = false;
231 base::FileEnumerator enumerator(
232 cache_dir, /*recursive=*/false,
233 base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES);
234
235 for (auto name = enumerator.Next(); !name.empty(); name = enumerator.Next()) {
236 base::FileEnumerator::FileInfo info = enumerator.GetInfo();
237 DCHECK_EQ(info.GetName(), name.BaseName());
238
239 if (info.IsDirectory()) {
240 if (name.BaseName().value() == kCacheDataDirectoryName)
241 continue;
242 }
243 base::DeletePathRecursively(name);
244 deleted_old_files = true;
245 }
246
247 base::UmaHistogramBoolean("NetworkService.DeletedOldCacheData",
248 deleted_old_files);
249}
250
Will Harrisdac11fb2021-09-08 02:21:41251void CreateNetworkContextInternal(
252 mojo::PendingReceiver<network::mojom::NetworkContext> context,
253 network::mojom::NetworkContextParamsPtr params,
254 SandboxGrantResult grant_access_result) {
Egor Pasko75389f12022-03-22 16:09:11255 TRACE_EVENT0("loading", "CreateNetworkContextInternal");
Will Harris3d6f9e4c2021-09-17 19:11:16256 // These two histograms are logged from elsewhere, so don't log them twice.
257 DCHECK(grant_access_result !=
258 SandboxGrantResult::kFailedToCreateCacheDirectory);
259 DCHECK(grant_access_result !=
260 SandboxGrantResult::kFailedToGrantSandboxAccessToCache);
Will Harrisdac11fb2021-09-08 02:21:41261 base::UmaHistogramEnumeration("NetworkService.GrantSandboxResult",
262 grant_access_result);
Will Harris3d6f9e4c2021-09-17 19:11:16263
264 if (grant_access_result != SandboxGrantResult::kSuccess &&
265 grant_access_result !=
266 SandboxGrantResult::kDidNotAttemptToGrantSandboxAccess &&
267 grant_access_result != SandboxGrantResult::kNoMigrationRequested &&
268 grant_access_result != SandboxGrantResult::kMigrationAlreadySucceeded) {
269 PLOG(ERROR) << "Encountered error while migrating network context data or "
270 "granting sandbox access for "
Kevin Marshalleece67f2022-03-30 20:30:04271 << (params->file_paths
272 ? params->file_paths->data_directory.path()
273 : base::FilePath())
Will Harris3d6f9e4c2021-09-17 19:11:16274 << ". Result: " << static_cast<int>(grant_access_result);
275 }
276
277 if (!IsSafeToUseDataPath(grant_access_result)) {
Kevin Marshall4bdfa5df2022-03-21 22:33:27278 // Unsafe to use new `data_directory`. This means that a migration was
279 // attempted, and `unsandboxed_data_path` contains the still-valid set of
280 // data. Swap the parameters to instruct the network service to use this
281 // path for the network context. This of course will mean that if the
282 // network service is running sandboxed then this data might not be
283 // accessible, but does provide a pathway to user recovery, as the sandbox
284 // can just be disabled in this case.
Will Harris3d6f9e4c2021-09-17 19:11:16285 DCHECK(params->file_paths->unsandboxed_data_path.has_value());
Kevin Marshall4bdfa5df2022-03-21 22:33:27286 params->file_paths->data_directory =
287 *params->file_paths->unsandboxed_data_path;
Will Harrisdac11fb2021-09-08 02:21:41288 }
Kevin Marshalleece67f2022-03-30 20:30:04289
290 if (network::TransferableDirectory::IsOpenForTransferRequired()) {
291 if (params->file_paths) {
292 params->file_paths->data_directory.OpenForTransfer();
293 }
294 if (params->http_cache_directory) {
295 params->http_cache_directory->OpenForTransfer();
296 }
Will Harrisb246f672021-10-28 06:47:13297 }
Kevin Marshalleece67f2022-03-30 20:30:04298
Will Harris78ccb552022-09-08 05:40:48299 // This might recreate g_client if the network service needed to be restarted.
300 auto* network_service = GetNetworkService();
301
302#if BUILDFLAG(USE_SOCKET_BROKER)
303 if (GetContentClient()->browser()->ShouldSandboxNetworkService() &&
304 !params->socket_broker) {
305 params->socket_broker = g_client->BindSocketBroker();
306 }
307#endif // BUILDFLAG(USE_SOCKET_BROKER)
308
309 network_service->CreateNetworkContext(std::move(context), std::move(params));
Will Harrisdac11fb2021-09-08 02:21:41310}
311
Alexander Timin7ab3ed82020-01-13 20:00:13312scoped_refptr<base::SequencedTaskRunner>& GetNetworkTaskRunnerStorage() {
313 static base::NoDestructor<scoped_refptr<base::SequencedTaskRunner>> storage;
314 return *storage;
315}
316
Felipe Andradea9174c62022-08-16 18:35:11317#if BUILDFLAG(IS_CHROMEOS_LACROS)
318base::FilePath GetKerberosDir() {
319 base::FilePath dir;
320 base::PathService::Get(base::DIR_HOME, &dir);
321 return dir.Append(kKrb5Directory);
322}
323
324std::string GetKrb5CCEnvValue() {
325 return kKrb5CCFilePrefix + GetKerberosDir().Append(kKrb5CCFile).value();
326}
327
328std::string GetKrb5ConfEnvValue() {
329 return GetKerberosDir().Append(kKrb5ConfFile).value();
330}
331#endif // BUILDFLAG(IS_CHROMEOS_LACROS)
332
Ken Rockot91216c0f2019-10-11 20:38:11333void CreateInProcessNetworkService(
334 mojo::PendingReceiver<network::mojom::NetworkService> receiver) {
Egor Pasko75389f12022-03-22 16:09:11335 TRACE_EVENT0("loading", "CreateInProcessNetworkService");
Ken Rockot91216c0f2019-10-11 20:38:11336 scoped_refptr<base::SingleThreadTaskRunner> task_runner;
John Abd-El-Maleka5fe84b2022-03-18 01:05:29337 if (base::FeatureList::IsEnabled(kNetworkServiceDedicatedThread)) {
Ken Rockot91216c0f2019-10-11 20:38:11338 base::Thread::Options options(base::MessagePumpType::IO, 0);
Olivier Li89911c42021-07-02 21:27:02339 GetNetworkServiceDedicatedThread().StartWithOptions(std::move(options));
Ken Rockot91216c0f2019-10-11 20:38:11340 task_runner = GetNetworkServiceDedicatedThread().task_runner();
341 } else {
Gabriel Charettee7cdc5cd2020-05-27 23:35:05342 task_runner = GetIOThreadTaskRunner({});
Ken Rockot91216c0f2019-10-11 20:38:11343 }
344
Alexander Timin7ab3ed82020-01-13 20:00:13345 GetNetworkTaskRunnerStorage() = std::move(task_runner);
346
347 GetNetworkTaskRunner()->PostTask(
348 FROM_HERE, base::BindOnce(&CreateInProcessNetworkServiceOnThread,
349 std::move(receiver)));
Ken Rockot91216c0f2019-10-11 20:38:11350}
351
John Abd-El-Malekd1e2a1c2019-02-28 20:01:03352network::mojom::NetworkServiceParamsPtr CreateNetworkServiceParams() {
353 network::mojom::NetworkServiceParamsPtr network_service_params =
354 network::mojom::NetworkServiceParams::New();
355 network_service_params->initial_connection_type =
356 network::mojom::ConnectionType(
357 net::NetworkChangeNotifier::GetConnectionType());
358 network_service_params->initial_connection_subtype =
359 network::mojom::ConnectionSubtype(
360 net::NetworkChangeNotifier::GetConnectionSubtype());
Dave Tapuska69f89252021-03-10 17:11:37361 network_service_params->default_observer =
362 g_client->BindURLLoaderNetworkServiceObserver();
Kirubel Aklilu60d316f2021-12-16 01:55:33363 network_service_params->first_party_sets_enabled =
364 GetContentClient()->browser()->IsFirstPartySetsEnabled();
365
Xiaohan Wang1ecfd002022-01-19 22:33:10366#if BUILDFLAG(IS_POSIX)
Robbie McElrathfa25a7c2019-03-13 17:54:36367 // Send Kerberos environment variables to the network service.
368 if (IsOutOfProcessNetworkService()) {
Felipe Andradea9174c62022-08-16 18:35:11369#if BUILDFLAG(IS_CHROMEOS_LACROS)
370 network_service_params->environment.push_back(
371 network::mojom::EnvironmentVariable::New(kKrb5CCEnvName,
372 GetKrb5CCEnvValue()));
373 network_service_params->environment.push_back(
374 network::mojom::EnvironmentVariable::New(kKrb5ConfEnvName,
375 GetKrb5ConfEnvValue()));
376#else
Robbie McElrathfa25a7c2019-03-13 17:54:36377 std::unique_ptr<base::Environment> env(base::Environment::Create());
378 std::string value;
379 if (env->HasVar(kKrb5CCEnvName)) {
380 env->GetVar(kKrb5CCEnvName, &value);
381 network_service_params->environment.push_back(
382 network::mojom::EnvironmentVariable::New(kKrb5CCEnvName, value));
383 }
384 if (env->HasVar(kKrb5ConfEnvName)) {
385 env->GetVar(kKrb5ConfEnvName, &value);
386 network_service_params->environment.push_back(
387 network::mojom::EnvironmentVariable::New(kKrb5ConfEnvName, value));
388 }
Felipe Andradea9174c62022-08-16 18:35:11389#endif // BUILDFLAG(IS_CHROMEOS_LACROS)
Robbie McElrathfa25a7c2019-03-13 17:54:36390 }
Felipe Andradea9174c62022-08-16 18:35:11391#endif // BUILDFLAG(IS_POSIX)
John Abd-El-Malekd1e2a1c2019-02-28 20:01:03392 return network_service_params;
393}
394
Robbie McElrath8dc3acc2019-08-15 20:43:04395void CreateNetworkServiceOnIOForTesting(
Julie Jeongeun Kima3471c62019-10-15 07:09:24396 mojo::PendingReceiver<network::mojom::NetworkService> receiver,
Robbie McElrath8dc3acc2019-08-15 20:43:04397 base::WaitableEvent* completion_event) {
John Abd-El-Malek984dc002019-05-29 01:26:59398 if (GetLocalNetworkService()) {
Julie Jeongeun Kima3471c62019-10-15 07:09:24399 GetLocalNetworkService()->Bind(std::move(receiver));
John Abd-El-Malekdeec0082017-12-20 20:47:47400 return;
401 }
402
Etienne Pierre-doray0df4474a2019-10-16 14:56:39403 GetLocalNetworkService() = std::make_unique<network::NetworkService>(
404 nullptr /* registry */, std::move(receiver),
405 true /* delay_initialization_until_set_client */);
406 GetLocalNetworkService()->Initialize(
407 network::mojom::NetworkServiceParams::New(),
408 true /* mock_network_change_notifier */);
Robbie McElrath8dc3acc2019-08-15 20:43:04409 if (completion_event)
410 completion_event->Signal();
John Abd-El-Malekdeec0082017-12-20 20:47:47411}
412
Gyuyoung Kim5f3bd4202019-09-27 01:59:49413void BindNetworkChangeManagerReceiver(
414 mojo::PendingReceiver<network::mojom::NetworkChangeManager> receiver) {
415 GetNetworkService()->GetNetworkChangeManager(std::move(receiver));
Robbie McElrathf572f5272018-08-17 21:21:42416}
417
Fabrice de Gans-Riberid82d1222021-03-22 22:23:11418base::RepeatingClosureList& GetCrashHandlersList() {
419 static base::NoDestructor<base::RepeatingClosureList> s_list;
Lukasz Anforowiczc195e912018-10-30 16:20:54420 return *s_list;
Lukasz Anforowiczce4487b72018-10-23 18:05:53421}
422
423void OnNetworkServiceCrash() {
424 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
Julie Jeongeun Kima3471c62019-10-15 07:09:24425 DCHECK(g_network_service_remote);
426 DCHECK(g_network_service_remote->is_bound());
427 DCHECK(!g_network_service_remote->is_connected());
Clark DuVallb026e582019-07-31 19:50:38428 g_last_network_service_crash = base::Time::Now();
Lukasz Anforowiczc195e912018-10-30 16:20:54429 GetCrashHandlersList().Notify();
Lukasz Anforowiczce4487b72018-10-23 18:05:53430}
431
Eric Romanc03b62622019-06-25 02:13:22432// Parses the desired granularity of NetLog capturing specified by the command
433// line.
434net::NetLogCaptureMode GetNetCaptureModeFromCommandLine(
435 const base::CommandLine& command_line) {
436 base::StringPiece switch_name = network::switches::kNetLogCaptureMode;
437
438 if (command_line.HasSwitch(switch_name)) {
439 std::string value = command_line.GetSwitchValueASCII(switch_name);
440
441 if (value == "Default")
Eric Roman3124cde2019-07-10 22:26:15442 return net::NetLogCaptureMode::kDefault;
443 if (value == "IncludeSensitive")
444 return net::NetLogCaptureMode::kIncludeSensitive;
445 if (value == "Everything")
446 return net::NetLogCaptureMode::kEverything;
447
448 // Warn when using the old command line switches.
449 if (value == "IncludeCookiesAndCredentials") {
450 LOG(ERROR) << "Deprecated value for --" << switch_name
451 << ". Use IncludeSensitive instead";
452 return net::NetLogCaptureMode::kIncludeSensitive;
453 }
454 if (value == "IncludeSocketBytes") {
455 LOG(ERROR) << "Deprecated value for --" << switch_name
456 << ". Use Everything instead";
457 return net::NetLogCaptureMode::kEverything;
458 }
Eric Romanc03b62622019-06-25 02:13:22459
460 LOG(ERROR) << "Unrecognized value for --" << switch_name;
461 }
462
Eric Roman3124cde2019-07-10 22:26:15463 return net::NetLogCaptureMode::kDefault;
Eric Romanc03b62622019-06-25 02:13:22464}
465
John Abd-El-Malekdeec0082017-12-20 20:47:47466} // namespace
467
Matt Menke04db81d2020-07-29 21:54:58468class NetworkServiceInstancePrivate {
469 public:
470 // Opens the specified file, blocking until the file is open. Used to open
471 // files specified by network::switches::kLogNetLog or
472 // network::switches::kSSLKeyLogFile. Since these arguments can be used to
473 // debug startup behavior, asynchronously opening the file on another thread
474 // would result in losing data, hence the need for blocking open operations.
475 // |file_flags| specifies the flags passed to the base::File constructor call.
476 //
477 // ThreadRestrictions needs to be able to friend the class/method to allow
478 // blocking, but can't friend CONTENT_EXPORT methods, so have it friend
479 // NetworkServiceInstancePrivate instead of GetNetworkService().
480 static base::File BlockingOpenFile(const base::FilePath& path,
481 int file_flags) {
482 base::ScopedAllowBlocking allow_blocking;
483 return base::File(path, file_flags);
484 }
485};
486
John Abd-El-Malek53670dd2018-01-18 22:07:21487network::mojom::NetworkService* GetNetworkService() {
Julie Jeongeun Kima3471c62019-10-15 07:09:24488 if (!g_network_service_remote)
489 g_network_service_remote = new mojo::Remote<network::mojom::NetworkService>;
Julie Jeongeun Kima3471c62019-10-15 07:09:24490 if (!g_network_service_remote->is_bound() ||
491 !g_network_service_remote->is_connected()) {
Matt Menke080a9172020-01-31 10:44:08492 bool service_was_bound = g_network_service_remote->is_bound();
Julie Jeongeun Kima3471c62019-10-15 07:09:24493 g_network_service_remote->reset();
John Abd-El-Malek1ae9dbb2019-03-04 23:40:47494 if (GetContentClient()->browser()->IsShuttingDown()) {
495 // This happens at system shutdown, since in other scenarios the network
496 // process would only be torn down once the message loop stopped running.
Oleh Lamzin0e228572019-12-06 16:46:09497 // We don't want to start the network service again so just create message
498 // pipe that's not bound to stop consumers from requesting creation of the
499 // service.
Julie Jeongeun Kima3471c62019-10-15 07:09:24500 auto receiver = g_network_service_remote->BindNewPipeAndPassReceiver();
501 auto leaked_pipe = receiver.PassPipe().release();
John Abd-El-Malekdeec0082017-12-20 20:47:47502 } else {
Ken Rockot91216c0f2019-10-11 20:38:11503 if (!g_force_create_network_service_directly) {
504 mojo::PendingReceiver<network::mojom::NetworkService> receiver =
Julie Jeongeun Kima3471c62019-10-15 07:09:24505 g_network_service_remote->BindNewPipeAndPassReceiver();
506 g_network_service_remote->set_disconnect_handler(
John Abd-El-Malek1ae9dbb2019-03-04 23:40:47507 base::BindOnce(&OnNetworkServiceCrash));
Ken Rockot91216c0f2019-10-11 20:38:11508 if (IsInProcessNetworkService()) {
509 CreateInProcessNetworkService(std::move(receiver));
510 } else {
Matt Menke080a9172020-01-31 10:44:08511 if (service_was_bound)
512 LOG(ERROR) << "Network service crashed, restarting service.";
Jan Wilken Dörrie2c470ea2021-03-22 22:26:24513 ServiceProcessHost::Launch(std::move(receiver),
514 ServiceProcessHost::Options()
515 .WithDisplayName(u"Network Service")
516 .Pass());
Ken Rockot91216c0f2019-10-11 20:38:11517 }
John Abd-El-Malek1ae9dbb2019-03-04 23:40:47518 } else {
Robbie McElrath8dc3acc2019-08-15 20:43:04519 // This should only be reached in unit tests.
520 if (BrowserThread::CurrentlyOn(BrowserThread::IO)) {
521 CreateNetworkServiceOnIOForTesting(
Julie Jeongeun Kima3471c62019-10-15 07:09:24522 g_network_service_remote->BindNewPipeAndPassReceiver(),
Robbie McElrath8dc3acc2019-08-15 20:43:04523 /*completion_event=*/nullptr);
524 } else {
525 base::WaitableEvent event;
Gabriel Charettee7cdc5cd2020-05-27 23:35:05526 GetIOThreadTaskRunner({})->PostTask(
527 FROM_HERE,
Julie Jeongeun Kima3471c62019-10-15 07:09:24528 base::BindOnce(
529 CreateNetworkServiceOnIOForTesting,
530 g_network_service_remote->BindNewPipeAndPassReceiver(),
531 base::Unretained(&event)));
Robbie McElrath8dc3acc2019-08-15 20:43:04532 event.Wait();
533 }
John Abd-El-Malek1ae9dbb2019-03-04 23:40:47534 }
John Abd-El-Malekdeec0082017-12-20 20:47:47535
Dave Tapuska69f89252021-03-10 17:11:37536 delete g_client; // In case we're recreating the network service.
537 g_client = new NetworkServiceClient();
538
John Abd-El-Malek1ae9dbb2019-03-04 23:40:47539 // Call SetClient before creating NetworkServiceClient, as the latter
540 // might make requests to NetworkService that depend on initialization.
Dave Tapuska69f89252021-03-10 17:11:37541 (*g_network_service_remote)->SetParams(CreateNetworkServiceParams());
Yutaka Hirano136bd912022-01-31 16:26:11542 g_client->OnNetworkServiceInitialized(g_network_service_remote->get());
543
Clark DuVallb026e582019-07-31 19:50:38544 g_network_service_is_responding = false;
Jan Wilken Dörrie8c74db022020-04-20 09:05:00545 g_network_service_remote->QueryVersion(base::BindOnce(
Clark DuVall984239a2019-08-08 23:38:33546 [](base::Time start_time, uint32_t) {
547 g_network_service_is_responding = true;
548 base::TimeDelta delta = base::Time::Now() - start_time;
549 UMA_HISTOGRAM_MEDIUM_TIMES("NetworkService.TimeToFirstResponse",
550 delta);
551 if (g_last_network_service_crash.is_null()) {
552 UMA_HISTOGRAM_MEDIUM_TIMES(
553 "NetworkService.TimeToFirstResponse.OnStartup", delta);
554 } else {
555 UMA_HISTOGRAM_MEDIUM_TIMES(
556 "NetworkService.TimeToFirstResponse.AfterCrash", delta);
557 }
558 },
559 base::Time::Now()));
John Abd-El-Malekd1e2a1c2019-02-28 20:01:03560
Robbie McElrath35ef9672019-02-13 22:01:59561 const base::CommandLine* command_line =
562 base::CommandLine::ForCurrentProcess();
John Abd-El-Malekc134dd82019-07-31 20:51:44563 if (command_line->HasSwitch(network::switches::kLogNetLog)) {
564 base::FilePath log_path =
565 command_line->GetSwitchValuePath(network::switches::kLogNetLog);
Cheng Yu6e46b4d2021-09-02 06:43:08566 if (log_path.empty()) {
567 log_path = GetContentClient()->browser()->GetNetLogDefaultDirectory();
568 if (!log_path.empty())
569 log_path = log_path.Append(FILE_PATH_LITERAL("netlog.json"));
570 }
Doug Turner08512342018-09-24 20:54:19571
Matt Menke04db81d2020-07-29 21:54:58572 base::File file = NetworkServiceInstancePrivate::BlockingOpenFile(
John Abd-El-Malekc134dd82019-07-31 20:51:44573 log_path, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
574 if (!file.IsValid()) {
575 LOG(ERROR) << "Failed opening NetLog: " << log_path.value();
576 } else {
Julie Jeongeun Kima3471c62019-10-15 07:09:24577 (*g_network_service_remote)
Matt Menke04db81d2020-07-29 21:54:58578 ->StartNetLog(
579 std::move(file),
580 GetNetCaptureModeFromCommandLine(*command_line),
581 GetContentClient()->browser()->GetNetLogConstants());
Robbie McElrath35ef9672019-02-13 22:01:59582 }
Robbie McElrathd063ed02019-02-13 21:59:30583 }
Robbie McElrathd063ed02019-02-13 21:59:30584
David Benjamin887153852019-08-07 23:19:55585 base::FilePath ssl_key_log_path;
Robbie McElrath35ef9672019-02-13 22:01:59586 if (command_line->HasSwitch(network::switches::kSSLKeyLogFile)) {
Christopher Thompson2a4c69e92019-08-21 16:29:11587 UMA_HISTOGRAM_ENUMERATION(kSSLKeyLogFileHistogram,
588 SSLKeyLogFileAction::kSwitchFound);
David Benjamin887153852019-08-07 23:19:55589 ssl_key_log_path =
Robbie McElrath35ef9672019-02-13 22:01:59590 command_line->GetSwitchValuePath(network::switches::kSSLKeyLogFile);
David Benjamin887153852019-08-07 23:19:55591 LOG_IF(WARNING, ssl_key_log_path.empty())
Robbie McElrath35ef9672019-02-13 22:01:59592 << "ssl-key-log-file argument missing";
David Benjamin887153852019-08-07 23:19:55593 } else {
594 std::unique_ptr<base::Environment> env(base::Environment::Create());
595 std::string env_str;
596 if (env->GetVar("SSLKEYLOGFILE", &env_str)) {
Christopher Thompson2a4c69e92019-08-21 16:29:11597 UMA_HISTOGRAM_ENUMERATION(kSSLKeyLogFileHistogram,
598 SSLKeyLogFileAction::kEnvVarFound);
Xiaohan Wang1ecfd002022-01-19 22:33:10599#if BUILDFLAG(IS_WIN)
David Benjamin887153852019-08-07 23:19:55600 // base::Environment returns environment variables in UTF-8 on
601 // Windows.
Peter Kasting57fd6de42021-01-28 23:05:39602 ssl_key_log_path = base::FilePath(base::UTF8ToWide(env_str));
David Benjamin887153852019-08-07 23:19:55603#else
604 ssl_key_log_path = base::FilePath(env_str);
605#endif
606 }
Robbie McElrath35ef9672019-02-13 22:01:59607 }
Robbie McElrathd063ed02019-02-13 21:59:30608
David Benjamin887153852019-08-07 23:19:55609 if (!ssl_key_log_path.empty()) {
Matt Menke04db81d2020-07-29 21:54:58610 base::File file = NetworkServiceInstancePrivate::BlockingOpenFile(
611 ssl_key_log_path,
612 base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_APPEND);
David Benjamin887153852019-08-07 23:19:55613 if (!file.IsValid()) {
614 LOG(ERROR) << "Failed opening SSL key log file: "
615 << ssl_key_log_path.value();
616 } else {
Christopher Thompson2a4c69e92019-08-21 16:29:11617 UMA_HISTOGRAM_ENUMERATION(kSSLKeyLogFileHistogram,
618 SSLKeyLogFileAction::kLogFileEnabled);
Julie Jeongeun Kima3471c62019-10-15 07:09:24619 (*g_network_service_remote)->SetSSLKeyLogFile(std::move(file));
David Benjamin887153852019-08-07 23:19:55620 }
Robbie McElrath35ef9672019-02-13 22:01:59621 }
Doug Turner08512342018-09-24 20:54:19622
Chris Fredricksona2092c9b2022-05-09 21:54:12623 if (FirstPartySetsHandlerImpl::GetInstance()->IsEnabled()) {
Chris Fredricksoned87d8e2022-08-17 18:30:10624 if (absl::optional<network::mojom::PublicFirstPartySetsPtr> sets =
Chris Fredricksona2092c9b2022-05-09 21:54:12625 FirstPartySetsHandlerImpl::GetInstance()->GetSets(
626 base::BindOnce(
Chris Fredricksoned87d8e2022-08-17 18:30:10627 [](network::mojom::PublicFirstPartySetsPtr sets) {
Chris Fredricksona2092c9b2022-05-09 21:54:12628 GetNetworkService()->SetFirstPartySets(
629 std::move(sets));
630 }));
631 sets.has_value()) {
632 g_network_service_remote->get()->SetFirstPartySets(
633 std::move(sets.value()));
634 }
cfredric763290422022-03-31 23:00:33635 }
Shuran Huang103981502022-03-28 21:52:18636
Robbie McElrath35ef9672019-02-13 22:01:59637 GetContentClient()->browser()->OnNetworkServiceCreated(
Julie Jeongeun Kima3471c62019-10-15 07:09:24638 g_network_service_remote->get());
John Abd-El-Malek1ae9dbb2019-03-04 23:40:47639 }
John Abd-El-Malekdeec0082017-12-20 20:47:47640 }
Julie Jeongeun Kima3471c62019-10-15 07:09:24641 return g_network_service_remote->get();
John Abd-El-Malekdeec0082017-12-20 20:47:47642}
643
Peter Kasting7ba9440c2020-11-22 01:49:02644base::CallbackListSubscription RegisterNetworkServiceCrashHandler(
645 base::RepeatingClosure handler) {
Lukasz Anforowiczce4487b72018-10-23 18:05:53646 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
647 DCHECK(!handler.is_null());
648
John Abd-El-Malekc134dd82019-07-31 20:51:44649 return GetCrashHandlersList().Add(std::move(handler));
John Abd-El-Malekdeec0082017-12-20 20:47:47650}
651
Eriko Kurimoto64656462022-07-21 01:07:49652#if BUILDFLAG(IS_CHROMEOS)
Robbie McElrath995a2bf2018-11-19 23:21:59653net::NetworkChangeNotifier* GetNetworkChangeNotifier() {
654 return BrowserMainLoop::GetInstance()->network_change_notifier();
655}
John Abd-El-Malek03438952019-05-16 22:53:51656#endif
Robbie McElrath995a2bf2018-11-19 23:21:59657
John Abd-El-Malekdeec0082017-12-20 20:47:47658void FlushNetworkServiceInstanceForTesting() {
659 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
John Abd-El-Malekdeec0082017-12-20 20:47:47660
Julie Jeongeun Kima3471c62019-10-15 07:09:24661 if (g_network_service_remote)
662 g_network_service_remote->FlushForTesting();
John Abd-El-Malekdeec0082017-12-20 20:47:47663}
664
Robbie McElrathf961dc52018-08-08 21:29:26665network::NetworkConnectionTracker* GetNetworkConnectionTracker() {
Andrew Paseltiner82a1f89f2022-02-28 21:59:36666 DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
667 BrowserThread::CurrentlyOn(BrowserThread::UI));
Robbie McElrathf961dc52018-08-08 21:29:26668 if (!g_network_connection_tracker) {
669 g_network_connection_tracker = new network::NetworkConnectionTracker(
Gyuyoung Kim5f3bd4202019-09-27 01:59:49670 base::BindRepeating(&BindNetworkChangeManagerReceiver));
Robbie McElrathf961dc52018-08-08 21:29:26671 }
672 return g_network_connection_tracker;
673}
674
Robbie McElrathf633990e2018-10-02 21:44:48675void GetNetworkConnectionTrackerFromUIThread(
676 base::OnceCallback<void(network::NetworkConnectionTracker*)> callback) {
Gabriel Charettee7cdc5cd2020-05-27 23:35:05677 GetUIThreadTaskRunner({base::TaskPriority::BEST_EFFORT})
678 ->PostTaskAndReplyWithResult(FROM_HERE,
679 base::BindOnce(&GetNetworkConnectionTracker),
680 std::move(callback));
Robbie McElrathf633990e2018-10-02 21:44:48681}
682
Jun Cai597752e42018-11-15 19:54:25683network::NetworkConnectionTrackerAsyncGetter
684CreateNetworkConnectionTrackerAsyncGetter() {
685 return base::BindRepeating(&content::GetNetworkConnectionTrackerFromUIThread);
686}
687
Robbie McElrathf961dc52018-08-08 21:29:26688void SetNetworkConnectionTrackerForTesting(
689 network::NetworkConnectionTracker* network_connection_tracker) {
Andrew Paseltiner82a1f89f2022-02-28 21:59:36690 DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
691 BrowserThread::CurrentlyOn(BrowserThread::UI));
Robbie McElrathdb12d8e2018-09-18 21:20:40692 if (g_network_connection_tracker != network_connection_tracker) {
693 DCHECK(!g_network_connection_tracker || !network_connection_tracker);
694 g_network_connection_tracker = network_connection_tracker;
695 }
Robbie McElrathf961dc52018-08-08 21:29:26696}
697
Alexander Timin7ab3ed82020-01-13 20:00:13698const scoped_refptr<base::SequencedTaskRunner>& GetNetworkTaskRunner() {
Clark DuVallb9924e92018-12-10 23:36:33699 DCHECK(IsInProcessNetworkService());
Alexander Timin7ab3ed82020-01-13 20:00:13700 return GetNetworkTaskRunnerStorage();
Clark DuVallb9924e92018-12-10 23:36:33701}
702
John Abd-El-Malek984dc002019-05-29 01:26:59703void ForceCreateNetworkServiceDirectlyForTesting() {
704 g_force_create_network_service_directly = true;
705}
706
707void ResetNetworkServiceForTesting() {
Ken Rockot91216c0f2019-10-11 20:38:11708 ShutDownNetworkService();
709}
710
711void ShutDownNetworkService() {
Julie Jeongeun Kima3471c62019-10-15 07:09:24712 delete g_network_service_remote;
713 g_network_service_remote = nullptr;
Sebastien Marchand0d68f75a2020-07-20 15:39:27714 delete g_client;
715 g_client = nullptr;
Ken Rockot7ff141d2019-11-01 21:09:44716 if (g_in_process_instance) {
717 GetNetworkTaskRunner()->DeleteSoon(FROM_HERE, g_in_process_instance);
718 g_in_process_instance = nullptr;
719 }
Ken Rockot91216c0f2019-10-11 20:38:11720 GetNetworkTaskRunnerStorage().reset();
John Abd-El-Malek984dc002019-05-29 01:26:59721}
722
Clark DuVallb026e582019-07-31 19:50:38723NetworkServiceAvailability GetNetworkServiceAvailability() {
Julie Jeongeun Kima3471c62019-10-15 07:09:24724 if (!g_network_service_remote)
Clark DuVallb026e582019-07-31 19:50:38725 return NetworkServiceAvailability::NOT_CREATED;
Julie Jeongeun Kima3471c62019-10-15 07:09:24726 else if (!g_network_service_remote->is_bound())
Clark DuVallb026e582019-07-31 19:50:38727 return NetworkServiceAvailability::NOT_BOUND;
Julie Jeongeun Kima3471c62019-10-15 07:09:24728 else if (!g_network_service_remote->is_connected())
Clark DuVallb026e582019-07-31 19:50:38729 return NetworkServiceAvailability::ENCOUNTERED_ERROR;
730 else if (!g_network_service_is_responding)
731 return NetworkServiceAvailability::NOT_RESPONDING;
732 else
733 return NetworkServiceAvailability::AVAILABLE;
734}
735
736base::TimeDelta GetTimeSinceLastNetworkServiceCrash() {
737 if (g_last_network_service_crash.is_null())
738 return base::TimeDelta();
739 return base::Time::Now() - g_last_network_service_crash;
740}
741
Clark DuVall1f94e9f42019-08-21 04:09:36742void PingNetworkService(base::OnceClosure closure) {
743 GetNetworkService();
744 // Unfortunately, QueryVersion requires a RepeatingCallback.
Jan Wilken Dörrie8c74db022020-04-20 09:05:00745 g_network_service_remote->QueryVersion(base::BindOnce(
Clark DuVall1f94e9f42019-08-21 04:09:36746 [](base::OnceClosure closure, uint32_t) {
747 if (closure)
748 std::move(closure).Run();
749 },
Daniel Cheng28a5ac482021-02-22 21:03:08750 std::move(closure)));
Clark DuVall1f94e9f42019-08-21 04:09:36751}
752
Matthew Denton03c45a22020-06-01 23:40:48753namespace {
754
Matthew Denton1d7839c2020-11-27 04:59:23755cert_verifier::mojom::CertVerifierServiceFactory*
756 g_cert_verifier_service_factory_for_testing = nullptr;
757
Matthew Denton03c45a22020-06-01 23:40:48758mojo::PendingRemote<cert_verifier::mojom::CertVerifierService>
759GetNewCertVerifierServiceRemote(
760 cert_verifier::mojom::CertVerifierServiceFactory*
761 cert_verifier_service_factory,
Matthew Denton6f6ca6ac2021-02-18 09:00:35762 cert_verifier::mojom::CertVerifierCreationParamsPtr creation_params) {
Matthew Denton03c45a22020-06-01 23:40:48763 mojo::PendingRemote<cert_verifier::mojom::CertVerifierService>
764 cert_verifier_remote;
765 cert_verifier_service_factory->GetNewCertVerifier(
766 cert_verifier_remote.InitWithNewPipeAndPassReceiver(),
767 std::move(creation_params));
768 return cert_verifier_remote;
769}
770
Matthew Denton1d7839c2020-11-27 04:59:23771void RunInProcessCertVerifierServiceFactory(
Matthew Dentonb6730bf2020-06-25 04:54:11772 mojo::PendingReceiver<cert_verifier::mojom::CertVerifierServiceFactory>
773 receiver) {
Michael Ershovcbdb8202022-02-21 19:17:01774#if BUILDFLAG(IS_CHROMEOS)
775 // See the comment in GetCertVerifierServiceFactory() for the thread-affinity
776 // of the CertVerifierService.
Matthew Denton1d7839c2020-11-27 04:59:23777 DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::IO) ||
778 BrowserThread::CurrentlyOn(BrowserThread::IO));
779#else
780 DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
781 BrowserThread::CurrentlyOn(BrowserThread::UI));
782#endif
Avi Drissmanded77172021-07-02 18:23:00783 static base::SequenceLocalStorageSlot<
784 std::unique_ptr<cert_verifier::CertVerifierServiceFactoryImpl>>
Matthew Denton1d7839c2020-11-27 04:59:23785 service_factory_slot;
Avi Drissmanded77172021-07-02 18:23:00786 service_factory_slot.GetOrCreateValue() =
Matthew Denton1d7839c2020-11-27 04:59:23787 std::make_unique<cert_verifier::CertVerifierServiceFactoryImpl>(
788 std::move(receiver));
Matthew Dentonb6730bf2020-06-25 04:54:11789}
790
Matthew Denton03c45a22020-06-01 23:40:48791// Owns the CertVerifierServiceFactory used by the browser.
792// Lives on the UI thread.
Matthew Denton1d7839c2020-11-27 04:59:23793mojo::Remote<cert_verifier::mojom::CertVerifierServiceFactory>&
794GetCertVerifierServiceFactoryRemoteStorage() {
Avi Drissmanded77172021-07-02 18:23:00795 static base::SequenceLocalStorageSlot<
796 mojo::Remote<cert_verifier::mojom::CertVerifierServiceFactory>>
Matthew Denton1d7839c2020-11-27 04:59:23797 cert_verifier_service_factory_remote;
Avi Drissmanded77172021-07-02 18:23:00798 return cert_verifier_service_factory_remote.GetOrCreateValue();
Matthew Denton1d7839c2020-11-27 04:59:23799}
Matthew Denton03c45a22020-06-01 23:40:48800
Hubert Chao2a000d72022-04-25 19:43:30801} // namespace
802
Matthew Denton1d7839c2020-11-27 04:59:23803// Returns a pointer to a CertVerifierServiceFactory usable on the UI thread.
804cert_verifier::mojom::CertVerifierServiceFactory*
805GetCertVerifierServiceFactory() {
Hubert Chao2a000d72022-04-25 19:43:30806 DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
807 BrowserThread::CurrentlyOn(BrowserThread::UI));
Matthew Denton1d7839c2020-11-27 04:59:23808 if (g_cert_verifier_service_factory_for_testing)
809 return g_cert_verifier_service_factory_for_testing;
Yuki Yamada709edde2020-11-24 05:47:21810
Matthew Denton1d7839c2020-11-27 04:59:23811 mojo::Remote<cert_verifier::mojom::CertVerifierServiceFactory>&
812 factory_remote_storage = GetCertVerifierServiceFactoryRemoteStorage();
813 if (!factory_remote_storage.is_bound() ||
814 !factory_remote_storage.is_connected()) {
815 factory_remote_storage.reset();
Michael Ershovcbdb8202022-02-21 19:17:01816#if BUILDFLAG(IS_CHROMEOS)
817 // In-process CertVerifierService in Ash and Lacros should run on the IO
818 // thread because it interacts with IO-bound NSS and ChromeOS user slots.
819 // See for example InitializeNSSForChromeOSUser() or
820 // CertDbInitializerIOImpl.
Matthew Denton1d7839c2020-11-27 04:59:23821 GetIOThreadTaskRunner({})->PostTask(
822 FROM_HERE,
823 base::BindOnce(&RunInProcessCertVerifierServiceFactory,
824 factory_remote_storage.BindNewPipeAndPassReceiver()));
Yuki Yamada709edde2020-11-24 05:47:21825#else
Matthew Denton1d7839c2020-11-27 04:59:23826 RunInProcessCertVerifierServiceFactory(
827 factory_remote_storage.BindNewPipeAndPassReceiver());
Yuki Yamada709edde2020-11-24 05:47:21828#endif
Yuki Yamada709edde2020-11-24 05:47:21829 }
Matthew Denton1d7839c2020-11-27 04:59:23830 return factory_remote_storage.get();
831}
Matthew Denton03c45a22020-06-01 23:40:48832
Matthew Denton82c211f2021-02-06 01:58:54833network::mojom::CertVerifierServiceRemoteParamsPtr GetCertVerifierParams(
Matthew Denton6f6ca6ac2021-02-18 09:00:35834 cert_verifier::mojom::CertVerifierCreationParamsPtr
Matthew Denton03c45a22020-06-01 23:40:48835 cert_verifier_creation_params) {
Matthew Denton82c211f2021-02-06 01:58:54836 return network::mojom::CertVerifierServiceRemoteParams::New(
837 GetNewCertVerifierServiceRemote(
838 GetCertVerifierServiceFactory(),
839 std::move(cert_verifier_creation_params)));
Matthew Denton03c45a22020-06-01 23:40:48840}
841
842void SetCertVerifierServiceFactoryForTesting(
843 cert_verifier::mojom::CertVerifierServiceFactory* service_factory) {
Matthew Denton1d7839c2020-11-27 04:59:23844 g_cert_verifier_service_factory_for_testing = service_factory;
Matthew Denton03c45a22020-06-01 23:40:48845}
846
Kevin Marshalleece67f2022-03-30 20:30:04847void MaybeCleanCacheDirectory(network::mojom::NetworkContextParams* params) {
848 if (params->http_cache_enabled && params->http_cache_directory) {
849 // Delete any old data except for the "Cache_Data" directory.
850 base::ThreadPool::PostTask(
851 FROM_HERE,
852 {base::TaskPriority::BEST_EFFORT, base::MayBlock(),
853 base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
854 base::BindOnce(MaybeDeleteOldCache,
855 params->http_cache_directory->path()));
856
857 params->http_cache_directory =
858 params->http_cache_directory->path().Append(kCacheDataDirectoryName);
859 }
860}
861
Will Harrisa6a750b2021-07-14 03:12:02862void CreateNetworkContextInNetworkService(
863 mojo::PendingReceiver<network::mojom::NetworkContext> context,
864 network::mojom::NetworkContextParamsPtr params) {
Egor Pasko75389f12022-03-22 16:09:11865 TRACE_EVENT0("loading", "CreateNetworkContextInNetworkService");
Will Harrisdac11fb2021-09-08 02:21:41866 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
Kevin Marshalleece67f2022-03-30 20:30:04867
868 MaybeCleanCacheDirectory(params.get());
869
Yutaka Hirano92bdfa22022-06-01 15:51:33870 const bool has_valid_http_cache_path =
871 params->http_cache_enabled && params->http_cache_directory &&
872 !params->http_cache_directory->path().empty();
873 const bool brokering_is_enabled =
874 IsOutOfProcessNetworkService() &&
875 base::FeatureList::IsEnabled(
876 features::kBrokerFileOperationsOnDiskCacheInNetworkService);
877 if (has_valid_http_cache_path && brokering_is_enabled) {
Yutaka Hiranode9868f2022-04-27 02:48:44878 mojo::MakeSelfOwnedReceiver(
879 std::make_unique<HttpCacheBackendFileOperationsFactory>(
880 params->http_cache_directory->path()),
881 params->http_cache_file_operations_factory
882 .InitWithNewPipeAndPassReceiver());
883 }
884
Will Harris7bcc5282022-07-29 00:51:03885#if BUILDFLAG(IS_ANDROID)
Will Harrisb57cfc562022-05-27 19:51:51886 // On Android, if a cookie_manager pending receiver was passed then migration
887 // should not be attempted as the cookie file is already being accessed by the
888 // browser instance.
889 if (params->cookie_manager) {
890 if (params->file_paths) {
891 // No migration should ever be attempted under this configuration.
892 DCHECK(!params->file_paths->unsandboxed_data_path);
893 }
894 CreateNetworkContextInternal(
895 std::move(context), std::move(params),
896 SandboxGrantResult::kDidNotAttemptToGrantSandboxAccess);
897 return;
898 }
899
900 // Note: This logic is duplicated from MaybeGrantAccessToDataPath to this fast
901 // path. This should be kept in sync if there are any changes to the logic.
902 SandboxGrantResult grant_result = SandboxGrantResult::kNoMigrationRequested;
903 if (!params->file_paths) {
904 // No file paths (e.g. in-memory context) so nothing to do.
905 grant_result = SandboxGrantResult::kDidNotAttemptToGrantSandboxAccess;
906 } else {
907 // If no `unsandboxed_data_path` is supplied, it means this is network
908 // context has been created by Android Webview, which does not understand
909 // the concept of `unsandboxed_data_path`. In this case, `data_directory`
910 // should always be used, if present.
911 if (!params->file_paths->unsandboxed_data_path)
912 grant_result = SandboxGrantResult::kDidNotAttemptToGrantSandboxAccess;
913 }
Egor Pasko75389f12022-03-22 16:09:11914 // Create network context immediately without thread hops.
Will Harrisb57cfc562022-05-27 19:51:51915 CreateNetworkContextInternal(std::move(context), std::move(params),
916 grant_result);
Egor Pasko75389f12022-03-22 16:09:11917#else
918 // Restrict disk access to a certain path (on another thread) and continue
919 // with network context creation.
920 GrantSandboxAccessOnThreadPool(
921 std::move(params),
922 base::BindOnce(&CreateNetworkContextInternal, std::move(context)));
Xiaohan Wang1ecfd002022-01-19 22:33:10923#endif // BUILDFLAG(IS_ANDROID)
Will Harrisa6a750b2021-07-14 03:12:02924}
925
Will Harrisf26ad342022-09-06 02:03:28926#if BUILDFLAG(IS_WIN)
927
928void SetNetworkServiceTrackerToCurrentProcessForTesting() {
929 internal::SetNetworkServiceTrackerToCurrentProcessForTesting();
930}
931
932#endif // BUILDFLAG(IS_WIN)
933
John Abd-El-Malekdeec0082017-12-20 20:47:47934} // namespace content