| OLD | NEW |
| 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/browser_child_process_host_impl.h" | 5 #include "content/browser/browser_child_process_host_impl.h" |
| 6 | 6 |
| 7 #include "base/base_switches.h" | 7 #include "base/base_switches.h" |
| 8 #include "base/bind.h" | 8 #include "base/bind.h" |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 73 | 73 |
| 74 // static | 74 // static |
| 75 BrowserChildProcessHostImpl::BrowserChildProcessList* | 75 BrowserChildProcessHostImpl::BrowserChildProcessList* |
| 76 BrowserChildProcessHostImpl::GetIterator() { | 76 BrowserChildProcessHostImpl::GetIterator() { |
| 77 return g_child_process_list.Pointer(); | 77 return g_child_process_list.Pointer(); |
| 78 } | 78 } |
| 79 | 79 |
| 80 // static | 80 // static |
| 81 void BrowserChildProcessHostImpl::AddObserver( | 81 void BrowserChildProcessHostImpl::AddObserver( |
| 82 BrowserChildProcessObserver* observer) { | 82 BrowserChildProcessObserver* observer) { |
| 83 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 83 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 84 g_observers.Get().AddObserver(observer); | 84 g_observers.Get().AddObserver(observer); |
| 85 } | 85 } |
| 86 | 86 |
| 87 // static | 87 // static |
| 88 void BrowserChildProcessHostImpl::RemoveObserver( | 88 void BrowserChildProcessHostImpl::RemoveObserver( |
| 89 BrowserChildProcessObserver* observer) { | 89 BrowserChildProcessObserver* observer) { |
| 90 // TODO(phajdan.jr): Check thread after fixing http://crbug.com/167126. | 90 // TODO(phajdan.jr): Check thread after fixing http://crbug.com/167126. |
| 91 g_observers.Get().RemoveObserver(observer); | 91 g_observers.Get().RemoveObserver(observer); |
| 92 } | 92 } |
| 93 | 93 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 109 | 109 |
| 110 power_monitor_message_broadcaster_.Init(); | 110 power_monitor_message_broadcaster_.Init(); |
| 111 } | 111 } |
| 112 | 112 |
| 113 BrowserChildProcessHostImpl::~BrowserChildProcessHostImpl() { | 113 BrowserChildProcessHostImpl::~BrowserChildProcessHostImpl() { |
| 114 g_child_process_list.Get().remove(this); | 114 g_child_process_list.Get().remove(this); |
| 115 } | 115 } |
| 116 | 116 |
| 117 // static | 117 // static |
| 118 void BrowserChildProcessHostImpl::TerminateAll() { | 118 void BrowserChildProcessHostImpl::TerminateAll() { |
| 119 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 119 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 120 // Make a copy since the BrowserChildProcessHost dtor mutates the original | 120 // Make a copy since the BrowserChildProcessHost dtor mutates the original |
| 121 // list. | 121 // list. |
| 122 BrowserChildProcessList copy = g_child_process_list.Get(); | 122 BrowserChildProcessList copy = g_child_process_list.Get(); |
| 123 for (BrowserChildProcessList::iterator it = copy.begin(); | 123 for (BrowserChildProcessList::iterator it = copy.begin(); |
| 124 it != copy.end(); ++it) { | 124 it != copy.end(); ++it) { |
| 125 delete (*it)->delegate(); // ~*HostDelegate deletes *HostImpl. | 125 delete (*it)->delegate(); // ~*HostDelegate deletes *HostImpl. |
| 126 } | 126 } |
| 127 } | 127 } |
| 128 | 128 |
| 129 void BrowserChildProcessHostImpl::Launch( | 129 void BrowserChildProcessHostImpl::Launch( |
| 130 SandboxedProcessLauncherDelegate* delegate, | 130 SandboxedProcessLauncherDelegate* delegate, |
| 131 base::CommandLine* cmd_line) { | 131 base::CommandLine* cmd_line) { |
| 132 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 132 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 133 | 133 |
| 134 GetContentClient()->browser()->AppendExtraCommandLineSwitches( | 134 GetContentClient()->browser()->AppendExtraCommandLineSwitches( |
| 135 cmd_line, data_.id); | 135 cmd_line, data_.id); |
| 136 | 136 |
| 137 const base::CommandLine& browser_command_line = | 137 const base::CommandLine& browser_command_line = |
| 138 *base::CommandLine::ForCurrentProcess(); | 138 *base::CommandLine::ForCurrentProcess(); |
| 139 static const char* kForwardSwitches[] = { | 139 static const char* kForwardSwitches[] = { |
| 140 switches::kDisableLogging, | 140 switches::kDisableLogging, |
| 141 switches::kEnableLogging, | 141 switches::kEnableLogging, |
| 142 switches::kIPCConnectionTimeout, | 142 switches::kIPCConnectionTimeout, |
| 143 switches::kLoggingLevel, | 143 switches::kLoggingLevel, |
| 144 switches::kTraceToConsole, | 144 switches::kTraceToConsole, |
| 145 switches::kV, | 145 switches::kV, |
| 146 switches::kVModule, | 146 switches::kVModule, |
| 147 }; | 147 }; |
| 148 cmd_line->CopySwitchesFrom(browser_command_line, kForwardSwitches, | 148 cmd_line->CopySwitchesFrom(browser_command_line, kForwardSwitches, |
| 149 arraysize(kForwardSwitches)); | 149 arraysize(kForwardSwitches)); |
| 150 | 150 |
| 151 child_process_.reset(new ChildProcessLauncher( | 151 child_process_.reset(new ChildProcessLauncher( |
| 152 delegate, | 152 delegate, |
| 153 cmd_line, | 153 cmd_line, |
| 154 data_.id, | 154 data_.id, |
| 155 this)); | 155 this)); |
| 156 } | 156 } |
| 157 | 157 |
| 158 const ChildProcessData& BrowserChildProcessHostImpl::GetData() const { | 158 const ChildProcessData& BrowserChildProcessHostImpl::GetData() const { |
| 159 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 159 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 160 return data_; | 160 return data_; |
| 161 } | 161 } |
| 162 | 162 |
| 163 ChildProcessHost* BrowserChildProcessHostImpl::GetHost() const { | 163 ChildProcessHost* BrowserChildProcessHostImpl::GetHost() const { |
| 164 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 164 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 165 return child_process_host_.get(); | 165 return child_process_host_.get(); |
| 166 } | 166 } |
| 167 | 167 |
| 168 const base::Process& BrowserChildProcessHostImpl::GetProcess() const { | 168 const base::Process& BrowserChildProcessHostImpl::GetProcess() const { |
| 169 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 169 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 170 DCHECK(child_process_.get()) | 170 DCHECK(child_process_.get()) |
| 171 << "Requesting a child process handle before launching."; | 171 << "Requesting a child process handle before launching."; |
| 172 DCHECK(child_process_->GetProcess().IsValid()) | 172 DCHECK(child_process_->GetProcess().IsValid()) |
| 173 << "Requesting a child process handle before launch has completed OK."; | 173 << "Requesting a child process handle before launch has completed OK."; |
| 174 return child_process_->GetProcess(); | 174 return child_process_->GetProcess(); |
| 175 } | 175 } |
| 176 | 176 |
| 177 void BrowserChildProcessHostImpl::SetName(const base::string16& name) { | 177 void BrowserChildProcessHostImpl::SetName(const base::string16& name) { |
| 178 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 178 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 179 data_.name = name; | 179 data_.name = name; |
| 180 } | 180 } |
| 181 | 181 |
| 182 void BrowserChildProcessHostImpl::SetHandle(base::ProcessHandle handle) { | 182 void BrowserChildProcessHostImpl::SetHandle(base::ProcessHandle handle) { |
| 183 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 183 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 184 data_.handle = handle; | 184 data_.handle = handle; |
| 185 } | 185 } |
| 186 | 186 |
| 187 void BrowserChildProcessHostImpl::ForceShutdown() { | 187 void BrowserChildProcessHostImpl::ForceShutdown() { |
| 188 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 188 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 189 g_child_process_list.Get().remove(this); | 189 g_child_process_list.Get().remove(this); |
| 190 child_process_host_->ForceShutdown(); | 190 child_process_host_->ForceShutdown(); |
| 191 } | 191 } |
| 192 | 192 |
| 193 void BrowserChildProcessHostImpl::SetBackgrounded(bool backgrounded) { | 193 void BrowserChildProcessHostImpl::SetBackgrounded(bool backgrounded) { |
| 194 child_process_->SetProcessBackgrounded(backgrounded); | 194 child_process_->SetProcessBackgrounded(backgrounded); |
| 195 } | 195 } |
| 196 | 196 |
| 197 void BrowserChildProcessHostImpl::SetTerminateChildOnShutdown( | 197 void BrowserChildProcessHostImpl::SetTerminateChildOnShutdown( |
| 198 bool terminate_on_shutdown) { | 198 bool terminate_on_shutdown) { |
| 199 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 199 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 200 child_process_->SetTerminateChildOnShutdown(terminate_on_shutdown); | 200 child_process_->SetTerminateChildOnShutdown(terminate_on_shutdown); |
| 201 } | 201 } |
| 202 | 202 |
| 203 void BrowserChildProcessHostImpl::AddFilter(BrowserMessageFilter* filter) { | 203 void BrowserChildProcessHostImpl::AddFilter(BrowserMessageFilter* filter) { |
| 204 child_process_host_->AddFilter(filter->GetFilter()); | 204 child_process_host_->AddFilter(filter->GetFilter()); |
| 205 } | 205 } |
| 206 | 206 |
| 207 void BrowserChildProcessHostImpl::NotifyProcessInstanceCreated( | 207 void BrowserChildProcessHostImpl::NotifyProcessInstanceCreated( |
| 208 const ChildProcessData& data) { | 208 const ChildProcessData& data) { |
| 209 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 209 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 210 FOR_EACH_OBSERVER(BrowserChildProcessObserver, g_observers.Get(), | 210 FOR_EACH_OBSERVER(BrowserChildProcessObserver, g_observers.Get(), |
| 211 BrowserChildProcessInstanceCreated(data)); | 211 BrowserChildProcessInstanceCreated(data)); |
| 212 } | 212 } |
| 213 | 213 |
| 214 void BrowserChildProcessHostImpl::HistogramBadMessageTerminated( | 214 void BrowserChildProcessHostImpl::HistogramBadMessageTerminated( |
| 215 int process_type) { | 215 int process_type) { |
| 216 UMA_HISTOGRAM_ENUMERATION("ChildProcess.BadMessgeTerminated", process_type, | 216 UMA_HISTOGRAM_ENUMERATION("ChildProcess.BadMessgeTerminated", process_type, |
| 217 PROCESS_TYPE_MAX); | 217 PROCESS_TYPE_MAX); |
| 218 } | 218 } |
| 219 | 219 |
| 220 base::TerminationStatus BrowserChildProcessHostImpl::GetTerminationStatus( | 220 base::TerminationStatus BrowserChildProcessHostImpl::GetTerminationStatus( |
| 221 bool known_dead, int* exit_code) { | 221 bool known_dead, int* exit_code) { |
| 222 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 222 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 223 if (!child_process_) // If the delegate doesn't use Launch() helper. | 223 if (!child_process_) // If the delegate doesn't use Launch() helper. |
| 224 return base::GetTerminationStatus(data_.handle, exit_code); | 224 return base::GetTerminationStatus(data_.handle, exit_code); |
| 225 return child_process_->GetChildTerminationStatus(known_dead, | 225 return child_process_->GetChildTerminationStatus(known_dead, |
| 226 exit_code); | 226 exit_code); |
| 227 } | 227 } |
| 228 | 228 |
| 229 bool BrowserChildProcessHostImpl::OnMessageReceived( | 229 bool BrowserChildProcessHostImpl::OnMessageReceived( |
| 230 const IPC::Message& message) { | 230 const IPC::Message& message) { |
| 231 return delegate_->OnMessageReceived(message); | 231 return delegate_->OnMessageReceived(message); |
| 232 } | 232 } |
| 233 | 233 |
| 234 void BrowserChildProcessHostImpl::OnChannelConnected(int32 peer_pid) { | 234 void BrowserChildProcessHostImpl::OnChannelConnected(int32 peer_pid) { |
| 235 #if defined(OS_WIN) | 235 #if defined(OS_WIN) |
| 236 // From this point onward, the exit of the child process is detected by an | 236 // From this point onward, the exit of the child process is detected by an |
| 237 // error on the IPC channel. | 237 // error on the IPC channel. |
| 238 early_exit_watcher_.StopWatching(); | 238 early_exit_watcher_.StopWatching(); |
| 239 #endif | 239 #endif |
| 240 | 240 |
| 241 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 241 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 242 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 242 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 243 base::Bind(&NotifyProcessHostConnected, data_)); | 243 base::Bind(&NotifyProcessHostConnected, data_)); |
| 244 | 244 |
| 245 delegate_->OnChannelConnected(peer_pid); | 245 delegate_->OnChannelConnected(peer_pid); |
| 246 } | 246 } |
| 247 | 247 |
| 248 void BrowserChildProcessHostImpl::OnChannelError() { | 248 void BrowserChildProcessHostImpl::OnChannelError() { |
| 249 delegate_->OnChannelError(); | 249 delegate_->OnChannelError(); |
| 250 } | 250 } |
| 251 | 251 |
| 252 void BrowserChildProcessHostImpl::OnBadMessageReceived( | 252 void BrowserChildProcessHostImpl::OnBadMessageReceived( |
| 253 const IPC::Message& message) { | 253 const IPC::Message& message) { |
| 254 HistogramBadMessageTerminated(data_.process_type); | 254 HistogramBadMessageTerminated(data_.process_type); |
| 255 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 255 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 256 switches::kDisableKillAfterBadIPC)) { | 256 switches::kDisableKillAfterBadIPC)) { |
| 257 return; | 257 return; |
| 258 } | 258 } |
| 259 base::KillProcess(child_process_->GetProcess().Handle(), | 259 base::KillProcess(child_process_->GetProcess().Handle(), |
| 260 RESULT_CODE_KILLED_BAD_MESSAGE, false); | 260 RESULT_CODE_KILLED_BAD_MESSAGE, false); |
| 261 } | 261 } |
| 262 | 262 |
| 263 bool BrowserChildProcessHostImpl::CanShutdown() { | 263 bool BrowserChildProcessHostImpl::CanShutdown() { |
| 264 return delegate_->CanShutdown(); | 264 return delegate_->CanShutdown(); |
| 265 } | 265 } |
| 266 | 266 |
| 267 void BrowserChildProcessHostImpl::OnChildDisconnected() { | 267 void BrowserChildProcessHostImpl::OnChildDisconnected() { |
| 268 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 268 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 269 #if defined(OS_WIN) | 269 #if defined(OS_WIN) |
| 270 // OnChildDisconnected may be called without OnChannelConnected, so stop the | 270 // OnChildDisconnected may be called without OnChannelConnected, so stop the |
| 271 // early exit watcher so GetTerminationStatus can close the process handle. | 271 // early exit watcher so GetTerminationStatus can close the process handle. |
| 272 early_exit_watcher_.StopWatching(); | 272 early_exit_watcher_.StopWatching(); |
| 273 #endif | 273 #endif |
| 274 if (child_process_.get() || data_.handle) { | 274 if (child_process_.get() || data_.handle) { |
| 275 int exit_code; | 275 int exit_code; |
| 276 base::TerminationStatus status = GetTerminationStatus( | 276 base::TerminationStatus status = GetTerminationStatus( |
| 277 true /* known_dead */, &exit_code); | 277 true /* known_dead */, &exit_code); |
| 278 switch (status) { | 278 switch (status) { |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 345 | 345 |
| 346 #if defined(OS_WIN) | 346 #if defined(OS_WIN) |
| 347 | 347 |
| 348 void BrowserChildProcessHostImpl::OnObjectSignaled(HANDLE object) { | 348 void BrowserChildProcessHostImpl::OnObjectSignaled(HANDLE object) { |
| 349 OnChildDisconnected(); | 349 OnChildDisconnected(); |
| 350 } | 350 } |
| 351 | 351 |
| 352 #endif | 352 #endif |
| 353 | 353 |
| 354 } // namespace content | 354 } // namespace content |
| OLD | NEW |