blob: 2202de9caa2864b3523ce5739442b77a7da31166 [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"
Chris Fredrickson878d06b2022-09-08 15:20:3755#include "net/first_party_sets/public_sets.h"
Matt Menke38662e22018-08-07 12:18:1156#include "net/log/net_log_util.h"
Liza Burakova27070602022-07-01 05:27:4057#include "sandbox/policy/features.h"
Matthew Denton03c45a22020-06-01 23:40:4858#include "services/cert_verifier/cert_verifier_service_factory.h"
Matthew Denton1d7839c2020-11-27 04:59:2359#include "services/cert_verifier/public/mojom/cert_verifier_service_factory.mojom.h"
John Abd-El-Malek8e82a322018-01-31 20:30:4760#include "services/network/network_service.h"
Yutaka Hiranod8789f92018-01-30 09:59:5161#include "services/network/public/cpp/features.h"
Matt Menke38662e22018-08-07 12:18:1162#include "services/network/public/cpp/network_switches.h"
Matt Menke55a16f02018-10-09 23:07:5363#include "services/network/public/mojom/net_log.mojom.h"
Robbie McElrathf572f5272018-08-17 21:21:4264#include "services/network/public/mojom/network_change_manager.mojom.h"
Hans Wennborg78b52182021-06-15 13:42:1565#include "services/network/public/mojom/network_context.mojom.h"
Etienne Pierre-doray0df4474a2019-10-16 14:56:3966#include "services/network/public/mojom/network_service.mojom.h"
Ken Rockot91216c0f2019-10-11 20:38:1167#include "services/network/public/mojom/network_service_test.mojom.h"
Liza Burakova27070602022-07-01 05:27:4068#include "services/network/public/mojom/socket_broker.mojom.h"
John Abd-El-Malekdeec0082017-12-20 20:47:4769
Egor Pasko75389f12022-03-22 16:09:1170#if !BUILDFLAG(IS_ANDROID)
71#include "content/browser/network_sandbox.h"
72#endif
Will Harris1967f8442021-02-05 20:34:2273
Will Harrisf26ad342022-09-06 02:03:2874#if BUILDFLAG(IS_WIN)
75#include "content/browser/net/network_service_process_tracker_win.h"
76#endif
77
John Abd-El-Malekdeec0082017-12-20 20:47:4778namespace content {
79
80namespace {
81
Xiaohan Wang1ecfd002022-01-19 22:33:1082#if BUILDFLAG(IS_POSIX)
Robbie McElrathfa25a7c2019-03-13 17:54:3683// Environment variable pointing to credential cache file.
84constexpr char kKrb5CCEnvName[] = "KRB5CCNAME";
85// Environment variable pointing to Kerberos config file.
86constexpr char kKrb5ConfEnvName[] = "KRB5_CONFIG";
87#endif
88
Felipe Andradea9174c62022-08-16 18:35:1189#if BUILDFLAG(IS_CHROMEOS_LACROS)
90constexpr char kKrb5CCFilePrefix[] = "FILE:";
91constexpr char kKrb5Directory[] = "kerberos";
92constexpr char kKrb5CCFile[] = "krb5cc";
93constexpr char kKrb5ConfFile[] = "krb5.conf";
94#endif // BUILDFLAG(IS_CHROMEOS_LACROS)
95
John Abd-El-Malek984dc002019-05-29 01:26:5996bool g_force_create_network_service_directly = false;
Julie Jeongeun Kima3471c62019-10-15 07:09:2497mojo::Remote<network::mojom::NetworkService>* g_network_service_remote =
98 nullptr;
Robbie McElrathf961dc52018-08-08 21:29:2699network::NetworkConnectionTracker* g_network_connection_tracker;
Clark DuVallb026e582019-07-31 19:50:38100bool g_network_service_is_responding = false;
101base::Time g_last_network_service_crash;
John Abd-El-Malek984dc002019-05-29 01:26:59102
Will Harrisb246f672021-10-28 06:47:13103// A directory name that is created below the http cache path and passed to the
104// network context when creating a network context with cache enabled.
105// This must be a directory below the main cache path so operations such as
106// resetting the cache via HttpCacheParams.reset_cache can function correctly
107// as they rely on having access to the parent directory of the cache.
108const base::FilePath::CharType kCacheDataDirectoryName[] =
109 FILE_PATH_LITERAL("Cache_Data");
110
John Abd-El-Malek984dc002019-05-29 01:26:59111std::unique_ptr<network::NetworkService>& GetLocalNetworkService() {
Avi Drissmanded77172021-07-02 18:23:00112 static base::SequenceLocalStorageSlot<
113 std::unique_ptr<network::NetworkService>>
John Abd-El-Malek984dc002019-05-29 01:26:59114 service;
Avi Drissmanded77172021-07-02 18:23:00115 return service.GetOrCreateValue();
John Abd-El-Malek984dc002019-05-29 01:26:59116}
John Abd-El-Malekdeec0082017-12-20 20:47:47117
Ken Rockot91216c0f2019-10-11 20:38:11118// If this feature is enabled, the Network Service will run on its own thread
119// when running in-process; otherwise it will run on the IO thread.
120//
121// On Chrome OS, the Network Service must run on the IO thread because
122// ProfileIOData and NetworkContext both try to set up NSS, which has to be
123// called from the IO thread.
124const base::Feature kNetworkServiceDedicatedThread {
125 "NetworkServiceDedicatedThread",
Michael Ershovcbdb8202022-02-21 19:17:01126#if BUILDFLAG(IS_CHROMEOS)
Ken Rockot91216c0f2019-10-11 20:38:11127 base::FEATURE_DISABLED_BY_DEFAULT
128#else
129 base::FEATURE_ENABLED_BY_DEFAULT
130#endif
131};
132
133base::Thread& GetNetworkServiceDedicatedThread() {
134 static base::NoDestructor<base::Thread> thread{"NetworkService"};
John Abd-El-Maleka5fe84b2022-03-18 01:05:29135 DCHECK(base::FeatureList::IsEnabled(kNetworkServiceDedicatedThread));
Ken Rockot91216c0f2019-10-11 20:38:11136 return *thread;
137}
138
Ken Rockot7ff141d2019-11-01 21:09:44139// The instance NetworkService used when hosting the service in-process. This is
140// set up by |CreateInProcessNetworkServiceOnThread()| and destroyed by
141// |ShutDownNetworkService()|.
142network::NetworkService* g_in_process_instance = nullptr;
143
Dave Tapuska69f89252021-03-10 17:11:37144static NetworkServiceClient* g_client = nullptr;
145
Ken Rockot91216c0f2019-10-11 20:38:11146void CreateInProcessNetworkServiceOnThread(
147 mojo::PendingReceiver<network::mojom::NetworkService> receiver) {
148 // The test interface doesn't need to be implemented in the in-process case.
149 auto registry = std::make_unique<service_manager::BinderRegistry>();
Daniel Chengb7b2f5b2021-09-25 21:37:19150 registry->AddInterface(base::BindRepeating(
151 [](mojo::PendingReceiver<network::mojom::NetworkServiceTest>) {}));
Scott Sheehan8e1d03c2019-11-05 16:11:15152 g_in_process_instance = new network::NetworkService(
153 std::move(registry), std::move(receiver),
154 true /* delay_initialization_until_set_client */);
Ken Rockot91216c0f2019-10-11 20:38:11155}
156
Will Harris3d6f9e4c2021-09-17 19:11:16157// A utility function to make it clear what behavior is expected by the network
158// context instance depending on the various errors that can happen during data
159// migration.
160//
Kevin Marshall4bdfa5df2022-03-21 22:33:27161// If this function returns 'true' then the `data_directory` should be used (if
Will Harris3d6f9e4c2021-09-17 19:11:16162// specified in the network context params). If this function returns 'false'
163// then the `unsandboxed_data_path` should be used.
164bool IsSafeToUseDataPath(SandboxGrantResult result) {
165 switch (result) {
166 case SandboxGrantResult::kSuccess:
167 // A migration occurred, and it was successful.
168 return true;
169 case SandboxGrantResult::kFailedToGrantSandboxAccessToCache:
170 case SandboxGrantResult::kFailedToCreateCacheDirectory:
171 // A failure to grant create or grant access to the cache dir does not
Kevin Marshall4bdfa5df2022-03-21 22:33:27172 // affect the providence of the data contained in `data_directory` as the
Will Harris3d6f9e4c2021-09-17 19:11:16173 // migration could have still occurred.
174 //
175 // These cases are handled internally and so this case should never be
176 // hit. It is undefined behavior to proceed in this case so CHECK here.
177 IMMEDIATE_CRASH();
178 return false;
179 case SandboxGrantResult::kFailedToCreateDataDirectory:
Kevin Marshall4bdfa5df2022-03-21 22:33:27180 // A failure to create the `data_directory` is fatal, and the
Will Harris3d6f9e4c2021-09-17 19:11:16181 // `unsandboxed_data_path` should be used.
182 return false;
183 case SandboxGrantResult::kFailedToCopyData:
184 // A failure to copy the data from `unsandboxed_data_path` to the
Kevin Marshall4bdfa5df2022-03-21 22:33:27185 // `data_directory` is fatal, and the `unsandboxed_data_path` should be
186 // used.
Will Harris3d6f9e4c2021-09-17 19:11:16187 return false;
188 case SandboxGrantResult::kFailedToDeleteOldData:
189 // This is not fatal, as the new data has been correctly migrated, and the
190 // deletion will be retried at a later time.
191 return true;
192 case SandboxGrantResult::kFailedToGrantSandboxAccessToData:
193 // If the sandbox could not be granted access to the new data dir, then
194 // don't attempt to migrate. This means that the old
195 // `unsandboxed_data_path` should be used.
196 return false;
197 case SandboxGrantResult::kDidNotAttemptToGrantSandboxAccess:
198 // No migration was attempted either because of platform constraints or
199 // because the network context had no valid data paths (e.g. in-memory or
Kevin Marshall4bdfa5df2022-03-21 22:33:27200 // incognito), or `unsandboxed_data_path` was not specified.
201 // `data_directory` should be used in this case (if present).
Will Harris3d6f9e4c2021-09-17 19:11:16202 return true;
203 case SandboxGrantResult::kFailedToCreateCheckpointFile:
204 // This is fatal, as a failure to create the checkpoint file means that
205 // the next time the same network context is used, the data in
Kevin Marshall4bdfa5df2022-03-21 22:33:27206 // `unsandboxed_data_path` will be re-copied to the new `data_directory`
207 // and thus any changes to the data will be discarded. So in this case,
Will Harris3d6f9e4c2021-09-17 19:11:16208 // `unsandboxed_data_path` should be used.
209 return false;
210 case SandboxGrantResult::kNoMigrationRequested:
211 // The caller supplied an `unsandboxed_data_path` but did not trigger a
212 // migration so the data should be read from the `unsandboxed_data_path`.
213 return false;
214 case SandboxGrantResult::kMigrationAlreadySucceeded:
Kevin Marshall4bdfa5df2022-03-21 22:33:27215 // Migration has already taken place, so `data_directory` contains the
216 // valid data.
Will Harris3d6f9e4c2021-09-17 19:11:16217 return true;
218 case SandboxGrantResult::kMigrationAlreadySucceededWithNoAccess:
219 // If the sandbox could not be granted access to the new data dir, but the
Kevin Marshall4bdfa5df2022-03-21 22:33:27220 // migration has already happened to `data_directory`. This means that the
221 // sandbox might not have access to the data but `data_directory` should
222 // still be used because it's been migrated.
Will Harris3d6f9e4c2021-09-17 19:11:16223 return true;
224 }
225}
226
Will Harrisb246f672021-10-28 06:47:13227// Takes a cache dir and deletes all files in it except those in 'Cache_Data'
228// directory. This can be removed once all caches have been moved to the new
229// sub-directory, around M99.
230void MaybeDeleteOldCache(const base::FilePath& cache_dir) {
231 bool deleted_old_files = false;
232 base::FileEnumerator enumerator(
233 cache_dir, /*recursive=*/false,
234 base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES);
235
236 for (auto name = enumerator.Next(); !name.empty(); name = enumerator.Next()) {
237 base::FileEnumerator::FileInfo info = enumerator.GetInfo();
238 DCHECK_EQ(info.GetName(), name.BaseName());
239
240 if (info.IsDirectory()) {
241 if (name.BaseName().value() == kCacheDataDirectoryName)
242 continue;
243 }
244 base::DeletePathRecursively(name);
245 deleted_old_files = true;
246 }
247
248 base::UmaHistogramBoolean("NetworkService.DeletedOldCacheData",
249 deleted_old_files);
250}
251
Will Harrisdac11fb2021-09-08 02:21:41252void CreateNetworkContextInternal(
253 mojo::PendingReceiver<network::mojom::NetworkContext> context,
254 network::mojom::NetworkContextParamsPtr params,
255 SandboxGrantResult grant_access_result) {
Egor Pasko75389f12022-03-22 16:09:11256 TRACE_EVENT0("loading", "CreateNetworkContextInternal");
Will Harris3d6f9e4c2021-09-17 19:11:16257 // These two histograms are logged from elsewhere, so don't log them twice.
258 DCHECK(grant_access_result !=
259 SandboxGrantResult::kFailedToCreateCacheDirectory);
260 DCHECK(grant_access_result !=
261 SandboxGrantResult::kFailedToGrantSandboxAccessToCache);
Will Harrisdac11fb2021-09-08 02:21:41262 base::UmaHistogramEnumeration("NetworkService.GrantSandboxResult",
263 grant_access_result);
Will Harris3d6f9e4c2021-09-17 19:11:16264
265 if (grant_access_result != SandboxGrantResult::kSuccess &&
266 grant_access_result !=
267 SandboxGrantResult::kDidNotAttemptToGrantSandboxAccess &&
268 grant_access_result != SandboxGrantResult::kNoMigrationRequested &&
269 grant_access_result != SandboxGrantResult::kMigrationAlreadySucceeded) {
270 PLOG(ERROR) << "Encountered error while migrating network context data or "
271 "granting sandbox access for "
Kevin Marshalleece67f2022-03-30 20:30:04272 << (params->file_paths
273 ? params->file_paths->data_directory.path()
274 : base::FilePath())
Will Harris3d6f9e4c2021-09-17 19:11:16275 << ". Result: " << static_cast<int>(grant_access_result);
276 }
277
278 if (!IsSafeToUseDataPath(grant_access_result)) {
Kevin Marshall4bdfa5df2022-03-21 22:33:27279 // Unsafe to use new `data_directory`. This means that a migration was
280 // attempted, and `unsandboxed_data_path` contains the still-valid set of
281 // data. Swap the parameters to instruct the network service to use this
282 // path for the network context. This of course will mean that if the
283 // network service is running sandboxed then this data might not be
284 // accessible, but does provide a pathway to user recovery, as the sandbox
285 // can just be disabled in this case.
Will Harris3d6f9e4c2021-09-17 19:11:16286 DCHECK(params->file_paths->unsandboxed_data_path.has_value());
Kevin Marshall4bdfa5df2022-03-21 22:33:27287 params->file_paths->data_directory =
288 *params->file_paths->unsandboxed_data_path;
Will Harrisdac11fb2021-09-08 02:21:41289 }
Kevin Marshalleece67f2022-03-30 20:30:04290
291 if (network::TransferableDirectory::IsOpenForTransferRequired()) {
292 if (params->file_paths) {
293 params->file_paths->data_directory.OpenForTransfer();
294 }
295 if (params->http_cache_directory) {
296 params->http_cache_directory->OpenForTransfer();
297 }
Will Harrisb246f672021-10-28 06:47:13298 }
Kevin Marshalleece67f2022-03-30 20:30:04299
Will Harris78ccb552022-09-08 05:40:48300 // This might recreate g_client if the network service needed to be restarted.
301 auto* network_service = GetNetworkService();
302
303#if BUILDFLAG(USE_SOCKET_BROKER)
304 if (GetContentClient()->browser()->ShouldSandboxNetworkService() &&
305 !params->socket_broker) {
306 params->socket_broker = g_client->BindSocketBroker();
307 }
308#endif // BUILDFLAG(USE_SOCKET_BROKER)
309
310 network_service->CreateNetworkContext(std::move(context), std::move(params));
Will Harrisdac11fb2021-09-08 02:21:41311}
312
Alexander Timin7ab3ed82020-01-13 20:00:13313scoped_refptr<base::SequencedTaskRunner>& GetNetworkTaskRunnerStorage() {
314 static base::NoDestructor<scoped_refptr<base::SequencedTaskRunner>> storage;
315 return *storage;
316}
317
Felipe Andradea9174c62022-08-16 18:35:11318#if BUILDFLAG(IS_CHROMEOS_LACROS)
319base::FilePath GetKerberosDir() {
320 base::FilePath dir;
321 base::PathService::Get(base::DIR_HOME, &dir);
322 return dir.Append(kKrb5Directory);
323}
324
325std::string GetKrb5CCEnvValue() {
326 return kKrb5CCFilePrefix + GetKerberosDir().Append(kKrb5CCFile).value();
327}
328
329std::string GetKrb5ConfEnvValue() {
330 return GetKerberosDir().Append(kKrb5ConfFile).value();
331}
332#endif // BUILDFLAG(IS_CHROMEOS_LACROS)
333
Ken Rockot91216c0f2019-10-11 20:38:11334void CreateInProcessNetworkService(
335 mojo::PendingReceiver<network::mojom::NetworkService> receiver) {
Egor Pasko75389f12022-03-22 16:09:11336 TRACE_EVENT0("loading", "CreateInProcessNetworkService");
Ken Rockot91216c0f2019-10-11 20:38:11337 scoped_refptr<base::SingleThreadTaskRunner> task_runner;
John Abd-El-Maleka5fe84b2022-03-18 01:05:29338 if (base::FeatureList::IsEnabled(kNetworkServiceDedicatedThread)) {
Ken Rockot91216c0f2019-10-11 20:38:11339 base::Thread::Options options(base::MessagePumpType::IO, 0);
Olivier Li89911c42021-07-02 21:27:02340 GetNetworkServiceDedicatedThread().StartWithOptions(std::move(options));
Ken Rockot91216c0f2019-10-11 20:38:11341 task_runner = GetNetworkServiceDedicatedThread().task_runner();
342 } else {
Gabriel Charettee7cdc5cd2020-05-27 23:35:05343 task_runner = GetIOThreadTaskRunner({});
Ken Rockot91216c0f2019-10-11 20:38:11344 }
345
Alexander Timin7ab3ed82020-01-13 20:00:13346 GetNetworkTaskRunnerStorage() = std::move(task_runner);
347
348 GetNetworkTaskRunner()->PostTask(
349 FROM_HERE, base::BindOnce(&CreateInProcessNetworkServiceOnThread,
350 std::move(receiver)));
Ken Rockot91216c0f2019-10-11 20:38:11351}
352
John Abd-El-Malekd1e2a1c2019-02-28 20:01:03353network::mojom::NetworkServiceParamsPtr CreateNetworkServiceParams() {
354 network::mojom::NetworkServiceParamsPtr network_service_params =
355 network::mojom::NetworkServiceParams::New();
356 network_service_params->initial_connection_type =
357 network::mojom::ConnectionType(
358 net::NetworkChangeNotifier::GetConnectionType());
359 network_service_params->initial_connection_subtype =
360 network::mojom::ConnectionSubtype(
361 net::NetworkChangeNotifier::GetConnectionSubtype());
Dave Tapuska69f89252021-03-10 17:11:37362 network_service_params->default_observer =
363 g_client->BindURLLoaderNetworkServiceObserver();
Kirubel Aklilu60d316f2021-12-16 01:55:33364 network_service_params->first_party_sets_enabled =
365 GetContentClient()->browser()->IsFirstPartySetsEnabled();
366
Xiaohan Wang1ecfd002022-01-19 22:33:10367#if BUILDFLAG(IS_POSIX)
Robbie McElrathfa25a7c2019-03-13 17:54:36368 // Send Kerberos environment variables to the network service.
369 if (IsOutOfProcessNetworkService()) {
Felipe Andradea9174c62022-08-16 18:35:11370#if BUILDFLAG(IS_CHROMEOS_LACROS)
371 network_service_params->environment.push_back(
372 network::mojom::EnvironmentVariable::New(kKrb5CCEnvName,
373 GetKrb5CCEnvValue()));
374 network_service_params->environment.push_back(
375 network::mojom::EnvironmentVariable::New(kKrb5ConfEnvName,
376 GetKrb5ConfEnvValue()));
377#else
Robbie McElrathfa25a7c2019-03-13 17:54:36378 std::unique_ptr<base::Environment> env(base::Environment::Create());
379 std::string value;
380 if (env->HasVar(kKrb5CCEnvName)) {
381 env->GetVar(kKrb5CCEnvName, &value);
382 network_service_params->environment.push_back(
383 network::mojom::EnvironmentVariable::New(kKrb5CCEnvName, value));
384 }
385 if (env->HasVar(kKrb5ConfEnvName)) {
386 env->GetVar(kKrb5ConfEnvName, &value);
387 network_service_params->environment.push_back(
388 network::mojom::EnvironmentVariable::New(kKrb5ConfEnvName, value));
389 }
Felipe Andradea9174c62022-08-16 18:35:11390#endif // BUILDFLAG(IS_CHROMEOS_LACROS)
Robbie McElrathfa25a7c2019-03-13 17:54:36391 }
Felipe Andradea9174c62022-08-16 18:35:11392#endif // BUILDFLAG(IS_POSIX)
John Abd-El-Malekd1e2a1c2019-02-28 20:01:03393 return network_service_params;
394}
395
Robbie McElrath8dc3acc2019-08-15 20:43:04396void CreateNetworkServiceOnIOForTesting(
Julie Jeongeun Kima3471c62019-10-15 07:09:24397 mojo::PendingReceiver<network::mojom::NetworkService> receiver,
Robbie McElrath8dc3acc2019-08-15 20:43:04398 base::WaitableEvent* completion_event) {
John Abd-El-Malek984dc002019-05-29 01:26:59399 if (GetLocalNetworkService()) {
Julie Jeongeun Kima3471c62019-10-15 07:09:24400 GetLocalNetworkService()->Bind(std::move(receiver));
John Abd-El-Malekdeec0082017-12-20 20:47:47401 return;
402 }
403
Etienne Pierre-doray0df4474a2019-10-16 14:56:39404 GetLocalNetworkService() = std::make_unique<network::NetworkService>(
405 nullptr /* registry */, std::move(receiver),
406 true /* delay_initialization_until_set_client */);
407 GetLocalNetworkService()->Initialize(
408 network::mojom::NetworkServiceParams::New(),
409 true /* mock_network_change_notifier */);
Robbie McElrath8dc3acc2019-08-15 20:43:04410 if (completion_event)
411 completion_event->Signal();
John Abd-El-Malekdeec0082017-12-20 20:47:47412}
413
Gyuyoung Kim5f3bd4202019-09-27 01:59:49414void BindNetworkChangeManagerReceiver(
415 mojo::PendingReceiver<network::mojom::NetworkChangeManager> receiver) {
416 GetNetworkService()->GetNetworkChangeManager(std::move(receiver));
Robbie McElrathf572f5272018-08-17 21:21:42417}
418
Fabrice de Gans-Riberid82d1222021-03-22 22:23:11419base::RepeatingClosureList& GetCrashHandlersList() {
420 static base::NoDestructor<base::RepeatingClosureList> s_list;
Lukasz Anforowiczc195e912018-10-30 16:20:54421 return *s_list;
Lukasz Anforowiczce4487b72018-10-23 18:05:53422}
423
424void OnNetworkServiceCrash() {
425 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
Julie Jeongeun Kima3471c62019-10-15 07:09:24426 DCHECK(g_network_service_remote);
427 DCHECK(g_network_service_remote->is_bound());
428 DCHECK(!g_network_service_remote->is_connected());
Clark DuVallb026e582019-07-31 19:50:38429 g_last_network_service_crash = base::Time::Now();
Lukasz Anforowiczc195e912018-10-30 16:20:54430 GetCrashHandlersList().Notify();
Lukasz Anforowiczce4487b72018-10-23 18:05:53431}
432
Eric Romanc03b62622019-06-25 02:13:22433// Parses the desired granularity of NetLog capturing specified by the command
434// line.
435net::NetLogCaptureMode GetNetCaptureModeFromCommandLine(
436 const base::CommandLine& command_line) {
437 base::StringPiece switch_name = network::switches::kNetLogCaptureMode;
438
439 if (command_line.HasSwitch(switch_name)) {
440 std::string value = command_line.GetSwitchValueASCII(switch_name);
441
442 if (value == "Default")
Eric Roman3124cde2019-07-10 22:26:15443 return net::NetLogCaptureMode::kDefault;
444 if (value == "IncludeSensitive")
445 return net::NetLogCaptureMode::kIncludeSensitive;
446 if (value == "Everything")
447 return net::NetLogCaptureMode::kEverything;
448
449 // Warn when using the old command line switches.
450 if (value == "IncludeCookiesAndCredentials") {
451 LOG(ERROR) << "Deprecated value for --" << switch_name
452 << ". Use IncludeSensitive instead";
453 return net::NetLogCaptureMode::kIncludeSensitive;
454 }
455 if (value == "IncludeSocketBytes") {
456 LOG(ERROR) << "Deprecated value for --" << switch_name
457 << ". Use Everything instead";
458 return net::NetLogCaptureMode::kEverything;
459 }
Eric Romanc03b62622019-06-25 02:13:22460
461 LOG(ERROR) << "Unrecognized value for --" << switch_name;
462 }
463
Eric Roman3124cde2019-07-10 22:26:15464 return net::NetLogCaptureMode::kDefault;
Eric Romanc03b62622019-06-25 02:13:22465}
466
John Abd-El-Malekdeec0082017-12-20 20:47:47467} // namespace
468
Matt Menke04db81d2020-07-29 21:54:58469class NetworkServiceInstancePrivate {
470 public:
471 // Opens the specified file, blocking until the file is open. Used to open
472 // files specified by network::switches::kLogNetLog or
473 // network::switches::kSSLKeyLogFile. Since these arguments can be used to
474 // debug startup behavior, asynchronously opening the file on another thread
475 // would result in losing data, hence the need for blocking open operations.
476 // |file_flags| specifies the flags passed to the base::File constructor call.
477 //
478 // ThreadRestrictions needs to be able to friend the class/method to allow
479 // blocking, but can't friend CONTENT_EXPORT methods, so have it friend
480 // NetworkServiceInstancePrivate instead of GetNetworkService().
481 static base::File BlockingOpenFile(const base::FilePath& path,
482 int file_flags) {
483 base::ScopedAllowBlocking allow_blocking;
484 return base::File(path, file_flags);
485 }
486};
487
John Abd-El-Malek53670dd2018-01-18 22:07:21488network::mojom::NetworkService* GetNetworkService() {
Julie Jeongeun Kima3471c62019-10-15 07:09:24489 if (!g_network_service_remote)
490 g_network_service_remote = new mojo::Remote<network::mojom::NetworkService>;
Julie Jeongeun Kima3471c62019-10-15 07:09:24491 if (!g_network_service_remote->is_bound() ||
492 !g_network_service_remote->is_connected()) {
Matt Menke080a9172020-01-31 10:44:08493 bool service_was_bound = g_network_service_remote->is_bound();
Julie Jeongeun Kima3471c62019-10-15 07:09:24494 g_network_service_remote->reset();
John Abd-El-Malek1ae9dbb2019-03-04 23:40:47495 if (GetContentClient()->browser()->IsShuttingDown()) {
496 // This happens at system shutdown, since in other scenarios the network
497 // process would only be torn down once the message loop stopped running.
Oleh Lamzin0e228572019-12-06 16:46:09498 // We don't want to start the network service again so just create message
499 // pipe that's not bound to stop consumers from requesting creation of the
500 // service.
Julie Jeongeun Kima3471c62019-10-15 07:09:24501 auto receiver = g_network_service_remote->BindNewPipeAndPassReceiver();
502 auto leaked_pipe = receiver.PassPipe().release();
John Abd-El-Malekdeec0082017-12-20 20:47:47503 } else {
Ken Rockot91216c0f2019-10-11 20:38:11504 if (!g_force_create_network_service_directly) {
505 mojo::PendingReceiver<network::mojom::NetworkService> receiver =
Julie Jeongeun Kima3471c62019-10-15 07:09:24506 g_network_service_remote->BindNewPipeAndPassReceiver();
507 g_network_service_remote->set_disconnect_handler(
John Abd-El-Malek1ae9dbb2019-03-04 23:40:47508 base::BindOnce(&OnNetworkServiceCrash));
Ken Rockot91216c0f2019-10-11 20:38:11509 if (IsInProcessNetworkService()) {
510 CreateInProcessNetworkService(std::move(receiver));
511 } else {
Matt Menke080a9172020-01-31 10:44:08512 if (service_was_bound)
513 LOG(ERROR) << "Network service crashed, restarting service.";
Jan Wilken Dörrie2c470ea2021-03-22 22:26:24514 ServiceProcessHost::Launch(std::move(receiver),
515 ServiceProcessHost::Options()
516 .WithDisplayName(u"Network Service")
517 .Pass());
Ken Rockot91216c0f2019-10-11 20:38:11518 }
John Abd-El-Malek1ae9dbb2019-03-04 23:40:47519 } else {
Robbie McElrath8dc3acc2019-08-15 20:43:04520 // This should only be reached in unit tests.
521 if (BrowserThread::CurrentlyOn(BrowserThread::IO)) {
522 CreateNetworkServiceOnIOForTesting(
Julie Jeongeun Kima3471c62019-10-15 07:09:24523 g_network_service_remote->BindNewPipeAndPassReceiver(),
Robbie McElrath8dc3acc2019-08-15 20:43:04524 /*completion_event=*/nullptr);
525 } else {
526 base::WaitableEvent event;
Gabriel Charettee7cdc5cd2020-05-27 23:35:05527 GetIOThreadTaskRunner({})->PostTask(
528 FROM_HERE,
Julie Jeongeun Kima3471c62019-10-15 07:09:24529 base::BindOnce(
530 CreateNetworkServiceOnIOForTesting,
531 g_network_service_remote->BindNewPipeAndPassReceiver(),
532 base::Unretained(&event)));
Robbie McElrath8dc3acc2019-08-15 20:43:04533 event.Wait();
534 }
John Abd-El-Malek1ae9dbb2019-03-04 23:40:47535 }
John Abd-El-Malekdeec0082017-12-20 20:47:47536
Dave Tapuska69f89252021-03-10 17:11:37537 delete g_client; // In case we're recreating the network service.
538 g_client = new NetworkServiceClient();
539
John Abd-El-Malek1ae9dbb2019-03-04 23:40:47540 // Call SetClient before creating NetworkServiceClient, as the latter
541 // might make requests to NetworkService that depend on initialization.
Dave Tapuska69f89252021-03-10 17:11:37542 (*g_network_service_remote)->SetParams(CreateNetworkServiceParams());
Yutaka Hirano136bd912022-01-31 16:26:11543 g_client->OnNetworkServiceInitialized(g_network_service_remote->get());
544
Clark DuVallb026e582019-07-31 19:50:38545 g_network_service_is_responding = false;
Jan Wilken Dörrie8c74db022020-04-20 09:05:00546 g_network_service_remote->QueryVersion(base::BindOnce(
Clark DuVall984239a2019-08-08 23:38:33547 [](base::Time start_time, uint32_t) {
548 g_network_service_is_responding = true;
549 base::TimeDelta delta = base::Time::Now() - start_time;
550 UMA_HISTOGRAM_MEDIUM_TIMES("NetworkService.TimeToFirstResponse",
551 delta);
552 if (g_last_network_service_crash.is_null()) {
553 UMA_HISTOGRAM_MEDIUM_TIMES(
554 "NetworkService.TimeToFirstResponse.OnStartup", delta);
555 } else {
556 UMA_HISTOGRAM_MEDIUM_TIMES(
557 "NetworkService.TimeToFirstResponse.AfterCrash", delta);
558 }
559 },
560 base::Time::Now()));
John Abd-El-Malekd1e2a1c2019-02-28 20:01:03561
Robbie McElrath35ef9672019-02-13 22:01:59562 const base::CommandLine* command_line =
563 base::CommandLine::ForCurrentProcess();
John Abd-El-Malekc134dd82019-07-31 20:51:44564 if (command_line->HasSwitch(network::switches::kLogNetLog)) {
565 base::FilePath log_path =
566 command_line->GetSwitchValuePath(network::switches::kLogNetLog);
Cheng Yu6e46b4d2021-09-02 06:43:08567 if (log_path.empty()) {
568 log_path = GetContentClient()->browser()->GetNetLogDefaultDirectory();
569 if (!log_path.empty())
570 log_path = log_path.Append(FILE_PATH_LITERAL("netlog.json"));
571 }
Doug Turner08512342018-09-24 20:54:19572
Matt Menke04db81d2020-07-29 21:54:58573 base::File file = NetworkServiceInstancePrivate::BlockingOpenFile(
John Abd-El-Malekc134dd82019-07-31 20:51:44574 log_path, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
575 if (!file.IsValid()) {
576 LOG(ERROR) << "Failed opening NetLog: " << log_path.value();
577 } else {
Julie Jeongeun Kima3471c62019-10-15 07:09:24578 (*g_network_service_remote)
Matt Menke04db81d2020-07-29 21:54:58579 ->StartNetLog(
580 std::move(file),
581 GetNetCaptureModeFromCommandLine(*command_line),
582 GetContentClient()->browser()->GetNetLogConstants());
Robbie McElrath35ef9672019-02-13 22:01:59583 }
Robbie McElrathd063ed02019-02-13 21:59:30584 }
Robbie McElrathd063ed02019-02-13 21:59:30585
David Benjamin887153852019-08-07 23:19:55586 base::FilePath ssl_key_log_path;
Robbie McElrath35ef9672019-02-13 22:01:59587 if (command_line->HasSwitch(network::switches::kSSLKeyLogFile)) {
Christopher Thompson2a4c69e92019-08-21 16:29:11588 UMA_HISTOGRAM_ENUMERATION(kSSLKeyLogFileHistogram,
589 SSLKeyLogFileAction::kSwitchFound);
David Benjamin887153852019-08-07 23:19:55590 ssl_key_log_path =
Robbie McElrath35ef9672019-02-13 22:01:59591 command_line->GetSwitchValuePath(network::switches::kSSLKeyLogFile);
David Benjamin887153852019-08-07 23:19:55592 LOG_IF(WARNING, ssl_key_log_path.empty())
Robbie McElrath35ef9672019-02-13 22:01:59593 << "ssl-key-log-file argument missing";
David Benjamin887153852019-08-07 23:19:55594 } else {
595 std::unique_ptr<base::Environment> env(base::Environment::Create());
596 std::string env_str;
597 if (env->GetVar("SSLKEYLOGFILE", &env_str)) {
Christopher Thompson2a4c69e92019-08-21 16:29:11598 UMA_HISTOGRAM_ENUMERATION(kSSLKeyLogFileHistogram,
599 SSLKeyLogFileAction::kEnvVarFound);
Xiaohan Wang1ecfd002022-01-19 22:33:10600#if BUILDFLAG(IS_WIN)
David Benjamin887153852019-08-07 23:19:55601 // base::Environment returns environment variables in UTF-8 on
602 // Windows.
Peter Kasting57fd6de42021-01-28 23:05:39603 ssl_key_log_path = base::FilePath(base::UTF8ToWide(env_str));
David Benjamin887153852019-08-07 23:19:55604#else
605 ssl_key_log_path = base::FilePath(env_str);
606#endif
607 }
Robbie McElrath35ef9672019-02-13 22:01:59608 }
Robbie McElrathd063ed02019-02-13 21:59:30609
David Benjamin887153852019-08-07 23:19:55610 if (!ssl_key_log_path.empty()) {
Matt Menke04db81d2020-07-29 21:54:58611 base::File file = NetworkServiceInstancePrivate::BlockingOpenFile(
612 ssl_key_log_path,
613 base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_APPEND);
David Benjamin887153852019-08-07 23:19:55614 if (!file.IsValid()) {
615 LOG(ERROR) << "Failed opening SSL key log file: "
616 << ssl_key_log_path.value();
617 } else {
Christopher Thompson2a4c69e92019-08-21 16:29:11618 UMA_HISTOGRAM_ENUMERATION(kSSLKeyLogFileHistogram,
619 SSLKeyLogFileAction::kLogFileEnabled);
Julie Jeongeun Kima3471c62019-10-15 07:09:24620 (*g_network_service_remote)->SetSSLKeyLogFile(std::move(file));
David Benjamin887153852019-08-07 23:19:55621 }
Robbie McElrath35ef9672019-02-13 22:01:59622 }
Doug Turner08512342018-09-24 20:54:19623
Chris Fredricksona2092c9b2022-05-09 21:54:12624 if (FirstPartySetsHandlerImpl::GetInstance()->IsEnabled()) {
Chris Fredrickson878d06b2022-09-08 15:20:37625 if (absl::optional<net::PublicSets> sets =
Chris Fredricksona2092c9b2022-05-09 21:54:12626 FirstPartySetsHandlerImpl::GetInstance()->GetSets(
Chris Fredrickson878d06b2022-09-08 15:20:37627 base::BindOnce([](net::PublicSets sets) {
628 GetNetworkService()->SetFirstPartySets(std::move(sets));
629 }));
Chris Fredricksona2092c9b2022-05-09 21:54:12630 sets.has_value()) {
631 g_network_service_remote->get()->SetFirstPartySets(
632 std::move(sets.value()));
633 }
cfredric763290422022-03-31 23:00:33634 }
Shuran Huang103981502022-03-28 21:52:18635
Robbie McElrath35ef9672019-02-13 22:01:59636 GetContentClient()->browser()->OnNetworkServiceCreated(
Julie Jeongeun Kima3471c62019-10-15 07:09:24637 g_network_service_remote->get());
John Abd-El-Malek1ae9dbb2019-03-04 23:40:47638 }
John Abd-El-Malekdeec0082017-12-20 20:47:47639 }
Julie Jeongeun Kima3471c62019-10-15 07:09:24640 return g_network_service_remote->get();
John Abd-El-Malekdeec0082017-12-20 20:47:47641}
642
Peter Kasting7ba9440c2020-11-22 01:49:02643base::CallbackListSubscription RegisterNetworkServiceCrashHandler(
644 base::RepeatingClosure handler) {
Lukasz Anforowiczce4487b72018-10-23 18:05:53645 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
646 DCHECK(!handler.is_null());
647
John Abd-El-Malekc134dd82019-07-31 20:51:44648 return GetCrashHandlersList().Add(std::move(handler));
John Abd-El-Malekdeec0082017-12-20 20:47:47649}
650
Eriko Kurimoto64656462022-07-21 01:07:49651#if BUILDFLAG(IS_CHROMEOS)
Robbie McElrath995a2bf2018-11-19 23:21:59652net::NetworkChangeNotifier* GetNetworkChangeNotifier() {
653 return BrowserMainLoop::GetInstance()->network_change_notifier();
654}
John Abd-El-Malek03438952019-05-16 22:53:51655#endif
Robbie McElrath995a2bf2018-11-19 23:21:59656
John Abd-El-Malekdeec0082017-12-20 20:47:47657void FlushNetworkServiceInstanceForTesting() {
658 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
John Abd-El-Malekdeec0082017-12-20 20:47:47659
Julie Jeongeun Kima3471c62019-10-15 07:09:24660 if (g_network_service_remote)
661 g_network_service_remote->FlushForTesting();
John Abd-El-Malekdeec0082017-12-20 20:47:47662}
663
Robbie McElrathf961dc52018-08-08 21:29:26664network::NetworkConnectionTracker* GetNetworkConnectionTracker() {
Andrew Paseltiner82a1f89f2022-02-28 21:59:36665 DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
666 BrowserThread::CurrentlyOn(BrowserThread::UI));
Robbie McElrathf961dc52018-08-08 21:29:26667 if (!g_network_connection_tracker) {
668 g_network_connection_tracker = new network::NetworkConnectionTracker(
Gyuyoung Kim5f3bd4202019-09-27 01:59:49669 base::BindRepeating(&BindNetworkChangeManagerReceiver));
Robbie McElrathf961dc52018-08-08 21:29:26670 }
671 return g_network_connection_tracker;
672}
673
Robbie McElrathf633990e2018-10-02 21:44:48674void GetNetworkConnectionTrackerFromUIThread(
675 base::OnceCallback<void(network::NetworkConnectionTracker*)> callback) {
Gabriel Charettee7cdc5cd2020-05-27 23:35:05676 GetUIThreadTaskRunner({base::TaskPriority::BEST_EFFORT})
677 ->PostTaskAndReplyWithResult(FROM_HERE,
678 base::BindOnce(&GetNetworkConnectionTracker),
679 std::move(callback));
Robbie McElrathf633990e2018-10-02 21:44:48680}
681
Jun Cai597752e42018-11-15 19:54:25682network::NetworkConnectionTrackerAsyncGetter
683CreateNetworkConnectionTrackerAsyncGetter() {
684 return base::BindRepeating(&content::GetNetworkConnectionTrackerFromUIThread);
685}
686
Robbie McElrathf961dc52018-08-08 21:29:26687void SetNetworkConnectionTrackerForTesting(
688 network::NetworkConnectionTracker* network_connection_tracker) {
Andrew Paseltiner82a1f89f2022-02-28 21:59:36689 DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
690 BrowserThread::CurrentlyOn(BrowserThread::UI));
Robbie McElrathdb12d8e2018-09-18 21:20:40691 if (g_network_connection_tracker != network_connection_tracker) {
692 DCHECK(!g_network_connection_tracker || !network_connection_tracker);
693 g_network_connection_tracker = network_connection_tracker;
694 }
Robbie McElrathf961dc52018-08-08 21:29:26695}
696
Alexander Timin7ab3ed82020-01-13 20:00:13697const scoped_refptr<base::SequencedTaskRunner>& GetNetworkTaskRunner() {
Clark DuVallb9924e92018-12-10 23:36:33698 DCHECK(IsInProcessNetworkService());
Alexander Timin7ab3ed82020-01-13 20:00:13699 return GetNetworkTaskRunnerStorage();
Clark DuVallb9924e92018-12-10 23:36:33700}
701
John Abd-El-Malek984dc002019-05-29 01:26:59702void ForceCreateNetworkServiceDirectlyForTesting() {
703 g_force_create_network_service_directly = true;
704}
705
706void ResetNetworkServiceForTesting() {
Ken Rockot91216c0f2019-10-11 20:38:11707 ShutDownNetworkService();
708}
709
710void ShutDownNetworkService() {
Julie Jeongeun Kima3471c62019-10-15 07:09:24711 delete g_network_service_remote;
712 g_network_service_remote = nullptr;
Sebastien Marchand0d68f75a2020-07-20 15:39:27713 delete g_client;
714 g_client = nullptr;
Ken Rockot7ff141d2019-11-01 21:09:44715 if (g_in_process_instance) {
716 GetNetworkTaskRunner()->DeleteSoon(FROM_HERE, g_in_process_instance);
717 g_in_process_instance = nullptr;
718 }
Ken Rockot91216c0f2019-10-11 20:38:11719 GetNetworkTaskRunnerStorage().reset();
John Abd-El-Malek984dc002019-05-29 01:26:59720}
721
Clark DuVallb026e582019-07-31 19:50:38722NetworkServiceAvailability GetNetworkServiceAvailability() {
Julie Jeongeun Kima3471c62019-10-15 07:09:24723 if (!g_network_service_remote)
Clark DuVallb026e582019-07-31 19:50:38724 return NetworkServiceAvailability::NOT_CREATED;
Julie Jeongeun Kima3471c62019-10-15 07:09:24725 else if (!g_network_service_remote->is_bound())
Clark DuVallb026e582019-07-31 19:50:38726 return NetworkServiceAvailability::NOT_BOUND;
Julie Jeongeun Kima3471c62019-10-15 07:09:24727 else if (!g_network_service_remote->is_connected())
Clark DuVallb026e582019-07-31 19:50:38728 return NetworkServiceAvailability::ENCOUNTERED_ERROR;
729 else if (!g_network_service_is_responding)
730 return NetworkServiceAvailability::NOT_RESPONDING;
731 else
732 return NetworkServiceAvailability::AVAILABLE;
733}
734
735base::TimeDelta GetTimeSinceLastNetworkServiceCrash() {
736 if (g_last_network_service_crash.is_null())
737 return base::TimeDelta();
738 return base::Time::Now() - g_last_network_service_crash;
739}
740
Clark DuVall1f94e9f42019-08-21 04:09:36741void PingNetworkService(base::OnceClosure closure) {
742 GetNetworkService();
743 // Unfortunately, QueryVersion requires a RepeatingCallback.
Jan Wilken Dörrie8c74db022020-04-20 09:05:00744 g_network_service_remote->QueryVersion(base::BindOnce(
Clark DuVall1f94e9f42019-08-21 04:09:36745 [](base::OnceClosure closure, uint32_t) {
746 if (closure)
747 std::move(closure).Run();
748 },
Daniel Cheng28a5ac482021-02-22 21:03:08749 std::move(closure)));
Clark DuVall1f94e9f42019-08-21 04:09:36750}
751
Matthew Denton03c45a22020-06-01 23:40:48752namespace {
753
Matthew Denton1d7839c2020-11-27 04:59:23754cert_verifier::mojom::CertVerifierServiceFactory*
755 g_cert_verifier_service_factory_for_testing = nullptr;
756
Matthew Denton03c45a22020-06-01 23:40:48757mojo::PendingRemote<cert_verifier::mojom::CertVerifierService>
758GetNewCertVerifierServiceRemote(
759 cert_verifier::mojom::CertVerifierServiceFactory*
760 cert_verifier_service_factory,
Matthew Denton6f6ca6ac2021-02-18 09:00:35761 cert_verifier::mojom::CertVerifierCreationParamsPtr creation_params) {
Matthew Denton03c45a22020-06-01 23:40:48762 mojo::PendingRemote<cert_verifier::mojom::CertVerifierService>
763 cert_verifier_remote;
764 cert_verifier_service_factory->GetNewCertVerifier(
765 cert_verifier_remote.InitWithNewPipeAndPassReceiver(),
766 std::move(creation_params));
767 return cert_verifier_remote;
768}
769
Matthew Denton1d7839c2020-11-27 04:59:23770void RunInProcessCertVerifierServiceFactory(
Matthew Dentonb6730bf2020-06-25 04:54:11771 mojo::PendingReceiver<cert_verifier::mojom::CertVerifierServiceFactory>
772 receiver) {
Michael Ershovcbdb8202022-02-21 19:17:01773#if BUILDFLAG(IS_CHROMEOS)
774 // See the comment in GetCertVerifierServiceFactory() for the thread-affinity
775 // of the CertVerifierService.
Matthew Denton1d7839c2020-11-27 04:59:23776 DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::IO) ||
777 BrowserThread::CurrentlyOn(BrowserThread::IO));
778#else
779 DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
780 BrowserThread::CurrentlyOn(BrowserThread::UI));
781#endif
Avi Drissmanded77172021-07-02 18:23:00782 static base::SequenceLocalStorageSlot<
783 std::unique_ptr<cert_verifier::CertVerifierServiceFactoryImpl>>
Matthew Denton1d7839c2020-11-27 04:59:23784 service_factory_slot;
Avi Drissmanded77172021-07-02 18:23:00785 service_factory_slot.GetOrCreateValue() =
Matthew Denton1d7839c2020-11-27 04:59:23786 std::make_unique<cert_verifier::CertVerifierServiceFactoryImpl>(
787 std::move(receiver));
Matthew Dentonb6730bf2020-06-25 04:54:11788}
789
Matthew Denton03c45a22020-06-01 23:40:48790// Owns the CertVerifierServiceFactory used by the browser.
791// Lives on the UI thread.
Matthew Denton1d7839c2020-11-27 04:59:23792mojo::Remote<cert_verifier::mojom::CertVerifierServiceFactory>&
793GetCertVerifierServiceFactoryRemoteStorage() {
Avi Drissmanded77172021-07-02 18:23:00794 static base::SequenceLocalStorageSlot<
795 mojo::Remote<cert_verifier::mojom::CertVerifierServiceFactory>>
Matthew Denton1d7839c2020-11-27 04:59:23796 cert_verifier_service_factory_remote;
Avi Drissmanded77172021-07-02 18:23:00797 return cert_verifier_service_factory_remote.GetOrCreateValue();
Matthew Denton1d7839c2020-11-27 04:59:23798}
Matthew Denton03c45a22020-06-01 23:40:48799
Hubert Chao2a000d72022-04-25 19:43:30800} // namespace
801
Matthew Denton1d7839c2020-11-27 04:59:23802// Returns a pointer to a CertVerifierServiceFactory usable on the UI thread.
803cert_verifier::mojom::CertVerifierServiceFactory*
804GetCertVerifierServiceFactory() {
Hubert Chao2a000d72022-04-25 19:43:30805 DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
806 BrowserThread::CurrentlyOn(BrowserThread::UI));
Matthew Denton1d7839c2020-11-27 04:59:23807 if (g_cert_verifier_service_factory_for_testing)
808 return g_cert_verifier_service_factory_for_testing;
Yuki Yamada709edde2020-11-24 05:47:21809
Matthew Denton1d7839c2020-11-27 04:59:23810 mojo::Remote<cert_verifier::mojom::CertVerifierServiceFactory>&
811 factory_remote_storage = GetCertVerifierServiceFactoryRemoteStorage();
812 if (!factory_remote_storage.is_bound() ||
813 !factory_remote_storage.is_connected()) {
814 factory_remote_storage.reset();
Michael Ershovcbdb8202022-02-21 19:17:01815#if BUILDFLAG(IS_CHROMEOS)
816 // In-process CertVerifierService in Ash and Lacros should run on the IO
817 // thread because it interacts with IO-bound NSS and ChromeOS user slots.
818 // See for example InitializeNSSForChromeOSUser() or
819 // CertDbInitializerIOImpl.
Matthew Denton1d7839c2020-11-27 04:59:23820 GetIOThreadTaskRunner({})->PostTask(
821 FROM_HERE,
822 base::BindOnce(&RunInProcessCertVerifierServiceFactory,
823 factory_remote_storage.BindNewPipeAndPassReceiver()));
Yuki Yamada709edde2020-11-24 05:47:21824#else
Matthew Denton1d7839c2020-11-27 04:59:23825 RunInProcessCertVerifierServiceFactory(
826 factory_remote_storage.BindNewPipeAndPassReceiver());
Yuki Yamada709edde2020-11-24 05:47:21827#endif
Yuki Yamada709edde2020-11-24 05:47:21828 }
Matthew Denton1d7839c2020-11-27 04:59:23829 return factory_remote_storage.get();
830}
Matthew Denton03c45a22020-06-01 23:40:48831
Matthew Denton82c211f2021-02-06 01:58:54832network::mojom::CertVerifierServiceRemoteParamsPtr GetCertVerifierParams(
Matthew Denton6f6ca6ac2021-02-18 09:00:35833 cert_verifier::mojom::CertVerifierCreationParamsPtr
Matthew Denton03c45a22020-06-01 23:40:48834 cert_verifier_creation_params) {
Matthew Denton82c211f2021-02-06 01:58:54835 return network::mojom::CertVerifierServiceRemoteParams::New(
836 GetNewCertVerifierServiceRemote(
837 GetCertVerifierServiceFactory(),
838 std::move(cert_verifier_creation_params)));
Matthew Denton03c45a22020-06-01 23:40:48839}
840
841void SetCertVerifierServiceFactoryForTesting(
842 cert_verifier::mojom::CertVerifierServiceFactory* service_factory) {
Matthew Denton1d7839c2020-11-27 04:59:23843 g_cert_verifier_service_factory_for_testing = service_factory;
Matthew Denton03c45a22020-06-01 23:40:48844}
845
Kevin Marshalleece67f2022-03-30 20:30:04846void MaybeCleanCacheDirectory(network::mojom::NetworkContextParams* params) {
847 if (params->http_cache_enabled && params->http_cache_directory) {
848 // Delete any old data except for the "Cache_Data" directory.
849 base::ThreadPool::PostTask(
850 FROM_HERE,
851 {base::TaskPriority::BEST_EFFORT, base::MayBlock(),
852 base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
853 base::BindOnce(MaybeDeleteOldCache,
854 params->http_cache_directory->path()));
855
856 params->http_cache_directory =
857 params->http_cache_directory->path().Append(kCacheDataDirectoryName);
858 }
859}
860
Will Harrisa6a750b2021-07-14 03:12:02861void CreateNetworkContextInNetworkService(
862 mojo::PendingReceiver<network::mojom::NetworkContext> context,
863 network::mojom::NetworkContextParamsPtr params) {
Egor Pasko75389f12022-03-22 16:09:11864 TRACE_EVENT0("loading", "CreateNetworkContextInNetworkService");
Will Harrisdac11fb2021-09-08 02:21:41865 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
Kevin Marshalleece67f2022-03-30 20:30:04866
867 MaybeCleanCacheDirectory(params.get());
868
Yutaka Hirano92bdfa22022-06-01 15:51:33869 const bool has_valid_http_cache_path =
870 params->http_cache_enabled && params->http_cache_directory &&
871 !params->http_cache_directory->path().empty();
872 const bool brokering_is_enabled =
873 IsOutOfProcessNetworkService() &&
874 base::FeatureList::IsEnabled(
875 features::kBrokerFileOperationsOnDiskCacheInNetworkService);
876 if (has_valid_http_cache_path && brokering_is_enabled) {
Yutaka Hiranode9868f2022-04-27 02:48:44877 mojo::MakeSelfOwnedReceiver(
878 std::make_unique<HttpCacheBackendFileOperationsFactory>(
879 params->http_cache_directory->path()),
880 params->http_cache_file_operations_factory
881 .InitWithNewPipeAndPassReceiver());
882 }
883
Will Harris7bcc5282022-07-29 00:51:03884#if BUILDFLAG(IS_ANDROID)
Will Harrisb57cfc562022-05-27 19:51:51885 // On Android, if a cookie_manager pending receiver was passed then migration
886 // should not be attempted as the cookie file is already being accessed by the
887 // browser instance.
888 if (params->cookie_manager) {
889 if (params->file_paths) {
890 // No migration should ever be attempted under this configuration.
891 DCHECK(!params->file_paths->unsandboxed_data_path);
892 }
893 CreateNetworkContextInternal(
894 std::move(context), std::move(params),
895 SandboxGrantResult::kDidNotAttemptToGrantSandboxAccess);
896 return;
897 }
898
899 // Note: This logic is duplicated from MaybeGrantAccessToDataPath to this fast
900 // path. This should be kept in sync if there are any changes to the logic.
901 SandboxGrantResult grant_result = SandboxGrantResult::kNoMigrationRequested;
902 if (!params->file_paths) {
903 // No file paths (e.g. in-memory context) so nothing to do.
904 grant_result = SandboxGrantResult::kDidNotAttemptToGrantSandboxAccess;
905 } else {
906 // If no `unsandboxed_data_path` is supplied, it means this is network
907 // context has been created by Android Webview, which does not understand
908 // the concept of `unsandboxed_data_path`. In this case, `data_directory`
909 // should always be used, if present.
910 if (!params->file_paths->unsandboxed_data_path)
911 grant_result = SandboxGrantResult::kDidNotAttemptToGrantSandboxAccess;
912 }
Egor Pasko75389f12022-03-22 16:09:11913 // Create network context immediately without thread hops.
Will Harrisb57cfc562022-05-27 19:51:51914 CreateNetworkContextInternal(std::move(context), std::move(params),
915 grant_result);
Egor Pasko75389f12022-03-22 16:09:11916#else
917 // Restrict disk access to a certain path (on another thread) and continue
918 // with network context creation.
919 GrantSandboxAccessOnThreadPool(
920 std::move(params),
921 base::BindOnce(&CreateNetworkContextInternal, std::move(context)));
Xiaohan Wang1ecfd002022-01-19 22:33:10922#endif // BUILDFLAG(IS_ANDROID)
Will Harrisa6a750b2021-07-14 03:12:02923}
924
Will Harrisf26ad342022-09-06 02:03:28925#if BUILDFLAG(IS_WIN)
926
927void SetNetworkServiceTrackerToCurrentProcessForTesting() {
928 internal::SetNetworkServiceTrackerToCurrentProcessForTesting();
929}
930
931#endif // BUILDFLAG(IS_WIN)
932
John Abd-El-Malekdeec0082017-12-20 20:47:47933} // namespace content