1 // 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
5 #include "content/browser/network_service_instance_impl.h"
6
7 #include <map>
8 #include <memory>
9 #include <string>
10 #include <utility>
11
12 #include "base/bind.h"
13 #include "base/environment.h"
14 #include "base/feature_list.h"
15 #include "base/files/file.h"
16 #include "base/message_loop/message_pump_type.h"
17 #include "base/metrics/histogram_macros.h"
18 #include "base/no_destructor.h"
19 #include "base/sequenced_task_runner.h"
20 #include "base/strings/string_util.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "base/synchronization/waitable_event.h"
23 #include "base/threading/sequence_local_storage_slot.h"
24 #include "base/threading/thread.h"
25 #include "base/threading/thread_restrictions.h"
26 #include "build/build_config.h"
27 #include "content/browser/browser_main_loop.h"
28 #include "content/browser/network_service_client.h"
29 #include "content/browser/service_sandbox_type.h"
30 #include "content/public/browser/browser_task_traits.h"
31 #include "content/public/browser/browser_thread.h"
32 #include "content/public/browser/content_browser_client.h"
33 #include "content/public/browser/network_service_instance.h"
34 #include "content/public/browser/service_process_host.h"
35 #include "content/public/browser/system_connector.h"
36 #include "content/public/common/content_client.h"
37 #include "content/public/common/network_service_util.h"
38 #include "content/public/common/service_names.mojom.h"
39 #include "mojo/public/cpp/bindings/pending_receiver.h"
40 #include "mojo/public/cpp/bindings/remote.h"
41 #include "net/log/net_log_util.h"
42 #include "services/cert_verifier/cert_verifier_service_factory.h"
43 #include "services/network/network_service.h"
44 #include "services/network/public/cpp/features.h"
45 #include "services/network/public/cpp/network_switches.h"
46 #include "services/network/public/mojom/net_log.mojom.h"
47 #include "services/network/public/mojom/network_change_manager.mojom.h"
48 #include "services/network/public/mojom/network_service.mojom.h"
49 #include "services/network/public/mojom/network_service_test.mojom.h"
50
51 namespace content {
52
53 namespace {
54
55 #if defined(OS_POSIX)
56 // Environment variable pointing to credential cache file.
57 constexpr char kKrb5CCEnvName[] = "KRB5CCNAME";
58 // Environment variable pointing to Kerberos config file.
59 constexpr char kKrb5ConfEnvName[] = "KRB5_CONFIG";
60 #endif
61
62 bool g_force_create_network_service_directly = false;
63 mojo::Remote<network::mojom::NetworkService>* g_network_service_remote =
64 nullptr;
65 network::NetworkConnectionTracker* g_network_connection_tracker;
66 bool g_network_service_is_responding = false;
67 base::Time g_last_network_service_crash;
68
GetLocalNetworkService()69 std::unique_ptr<network::NetworkService>& GetLocalNetworkService() {
70 static base::NoDestructor<
71 base::SequenceLocalStorageSlot<std::unique_ptr<network::NetworkService>>>
72 service;
73 return service->GetOrCreateValue();
74 }
75
76 // If this feature is enabled, the Network Service will run on its own thread
77 // when running in-process; otherwise it will run on the IO thread.
78 //
79 // On Chrome OS, the Network Service must run on the IO thread because
80 // ProfileIOData and NetworkContext both try to set up NSS, which has to be
81 // called from the IO thread.
82 const base::Feature kNetworkServiceDedicatedThread {
83 "NetworkServiceDedicatedThread",
84 #if defined(OS_CHROMEOS)
85 base::FEATURE_DISABLED_BY_DEFAULT
86 #else
87 base::FEATURE_ENABLED_BY_DEFAULT
88 #endif
89 };
90
GetNetworkServiceDedicatedThread()91 base::Thread& GetNetworkServiceDedicatedThread() {
92 static base::NoDestructor<base::Thread> thread{"NetworkService"};
93 DCHECK(base::FeatureList::IsEnabled(kNetworkServiceDedicatedThread));
94 return *thread;
95 }
96
97 // The instance NetworkService used when hosting the service in-process. This is
98 // set up by |CreateInProcessNetworkServiceOnThread()| and destroyed by
99 // |ShutDownNetworkService()|.
100 network::NetworkService* g_in_process_instance = nullptr;
101
CreateInProcessNetworkServiceOnThread(mojo::PendingReceiver<network::mojom::NetworkService> receiver)102 void CreateInProcessNetworkServiceOnThread(
103 mojo::PendingReceiver<network::mojom::NetworkService> receiver) {
104 // The test interface doesn't need to be implemented in the in-process case.
105 auto registry = std::make_unique<service_manager::BinderRegistry>();
106 registry->AddInterface(base::BindRepeating(
107 [](mojo::PendingReceiver<network::mojom::NetworkServiceTest>) {}));
108 g_in_process_instance = new network::NetworkService(
109 std::move(registry), std::move(receiver),
110 true /* delay_initialization_until_set_client */);
111 }
112
GetNetworkTaskRunnerStorage()113 scoped_refptr<base::SequencedTaskRunner>& GetNetworkTaskRunnerStorage() {
114 static base::NoDestructor<scoped_refptr<base::SequencedTaskRunner>> storage;
115 return *storage;
116 }
117
CreateInProcessNetworkService(mojo::PendingReceiver<network::mojom::NetworkService> receiver)118 void CreateInProcessNetworkService(
119 mojo::PendingReceiver<network::mojom::NetworkService> receiver) {
120 scoped_refptr<base::SingleThreadTaskRunner> task_runner;
121 if (base::FeatureList::IsEnabled(kNetworkServiceDedicatedThread)) {
122 base::Thread::Options options(base::MessagePumpType::IO, 0);
123 GetNetworkServiceDedicatedThread().StartWithOptions(options);
124 task_runner = GetNetworkServiceDedicatedThread().task_runner();
125 } else {
126 task_runner = GetIOThreadTaskRunner({});
127 }
128
129 GetNetworkTaskRunnerStorage() = std::move(task_runner);
130
131 GetNetworkTaskRunner()->PostTask(
132 FROM_HERE, base::BindOnce(&CreateInProcessNetworkServiceOnThread,
133 std::move(receiver)));
134 }
135
CreateNetworkServiceParams()136 network::mojom::NetworkServiceParamsPtr CreateNetworkServiceParams() {
137 network::mojom::NetworkServiceParamsPtr network_service_params =
138 network::mojom::NetworkServiceParams::New();
139 network_service_params->initial_connection_type =
140 network::mojom::ConnectionType(
141 net::NetworkChangeNotifier::GetConnectionType());
142 network_service_params->initial_connection_subtype =
143 network::mojom::ConnectionSubtype(
144 net::NetworkChangeNotifier::GetConnectionSubtype());
145
146 #if defined(OS_POSIX)
147 // Send Kerberos environment variables to the network service.
148 if (IsOutOfProcessNetworkService()) {
149 std::unique_ptr<base::Environment> env(base::Environment::Create());
150 std::string value;
151 if (env->HasVar(kKrb5CCEnvName)) {
152 env->GetVar(kKrb5CCEnvName, &value);
153 network_service_params->environment.push_back(
154 network::mojom::EnvironmentVariable::New(kKrb5CCEnvName, value));
155 }
156 if (env->HasVar(kKrb5ConfEnvName)) {
157 env->GetVar(kKrb5ConfEnvName, &value);
158 network_service_params->environment.push_back(
159 network::mojom::EnvironmentVariable::New(kKrb5ConfEnvName, value));
160 }
161 }
162 #endif
163 return network_service_params;
164 }
165
CreateNetworkServiceOnIOForTesting(mojo::PendingReceiver<network::mojom::NetworkService> receiver,base::WaitableEvent * completion_event)166 void CreateNetworkServiceOnIOForTesting(
167 mojo::PendingReceiver<network::mojom::NetworkService> receiver,
168 base::WaitableEvent* completion_event) {
169 if (GetLocalNetworkService()) {
170 GetLocalNetworkService()->Bind(std::move(receiver));
171 return;
172 }
173
174 GetLocalNetworkService() = std::make_unique<network::NetworkService>(
175 nullptr /* registry */, std::move(receiver),
176 true /* delay_initialization_until_set_client */);
177 GetLocalNetworkService()->StopMetricsTimerForTesting();
178 GetLocalNetworkService()->Initialize(
179 network::mojom::NetworkServiceParams::New(),
180 true /* mock_network_change_notifier */);
181 if (completion_event)
182 completion_event->Signal();
183 }
184
BindNetworkChangeManagerReceiver(mojo::PendingReceiver<network::mojom::NetworkChangeManager> receiver)185 void BindNetworkChangeManagerReceiver(
186 mojo::PendingReceiver<network::mojom::NetworkChangeManager> receiver) {
187 GetNetworkService()->GetNetworkChangeManager(std::move(receiver));
188 }
189
GetCrashHandlersList()190 base::CallbackList<void()>& GetCrashHandlersList() {
191 static base::NoDestructor<base::CallbackList<void()>> s_list;
192 return *s_list;
193 }
194
OnNetworkServiceCrash()195 void OnNetworkServiceCrash() {
196 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
197 DCHECK(g_network_service_remote);
198 DCHECK(g_network_service_remote->is_bound());
199 DCHECK(!g_network_service_remote->is_connected());
200 g_last_network_service_crash = base::Time::Now();
201 GetCrashHandlersList().Notify();
202 }
203
204 // Parses the desired granularity of NetLog capturing specified by the command
205 // line.
GetNetCaptureModeFromCommandLine(const base::CommandLine & command_line)206 net::NetLogCaptureMode GetNetCaptureModeFromCommandLine(
207 const base::CommandLine& command_line) {
208 base::StringPiece switch_name = network::switches::kNetLogCaptureMode;
209
210 if (command_line.HasSwitch(switch_name)) {
211 std::string value = command_line.GetSwitchValueASCII(switch_name);
212
213 if (value == "Default")
214 return net::NetLogCaptureMode::kDefault;
215 if (value == "IncludeSensitive")
216 return net::NetLogCaptureMode::kIncludeSensitive;
217 if (value == "Everything")
218 return net::NetLogCaptureMode::kEverything;
219
220 // Warn when using the old command line switches.
221 if (value == "IncludeCookiesAndCredentials") {
222 LOG(ERROR) << "Deprecated value for --" << switch_name
223 << ". Use IncludeSensitive instead";
224 return net::NetLogCaptureMode::kIncludeSensitive;
225 }
226 if (value == "IncludeSocketBytes") {
227 LOG(ERROR) << "Deprecated value for --" << switch_name
228 << ". Use Everything instead";
229 return net::NetLogCaptureMode::kEverything;
230 }
231
232 LOG(ERROR) << "Unrecognized value for --" << switch_name;
233 }
234
235 return net::NetLogCaptureMode::kDefault;
236 }
237
238 static NetworkServiceClient* g_client = nullptr;
239
240 } // namespace
241
242 class NetworkServiceInstancePrivate {
243 public:
244 // Opens the specified file, blocking until the file is open. Used to open
245 // files specified by network::switches::kLogNetLog or
246 // network::switches::kSSLKeyLogFile. Since these arguments can be used to
247 // debug startup behavior, asynchronously opening the file on another thread
248 // would result in losing data, hence the need for blocking open operations.
249 // |file_flags| specifies the flags passed to the base::File constructor call.
250 //
251 // ThreadRestrictions needs to be able to friend the class/method to allow
252 // blocking, but can't friend CONTENT_EXPORT methods, so have it friend
253 // NetworkServiceInstancePrivate instead of GetNetworkService().
BlockingOpenFile(const base::FilePath & path,int file_flags)254 static base::File BlockingOpenFile(const base::FilePath& path,
255 int file_flags) {
256 base::ScopedAllowBlocking allow_blocking;
257 return base::File(path, file_flags);
258 }
259 };
260
GetNetworkService()261 network::mojom::NetworkService* GetNetworkService() {
262 if (!g_network_service_remote)
263 g_network_service_remote = new mojo::Remote<network::mojom::NetworkService>;
264 if (!g_network_service_remote->is_bound() ||
265 !g_network_service_remote->is_connected()) {
266 bool service_was_bound = g_network_service_remote->is_bound();
267 g_network_service_remote->reset();
268 if (GetContentClient()->browser()->IsShuttingDown()) {
269 // This happens at system shutdown, since in other scenarios the network
270 // process would only be torn down once the message loop stopped running.
271 // We don't want to start the network service again so just create message
272 // pipe that's not bound to stop consumers from requesting creation of the
273 // service.
274 auto receiver = g_network_service_remote->BindNewPipeAndPassReceiver();
275 auto leaked_pipe = receiver.PassPipe().release();
276 } else {
277 if (!g_force_create_network_service_directly) {
278 mojo::PendingReceiver<network::mojom::NetworkService> receiver =
279 g_network_service_remote->BindNewPipeAndPassReceiver();
280 g_network_service_remote->set_disconnect_handler(
281 base::BindOnce(&OnNetworkServiceCrash));
282 if (IsInProcessNetworkService()) {
283 CreateInProcessNetworkService(std::move(receiver));
284 } else {
285 if (service_was_bound)
286 LOG(ERROR) << "Network service crashed, restarting service.";
287 ServiceProcessHost::Launch(
288 std::move(receiver),
289 ServiceProcessHost::Options()
290 .WithDisplayName(base::UTF8ToUTF16("Network Service"))
291 .Pass());
292 }
293 } else {
294 // This should only be reached in unit tests.
295 if (BrowserThread::CurrentlyOn(BrowserThread::IO)) {
296 CreateNetworkServiceOnIOForTesting(
297 g_network_service_remote->BindNewPipeAndPassReceiver(),
298 /*completion_event=*/nullptr);
299 } else {
300 base::WaitableEvent event;
301 GetIOThreadTaskRunner({})->PostTask(
302 FROM_HERE,
303 base::BindOnce(
304 CreateNetworkServiceOnIOForTesting,
305 g_network_service_remote->BindNewPipeAndPassReceiver(),
306 base::Unretained(&event)));
307 event.Wait();
308 }
309 }
310
311 mojo::PendingRemote<network::mojom::NetworkServiceClient> client_remote;
312 auto client_receiver = client_remote.InitWithNewPipeAndPassReceiver();
313 // Call SetClient before creating NetworkServiceClient, as the latter
314 // might make requests to NetworkService that depend on initialization.
315 (*g_network_service_remote)
316 ->SetClient(std::move(client_remote), CreateNetworkServiceParams());
317 g_network_service_is_responding = false;
318 g_network_service_remote->QueryVersion(base::BindOnce(
319 [](base::Time start_time, uint32_t) {
320 g_network_service_is_responding = true;
321 base::TimeDelta delta = base::Time::Now() - start_time;
322 UMA_HISTOGRAM_MEDIUM_TIMES("NetworkService.TimeToFirstResponse",
323 delta);
324 if (g_last_network_service_crash.is_null()) {
325 UMA_HISTOGRAM_MEDIUM_TIMES(
326 "NetworkService.TimeToFirstResponse.OnStartup", delta);
327 } else {
328 UMA_HISTOGRAM_MEDIUM_TIMES(
329 "NetworkService.TimeToFirstResponse.AfterCrash", delta);
330 }
331 },
332 base::Time::Now()));
333
334 delete g_client; // In case we're recreating the network service.
335 g_client = new NetworkServiceClient(std::move(client_receiver));
336
337 const base::CommandLine* command_line =
338 base::CommandLine::ForCurrentProcess();
339 if (command_line->HasSwitch(network::switches::kLogNetLog)) {
340 base::FilePath log_path =
341 command_line->GetSwitchValuePath(network::switches::kLogNetLog);
342
343 base::File file = NetworkServiceInstancePrivate::BlockingOpenFile(
344 log_path, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
345 if (!file.IsValid()) {
346 LOG(ERROR) << "Failed opening NetLog: " << log_path.value();
347 } else {
348 (*g_network_service_remote)
349 ->StartNetLog(
350 std::move(file),
351 GetNetCaptureModeFromCommandLine(*command_line),
352 GetContentClient()->browser()->GetNetLogConstants());
353 }
354 }
355
356 base::FilePath ssl_key_log_path;
357 if (command_line->HasSwitch(network::switches::kSSLKeyLogFile)) {
358 UMA_HISTOGRAM_ENUMERATION(kSSLKeyLogFileHistogram,
359 SSLKeyLogFileAction::kSwitchFound);
360 ssl_key_log_path =
361 command_line->GetSwitchValuePath(network::switches::kSSLKeyLogFile);
362 LOG_IF(WARNING, ssl_key_log_path.empty())
363 << "ssl-key-log-file argument missing";
364 } else {
365 std::unique_ptr<base::Environment> env(base::Environment::Create());
366 std::string env_str;
367 if (env->GetVar("SSLKEYLOGFILE", &env_str)) {
368 UMA_HISTOGRAM_ENUMERATION(kSSLKeyLogFileHistogram,
369 SSLKeyLogFileAction::kEnvVarFound);
370 #if defined(OS_WIN)
371 // base::Environment returns environment variables in UTF-8 on
372 // Windows.
373 ssl_key_log_path = base::FilePath(base::UTF8ToUTF16(env_str));
374 #else
375 ssl_key_log_path = base::FilePath(env_str);
376 #endif
377 }
378 }
379
380 if (!ssl_key_log_path.empty()) {
381 base::File file = NetworkServiceInstancePrivate::BlockingOpenFile(
382 ssl_key_log_path,
383 base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_APPEND);
384 if (!file.IsValid()) {
385 LOG(ERROR) << "Failed opening SSL key log file: "
386 << ssl_key_log_path.value();
387 } else {
388 UMA_HISTOGRAM_ENUMERATION(kSSLKeyLogFileHistogram,
389 SSLKeyLogFileAction::kLogFileEnabled);
390 (*g_network_service_remote)->SetSSLKeyLogFile(std::move(file));
391 }
392 }
393
394 GetContentClient()->browser()->OnNetworkServiceCreated(
395 g_network_service_remote->get());
396 }
397 }
398 return g_network_service_remote->get();
399 }
400
401 std::unique_ptr<base::CallbackList<void()>::Subscription>
RegisterNetworkServiceCrashHandler(base::RepeatingClosure handler)402 RegisterNetworkServiceCrashHandler(base::RepeatingClosure handler) {
403 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
404 DCHECK(!handler.is_null());
405
406 return GetCrashHandlersList().Add(std::move(handler));
407 }
408
409 #if defined(OS_CHROMEOS)
GetNetworkChangeNotifier()410 net::NetworkChangeNotifier* GetNetworkChangeNotifier() {
411 return BrowserMainLoop::GetInstance()->network_change_notifier();
412 }
413 #endif
414
FlushNetworkServiceInstanceForTesting()415 void FlushNetworkServiceInstanceForTesting() {
416 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
417
418 if (g_network_service_remote)
419 g_network_service_remote->FlushForTesting();
420 }
421
GetNetworkConnectionTracker()422 network::NetworkConnectionTracker* GetNetworkConnectionTracker() {
423 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) ||
424 !BrowserThread::IsThreadInitialized(BrowserThread::UI));
425 if (!g_network_connection_tracker) {
426 g_network_connection_tracker = new network::NetworkConnectionTracker(
427 base::BindRepeating(&BindNetworkChangeManagerReceiver));
428 }
429 return g_network_connection_tracker;
430 }
431
GetNetworkConnectionTrackerFromUIThread(base::OnceCallback<void (network::NetworkConnectionTracker *)> callback)432 void GetNetworkConnectionTrackerFromUIThread(
433 base::OnceCallback<void(network::NetworkConnectionTracker*)> callback) {
434 GetUIThreadTaskRunner({base::TaskPriority::BEST_EFFORT})
435 ->PostTaskAndReplyWithResult(FROM_HERE,
436 base::BindOnce(&GetNetworkConnectionTracker),
437 std::move(callback));
438 }
439
440 network::NetworkConnectionTrackerAsyncGetter
CreateNetworkConnectionTrackerAsyncGetter()441 CreateNetworkConnectionTrackerAsyncGetter() {
442 return base::BindRepeating(&content::GetNetworkConnectionTrackerFromUIThread);
443 }
444
SetNetworkConnectionTrackerForTesting(network::NetworkConnectionTracker * network_connection_tracker)445 void SetNetworkConnectionTrackerForTesting(
446 network::NetworkConnectionTracker* network_connection_tracker) {
447 if (g_network_connection_tracker != network_connection_tracker) {
448 DCHECK(!g_network_connection_tracker || !network_connection_tracker);
449 g_network_connection_tracker = network_connection_tracker;
450 }
451 }
452
GetNetworkTaskRunner()453 const scoped_refptr<base::SequencedTaskRunner>& GetNetworkTaskRunner() {
454 DCHECK(IsInProcessNetworkService());
455 return GetNetworkTaskRunnerStorage();
456 }
457
ForceCreateNetworkServiceDirectlyForTesting()458 void ForceCreateNetworkServiceDirectlyForTesting() {
459 g_force_create_network_service_directly = true;
460 }
461
ResetNetworkServiceForTesting()462 void ResetNetworkServiceForTesting() {
463 ShutDownNetworkService();
464 }
465
ShutDownNetworkService()466 void ShutDownNetworkService() {
467 delete g_network_service_remote;
468 g_network_service_remote = nullptr;
469 delete g_client;
470 g_client = nullptr;
471 if (g_in_process_instance) {
472 GetNetworkTaskRunner()->DeleteSoon(FROM_HERE, g_in_process_instance);
473 g_in_process_instance = nullptr;
474 }
475 GetNetworkTaskRunnerStorage().reset();
476 }
477
GetNetworkServiceAvailability()478 NetworkServiceAvailability GetNetworkServiceAvailability() {
479 if (!g_network_service_remote)
480 return NetworkServiceAvailability::NOT_CREATED;
481 else if (!g_network_service_remote->is_bound())
482 return NetworkServiceAvailability::NOT_BOUND;
483 else if (!g_network_service_remote->is_connected())
484 return NetworkServiceAvailability::ENCOUNTERED_ERROR;
485 else if (!g_network_service_is_responding)
486 return NetworkServiceAvailability::NOT_RESPONDING;
487 else
488 return NetworkServiceAvailability::AVAILABLE;
489 }
490
GetTimeSinceLastNetworkServiceCrash()491 base::TimeDelta GetTimeSinceLastNetworkServiceCrash() {
492 if (g_last_network_service_crash.is_null())
493 return base::TimeDelta();
494 return base::Time::Now() - g_last_network_service_crash;
495 }
496
PingNetworkService(base::OnceClosure closure)497 void PingNetworkService(base::OnceClosure closure) {
498 GetNetworkService();
499 // Unfortunately, QueryVersion requires a RepeatingCallback.
500 g_network_service_remote->QueryVersion(base::BindOnce(
501 [](base::OnceClosure closure, uint32_t) {
502 if (closure)
503 std::move(closure).Run();
504 },
505 base::Passed(std::move(closure))));
506 }
507
508 namespace {
509
510 mojo::PendingRemote<cert_verifier::mojom::CertVerifierService>
GetNewCertVerifierServiceRemote(cert_verifier::mojom::CertVerifierServiceFactory * cert_verifier_service_factory,network::mojom::CertVerifierCreationParamsPtr creation_params)511 GetNewCertVerifierServiceRemote(
512 cert_verifier::mojom::CertVerifierServiceFactory*
513 cert_verifier_service_factory,
514 network::mojom::CertVerifierCreationParamsPtr creation_params) {
515 mojo::PendingRemote<cert_verifier::mojom::CertVerifierService>
516 cert_verifier_remote;
517 cert_verifier_service_factory->GetNewCertVerifier(
518 cert_verifier_remote.InitWithNewPipeAndPassReceiver(),
519 std::move(creation_params));
520 return cert_verifier_remote;
521 }
522
CreateInProcessCertVerifierServiceOnThread(mojo::PendingReceiver<cert_verifier::mojom::CertVerifierServiceFactory> receiver)523 void CreateInProcessCertVerifierServiceOnThread(
524 mojo::PendingReceiver<cert_verifier::mojom::CertVerifierServiceFactory>
525 receiver) {
526 // Except in tests, our CertVerifierServiceFactoryImpl is a singleton.
527 static base::NoDestructor<cert_verifier::CertVerifierServiceFactoryImpl>
528 cv_service_factory(std::move(receiver));
529 }
530
531 // Owns the CertVerifierServiceFactory used by the browser.
532 // Lives on the UI thread.
533 class CertVerifierServiceFactoryOwner {
534 public:
535 CertVerifierServiceFactoryOwner() = default;
536 CertVerifierServiceFactoryOwner(const CertVerifierServiceFactoryOwner&) =
537 delete;
538 CertVerifierServiceFactoryOwner& operator=(
539 const CertVerifierServiceFactoryOwner&) = delete;
540 ~CertVerifierServiceFactoryOwner() = delete;
541
Get()542 static CertVerifierServiceFactoryOwner* Get() {
543 static base::NoDestructor<CertVerifierServiceFactoryOwner>
544 cert_verifier_service_factory_owner;
545 return &*cert_verifier_service_factory_owner;
546 }
547
548 // Passing nullptr will reset the current remote.
SetCertVerifierServiceFactoryForTesting(cert_verifier::mojom::CertVerifierServiceFactory * service_factory)549 void SetCertVerifierServiceFactoryForTesting(
550 cert_verifier::mojom::CertVerifierServiceFactory* service_factory) {
551 if (service_factory) {
552 DCHECK(!service_factory_);
553 }
554 service_factory_ = service_factory;
555 service_factory_remote_.reset();
556 }
557
558 // Returns a pointer to a CertVerifierServiceFactory usable on the UI thread.
559 cert_verifier::mojom::CertVerifierServiceFactory*
GetCertVerifierServiceFactory()560 GetCertVerifierServiceFactory() {
561 if (!service_factory_) {
562 #if defined(OS_CHROMEOS)
563 // ChromeOS's in-process CertVerifierService should run on the IO thread
564 // because it interacts with IO-bound NSS and ChromeOS user slots.
565 // See for example InitializeNSSForChromeOSUser().
566 GetIOThreadTaskRunner({})->PostTask(
567 FROM_HERE,
568 base::BindOnce(&CreateInProcessCertVerifierServiceOnThread,
569 service_factory_remote_.BindNewPipeAndPassReceiver()));
570 #else
571 CreateInProcessCertVerifierServiceOnThread(
572 service_factory_remote_.BindNewPipeAndPassReceiver());
573 #endif
574 service_factory_ = service_factory_remote_.get();
575 }
576 return service_factory_;
577 }
578
579 private:
580 // Bound to UI thread.
581 mojo::Remote<cert_verifier::mojom::CertVerifierServiceFactory>
582 service_factory_remote_;
583 cert_verifier::mojom::CertVerifierServiceFactory* service_factory_ = nullptr;
584 };
585
586 } // namespace
587
GetCertVerifierParams(network::mojom::CertVerifierCreationParamsPtr cert_verifier_creation_params)588 network::mojom::CertVerifierParamsPtr GetCertVerifierParams(
589 network::mojom::CertVerifierCreationParamsPtr
590 cert_verifier_creation_params) {
591 if (!base::FeatureList::IsEnabled(network::features::kCertVerifierService)) {
592 return network::mojom::CertVerifierParams::NewCreationParams(
593 std::move(cert_verifier_creation_params));
594 }
595
596 auto cv_service_remote_params =
597 network::mojom::CertVerifierServiceRemoteParams::New();
598
599 // Create a cert verifier service.
600 cv_service_remote_params
601 ->cert_verifier_service = GetNewCertVerifierServiceRemote(
602 CertVerifierServiceFactoryOwner::Get()->GetCertVerifierServiceFactory(),
603 std::move(cert_verifier_creation_params));
604
605 return network::mojom::CertVerifierParams::NewRemoteParams(
606 std::move(cv_service_remote_params));
607 }
608
SetCertVerifierServiceFactoryForTesting(cert_verifier::mojom::CertVerifierServiceFactory * service_factory)609 void SetCertVerifierServiceFactoryForTesting(
610 cert_verifier::mojom::CertVerifierServiceFactory* service_factory) {
611 CertVerifierServiceFactoryOwner::Get()
612 ->SetCertVerifierServiceFactoryForTesting(service_factory);
613 }
614
615 } // namespace content
616