Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(306)

Side by Side Diff: content/browser/utility_process_host_impl.cc

Issue 18119009: Make utility process run in-process when running in single-process mode. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: undo unnecessary changes Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « content/browser/utility_process_host_impl.h ('k') | content/content.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/utility_process_host_impl.h" 5 #include "content/browser/utility_process_host_impl.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/bind_helpers.h" 8 #include "base/bind_helpers.h"
9 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "base/lazy_instance.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/run_loop.h"
10 #include "base/sequenced_task_runner.h" 13 #include "base/sequenced_task_runner.h"
11 #include "base/strings/utf_string_conversions.h" 14 #include "base/strings/utf_string_conversions.h"
15 #include "base/synchronization/lock.h"
16 #include "base/synchronization/waitable_event.h"
12 #include "content/browser/browser_child_process_host_impl.h" 17 #include "content/browser/browser_child_process_host_impl.h"
18 #include "content/browser/renderer_host/render_process_host_impl.h"
19 #include "content/child/child_process.h"
13 #include "content/common/child_process_host_impl.h" 20 #include "content/common/child_process_host_impl.h"
14 #include "content/common/utility_messages.h" 21 #include "content/common/utility_messages.h"
15 #include "content/public/browser/browser_thread.h" 22 #include "content/public/browser/browser_thread.h"
16 #include "content/public/browser/content_browser_client.h" 23 #include "content/public/browser/content_browser_client.h"
17 #include "content/public/browser/utility_process_host_client.h" 24 #include "content/public/browser/utility_process_host_client.h"
18 #include "content/public/common/content_switches.h" 25 #include "content/public/common/content_switches.h"
26 #include "content/public/common/process_type.h"
27 #include "content/utility/utility_thread_impl.h"
19 #include "ipc/ipc_switches.h" 28 #include "ipc/ipc_switches.h"
20 #include "ui/base/ui_base_switches.h" 29 #include "ui/base/ui_base_switches.h"
21 #include "webkit/plugins/plugin_switches.h" 30 #include "webkit/plugins/plugin_switches.h"
22 31
23 #if defined(OS_WIN) 32 #if defined(OS_WIN)
24 #include "content/public/common/sandboxed_process_launcher_delegate.h" 33 #include "content/public/common/sandboxed_process_launcher_delegate.h"
25 #endif 34 #endif
26 35
27 namespace content { 36 namespace content {
28 37
29 #if defined(OS_WIN) 38 #if defined(OS_WIN)
30 // NOTE: changes to this class need to be reviewed by the security team. 39 // NOTE: changes to this class need to be reviewed by the security team.
31 class UtilitySandboxedProcessLauncherDelegate 40 class UtilitySandboxedProcessLauncherDelegate
32 : public SandboxedProcessLauncherDelegate { 41 : public SandboxedProcessLauncherDelegate {
33 public: 42 public:
34 explicit UtilitySandboxedProcessLauncherDelegate( 43 explicit UtilitySandboxedProcessLauncherDelegate(
35 const base::FilePath& exposed_dir) : exposed_dir_(exposed_dir) {} 44 const base::FilePath& exposed_dir) : exposed_dir_(exposed_dir) {}
36 virtual ~UtilitySandboxedProcessLauncherDelegate() {} 45 virtual ~UtilitySandboxedProcessLauncherDelegate() {}
37 46
38 virtual void PreSandbox(bool* disable_default_policy, 47 virtual void PreSandbox(bool* disable_default_policy,
39 base::FilePath* exposed_dir) OVERRIDE { 48 base::FilePath* exposed_dir) OVERRIDE {
40 *exposed_dir = exposed_dir_; 49 *exposed_dir = exposed_dir_;
41 } 50 }
42 51
43 private: 52 private:
44 base::FilePath exposed_dir_; 53 base::FilePath exposed_dir_;
45 }; 54 };
46 #endif 55 #endif
47 56
57 // We want to ensure there's only one utility thread running at a time, as there
58 // are many globals used in the utility process.
59 static base::LazyInstance<base::Lock> g_one_utility_thread_lock;
60
61 class UtilityMainThread : public base::Thread {
62 public:
63 UtilityMainThread(const std::string& channel_id)
64 : Thread("Chrome_InProcUtilityThread"),
65 channel_id_(channel_id) {
66 }
67
68 virtual ~UtilityMainThread() {
69 Stop();
70 }
71
72 private:
73 // base::Thread implementation:
74 virtual void Init() OVERRIDE {
75 // We need to return right away or else the main thread that started us will
76 // hang.
77 base::MessageLoop::current()->PostTask(
78 FROM_HERE,
79 base::Bind(&UtilityMainThread::InitInternal, base::Unretained(this)));
80 }
81
82 virtual void CleanUp() OVERRIDE {
83 child_process_.reset();
84
85 // See comment in RendererMainThread.
86 SetThreadWasQuitProperly(true);
87 g_one_utility_thread_lock.Get().Release();
88 }
89
90 void InitInternal() {
91 g_one_utility_thread_lock.Get().Acquire();
92 child_process_.reset(new ChildProcess());
93 child_process_->set_main_thread(new UtilityThreadImpl(channel_id_));
94 }
95
96 std::string channel_id_;
97 scoped_ptr<ChildProcess> child_process_;
98
99 DISALLOW_COPY_AND_ASSIGN(UtilityMainThread);
100 };
101
48 UtilityProcessHost* UtilityProcessHost::Create( 102 UtilityProcessHost* UtilityProcessHost::Create(
49 UtilityProcessHostClient* client, 103 UtilityProcessHostClient* client,
50 base::SequencedTaskRunner* client_task_runner) { 104 base::SequencedTaskRunner* client_task_runner) {
51 return new UtilityProcessHostImpl(client, client_task_runner); 105 return new UtilityProcessHostImpl(client, client_task_runner);
52 } 106 }
53 107
54 UtilityProcessHostImpl::UtilityProcessHostImpl( 108 UtilityProcessHostImpl::UtilityProcessHostImpl(
55 UtilityProcessHostClient* client, 109 UtilityProcessHostClient* client,
56 base::SequencedTaskRunner* client_task_runner) 110 base::SequencedTaskRunner* client_task_runner)
57 : client_(client), 111 : client_(client),
58 client_task_runner_(client_task_runner), 112 client_task_runner_(client_task_runner),
59 is_batch_mode_(false), 113 is_batch_mode_(false),
60 no_sandbox_(false), 114 no_sandbox_(false),
61 #if defined(OS_LINUX) 115 #if defined(OS_LINUX)
62 child_flags_(ChildProcessHost::CHILD_ALLOW_SELF), 116 child_flags_(ChildProcessHost::CHILD_ALLOW_SELF),
63 #else 117 #else
64 child_flags_(ChildProcessHost::CHILD_NORMAL), 118 child_flags_(ChildProcessHost::CHILD_NORMAL),
65 #endif 119 #endif
66 use_linux_zygote_(false), 120 use_linux_zygote_(false),
67 started_(false) { 121 started_(false) {
68 process_.reset(new BrowserChildProcessHostImpl(PROCESS_TYPE_UTILITY, this));
69 } 122 }
70 123
71 UtilityProcessHostImpl::~UtilityProcessHostImpl() { 124 UtilityProcessHostImpl::~UtilityProcessHostImpl() {
72 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 125 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
73 DCHECK(!is_batch_mode_); 126 DCHECK(!is_batch_mode_);
74 } 127 }
75 128
76 bool UtilityProcessHostImpl::Send(IPC::Message* message) { 129 bool UtilityProcessHostImpl::Send(IPC::Message* message) {
77 if (!StartProcess()) 130 if (!StartProcess())
78 return false; 131 return false;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
117 170
118 #endif // OS_POSIX 171 #endif // OS_POSIX
119 172
120 bool UtilityProcessHostImpl::StartProcess() { 173 bool UtilityProcessHostImpl::StartProcess() {
121 if (started_) 174 if (started_)
122 return true; 175 return true;
123 started_ = true; 176 started_ = true;
124 177
125 if (is_batch_mode_) 178 if (is_batch_mode_)
126 return true; 179 return true;
180
127 // Name must be set or metrics_service will crash in any test which 181 // Name must be set or metrics_service will crash in any test which
128 // launches a UtilityProcessHost. 182 // launches a UtilityProcessHost.
183 process_.reset(new BrowserChildProcessHostImpl(PROCESS_TYPE_UTILITY, this));
129 process_->SetName(ASCIIToUTF16("utility process")); 184 process_->SetName(ASCIIToUTF16("utility process"));
130 185
131 std::string channel_id = process_->GetHost()->CreateChannel(); 186 std::string channel_id = process_->GetHost()->CreateChannel();
132 if (channel_id.empty()) 187 if (channel_id.empty())
133 return false; 188 return false;
134 189
135 const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess(); 190 if (RenderProcessHost::run_renderer_in_process()) {
136 int child_flags = child_flags_; 191 // See comment in RenderProcessHostImpl::Init() for the background on why we
192 // support single process mode this way.
193 in_process_thread_.reset(new UtilityMainThread(channel_id));
194 in_process_thread_->Start();
195 } else {
196 const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
197 int child_flags = child_flags_;
137 198
138 #if defined(OS_POSIX) 199 #if defined(OS_POSIX)
139 bool has_cmd_prefix = browser_command_line.HasSwitch( 200 bool has_cmd_prefix = browser_command_line.HasSwitch(
140 switches::kUtilityCmdPrefix); 201 switches::kUtilityCmdPrefix);
141 202
142 // When running under gdb, forking /proc/self/exe ends up forking the gdb 203 // When running under gdb, forking /proc/self/exe ends up forking the gdb
143 // executable instead of Chromium. It is almost safe to assume that no 204 // executable instead of Chromium. It is almost safe to assume that no
144 // updates will happen while a developer is running with 205 // updates will happen while a developer is running with
145 // |switches::kUtilityCmdPrefix|. See ChildProcessHost::GetChildPath() for 206 // |switches::kUtilityCmdPrefix|. See ChildProcessHost::GetChildPath() for
146 // a similar case with Valgrind. 207 // a similar case with Valgrind.
147 if (has_cmd_prefix) 208 if (has_cmd_prefix)
148 child_flags = ChildProcessHost::CHILD_NORMAL; 209 child_flags = ChildProcessHost::CHILD_NORMAL;
149 #endif 210 #endif
150 211
151 base::FilePath exe_path = ChildProcessHost::GetChildPath(child_flags); 212 base::FilePath exe_path = ChildProcessHost::GetChildPath(child_flags);
152 if (exe_path.empty()) { 213 if (exe_path.empty()) {
153 NOTREACHED() << "Unable to get utility process binary name."; 214 NOTREACHED() << "Unable to get utility process binary name.";
154 return false; 215 return false;
155 } 216 }
156 217
157 CommandLine* cmd_line = new CommandLine(exe_path); 218 CommandLine* cmd_line = new CommandLine(exe_path);
158 cmd_line->AppendSwitchASCII(switches::kProcessType, 219 cmd_line->AppendSwitchASCII(switches::kProcessType,
159 switches::kUtilityProcess); 220 switches::kUtilityProcess);
160 cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id); 221 cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id);
161 std::string locale = GetContentClient()->browser()->GetApplicationLocale(); 222 std::string locale = GetContentClient()->browser()->GetApplicationLocale();
162 cmd_line->AppendSwitchASCII(switches::kLang, locale); 223 cmd_line->AppendSwitchASCII(switches::kLang, locale);
163 224
164 if (no_sandbox_ || browser_command_line.HasSwitch(switches::kNoSandbox)) 225 if (no_sandbox_ || browser_command_line.HasSwitch(switches::kNoSandbox))
165 cmd_line->AppendSwitch(switches::kNoSandbox); 226 cmd_line->AppendSwitch(switches::kNoSandbox);
166 #if defined(OS_MACOSX) 227 #if defined(OS_MACOSX)
167 if (browser_command_line.HasSwitch(switches::kEnableSandboxLogging)) 228 if (browser_command_line.HasSwitch(switches::kEnableSandboxLogging))
168 cmd_line->AppendSwitch(switches::kEnableSandboxLogging); 229 cmd_line->AppendSwitch(switches::kEnableSandboxLogging);
169 #endif 230 #endif
170 if (browser_command_line.HasSwitch(switches::kDebugPluginLoading)) 231 if (browser_command_line.HasSwitch(switches::kDebugPluginLoading))
171 cmd_line->AppendSwitch(switches::kDebugPluginLoading); 232 cmd_line->AppendSwitch(switches::kDebugPluginLoading);
172 233
173 #if defined(OS_POSIX) 234 #if defined(OS_POSIX)
174 // TODO(port): Sandbox this on Linux. Also, zygote this to work with 235 // TODO(port): Sandbox this on Linux. Also, zygote this to work with
175 // Linux updating. 236 // Linux updating.
176 if (has_cmd_prefix) { 237 if (has_cmd_prefix) {
177 // launch the utility child process with some prefix (usually "xterm -e gdb 238 // launch the utility child process with some prefix (usually "xterm -e gd b
178 // --args"). 239 // --args").
179 cmd_line->PrependWrapper(browser_command_line.GetSwitchValueNative( 240 cmd_line->PrependWrapper(browser_command_line.GetSwitchValueNative(
180 switches::kUtilityCmdPrefix)); 241 switches::kUtilityCmdPrefix));
181 } 242 }
182 243
183 cmd_line->AppendSwitchPath(switches::kUtilityProcessAllowedDir, exposed_dir_); 244 cmd_line->AppendSwitchPath(switches::kUtilityProcessAllowedDir, exposed_dir_ );
184 #endif 245 #endif
185 246
186 bool use_zygote = false; 247 bool use_zygote = false;
187 248
188 #if defined(OS_LINUX) 249 #if defined(OS_LINUX)
189 use_zygote = !no_sandbox_ && use_linux_zygote_; 250 use_zygote = !no_sandbox_ && use_linux_zygote_;
190 #endif 251 #endif
191 252
192 process_->Launch( 253 process_->Launch(
193 #if defined(OS_WIN) 254 #if defined(OS_WIN)
194 new UtilitySandboxedProcessLauncherDelegate(exposed_dir_), 255 new UtilitySandboxedProcessLauncherDelegate(exposed_dir_),
195 #elif defined(OS_POSIX) 256 #elif defined(OS_POSIX)
196 use_zygote, 257 use_zygote,
197 env_, 258 env_,
198 #endif 259 #endif
199 cmd_line); 260 cmd_line);
261 }
200 262
201 return true; 263 return true;
202 } 264 }
203 265
204 bool UtilityProcessHostImpl::OnMessageReceived(const IPC::Message& message) { 266 bool UtilityProcessHostImpl::OnMessageReceived(const IPC::Message& message) {
205 client_task_runner_->PostTask( 267 client_task_runner_->PostTask(
206 FROM_HERE, 268 FROM_HERE,
207 base::Bind(base::IgnoreResult( 269 base::Bind(base::IgnoreResult(
208 &UtilityProcessHostClient::OnMessageReceived), client_.get(), 270 &UtilityProcessHostClient::OnMessageReceived), client_.get(),
209 message)); 271 message));
210 return true; 272 return true;
211 } 273 }
212 274
213 void UtilityProcessHostImpl::OnProcessCrashed(int exit_code) { 275 void UtilityProcessHostImpl::OnProcessCrashed(int exit_code) {
214 client_task_runner_->PostTask( 276 client_task_runner_->PostTask(
215 FROM_HERE, 277 FROM_HERE,
216 base::Bind(&UtilityProcessHostClient::OnProcessCrashed, client_.get(), 278 base::Bind(&UtilityProcessHostClient::OnProcessCrashed, client_.get(),
217 exit_code)); 279 exit_code));
218 } 280 }
219 281
220 } // namespace content 282 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/utility_process_host_impl.h ('k') | content/content.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698