Chromium Code Reviews| 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/child/child_thread.h" | 5 #include "content/child/child_thread.h" |
| 6 | 6 |
| 7 #include "base/allocator/allocator_extension.h" | 7 #include "base/allocator/allocator_extension.h" |
| 8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
| 9 #include "base/lazy_instance.h" | |
| 9 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
| 10 #include "base/process.h" | 11 #include "base/process.h" |
| 11 #include "base/process_util.h" | 12 #include "base/process_util.h" |
| 12 #include "base/strings/string_util.h" | 13 #include "base/strings/string_util.h" |
| 14 #include "base/threading/thread_local.h" | |
| 13 #include "base/tracked_objects.h" | 15 #include "base/tracked_objects.h" |
| 14 #include "components/tracing/child_trace_message_filter.h" | 16 #include "components/tracing/child_trace_message_filter.h" |
| 15 #include "content/child/child_histogram_message_filter.h" | 17 #include "content/child/child_histogram_message_filter.h" |
| 16 #include "content/child/child_process.h" | 18 #include "content/child/child_process.h" |
| 17 #include "content/child/child_resource_message_filter.h" | 19 #include "content/child/child_resource_message_filter.h" |
| 18 #include "content/child/fileapi/file_system_dispatcher.h" | 20 #include "content/child/fileapi/file_system_dispatcher.h" |
| 19 #include "content/child/quota_dispatcher.h" | 21 #include "content/child/quota_dispatcher.h" |
| 20 #include "content/child/resource_dispatcher.h" | 22 #include "content/child/resource_dispatcher.h" |
| 21 #include "content/child/socket_stream_dispatcher.h" | 23 #include "content/child/socket_stream_dispatcher.h" |
| 22 #include "content/child/thread_safe_sender.h" | 24 #include "content/child/thread_safe_sender.h" |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 33 #endif | 35 #endif |
| 34 | 36 |
| 35 using tracked_objects::ThreadData; | 37 using tracked_objects::ThreadData; |
| 36 | 38 |
| 37 namespace content { | 39 namespace content { |
| 38 namespace { | 40 namespace { |
| 39 | 41 |
| 40 // How long to wait for a connection to the browser process before giving up. | 42 // How long to wait for a connection to the browser process before giving up. |
| 41 const int kConnectionTimeoutS = 15; | 43 const int kConnectionTimeoutS = 15; |
| 42 | 44 |
| 45 base::LazyInstance<base::ThreadLocalPointer<ChildThread> > g_lazy_tls = | |
| 46 LAZY_INSTANCE_INITIALIZER; | |
| 47 | |
| 43 // This isn't needed on Windows because there the sandbox's job object | 48 // This isn't needed on Windows because there the sandbox's job object |
| 44 // terminates child processes automatically. For unsandboxed processes (i.e. | 49 // terminates child processes automatically. For unsandboxed processes (i.e. |
| 45 // plugins), PluginThread has EnsureTerminateMessageFilter. | 50 // plugins), PluginThread has EnsureTerminateMessageFilter. |
| 46 #if defined(OS_POSIX) | 51 #if defined(OS_POSIX) |
| 47 | 52 |
| 48 class SuicideOnChannelErrorFilter : public IPC::ChannelProxy::MessageFilter { | 53 class SuicideOnChannelErrorFilter : public IPC::ChannelProxy::MessageFilter { |
| 49 public: | 54 public: |
| 50 // IPC::ChannelProxy::MessageFilter | 55 // IPC::ChannelProxy::MessageFilter |
| 51 virtual void OnChannelError() OVERRIDE { | 56 virtual void OnChannelError() OVERRIDE { |
| 52 // For renderer/worker processes: | 57 // For renderer/worker processes: |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 73 else | 78 else |
| 74 _exit(0); | 79 _exit(0); |
| 75 } | 80 } |
| 76 | 81 |
| 77 protected: | 82 protected: |
| 78 virtual ~SuicideOnChannelErrorFilter() {} | 83 virtual ~SuicideOnChannelErrorFilter() {} |
| 79 }; | 84 }; |
| 80 | 85 |
| 81 #endif // OS(POSIX) | 86 #endif // OS(POSIX) |
| 82 | 87 |
| 88 #if defined(OS_ANDROID) | |
| 89 ChildThread* g_child_thread; | |
| 90 | |
| 91 void QuitMainThreadMessageLoop() { | |
| 92 base::MessageLoop::current()->Quit(); | |
| 93 } | |
| 94 | |
| 95 #endif | |
| 96 | |
| 83 } // namespace | 97 } // namespace |
| 84 | 98 |
| 85 ChildThread::ChildThread() | 99 ChildThread::ChildThread() |
| 86 : channel_connected_factory_(this) { | 100 : channel_connected_factory_(this) { |
| 87 channel_name_ = CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | 101 channel_name_ = CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
| 88 switches::kProcessChannelID); | 102 switches::kProcessChannelID); |
| 89 Init(); | 103 Init(); |
| 90 } | 104 } |
| 91 | 105 |
| 92 ChildThread::ChildThread(const std::string& channel_name) | 106 ChildThread::ChildThread(const std::string& channel_name) |
| 93 : channel_name_(channel_name), | 107 : channel_name_(channel_name), |
| 94 channel_connected_factory_(this) { | 108 channel_connected_factory_(this) { |
| 95 Init(); | 109 Init(); |
| 96 } | 110 } |
| 97 | 111 |
| 98 void ChildThread::Init() { | 112 void ChildThread::Init() { |
| 113 g_lazy_tls.Pointer()->Set(this); | |
| 99 on_channel_error_called_ = false; | 114 on_channel_error_called_ = false; |
| 100 message_loop_ = base::MessageLoop::current(); | 115 message_loop_ = base::MessageLoop::current(); |
| 101 channel_.reset( | 116 channel_.reset( |
| 102 new IPC::SyncChannel(channel_name_, | 117 new IPC::SyncChannel(channel_name_, |
| 103 IPC::Channel::MODE_CLIENT, | 118 IPC::Channel::MODE_CLIENT, |
| 104 this, | 119 this, |
| 105 ChildProcess::current()->io_message_loop_proxy(), | 120 ChildProcess::current()->io_message_loop_proxy(), |
| 106 true, | 121 true, |
| 107 ChildProcess::current()->GetShutDownEvent())); | 122 ChildProcess::current()->GetShutDownEvent())); |
| 108 #ifdef IPC_MESSAGE_LOG_ENABLED | 123 #ifdef IPC_MESSAGE_LOG_ENABLED |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 133 // and single-process mode. | 148 // and single-process mode. |
| 134 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessType)) | 149 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessType)) |
| 135 channel_->AddFilter(new SuicideOnChannelErrorFilter()); | 150 channel_->AddFilter(new SuicideOnChannelErrorFilter()); |
| 136 #endif | 151 #endif |
| 137 | 152 |
| 138 base::MessageLoop::current()->PostDelayedTask( | 153 base::MessageLoop::current()->PostDelayedTask( |
| 139 FROM_HERE, | 154 FROM_HERE, |
| 140 base::Bind(&ChildThread::EnsureConnected, | 155 base::Bind(&ChildThread::EnsureConnected, |
| 141 channel_connected_factory_.GetWeakPtr()), | 156 channel_connected_factory_.GetWeakPtr()), |
| 142 base::TimeDelta::FromSeconds(kConnectionTimeoutS)); | 157 base::TimeDelta::FromSeconds(kConnectionTimeoutS)); |
| 158 | |
| 159 #if defined(OS_ANDROID) | |
| 160 g_child_thread = this; | |
| 161 #endif | |
| 143 } | 162 } |
| 144 | 163 |
| 145 ChildThread::~ChildThread() { | 164 ChildThread::~ChildThread() { |
| 146 #ifdef IPC_MESSAGE_LOG_ENABLED | 165 #ifdef IPC_MESSAGE_LOG_ENABLED |
| 147 IPC::Logging::GetInstance()->SetIPCSender(NULL); | 166 IPC::Logging::GetInstance()->SetIPCSender(NULL); |
| 148 #endif | 167 #endif |
| 149 | 168 |
| 150 channel_->RemoveFilter(histogram_message_filter_.get()); | 169 channel_->RemoveFilter(histogram_message_filter_.get()); |
| 151 channel_->RemoveFilter(sync_message_filter_.get()); | 170 channel_->RemoveFilter(sync_message_filter_.get()); |
| 152 | 171 |
| 153 // The ChannelProxy object caches a pointer to the IPC thread, so need to | 172 // The ChannelProxy object caches a pointer to the IPC thread, so need to |
| 154 // reset it as it's not guaranteed to outlive this object. | 173 // reset it as it's not guaranteed to outlive this object. |
| 155 // NOTE: this also has the side-effect of not closing the main IPC channel to | 174 // NOTE: this also has the side-effect of not closing the main IPC channel to |
| 156 // the browser process. This is needed because this is the signal that the | 175 // the browser process. This is needed because this is the signal that the |
| 157 // browser uses to know that this process has died, so we need it to be alive | 176 // browser uses to know that this process has died, so we need it to be alive |
| 158 // until this process is shut down, and the OS closes the handle | 177 // until this process is shut down, and the OS closes the handle |
| 159 // automatically. We used to watch the object handle on Windows to do this, | 178 // automatically. We used to watch the object handle on Windows to do this, |
| 160 // but it wasn't possible to do so on POSIX. | 179 // but it wasn't possible to do so on POSIX. |
| 161 channel_->ClearIPCTaskRunner(); | 180 channel_->ClearIPCTaskRunner(); |
| 181 g_lazy_tls.Pointer()->Set(NULL); | |
| 162 } | 182 } |
| 163 | 183 |
| 164 void ChildThread::OnChannelConnected(int32 peer_pid) { | 184 void ChildThread::OnChannelConnected(int32 peer_pid) { |
| 165 channel_connected_factory_.InvalidateWeakPtrs(); | 185 channel_connected_factory_.InvalidateWeakPtrs(); |
| 166 } | 186 } |
| 167 | 187 |
| 168 void ChildThread::OnChannelError() { | 188 void ChildThread::OnChannelError() { |
| 169 set_on_channel_error_called(true); | 189 set_on_channel_error_called(true); |
| 170 base::MessageLoop::current()->Quit(); | 190 base::MessageLoop::current()->Quit(); |
| 171 } | 191 } |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 321 void ChildThread::OnGetTcmallocStats() { | 341 void ChildThread::OnGetTcmallocStats() { |
| 322 std::string result; | 342 std::string result; |
| 323 char buffer[1024 * 32]; | 343 char buffer[1024 * 32]; |
| 324 base::allocator::GetStats(buffer, sizeof(buffer)); | 344 base::allocator::GetStats(buffer, sizeof(buffer)); |
| 325 result.append(buffer); | 345 result.append(buffer); |
| 326 Send(new ChildProcessHostMsg_TcmallocStats(result)); | 346 Send(new ChildProcessHostMsg_TcmallocStats(result)); |
| 327 } | 347 } |
| 328 #endif | 348 #endif |
| 329 | 349 |
| 330 ChildThread* ChildThread::current() { | 350 ChildThread* ChildThread::current() { |
| 331 return ChildProcess::current() ? | 351 return g_lazy_tls.Pointer()->Get(); |
|
scottmg
2013/06/26 15:21:50
(same here)
| |
| 332 ChildProcess::current()->main_thread() : NULL; | |
| 333 } | 352 } |
| 334 | 353 |
| 335 bool ChildThread::IsWebFrameValid(WebKit::WebFrame* frame) { | 354 #if defined(OS_ANDROID) |
| 336 // Return false so that it is overridden in any process in which it is used. | 355 void ChildThread::ShutdownThread() { |
| 337 return false; | 356 DCHECK_NE(base::MessageLoop::current(), g_child_thread->message_loop()); |
| 357 g_child_thread->message_loop()->PostTask( | |
| 358 FROM_HERE, base::Bind(&QuitMainThreadMessageLoop)); | |
| 338 } | 359 } |
| 339 | 360 |
| 361 #endif | |
| 362 | |
| 340 void ChildThread::OnProcessFinalRelease() { | 363 void ChildThread::OnProcessFinalRelease() { |
| 341 if (on_channel_error_called_) { | 364 if (on_channel_error_called_) { |
| 342 base::MessageLoop::current()->Quit(); | 365 base::MessageLoop::current()->Quit(); |
| 343 return; | 366 return; |
| 344 } | 367 } |
| 345 | 368 |
| 346 // The child process shutdown sequence is a request response based mechanism, | 369 // The child process shutdown sequence is a request response based mechanism, |
| 347 // where we send out an initial feeler request to the child process host | 370 // where we send out an initial feeler request to the child process host |
| 348 // instance in the browser to verify if it's ok to shutdown the child process. | 371 // instance in the browser to verify if it's ok to shutdown the child process. |
| 349 // The browser then sends back a response if it's ok to shutdown. This avoids | 372 // The browser then sends back a response if it's ok to shutdown. This avoids |
| 350 // race conditions if the process refcount is 0 but there's an IPC message | 373 // race conditions if the process refcount is 0 but there's an IPC message |
| 351 // inflight that would addref it. | 374 // inflight that would addref it. |
| 352 Send(new ChildProcessHostMsg_ShutdownRequest); | 375 Send(new ChildProcessHostMsg_ShutdownRequest); |
| 353 } | 376 } |
| 354 | 377 |
| 355 void ChildThread::EnsureConnected() { | 378 void ChildThread::EnsureConnected() { |
| 356 LOG(INFO) << "ChildThread::EnsureConnected()"; | 379 LOG(INFO) << "ChildThread::EnsureConnected()"; |
| 357 base::KillProcess(base::GetCurrentProcessHandle(), 0, false); | 380 base::KillProcess(base::GetCurrentProcessHandle(), 0, false); |
| 358 } | 381 } |
| 359 | 382 |
| 360 } // namespace content | 383 } // namespace content |
| OLD | NEW |