OLD | NEW |
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_impl.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" |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
67 .Append(kContentsName) | 67 .Append(kContentsName) |
68 .Append(kMacOSName) | 68 .Append(kMacOSName) |
69 .Append(new_basename); | 69 .Append(new_basename); |
70 | 70 |
71 return new_path; | 71 return new_path; |
72 } | 72 } |
73 | 73 |
74 } // namespace | 74 } // namespace |
75 #endif // OS_MACOSX | 75 #endif // OS_MACOSX |
76 | 76 |
77 ChildProcessHost::ChildProcessHost(content::ChildProcessHostDelegate* delegate) | 77 namespace content { |
78 : delegate_(delegate), | |
79 peer_handle_(base::kNullProcessHandle), | |
80 opening_channel_(false) { | |
81 #if defined(OS_WIN) | |
82 AddFilter(new FontCacheDispatcher()); | |
83 #endif | |
84 } | |
85 | 78 |
86 ChildProcessHost::~ChildProcessHost() { | 79 // static |
87 for (size_t i = 0; i < filters_.size(); ++i) { | 80 ChildProcessHost* ChildProcessHost::Create(ChildProcessHostDelegate* delegate) { |
88 filters_[i]->OnChannelClosing(); | 81 return new ChildProcessHostImpl(delegate); |
89 filters_[i]->OnFilterRemoved(); | |
90 } | |
91 | |
92 base::CloseProcessHandle(peer_handle_); | |
93 } | |
94 | |
95 void ChildProcessHost::AddFilter(IPC::ChannelProxy::MessageFilter* filter) { | |
96 filters_.push_back(filter); | |
97 | |
98 if (channel_.get()) | |
99 filter->OnFilterAdded(channel_.get()); | |
100 } | 82 } |
101 | 83 |
102 // static | 84 // static |
103 FilePath ChildProcessHost::GetChildPath(int flags) { | 85 FilePath ChildProcessHost::GetChildPath(int flags) { |
104 FilePath child_path; | 86 FilePath child_path; |
105 | 87 |
106 child_path = CommandLine::ForCurrentProcess()->GetSwitchValuePath( | 88 child_path = CommandLine::ForCurrentProcess()->GetSwitchValuePath( |
107 switches::kBrowserSubprocessPath); | 89 switches::kBrowserSubprocessPath); |
108 | 90 |
109 #if defined(OS_LINUX) | 91 #if defined(OS_LINUX) |
(...skipping 26 matching lines...) Expand all Loading... |
136 // non-executable heap, but the "EH" feature is provided to allow code | 118 // non-executable heap, but the "EH" feature is provided to allow code |
137 // intolerant of a non-executable heap to work properly on 10.7. This | 119 // intolerant of a non-executable heap to work properly on 10.7. This |
138 // results in Chromium Helper EH.app or Google Chrome Helper EH.app. | 120 // results in Chromium Helper EH.app or Google Chrome Helper EH.app. |
139 child_path = TransformPathForFeature(child_path, "EH"); | 121 child_path = TransformPathForFeature(child_path, "EH"); |
140 } | 122 } |
141 #endif | 123 #endif |
142 | 124 |
143 return child_path; | 125 return child_path; |
144 } | 126 } |
145 | 127 |
146 void ChildProcessHost::ForceShutdown() { | 128 ChildProcessHostImpl::ChildProcessHostImpl(ChildProcessHostDelegate* delegate) |
| 129 : delegate_(delegate), |
| 130 peer_handle_(base::kNullProcessHandle), |
| 131 opening_channel_(false) { |
| 132 #if defined(OS_WIN) |
| 133 AddFilter(new FontCacheDispatcher()); |
| 134 #endif |
| 135 } |
| 136 |
| 137 ChildProcessHostImpl::~ChildProcessHostImpl() { |
| 138 for (size_t i = 0; i < filters_.size(); ++i) { |
| 139 filters_[i]->OnChannelClosing(); |
| 140 filters_[i]->OnFilterRemoved(); |
| 141 } |
| 142 |
| 143 base::CloseProcessHandle(peer_handle_); |
| 144 } |
| 145 |
| 146 void ChildProcessHostImpl::AddFilter(IPC::ChannelProxy::MessageFilter* filter) { |
| 147 filters_.push_back(filter); |
| 148 |
| 149 if (channel_.get()) |
| 150 filter->OnFilterAdded(channel_.get()); |
| 151 } |
| 152 |
| 153 void ChildProcessHostImpl::ForceShutdown() { |
147 Send(new ChildProcessMsg_Shutdown()); | 154 Send(new ChildProcessMsg_Shutdown()); |
148 } | 155 } |
149 | 156 |
150 bool ChildProcessHost::CreateChannel() { | 157 std::string ChildProcessHostImpl::CreateChannel() { |
151 channel_id_ = GenerateRandomChannelID(this); | 158 channel_id_ = GenerateRandomChannelID(this); |
152 channel_.reset(new IPC::Channel( | 159 channel_.reset(new IPC::Channel( |
153 channel_id_, IPC::Channel::MODE_SERVER, this)); | 160 channel_id_, IPC::Channel::MODE_SERVER, this)); |
154 if (!channel_->Connect()) | 161 if (!channel_->Connect()) |
155 return false; | 162 return std::string(); |
156 | 163 |
157 for (size_t i = 0; i < filters_.size(); ++i) | 164 for (size_t i = 0; i < filters_.size(); ++i) |
158 filters_[i]->OnFilterAdded(channel_.get()); | 165 filters_[i]->OnFilterAdded(channel_.get()); |
159 | 166 |
160 // Make sure these messages get sent first. | 167 // Make sure these messages get sent first. |
161 #if defined(IPC_MESSAGE_LOG_ENABLED) | 168 #if defined(IPC_MESSAGE_LOG_ENABLED) |
162 bool enabled = IPC::Logging::GetInstance()->Enabled(); | 169 bool enabled = IPC::Logging::GetInstance()->Enabled(); |
163 Send(new ChildProcessMsg_SetIPCLoggingEnabled(enabled)); | 170 Send(new ChildProcessMsg_SetIPCLoggingEnabled(enabled)); |
164 #endif | 171 #endif |
165 | 172 |
166 Send(new ChildProcessMsg_AskBeforeShutdown()); | 173 Send(new ChildProcessMsg_AskBeforeShutdown()); |
167 | 174 |
168 opening_channel_ = true; | 175 opening_channel_ = true; |
169 | 176 |
170 return true; | 177 return channel_id_; |
171 } | 178 } |
172 | 179 |
173 bool ChildProcessHost::Send(IPC::Message* message) { | 180 bool ChildProcessHostImpl::IsChannelOpening() { |
| 181 return opening_channel_; |
| 182 } |
| 183 |
| 184 #if defined(OS_POSIX) |
| 185 int ChildProcessHostImpl::TakeClientFileDescriptor() { |
| 186 return channel_->TakeClientFileDescriptor(); |
| 187 } |
| 188 #endif |
| 189 |
| 190 bool ChildProcessHostImpl::Send(IPC::Message* message) { |
174 if (!channel_.get()) { | 191 if (!channel_.get()) { |
175 delete message; | 192 delete message; |
176 return false; | 193 return false; |
177 } | 194 } |
178 return channel_->Send(message); | 195 return channel_->Send(message); |
179 } | 196 } |
180 | 197 |
181 void ChildProcessHost::AllocateSharedMemory( | 198 void ChildProcessHostImpl::AllocateSharedMemory( |
182 uint32 buffer_size, base::ProcessHandle child_process_handle, | 199 uint32 buffer_size, base::ProcessHandle child_process_handle, |
183 base::SharedMemoryHandle* shared_memory_handle) { | 200 base::SharedMemoryHandle* shared_memory_handle) { |
184 base::SharedMemory shared_buf; | 201 base::SharedMemory shared_buf; |
185 if (!shared_buf.CreateAndMapAnonymous(buffer_size)) { | 202 if (!shared_buf.CreateAndMapAnonymous(buffer_size)) { |
186 *shared_memory_handle = base::SharedMemory::NULLHandle(); | 203 *shared_memory_handle = base::SharedMemory::NULLHandle(); |
187 NOTREACHED() << "Cannot map shared memory buffer"; | 204 NOTREACHED() << "Cannot map shared memory buffer"; |
188 return; | 205 return; |
189 } | 206 } |
190 shared_buf.GiveToProcess(child_process_handle, shared_memory_handle); | 207 shared_buf.GiveToProcess(child_process_handle, shared_memory_handle); |
191 } | 208 } |
192 | 209 |
193 std::string ChildProcessHost::GenerateRandomChannelID(void* instance) { | 210 std::string ChildProcessHostImpl::GenerateRandomChannelID(void* instance) { |
194 // Note: the string must start with the current process id, this is how | 211 // Note: the string must start with the current process id, this is how |
195 // child processes determine the pid of the parent. | 212 // child processes determine the pid of the parent. |
196 // Build the channel ID. This is composed of a unique identifier for the | 213 // Build the channel ID. This is composed of a unique identifier for the |
197 // parent browser process, an identifier for the child instance, and a random | 214 // parent browser process, an identifier for the child instance, and a random |
198 // component. We use a random component so that a hacked child process can't | 215 // component. We use a random component so that a hacked child process can't |
199 // cause denial of service by causing future named pipe creation to fail. | 216 // cause denial of service by causing future named pipe creation to fail. |
200 return base::StringPrintf("%d.%p.%d", | 217 return base::StringPrintf("%d.%p.%d", |
201 base::GetCurrentProcId(), instance, | 218 base::GetCurrentProcId(), instance, |
202 base::RandInt(0, std::numeric_limits<int>::max())); | 219 base::RandInt(0, std::numeric_limits<int>::max())); |
203 } | 220 } |
204 | 221 |
205 int ChildProcessHost::GenerateChildProcessUniqueId() { | 222 int ChildProcessHostImpl::GenerateChildProcessUniqueId() { |
206 // This function must be threadsafe. | 223 // This function must be threadsafe. |
207 static base::subtle::Atomic32 last_unique_child_id = 0; | 224 static base::subtle::Atomic32 last_unique_child_id = 0; |
208 return base::subtle::NoBarrier_AtomicIncrement(&last_unique_child_id, 1); | 225 return base::subtle::NoBarrier_AtomicIncrement(&last_unique_child_id, 1); |
209 } | 226 } |
210 | 227 |
211 bool ChildProcessHost::OnMessageReceived(const IPC::Message& msg) { | 228 bool ChildProcessHostImpl::OnMessageReceived(const IPC::Message& msg) { |
212 #ifdef IPC_MESSAGE_LOG_ENABLED | 229 #ifdef IPC_MESSAGE_LOG_ENABLED |
213 IPC::Logging* logger = IPC::Logging::GetInstance(); | 230 IPC::Logging* logger = IPC::Logging::GetInstance(); |
214 if (msg.type() == IPC_LOGGING_ID) { | 231 if (msg.type() == IPC_LOGGING_ID) { |
215 logger->OnReceivedLoggingMessage(msg); | 232 logger->OnReceivedLoggingMessage(msg); |
216 return true; | 233 return true; |
217 } | 234 } |
218 | 235 |
219 if (logger->Enabled()) | 236 if (logger->Enabled()) |
220 logger->OnPreDispatchMessage(msg); | 237 logger->OnPreDispatchMessage(msg); |
221 #endif | 238 #endif |
222 | 239 |
223 bool handled = false; | 240 bool handled = false; |
224 for (size_t i = 0; i < filters_.size(); ++i) { | 241 for (size_t i = 0; i < filters_.size(); ++i) { |
225 if (filters_[i]->OnMessageReceived(msg)) { | 242 if (filters_[i]->OnMessageReceived(msg)) { |
226 handled = true; | 243 handled = true; |
227 break; | 244 break; |
228 } | 245 } |
229 } | 246 } |
230 | 247 |
231 if (!handled) { | 248 if (!handled) { |
232 handled = true; | 249 handled = true; |
233 IPC_BEGIN_MESSAGE_MAP(ChildProcessHost, msg) | 250 IPC_BEGIN_MESSAGE_MAP(ChildProcessHostImpl, msg) |
234 IPC_MESSAGE_HANDLER(ChildProcessHostMsg_ShutdownRequest, | 251 IPC_MESSAGE_HANDLER(ChildProcessHostMsg_ShutdownRequest, |
235 OnShutdownRequest) | 252 OnShutdownRequest) |
236 IPC_MESSAGE_HANDLER(ChildProcessHostMsg_SyncAllocateSharedMemory, | 253 IPC_MESSAGE_HANDLER(ChildProcessHostMsg_SyncAllocateSharedMemory, |
237 OnAllocateSharedMemory) | 254 OnAllocateSharedMemory) |
238 IPC_MESSAGE_UNHANDLED(handled = false) | 255 IPC_MESSAGE_UNHANDLED(handled = false) |
239 IPC_END_MESSAGE_MAP() | 256 IPC_END_MESSAGE_MAP() |
240 | 257 |
241 if (!handled) | 258 if (!handled) |
242 handled = delegate_->OnMessageReceived(msg); | 259 handled = delegate_->OnMessageReceived(msg); |
243 } | 260 } |
244 | 261 |
245 #ifdef IPC_MESSAGE_LOG_ENABLED | 262 #ifdef IPC_MESSAGE_LOG_ENABLED |
246 if (logger->Enabled()) | 263 if (logger->Enabled()) |
247 logger->OnPostDispatchMessage(msg, channel_id_); | 264 logger->OnPostDispatchMessage(msg, channel_id_); |
248 #endif | 265 #endif |
249 return handled; | 266 return handled; |
250 } | 267 } |
251 | 268 |
252 void ChildProcessHost::OnChannelConnected(int32 peer_pid) { | 269 void ChildProcessHostImpl::OnChannelConnected(int32 peer_pid) { |
253 if (!base::OpenProcessHandle(peer_pid, &peer_handle_)) { | 270 if (!base::OpenProcessHandle(peer_pid, &peer_handle_)) { |
254 NOTREACHED(); | 271 NOTREACHED(); |
255 } | 272 } |
256 opening_channel_ = false; | 273 opening_channel_ = false; |
257 delegate_->OnChannelConnected(peer_pid); | 274 delegate_->OnChannelConnected(peer_pid); |
258 for (size_t i = 0; i < filters_.size(); ++i) | 275 for (size_t i = 0; i < filters_.size(); ++i) |
259 filters_[i]->OnChannelConnected(peer_pid); | 276 filters_[i]->OnChannelConnected(peer_pid); |
260 } | 277 } |
261 | 278 |
262 void ChildProcessHost::OnChannelError() { | 279 void ChildProcessHostImpl::OnChannelError() { |
263 opening_channel_ = false; | 280 opening_channel_ = false; |
264 delegate_->OnChannelError(); | 281 delegate_->OnChannelError(); |
265 | 282 |
266 for (size_t i = 0; i < filters_.size(); ++i) | 283 for (size_t i = 0; i < filters_.size(); ++i) |
267 filters_[i]->OnChannelError(); | 284 filters_[i]->OnChannelError(); |
268 | 285 |
269 // This will delete host_, which will also destroy this! | 286 // This will delete host_, which will also destroy this! |
270 delegate_->OnChildDisconnected(); | 287 delegate_->OnChildDisconnected(); |
271 } | 288 } |
272 | 289 |
273 void ChildProcessHost::OnAllocateSharedMemory( | 290 void ChildProcessHostImpl::OnAllocateSharedMemory( |
274 uint32 buffer_size, | 291 uint32 buffer_size, |
275 base::SharedMemoryHandle* handle) { | 292 base::SharedMemoryHandle* handle) { |
276 AllocateSharedMemory(buffer_size, peer_handle_, handle); | 293 AllocateSharedMemory(buffer_size, peer_handle_, handle); |
277 } | 294 } |
278 | 295 |
279 void ChildProcessHost::OnShutdownRequest() { | 296 void ChildProcessHostImpl::OnShutdownRequest() { |
280 if (delegate_->CanShutdown()) | 297 if (delegate_->CanShutdown()) |
281 Send(new ChildProcessMsg_Shutdown()); | 298 Send(new ChildProcessMsg_Shutdown()); |
282 } | 299 } |
| 300 |
| 301 } // namespace content |
OLD | NEW |