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

Side by Side Diff: content/common/child_process_host.cc

Issue 8774040: Don't make classes derive from ChildProcessHost, and instead have them use it through composition... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years 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
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/common/child_process_host.h" 5 #include "content/common/child_process_host.h"
6 6
7 #include <limits> 7 #include <limits>
8 8
9 #include "base/atomicops.h" 9 #include "base/atomicops.h"
10 #include "base/command_line.h" 10 #include "base/command_line.h"
11 #include "base/file_path.h" 11 #include "base/file_path.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/metrics/histogram.h" 13 #include "base/metrics/histogram.h"
14 #include "base/path_service.h" 14 #include "base/path_service.h"
15 #include "base/process_util.h" 15 #include "base/process_util.h"
16 #include "base/rand_util.h" 16 #include "base/rand_util.h"
17 #include "base/stringprintf.h" 17 #include "base/stringprintf.h"
18 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" 18 #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
19 #include "content/common/child_process_messages.h" 19 #include "content/common/child_process_messages.h"
20 #include "content/public/common/child_process_host_delegate.h"
20 #include "content/public/common/content_paths.h" 21 #include "content/public/common/content_paths.h"
21 #include "content/public/common/content_switches.h" 22 #include "content/public/common/content_switches.h"
22 #include "ipc/ipc_logging.h" 23 #include "ipc/ipc_logging.h"
23 24
24 #if defined(OS_LINUX) 25 #if defined(OS_LINUX)
25 #include "base/linux_util.h" 26 #include "base/linux_util.h"
26 #elif defined(OS_WIN) 27 #elif defined(OS_WIN)
27 #include "content/common/font_cache_dispatcher_win.h" 28 #include "content/common/font_cache_dispatcher_win.h"
28 #endif // OS_LINUX 29 #endif // OS_LINUX
29 30
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
66 .Append(kContentsName) 67 .Append(kContentsName)
67 .Append(kMacOSName) 68 .Append(kMacOSName)
68 .Append(new_basename); 69 .Append(new_basename);
69 70
70 return new_path; 71 return new_path;
71 } 72 }
72 73
73 } // namespace 74 } // namespace
74 #endif // OS_MACOSX 75 #endif // OS_MACOSX
75 76
76 ChildProcessHost::ChildProcessHost() 77 ChildProcessHost::ChildProcessHost(content::ChildProcessHostDelegate* delegate)
77 : ALLOW_THIS_IN_INITIALIZER_LIST(listener_(this)), 78 : delegate_(delegate),
79 peer_handle_(base::kNullProcessHandle),
78 opening_channel_(false) { 80 opening_channel_(false) {
79 #if defined(OS_WIN) 81 #if defined(OS_WIN)
80 AddFilter(new FontCacheDispatcher()); 82 AddFilter(new FontCacheDispatcher());
81 #endif 83 #endif
82 } 84 }
83 85
84 ChildProcessHost::~ChildProcessHost() { 86 ChildProcessHost::~ChildProcessHost() {
85 for (size_t i = 0; i < filters_.size(); ++i) { 87 for (size_t i = 0; i < filters_.size(); ++i) {
86 filters_[i]->OnChannelClosing(); 88 filters_[i]->OnChannelClosing();
87 filters_[i]->OnFilterRemoved(); 89 filters_[i]->OnFilterRemoved();
88 } 90 }
89 listener_.Shutdown(); 91
92 base::CloseProcessHandle(peer_handle_);
90 } 93 }
91 94
92 void ChildProcessHost::AddFilter(IPC::ChannelProxy::MessageFilter* filter) { 95 void ChildProcessHost::AddFilter(IPC::ChannelProxy::MessageFilter* filter) {
93 filters_.push_back(filter); 96 filters_.push_back(filter);
94 97
95 if (channel_.get()) 98 if (channel_.get())
96 filter->OnFilterAdded(channel_.get()); 99 filter->OnFilterAdded(channel_.get());
97 } 100 }
98 101
99 // static 102 // static
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
140 return child_path; 143 return child_path;
141 } 144 }
142 145
143 void ChildProcessHost::ForceShutdown() { 146 void ChildProcessHost::ForceShutdown() {
144 Send(new ChildProcessMsg_Shutdown()); 147 Send(new ChildProcessMsg_Shutdown());
145 } 148 }
146 149
147 bool ChildProcessHost::CreateChannel() { 150 bool ChildProcessHost::CreateChannel() {
148 channel_id_ = GenerateRandomChannelID(this); 151 channel_id_ = GenerateRandomChannelID(this);
149 channel_.reset(new IPC::Channel( 152 channel_.reset(new IPC::Channel(
150 channel_id_, IPC::Channel::MODE_SERVER, &listener_)); 153 channel_id_, IPC::Channel::MODE_SERVER, this));
151 if (!channel_->Connect()) 154 if (!channel_->Connect())
152 return false; 155 return false;
153 156
154 for (size_t i = 0; i < filters_.size(); ++i) 157 for (size_t i = 0; i < filters_.size(); ++i)
155 filters_[i]->OnFilterAdded(channel_.get()); 158 filters_[i]->OnFilterAdded(channel_.get());
156 159
157 // Make sure these messages get sent first. 160 // Make sure these messages get sent first.
158 #if defined(IPC_MESSAGE_LOG_ENABLED) 161 #if defined(IPC_MESSAGE_LOG_ENABLED)
159 bool enabled = IPC::Logging::GetInstance()->Enabled(); 162 bool enabled = IPC::Logging::GetInstance()->Enabled();
160 Send(new ChildProcessMsg_SetIPCLoggingEnabled(enabled)); 163 Send(new ChildProcessMsg_SetIPCLoggingEnabled(enabled));
161 #endif 164 #endif
162 165
163 Send(new ChildProcessMsg_AskBeforeShutdown()); 166 Send(new ChildProcessMsg_AskBeforeShutdown());
164 167
165 opening_channel_ = true; 168 opening_channel_ = true;
166 169
167 return true; 170 return true;
168 } 171 }
169 172
170 bool ChildProcessHost::OnMessageReceived(const IPC::Message& msg) {
171 return false;
172 }
173
174 void ChildProcessHost::OnChannelConnected(int32 peer_pid) {
175 }
176
177 void ChildProcessHost::OnChannelError() {
178 }
179
180 bool ChildProcessHost::Send(IPC::Message* message) { 173 bool ChildProcessHost::Send(IPC::Message* message) {
181 if (!channel_.get()) { 174 if (!channel_.get()) {
182 delete message; 175 delete message;
183 return false; 176 return false;
184 } 177 }
185 return channel_->Send(message); 178 return channel_->Send(message);
186 } 179 }
187 180
188 void ChildProcessHost::OnAllocateSharedMemory( 181 void ChildProcessHost::AllocateSharedMemory(
189 uint32 buffer_size, base::ProcessHandle child_process_handle, 182 uint32 buffer_size, base::ProcessHandle child_process_handle,
190 base::SharedMemoryHandle* shared_memory_handle) { 183 base::SharedMemoryHandle* shared_memory_handle) {
191 base::SharedMemory shared_buf; 184 base::SharedMemory shared_buf;
192 if (!shared_buf.CreateAndMapAnonymous(buffer_size)) { 185 if (!shared_buf.CreateAndMapAnonymous(buffer_size)) {
193 *shared_memory_handle = base::SharedMemory::NULLHandle(); 186 *shared_memory_handle = base::SharedMemory::NULLHandle();
194 NOTREACHED() << "Cannot map shared memory buffer"; 187 NOTREACHED() << "Cannot map shared memory buffer";
195 return; 188 return;
196 } 189 }
197 shared_buf.GiveToProcess(child_process_handle, shared_memory_handle); 190 shared_buf.GiveToProcess(child_process_handle, shared_memory_handle);
198 } 191 }
199 192
200 std::string ChildProcessHost::GenerateRandomChannelID(void* instance) { 193 std::string ChildProcessHost::GenerateRandomChannelID(void* instance) {
201 // Note: the string must start with the current process id, this is how 194 // Note: the string must start with the current process id, this is how
202 // child processes determine the pid of the parent. 195 // child processes determine the pid of the parent.
203 // Build the channel ID. This is composed of a unique identifier for the 196 // Build the channel ID. This is composed of a unique identifier for the
204 // parent browser process, an identifier for the child instance, and a random 197 // parent browser process, an identifier for the child instance, and a random
205 // component. We use a random component so that a hacked child process can't 198 // component. We use a random component so that a hacked child process can't
206 // cause denial of service by causing future named pipe creation to fail. 199 // cause denial of service by causing future named pipe creation to fail.
207 return base::StringPrintf("%d.%p.%d", 200 return base::StringPrintf("%d.%p.%d",
208 base::GetCurrentProcId(), instance, 201 base::GetCurrentProcId(), instance,
209 base::RandInt(0, std::numeric_limits<int>::max())); 202 base::RandInt(0, std::numeric_limits<int>::max()));
210 } 203 }
211 204
212 int ChildProcessHost::GenerateChildProcessUniqueId() { 205 int ChildProcessHost::GenerateChildProcessUniqueId() {
213 // This function must be threadsafe. 206 // This function must be threadsafe.
214 static base::subtle::Atomic32 last_unique_child_id = 0; 207 static base::subtle::Atomic32 last_unique_child_id = 0;
215 return base::subtle::NoBarrier_AtomicIncrement(&last_unique_child_id, 1); 208 return base::subtle::NoBarrier_AtomicIncrement(&last_unique_child_id, 1);
216 } 209 }
217 210
218 211 bool ChildProcessHost::OnMessageReceived(const IPC::Message& msg) {
219 void ChildProcessHost::OnChildDied() {
220 delete this;
221 }
222
223 void ChildProcessHost::OnChildDisconnected() {
224 OnChildDied();
225 }
226
227 void ChildProcessHost::ShutdownStarted() {
228 }
229
230 ChildProcessHost::ListenerHook::ListenerHook(ChildProcessHost* host)
231 : host_(host), peer_handle_(base::kNullProcessHandle) {
232 }
233
234 ChildProcessHost::ListenerHook::~ListenerHook() {
235 base::CloseProcessHandle(peer_handle_);
236 }
237
238 void ChildProcessHost::ListenerHook::Shutdown() {
239 host_ = NULL;
240 }
241
242 bool ChildProcessHost::ListenerHook::OnMessageReceived(
243 const IPC::Message& msg) {
244 if (!host_)
245 return true;
246
247 #ifdef IPC_MESSAGE_LOG_ENABLED 212 #ifdef IPC_MESSAGE_LOG_ENABLED
248 IPC::Logging* logger = IPC::Logging::GetInstance(); 213 IPC::Logging* logger = IPC::Logging::GetInstance();
249 if (msg.type() == IPC_LOGGING_ID) { 214 if (msg.type() == IPC_LOGGING_ID) {
250 logger->OnReceivedLoggingMessage(msg); 215 logger->OnReceivedLoggingMessage(msg);
251 return true; 216 return true;
252 } 217 }
253 218
254 if (logger->Enabled()) 219 if (logger->Enabled())
255 logger->OnPreDispatchMessage(msg); 220 logger->OnPreDispatchMessage(msg);
256 #endif 221 #endif
257 222
258 bool handled = false; 223 bool handled = false;
259 for (size_t i = 0; i < host_->filters_.size(); ++i) { 224 for (size_t i = 0; i < filters_.size(); ++i) {
260 if (host_->filters_[i]->OnMessageReceived(msg)) { 225 if (filters_[i]->OnMessageReceived(msg)) {
261 handled = true; 226 handled = true;
262 break; 227 break;
263 } 228 }
264 } 229 }
265 230
266 if (!handled) { 231 if (!handled) {
267 bool msg_is_good = false;
268 handled = true; 232 handled = true;
269 IPC_BEGIN_MESSAGE_MAP_EX(ListenerHook, msg, msg_is_good) 233 IPC_BEGIN_MESSAGE_MAP(ChildProcessHost, msg)
270 IPC_MESSAGE_HANDLER(ChildProcessHostMsg_ShutdownRequest, 234 IPC_MESSAGE_HANDLER(ChildProcessHostMsg_ShutdownRequest,
271 OnShutdownRequest) 235 OnShutdownRequest)
272 IPC_MESSAGE_HANDLER(ChildProcessHostMsg_SyncAllocateSharedMemory, 236 IPC_MESSAGE_HANDLER(ChildProcessHostMsg_SyncAllocateSharedMemory,
273 OnAllocateSharedMemory) 237 OnAllocateSharedMemory)
274 IPC_MESSAGE_UNHANDLED(handled = false) 238 IPC_MESSAGE_UNHANDLED(handled = false)
275 IPC_END_MESSAGE_MAP_EX() 239 IPC_END_MESSAGE_MAP()
276 240
277 if (!handled) 241 if (!handled)
278 handled = host_->OnMessageReceived(msg); 242 handled = delegate_->OnMessageReceived(msg);
279 } 243 }
280 244
281 #ifdef IPC_MESSAGE_LOG_ENABLED 245 #ifdef IPC_MESSAGE_LOG_ENABLED
282 if (logger->Enabled()) 246 if (logger->Enabled())
283 logger->OnPostDispatchMessage(msg, host_->channel_id_); 247 logger->OnPostDispatchMessage(msg, channel_id_);
284 #endif 248 #endif
285 return handled; 249 return handled;
286 } 250 }
287 251
288 void ChildProcessHost::ListenerHook::OnChannelConnected(int32 peer_pid) { 252 void ChildProcessHost::OnChannelConnected(int32 peer_pid) {
289 if (!host_)
290 return;
291 if (!base::OpenProcessHandle(peer_pid, &peer_handle_)) { 253 if (!base::OpenProcessHandle(peer_pid, &peer_handle_)) {
292 NOTREACHED(); 254 NOTREACHED();
293 } 255 }
294 host_->opening_channel_ = false; 256 opening_channel_ = false;
295 host_->OnChannelConnected(peer_pid); 257 delegate_->OnChannelConnected(peer_pid);
296 for (size_t i = 0; i < host_->filters_.size(); ++i) 258 for (size_t i = 0; i < filters_.size(); ++i)
297 host_->filters_[i]->OnChannelConnected(peer_pid); 259 filters_[i]->OnChannelConnected(peer_pid);
298 } 260 }
299 261
300 void ChildProcessHost::ListenerHook::OnChannelError() { 262 void ChildProcessHost::OnChannelError() {
301 if (!host_) 263 opening_channel_ = false;
302 return; 264 delegate_->OnChannelError();
303 host_->opening_channel_ = false;
304 host_->OnChannelError();
305 265
306 for (size_t i = 0; i < host_->filters_.size(); ++i) 266 for (size_t i = 0; i < filters_.size(); ++i)
307 host_->filters_[i]->OnChannelError(); 267 filters_[i]->OnChannelError();
308 268
309 // This will delete host_, which will also destroy this! 269 // This will delete host_, which will also destroy this!
310 host_->OnChildDisconnected(); 270 delegate_->OnChildDisconnected();
311 } 271 }
312 272
313 bool ChildProcessHost::ListenerHook::Send(IPC::Message* message) { 273 void ChildProcessHost::OnAllocateSharedMemory(
314 return host_->Send(message); 274 uint32 buffer_size,
275 base::SharedMemoryHandle* handle) {
276 AllocateSharedMemory(buffer_size, peer_handle_, handle);
315 } 277 }
316 278
317 void ChildProcessHost::ListenerHook::OnAllocateSharedMemory( 279 void ChildProcessHost::OnShutdownRequest() {
318 uint32 buffer_size, 280 if (delegate_->CanShutdown())
319 base::SharedMemoryHandle* handle) { 281 Send(new ChildProcessMsg_Shutdown());
320 ChildProcessHost::OnAllocateSharedMemory(
321 buffer_size, peer_handle_, handle);
322 } 282 }
323
324 void ChildProcessHost::ListenerHook::OnShutdownRequest() {
325 if (host_->CanShutdown())
326 host_->Send(new ChildProcessMsg_Shutdown());
327 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698