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_error_handler(this);
57 weak_utility_process_host_
= utility_process_host
->AsWeakPtr();
59 LOG(ERROR
) << "Unable to connect to utility process";
63 scoped_ptr
<base::ScopedClosureRunner
>
64 UtilityProcessMojoProxyResolverFactory::CreateResolver(
65 const mojo::String
& pac_script
,
66 mojo::InterfaceRequest
<net::interfaces::ProxyResolver
> req
,
67 net::interfaces::HostResolverPtr host_resolver
,
68 net::interfaces::ProxyResolverErrorObserverPtr error_observer
,
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(),
83 host_resolver
.Pass(), error_observer
.Pass(),
85 return make_scoped_ptr(new base::ScopedClosureRunner(
86 base::Bind(&UtilityProcessMojoProxyResolverFactory::OnResolverDestroyed
,
87 base::Unretained(this))));
90 void UtilityProcessMojoProxyResolverFactory::OnConnectionError() {
91 DVLOG(1) << "Disconnection from utility process detected";
92 resolver_factory_
.reset();
95 void UtilityProcessMojoProxyResolverFactory::OnResolverDestroyed() {
96 DCHECK(thread_checker_
.CalledOnValidThread());
97 DCHECK_GT(num_proxy_resolvers_
, 0u);
98 if (--num_proxy_resolvers_
== 0) {
99 // When all proxy resolvers have been destroyed, the proxy resolver utility
100 // process is no longer needed. However, new proxy resolvers may be created
101 // shortly after being destroyed (e.g. due to a network change). If the
102 // utility process is shut down immediately, this would cause unnecessary
103 // process churn, so wait for an idle timeout before shutting down the
104 // proxy resolver utility process.
107 base::TimeDelta::FromSeconds(kUtilityProcessIdleTimeoutSeconds
), this,
108 &UtilityProcessMojoProxyResolverFactory::OnIdleTimeout
);
112 void UtilityProcessMojoProxyResolverFactory::OnIdleTimeout() {
113 DCHECK(thread_checker_
.CalledOnValidThread());
114 DCHECK_EQ(num_proxy_resolvers_
, 0u);
115 delete weak_utility_process_host_
.get();
116 weak_utility_process_host_
.reset();
117 resolver_factory_
.reset();