| 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 |