[email protected] | 5c41e6e1 | 2012-03-17 02:20:46 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
[email protected] | d27893f6 | 2010-07-03 05:47:42 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
[email protected] | 4734d0b | 2011-12-03 07:10:44 | [diff] [blame] | 5 | #include "content/common/child_process_host_impl.h" |
[email protected] | d27893f6 | 2010-07-03 05:47:42 | [diff] [blame] | 6 | |
[email protected] | 4306c379 | 2011-12-02 01:57:53 | [diff] [blame] | 7 | #include <limits> |
| 8 | |
| 9 | #include "base/atomicops.h" |
[email protected] | d27893f6 | 2010-07-03 05:47:42 | [diff] [blame] | 10 | #include "base/command_line.h" |
[email protected] | 5799981 | 2013-02-24 05:40:52 | [diff] [blame] | 11 | #include "base/files/file_path.h" |
[email protected] | 8c40f32 | 2011-08-24 03:33:36 | [diff] [blame] | 12 | #include "base/logging.h" |
[email protected] | 835d7c8 | 2010-10-14 04:38:38 | [diff] [blame] | 13 | #include "base/metrics/histogram.h" |
[email protected] | d27893f6 | 2010-07-03 05:47:42 | [diff] [blame] | 14 | #include "base/path_service.h" |
[email protected] | bdae981 | 2011-10-15 00:33:03 | [diff] [blame] | 15 | #include "base/process_util.h" |
[email protected] | 4306c379 | 2011-12-02 01:57:53 | [diff] [blame] | 16 | #include "base/rand_util.h" |
| 17 | #include "base/stringprintf.h" |
[email protected] | a5f28b4 | 2011-01-17 10:30:13 | [diff] [blame] | 18 | #include "base/third_party/dynamic_annotations/dynamic_annotations.h" |
[email protected] | ff47b296 | 2011-03-07 23:51:49 | [diff] [blame] | 19 | #include "content/common/child_process_messages.h" |
[email protected] | 4cb4310 | 2011-12-02 20:24:49 | [diff] [blame] | 20 | #include "content/public/common/child_process_host_delegate.h" |
[email protected] | 5d921d4c | 2011-10-21 22:26:14 | [diff] [blame] | 21 | #include "content/public/common/content_paths.h" |
[email protected] | c08950d2 | 2011-10-13 22:20:29 | [diff] [blame] | 22 | #include "content/public/common/content_switches.h" |
[email protected] | 5c41e6e1 | 2012-03-17 02:20:46 | [diff] [blame] | 23 | #include "ipc/ipc_channel.h" |
[email protected] | a83d4229 | 2010-08-17 22:51:10 | [diff] [blame] | 24 | #include "ipc/ipc_logging.h" |
[email protected] | d27893f6 | 2010-07-03 05:47:42 | [diff] [blame] | 25 | |
| 26 | #if defined(OS_LINUX) |
| 27 | #include "base/linux_util.h" |
[email protected] | e35c9a8 | 2011-12-01 18:48:41 | [diff] [blame] | 28 | #elif defined(OS_WIN) |
| 29 | #include "content/common/font_cache_dispatcher_win.h" |
[email protected] | d27893f6 | 2010-07-03 05:47:42 | [diff] [blame] | 30 | #endif // OS_LINUX |
| 31 | |
[email protected] | 8c40f32 | 2011-08-24 03:33:36 | [diff] [blame] | 32 | #if defined(OS_MACOSX) |
| 33 | namespace { |
| 34 | |
| 35 | // Given |path| identifying a Mac-style child process executable path, adjusts |
| 36 | // it to correspond to |feature|. For a child process path such as |
| 37 | // ".../Chromium Helper.app/Contents/MacOS/Chromium Helper", the transformed |
| 38 | // path for feature "NP" would be |
| 39 | // ".../Chromium Helper NP.app/Contents/MacOS/Chromium Helper NP". The new |
| 40 | // path is returned. |
[email protected] | a732916 | 2013-02-07 19:21:48 | [diff] [blame] | 41 | base::FilePath TransformPathForFeature(const base::FilePath& path, |
[email protected] | 8c40f32 | 2011-08-24 03:33:36 | [diff] [blame] | 42 | const std::string& feature) { |
| 43 | std::string basename = path.BaseName().value(); |
| 44 | |
[email protected] | a732916 | 2013-02-07 19:21:48 | [diff] [blame] | 45 | base::FilePath macos_path = path.DirName(); |
[email protected] | 8c40f32 | 2011-08-24 03:33:36 | [diff] [blame] | 46 | const char kMacOSName[] = "MacOS"; |
| 47 | DCHECK_EQ(kMacOSName, macos_path.BaseName().value()); |
| 48 | |
[email protected] | a732916 | 2013-02-07 19:21:48 | [diff] [blame] | 49 | base::FilePath contents_path = macos_path.DirName(); |
[email protected] | 8c40f32 | 2011-08-24 03:33:36 | [diff] [blame] | 50 | const char kContentsName[] = "Contents"; |
| 51 | DCHECK_EQ(kContentsName, contents_path.BaseName().value()); |
| 52 | |
[email protected] | a732916 | 2013-02-07 19:21:48 | [diff] [blame] | 53 | base::FilePath helper_app_path = contents_path.DirName(); |
[email protected] | 8c40f32 | 2011-08-24 03:33:36 | [diff] [blame] | 54 | const char kAppExtension[] = ".app"; |
| 55 | std::string basename_app = basename; |
| 56 | basename_app.append(kAppExtension); |
| 57 | DCHECK_EQ(basename_app, helper_app_path.BaseName().value()); |
| 58 | |
[email protected] | a732916 | 2013-02-07 19:21:48 | [diff] [blame] | 59 | base::FilePath root_path = helper_app_path.DirName(); |
[email protected] | 8c40f32 | 2011-08-24 03:33:36 | [diff] [blame] | 60 | |
| 61 | std::string new_basename = basename; |
| 62 | new_basename.append(1, ' '); |
| 63 | new_basename.append(feature); |
| 64 | std::string new_basename_app = new_basename; |
| 65 | new_basename_app.append(kAppExtension); |
| 66 | |
[email protected] | a732916 | 2013-02-07 19:21:48 | [diff] [blame] | 67 | base::FilePath new_path = root_path.Append(new_basename_app) |
[email protected] | 8c40f32 | 2011-08-24 03:33:36 | [diff] [blame] | 68 | .Append(kContentsName) |
| 69 | .Append(kMacOSName) |
| 70 | .Append(new_basename); |
| 71 | |
| 72 | return new_path; |
| 73 | } |
| 74 | |
| 75 | } // namespace |
| 76 | #endif // OS_MACOSX |
| 77 | |
[email protected] | 4734d0b | 2011-12-03 07:10:44 | [diff] [blame] | 78 | namespace content { |
[email protected] | d27893f6 | 2010-07-03 05:47:42 | [diff] [blame] | 79 | |
[email protected] | d7c7c98a | 2012-07-12 21:27:44 | [diff] [blame] | 80 | int ChildProcessHostImpl::kInvalidChildProcessId = -1; |
| 81 | |
[email protected] | 4734d0b | 2011-12-03 07:10:44 | [diff] [blame] | 82 | // static |
| 83 | ChildProcessHost* ChildProcessHost::Create(ChildProcessHostDelegate* delegate) { |
| 84 | return new ChildProcessHostImpl(delegate); |
[email protected] | d27893f6 | 2010-07-03 05:47:42 | [diff] [blame] | 85 | } |
| 86 | |
| 87 | // static |
[email protected] | a732916 | 2013-02-07 19:21:48 | [diff] [blame] | 88 | base::FilePath ChildProcessHost::GetChildPath(int flags) { |
| 89 | base::FilePath child_path; |
[email protected] | d27893f6 | 2010-07-03 05:47:42 | [diff] [blame] | 90 | |
| 91 | child_path = CommandLine::ForCurrentProcess()->GetSwitchValuePath( |
| 92 | switches::kBrowserSubprocessPath); |
[email protected] | d27893f6 | 2010-07-03 05:47:42 | [diff] [blame] | 93 | |
[email protected] | d27893f6 | 2010-07-03 05:47:42 | [diff] [blame] | 94 | #if defined(OS_LINUX) |
| 95 | // Use /proc/self/exe rather than our known binary path so updates |
| 96 | // can't swap out the binary from underneath us. |
[email protected] | a5f28b4 | 2011-01-17 10:30:13 | [diff] [blame] | 97 | // When running under Valgrind, forking /proc/self/exe ends up forking the |
| 98 | // Valgrind executable, which then crashes. However, it's almost safe to |
| 99 | // assume that the updates won't happen while testing with Valgrind tools. |
[email protected] | bfd4748 | 2011-08-24 13:57:26 | [diff] [blame] | 100 | if (child_path.empty() && flags & CHILD_ALLOW_SELF && !RunningOnValgrind()) |
[email protected] | a732916 | 2013-02-07 19:21:48 | [diff] [blame] | 101 | child_path = base::FilePath(base::kProcSelfExe); |
[email protected] | d27893f6 | 2010-07-03 05:47:42 | [diff] [blame] | 102 | #endif |
| 103 | |
| 104 | // On most platforms, the child executable is the same as the current |
| 105 | // executable. |
[email protected] | bfd4748 | 2011-08-24 13:57:26 | [diff] [blame] | 106 | if (child_path.empty()) |
[email protected] | dcc72db | 2013-01-02 00:44:18 | [diff] [blame] | 107 | PathService::Get(CHILD_PROCESS_EXE, &child_path); |
[email protected] | 8c40f32 | 2011-08-24 03:33:36 | [diff] [blame] | 108 | |
| 109 | #if defined(OS_MACOSX) |
| 110 | DCHECK(!(flags & CHILD_NO_PIE && flags & CHILD_ALLOW_HEAP_EXECUTION)); |
| 111 | |
| 112 | // If needed, choose an executable with special flags set that inform the |
| 113 | // kernel to enable or disable specific optional process-wide features. |
| 114 | if (flags & CHILD_NO_PIE) { |
| 115 | // "NP" is "No PIE". This results in Chromium Helper NP.app or |
| 116 | // Google Chrome Helper NP.app. |
| 117 | child_path = TransformPathForFeature(child_path, "NP"); |
| 118 | } else if (flags & CHILD_ALLOW_HEAP_EXECUTION) { |
| 119 | // "EH" is "Executable Heap". A non-executable heap is only available to |
| 120 | // 32-bit processes on Mac OS X 10.7. Most code can and should run with a |
| 121 | // non-executable heap, but the "EH" feature is provided to allow code |
| 122 | // intolerant of a non-executable heap to work properly on 10.7. This |
| 123 | // results in Chromium Helper EH.app or Google Chrome Helper EH.app. |
| 124 | child_path = TransformPathForFeature(child_path, "EH"); |
| 125 | } |
| 126 | #endif |
| 127 | |
[email protected] | d27893f6 | 2010-07-03 05:47:42 | [diff] [blame] | 128 | return child_path; |
| 129 | } |
| 130 | |
[email protected] | 4734d0b | 2011-12-03 07:10:44 | [diff] [blame] | 131 | ChildProcessHostImpl::ChildProcessHostImpl(ChildProcessHostDelegate* delegate) |
| 132 | : delegate_(delegate), |
| 133 | peer_handle_(base::kNullProcessHandle), |
| 134 | opening_channel_(false) { |
| 135 | #if defined(OS_WIN) |
| 136 | AddFilter(new FontCacheDispatcher()); |
| 137 | #endif |
| 138 | } |
| 139 | |
| 140 | ChildProcessHostImpl::~ChildProcessHostImpl() { |
| 141 | for (size_t i = 0; i < filters_.size(); ++i) { |
| 142 | filters_[i]->OnChannelClosing(); |
| 143 | filters_[i]->OnFilterRemoved(); |
| 144 | } |
| 145 | |
| 146 | base::CloseProcessHandle(peer_handle_); |
| 147 | } |
| 148 | |
| 149 | void ChildProcessHostImpl::AddFilter(IPC::ChannelProxy::MessageFilter* filter) { |
| 150 | filters_.push_back(filter); |
| 151 | |
[email protected] | 59383c78 | 2013-04-17 16:43:27 | [diff] [blame^] | 152 | if (channel_) |
[email protected] | 4734d0b | 2011-12-03 07:10:44 | [diff] [blame] | 153 | filter->OnFilterAdded(channel_.get()); |
| 154 | } |
| 155 | |
| 156 | void ChildProcessHostImpl::ForceShutdown() { |
[email protected] | bdae981 | 2011-10-15 00:33:03 | [diff] [blame] | 157 | Send(new ChildProcessMsg_Shutdown()); |
| 158 | } |
[email protected] | 91443fc | 2010-07-14 05:08:46 | [diff] [blame] | 159 | |
[email protected] | 4734d0b | 2011-12-03 07:10:44 | [diff] [blame] | 160 | std::string ChildProcessHostImpl::CreateChannel() { |
[email protected] | 5c41e6e1 | 2012-03-17 02:20:46 | [diff] [blame] | 161 | channel_id_ = IPC::Channel::GenerateVerifiedChannelID(std::string()); |
[email protected] | d27893f6 | 2010-07-03 05:47:42 | [diff] [blame] | 162 | channel_.reset(new IPC::Channel( |
[email protected] | 4cb4310 | 2011-12-02 20:24:49 | [diff] [blame] | 163 | channel_id_, IPC::Channel::MODE_SERVER, this)); |
[email protected] | d27893f6 | 2010-07-03 05:47:42 | [diff] [blame] | 164 | if (!channel_->Connect()) |
[email protected] | 4734d0b | 2011-12-03 07:10:44 | [diff] [blame] | 165 | return std::string(); |
[email protected] | d27893f6 | 2010-07-03 05:47:42 | [diff] [blame] | 166 | |
[email protected] | 8e2b647 | 2010-12-15 22:19:48 | [diff] [blame] | 167 | for (size_t i = 0; i < filters_.size(); ++i) |
| 168 | filters_[i]->OnFilterAdded(channel_.get()); |
| 169 | |
[email protected] | 91443fc | 2010-07-14 05:08:46 | [diff] [blame] | 170 | // Make sure these messages get sent first. |
| 171 | #if defined(IPC_MESSAGE_LOG_ENABLED) |
[email protected] | 8e8bb6d | 2010-12-13 08:18:55 | [diff] [blame] | 172 | bool enabled = IPC::Logging::GetInstance()->Enabled(); |
[email protected] | ff47b296 | 2011-03-07 23:51:49 | [diff] [blame] | 173 | Send(new ChildProcessMsg_SetIPCLoggingEnabled(enabled)); |
[email protected] | 91443fc | 2010-07-14 05:08:46 | [diff] [blame] | 174 | #endif |
| 175 | |
[email protected] | d27893f6 | 2010-07-03 05:47:42 | [diff] [blame] | 176 | opening_channel_ = true; |
| 177 | |
[email protected] | 4734d0b | 2011-12-03 07:10:44 | [diff] [blame] | 178 | return channel_id_; |
[email protected] | d27893f6 | 2010-07-03 05:47:42 | [diff] [blame] | 179 | } |
| 180 | |
[email protected] | 4734d0b | 2011-12-03 07:10:44 | [diff] [blame] | 181 | bool ChildProcessHostImpl::IsChannelOpening() { |
| 182 | return opening_channel_; |
| 183 | } |
| 184 | |
| 185 | #if defined(OS_POSIX) |
| 186 | int ChildProcessHostImpl::TakeClientFileDescriptor() { |
| 187 | return channel_->TakeClientFileDescriptor(); |
| 188 | } |
| 189 | #endif |
| 190 | |
| 191 | bool ChildProcessHostImpl::Send(IPC::Message* message) { |
[email protected] | 59383c78 | 2013-04-17 16:43:27 | [diff] [blame^] | 192 | if (!channel_) { |
[email protected] | 8e2b647 | 2010-12-15 22:19:48 | [diff] [blame] | 193 | delete message; |
[email protected] | d27893f6 | 2010-07-03 05:47:42 | [diff] [blame] | 194 | return false; |
| 195 | } |
[email protected] | 8e2b647 | 2010-12-15 22:19:48 | [diff] [blame] | 196 | return channel_->Send(message); |
[email protected] | d27893f6 | 2010-07-03 05:47:42 | [diff] [blame] | 197 | } |
| 198 | |
[email protected] | 4734d0b | 2011-12-03 07:10:44 | [diff] [blame] | 199 | void ChildProcessHostImpl::AllocateSharedMemory( |
[email protected] | 3f89283 | 2013-01-11 03:23:59 | [diff] [blame] | 200 | size_t buffer_size, base::ProcessHandle child_process_handle, |
[email protected] | bdae981 | 2011-10-15 00:33:03 | [diff] [blame] | 201 | base::SharedMemoryHandle* shared_memory_handle) { |
| 202 | base::SharedMemory shared_buf; |
| 203 | if (!shared_buf.CreateAndMapAnonymous(buffer_size)) { |
| 204 | *shared_memory_handle = base::SharedMemory::NULLHandle(); |
| 205 | NOTREACHED() << "Cannot map shared memory buffer"; |
| 206 | return; |
| 207 | } |
| 208 | shared_buf.GiveToProcess(child_process_handle, shared_memory_handle); |
| 209 | } |
| 210 | |
[email protected] | 4734d0b | 2011-12-03 07:10:44 | [diff] [blame] | 211 | int ChildProcessHostImpl::GenerateChildProcessUniqueId() { |
[email protected] | 4306c379 | 2011-12-02 01:57:53 | [diff] [blame] | 212 | // This function must be threadsafe. |
[email protected] | d7c7c98a | 2012-07-12 21:27:44 | [diff] [blame] | 213 | // |
| 214 | // TODO(ajwong): Why not StaticAtomicSequenceNumber? |
[email protected] | 4306c379 | 2011-12-02 01:57:53 | [diff] [blame] | 215 | static base::subtle::Atomic32 last_unique_child_id = 0; |
[email protected] | d7c7c98a | 2012-07-12 21:27:44 | [diff] [blame] | 216 | int id = base::subtle::NoBarrier_AtomicIncrement(&last_unique_child_id, 1); |
| 217 | |
| 218 | CHECK_NE(kInvalidChildProcessId, id); |
| 219 | |
| 220 | return id; |
[email protected] | 4306c379 | 2011-12-02 01:57:53 | [diff] [blame] | 221 | } |
| 222 | |
[email protected] | 4734d0b | 2011-12-03 07:10:44 | [diff] [blame] | 223 | bool ChildProcessHostImpl::OnMessageReceived(const IPC::Message& msg) { |
[email protected] | d27893f6 | 2010-07-03 05:47:42 | [diff] [blame] | 224 | #ifdef IPC_MESSAGE_LOG_ENABLED |
[email protected] | 8e8bb6d | 2010-12-13 08:18:55 | [diff] [blame] | 225 | IPC::Logging* logger = IPC::Logging::GetInstance(); |
[email protected] | d27893f6 | 2010-07-03 05:47:42 | [diff] [blame] | 226 | if (msg.type() == IPC_LOGGING_ID) { |
| 227 | logger->OnReceivedLoggingMessage(msg); |
[email protected] | a95986a8 | 2010-12-24 06:19:28 | [diff] [blame] | 228 | return true; |
[email protected] | d27893f6 | 2010-07-03 05:47:42 | [diff] [blame] | 229 | } |
| 230 | |
| 231 | if (logger->Enabled()) |
| 232 | logger->OnPreDispatchMessage(msg); |
| 233 | #endif |
| 234 | |
[email protected] | 8e2b647 | 2010-12-15 22:19:48 | [diff] [blame] | 235 | bool handled = false; |
[email protected] | 4cb4310 | 2011-12-02 20:24:49 | [diff] [blame] | 236 | for (size_t i = 0; i < filters_.size(); ++i) { |
| 237 | if (filters_[i]->OnMessageReceived(msg)) { |
[email protected] | 8e2b647 | 2010-12-15 22:19:48 | [diff] [blame] | 238 | handled = true; |
| 239 | break; |
[email protected] | d27893f6 | 2010-07-03 05:47:42 | [diff] [blame] | 240 | } |
| 241 | } |
| 242 | |
[email protected] | bdae981 | 2011-10-15 00:33:03 | [diff] [blame] | 243 | if (!handled) { |
[email protected] | e525743 | 2010-12-21 01:18:37 | [diff] [blame] | 244 | handled = true; |
[email protected] | 4734d0b | 2011-12-03 07:10:44 | [diff] [blame] | 245 | IPC_BEGIN_MESSAGE_MAP(ChildProcessHostImpl, msg) |
[email protected] | bdae981 | 2011-10-15 00:33:03 | [diff] [blame] | 246 | IPC_MESSAGE_HANDLER(ChildProcessHostMsg_ShutdownRequest, |
| 247 | OnShutdownRequest) |
| 248 | IPC_MESSAGE_HANDLER(ChildProcessHostMsg_SyncAllocateSharedMemory, |
| 249 | OnAllocateSharedMemory) |
| 250 | IPC_MESSAGE_UNHANDLED(handled = false) |
[email protected] | 4cb4310 | 2011-12-02 20:24:49 | [diff] [blame] | 251 | IPC_END_MESSAGE_MAP() |
[email protected] | e525743 | 2010-12-21 01:18:37 | [diff] [blame] | 252 | |
[email protected] | bdae981 | 2011-10-15 00:33:03 | [diff] [blame] | 253 | if (!handled) |
[email protected] | 4cb4310 | 2011-12-02 20:24:49 | [diff] [blame] | 254 | handled = delegate_->OnMessageReceived(msg); |
[email protected] | bdae981 | 2011-10-15 00:33:03 | [diff] [blame] | 255 | } |
[email protected] | 8e2b647 | 2010-12-15 22:19:48 | [diff] [blame] | 256 | |
[email protected] | d27893f6 | 2010-07-03 05:47:42 | [diff] [blame] | 257 | #ifdef IPC_MESSAGE_LOG_ENABLED |
| 258 | if (logger->Enabled()) |
[email protected] | 4cb4310 | 2011-12-02 20:24:49 | [diff] [blame] | 259 | logger->OnPostDispatchMessage(msg, channel_id_); |
[email protected] | d27893f6 | 2010-07-03 05:47:42 | [diff] [blame] | 260 | #endif |
[email protected] | a95986a8 | 2010-12-24 06:19:28 | [diff] [blame] | 261 | return handled; |
[email protected] | d27893f6 | 2010-07-03 05:47:42 | [diff] [blame] | 262 | } |
| 263 | |
[email protected] | 4734d0b | 2011-12-03 07:10:44 | [diff] [blame] | 264 | void ChildProcessHostImpl::OnChannelConnected(int32 peer_pid) { |
[email protected] | a2b8542 | 2013-04-09 11:00:20 | [diff] [blame] | 265 | if (!base::OpenPrivilegedProcessHandle(peer_pid, &peer_handle_)) { |
[email protected] | bdae981 | 2011-10-15 00:33:03 | [diff] [blame] | 266 | NOTREACHED(); |
| 267 | } |
[email protected] | 4cb4310 | 2011-12-02 20:24:49 | [diff] [blame] | 268 | opening_channel_ = false; |
| 269 | delegate_->OnChannelConnected(peer_pid); |
| 270 | for (size_t i = 0; i < filters_.size(); ++i) |
| 271 | filters_[i]->OnChannelConnected(peer_pid); |
[email protected] | d27893f6 | 2010-07-03 05:47:42 | [diff] [blame] | 272 | } |
| 273 | |
[email protected] | 4734d0b | 2011-12-03 07:10:44 | [diff] [blame] | 274 | void ChildProcessHostImpl::OnChannelError() { |
[email protected] | 4cb4310 | 2011-12-02 20:24:49 | [diff] [blame] | 275 | opening_channel_ = false; |
| 276 | delegate_->OnChannelError(); |
[email protected] | d27893f6 | 2010-07-03 05:47:42 | [diff] [blame] | 277 | |
[email protected] | 4cb4310 | 2011-12-02 20:24:49 | [diff] [blame] | 278 | for (size_t i = 0; i < filters_.size(); ++i) |
| 279 | filters_[i]->OnChannelError(); |
[email protected] | 8e2b647 | 2010-12-15 22:19:48 | [diff] [blame] | 280 | |
[email protected] | d27893f6 | 2010-07-03 05:47:42 | [diff] [blame] | 281 | // This will delete host_, which will also destroy this! |
[email protected] | 4cb4310 | 2011-12-02 20:24:49 | [diff] [blame] | 282 | delegate_->OnChildDisconnected(); |
[email protected] | d27893f6 | 2010-07-03 05:47:42 | [diff] [blame] | 283 | } |
| 284 | |
[email protected] | 4734d0b | 2011-12-03 07:10:44 | [diff] [blame] | 285 | void ChildProcessHostImpl::OnAllocateSharedMemory( |
[email protected] | bdae981 | 2011-10-15 00:33:03 | [diff] [blame] | 286 | uint32 buffer_size, |
| 287 | base::SharedMemoryHandle* handle) { |
[email protected] | 4cb4310 | 2011-12-02 20:24:49 | [diff] [blame] | 288 | AllocateSharedMemory(buffer_size, peer_handle_, handle); |
[email protected] | bdae981 | 2011-10-15 00:33:03 | [diff] [blame] | 289 | } |
| 290 | |
[email protected] | 4734d0b | 2011-12-03 07:10:44 | [diff] [blame] | 291 | void ChildProcessHostImpl::OnShutdownRequest() { |
[email protected] | 4cb4310 | 2011-12-02 20:24:49 | [diff] [blame] | 292 | if (delegate_->CanShutdown()) |
| 293 | Send(new ChildProcessMsg_Shutdown()); |
[email protected] | d27893f6 | 2010-07-03 05:47:42 | [diff] [blame] | 294 | } |
[email protected] | 4734d0b | 2011-12-03 07:10:44 | [diff] [blame] | 295 | |
| 296 | } // namespace content |