diff options
author | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-08 05:05:28 +0000 |
---|---|---|
committer | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-08 05:05:28 +0000 |
commit | 7ef40ffe187f831fa843159744cd3365fc29ac71 (patch) | |
tree | 1d34dcc419411bccb0766d05542d21636a2ebfe6 /content/common/child_thread.cc | |
parent | e0549cec57a557495914d246cf21a95e69fe5ae1 (diff) | |
download | chromium_src-7ef40ffe187f831fa843159744cd3365fc29ac71.zip chromium_src-7ef40ffe187f831fa843159744cd3365fc29ac71.tar.gz chromium_src-7ef40ffe187f831fa843159744cd3365fc29ac71.tar.bz2 |
Move ChildThread and ChildProcess to content. Also move remaining code that they depend on and which depends on them.TBR=avi
Review URL: http://codereview.chromium.org/6628071
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@77249 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/common/child_thread.cc')
-rw-r--r-- | content/common/child_thread.cc | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/content/common/child_thread.cc b/content/common/child_thread.cc new file mode 100644 index 0000000..f2410e2 --- /dev/null +++ b/content/common/child_thread.cc @@ -0,0 +1,206 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/common/child_thread.h" + +#include "base/message_loop.h" +#include "base/string_util.h" +#include "base/command_line.h" +#include "content/common/child_process.h" +#include "content/common/child_process_messages.h" +#include "content/common/content_switches.h" +#include "content/common/file_system/file_system_dispatcher.h" +#include "content/common/notification_service.h" +#include "content/common/resource_dispatcher.h" +#include "content/common/socket_stream_dispatcher.h" +#include "ipc/ipc_logging.h" +#include "ipc/ipc_sync_channel.h" +#include "ipc/ipc_sync_message_filter.h" +#include "ipc/ipc_switches.h" +#include "webkit/glue/webkit_glue.h" + +ChildThread::ChildThread() { + channel_name_ = CommandLine::ForCurrentProcess()->GetSwitchValueASCII( + switches::kProcessChannelID); + Init(); +} + +ChildThread::ChildThread(const std::string& channel_name) + : channel_name_(channel_name) { + Init(); +} + +void ChildThread::Init() { + check_with_browser_before_shutdown_ = false; + on_channel_error_called_ = false; + message_loop_ = MessageLoop::current(); + if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kUserAgent)) { + webkit_glue::SetUserAgent( + CommandLine::ForCurrentProcess()->GetSwitchValueASCII( + switches::kUserAgent)); + } + + channel_.reset(new IPC::SyncChannel(channel_name_, + IPC::Channel::MODE_CLIENT, this, + ChildProcess::current()->io_message_loop(), true, + ChildProcess::current()->GetShutDownEvent())); +#ifdef IPC_MESSAGE_LOG_ENABLED + IPC::Logging::GetInstance()->SetIPCSender(this); +#endif + + resource_dispatcher_.reset(new ResourceDispatcher(this)); + socket_stream_dispatcher_.reset(new SocketStreamDispatcher()); + file_system_dispatcher_.reset(new FileSystemDispatcher()); + + sync_message_filter_ = + new IPC::SyncMessageFilter(ChildProcess::current()->GetShutDownEvent()); + channel_->AddFilter(sync_message_filter_.get()); + + // When running in unit tests, there is already a NotificationService object. + // Since only one can exist at a time per thread, check first. + if (!NotificationService::current()) + notification_service_.reset(new NotificationService); +} + +ChildThread::~ChildThread() { +#ifdef IPC_MESSAGE_LOG_ENABLED + IPC::Logging::GetInstance()->SetIPCSender(NULL); +#endif + + channel_->RemoveFilter(sync_message_filter_.get()); + + // Close this channel before resetting the message loop attached to it so + // the message loop can call ChannelProxy::Context::OnChannelClosed(), which + // releases the reference count to this channel. + channel_->Close(); + + // The ChannelProxy object caches a pointer to the IPC thread, so need to + // reset it as it's not guaranteed to outlive this object. + // NOTE: this also has the side-effect of not closing the main IPC channel to + // the browser process. This is needed because this is the signal that the + // browser uses to know that this process has died, so we need it to be alive + // until this process is shut down, and the OS closes the handle + // automatically. We used to watch the object handle on Windows to do this, + // but it wasn't possible to do so on POSIX. + channel_->ClearIPCMessageLoop(); +} + +void ChildThread::OnChannelError() { + set_on_channel_error_called(true); + MessageLoop::current()->Quit(); +} + +bool ChildThread::Send(IPC::Message* msg) { + if (!channel_.get()) { + delete msg; + return false; + } + + return channel_->Send(msg); +} + +void ChildThread::AddRoute(int32 routing_id, IPC::Channel::Listener* listener) { + DCHECK(MessageLoop::current() == message_loop()); + + router_.AddRoute(routing_id, listener); +} + +void ChildThread::RemoveRoute(int32 routing_id) { + DCHECK(MessageLoop::current() == message_loop()); + + router_.RemoveRoute(routing_id); +} + +IPC::Channel::Listener* ChildThread::ResolveRoute(int32 routing_id) { + DCHECK(MessageLoop::current() == message_loop()); + + return router_.ResolveRoute(routing_id); +} + +webkit_glue::ResourceLoaderBridge* ChildThread::CreateBridge( + const webkit_glue::ResourceLoaderBridge::RequestInfo& request_info, + int host_renderer_id, + int host_render_view_id) { + return resource_dispatcher()-> + CreateBridge(request_info, host_renderer_id, host_render_view_id); +} + +ResourceDispatcher* ChildThread::resource_dispatcher() { + return resource_dispatcher_.get(); +} + +IPC::SyncMessageFilter* ChildThread::sync_message_filter() { + return sync_message_filter_; +} + +MessageLoop* ChildThread::message_loop() { + return message_loop_; +} + +bool ChildThread::OnMessageReceived(const IPC::Message& msg) { + // Resource responses are sent to the resource dispatcher. + if (resource_dispatcher_->OnMessageReceived(msg)) + return true; + if (socket_stream_dispatcher_->OnMessageReceived(msg)) + return true; + if (file_system_dispatcher_->OnMessageReceived(msg)) + return true; + + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(ChildThread, msg) + IPC_MESSAGE_HANDLER(ChildProcessMsg_AskBeforeShutdown, OnAskBeforeShutdown) + IPC_MESSAGE_HANDLER(ChildProcessMsg_Shutdown, OnShutdown) +#if defined(IPC_MESSAGE_LOG_ENABLED) + IPC_MESSAGE_HANDLER(ChildProcessMsg_SetIPCLoggingEnabled, + OnSetIPCLoggingEnabled) +#endif + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + + if (handled) + return true; + + if (msg.routing_id() == MSG_ROUTING_CONTROL) + return OnControlMessageReceived(msg); + + return router_.OnMessageReceived(msg); +} + +bool ChildThread::OnControlMessageReceived(const IPC::Message& msg) { + return false; +} + +void ChildThread::OnAskBeforeShutdown() { + check_with_browser_before_shutdown_ = true; +} + +void ChildThread::OnShutdown() { + MessageLoop::current()->Quit(); +} + +#if defined(IPC_MESSAGE_LOG_ENABLED) +void ChildThread::OnSetIPCLoggingEnabled(bool enable) { + if (enable) + IPC::Logging::GetInstance()->Enable(); + else + IPC::Logging::GetInstance()->Disable(); +} +#endif // IPC_MESSAGE_LOG_ENABLED + +ChildThread* ChildThread::current() { + return ChildProcess::current()->main_thread(); +} + +void ChildThread::OnProcessFinalRelease() { + if (on_channel_error_called_ || !check_with_browser_before_shutdown_) { + MessageLoop::current()->Quit(); + return; + } + + // The child process shutdown sequence is a request response based mechanism, + // where we send out an initial feeler request to the child process host + // instance in the browser to verify if it's ok to shutdown the child process. + // The browser then sends back a response if it's ok to shutdown. + Send(new ChildProcessHostMsg_ShutdownRequest); +} |