1 // Copyright 2015 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.
5 #include "chrome/browser/net/utility_process_mojo_proxy_resolver_factory.h"
7 #include "base/logging.h"
8 #include "base/memory/singleton.h"
9 #include "base/single_thread_task_runner.h"
10 #include "base/thread_task_runner_handle.h"
11 #include "chrome/grit/generated_resources.h"
12 #include "content/public/browser/browser_thread.h"
13 #include "content/public/browser/utility_process_host.h"
14 #include "content/public/browser/utility_process_host_client.h"
15 #include "content/public/common/service_registry.h"
16 #include "ui/base/l10n/l10n_util.h"
19 const int kUtilityProcessIdleTimeoutSeconds
= 5;
23 UtilityProcessMojoProxyResolverFactory
*
24 UtilityProcessMojoProxyResolverFactory::GetInstance() {
25 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
27 UtilityProcessMojoProxyResolverFactory
,
28 LeakySingletonTraits
<UtilityProcessMojoProxyResolverFactory
>>::get();
31 UtilityProcessMojoProxyResolverFactory::
32 UtilityProcessMojoProxyResolverFactory() {
33 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
36 UtilityProcessMojoProxyResolverFactory::
37 ~UtilityProcessMojoProxyResolverFactory() {
38 DCHECK(thread_checker_
.CalledOnValidThread());
41 void UtilityProcessMojoProxyResolverFactory::CreateProcessAndConnect() {
42 DCHECK(thread_checker_
.CalledOnValidThread());
43 DVLOG(1) << "Attempting to create utility process for proxy resolver";
44 content::UtilityProcessHost
* utility_process_host
=
45 content::UtilityProcessHost::Create(
46 scoped_refptr
<content::UtilityProcessHostClient
>(),
47 base::ThreadTaskRunnerHandle::Get());
48 utility_process_host
->SetName(l10n_util::GetStringUTF16(
49 IDS_UTILITY_PROCESS_PROXY_RESOLVER_NAME
));
50 bool process_started
= utility_process_host
->StartMojoMode();
51 if (process_started
) {
52 content::ServiceRegistry
* service_registry
=
53 utility_process_host
->GetServiceRegistry();
54 service_registry
->ConnectToRemoteService(
55 mojo::GetProxy(&resolver_factory_
));
56 resolver_factory_
.set_connection_error_handler(
57 base::Bind(&UtilityProcessMojoProxyResolverFactory::OnConnectionError
,
58 base::Unretained(this)));
59 weak_utility_process_host_
= utility_process_host
->AsWeakPtr();
61 LOG(ERROR
) << "Unable to connect to utility process";
65 scoped_ptr
<base::ScopedClosureRunner
>
66 UtilityProcessMojoProxyResolverFactory::CreateResolver(
67 const mojo::String
& pac_script
,
68 mojo::InterfaceRequest
<net::interfaces::ProxyResolver
> req
,
69 net::interfaces::ProxyResolverFactoryRequestClientPtr client
) {
70 DCHECK(thread_checker_
.CalledOnValidThread());
71 if (!resolver_factory_
)
72 CreateProcessAndConnect();
74 if (!resolver_factory_
) {
75 // If there's still no factory, then utility process creation failed so
76 // close |req|'s message pipe, which should cause a connection error.
81 num_proxy_resolvers_
++;
82 resolver_factory_
->CreateResolver(pac_script
, req
.Pass(), client
.Pass());
83 return make_scoped_ptr(new base::ScopedClosureRunner(
84 base::Bind(&UtilityProcessMojoProxyResolverFactory::OnResolverDestroyed
,
85 base::Unretained(this))));
88 void UtilityProcessMojoProxyResolverFactory::OnConnectionError() {
89 DVLOG(1) << "Disconnection from utility process detected";
90 resolver_factory_
.reset();
93 void UtilityProcessMojoProxyResolverFactory::OnResolverDestroyed() {
94 DCHECK(thread_checker_
.CalledOnValidThread());
95 DCHECK_GT(num_proxy_resolvers_
, 0u);
96 if (--num_proxy_resolvers_
== 0) {
97 // When all proxy resolvers have been destroyed, the proxy resolver utility
98 // process is no longer needed. However, new proxy resolvers may be created
99 // shortly after being destroyed (e.g. due to a network change). If the
100 // utility process is shut down immediately, this would cause unnecessary
101 // process churn, so wait for an idle timeout before shutting down the
102 // proxy resolver utility process.
105 base::TimeDelta::FromSeconds(kUtilityProcessIdleTimeoutSeconds
), this,
106 &UtilityProcessMojoProxyResolverFactory::OnIdleTimeout
);
110 void UtilityProcessMojoProxyResolverFactory::OnIdleTimeout() {
111 DCHECK(thread_checker_
.CalledOnValidThread());
112 DCHECK_EQ(num_proxy_resolvers_
, 0u);
113 delete weak_utility_process_host_
.get();
114 weak_utility_process_host_
.reset();
115 resolver_factory_
.reset();