license.bot | bf09a50 | 2008-08-24 00:55:55 | [diff] [blame] | 1 | // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 4 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 5 | #include "chrome/plugin/plugin_channel.h" |
| 6 | |
[email protected] | bf24d2c | 2009-02-24 23:07:45 | [diff] [blame] | 7 | #include "base/command_line.h" |
[email protected] | 4566f13 | 2009-03-12 01:55:13 | [diff] [blame] | 8 | #include "base/process_util.h" |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 9 | #include "base/string_util.h" |
[email protected] | d2e884d | 2009-06-22 20:37:52 | [diff] [blame] | 10 | #include "build/build_config.h" |
[email protected] | 51d70e0 | 2009-03-27 20:45:59 | [diff] [blame] | 11 | #include "chrome/common/child_process.h" |
| 12 | #include "chrome/common/plugin_messages.h" |
[email protected] | bf24d2c | 2009-02-24 23:07:45 | [diff] [blame] | 13 | #include "chrome/common/chrome_switches.h" |
[email protected] | 8930d47 | 2009-02-21 08:05:28 | [diff] [blame] | 14 | #include "chrome/plugin/plugin_thread.h" |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 15 | |
[email protected] | d2e884d | 2009-06-22 20:37:52 | [diff] [blame] | 16 | #if defined(OS_POSIX) |
[email protected] | 946d1b2 | 2009-07-22 23:57:21 | [diff] [blame] | 17 | #include "ipc/ipc_channel_posix.h" |
[email protected] | d2e884d | 2009-06-22 20:37:52 | [diff] [blame] | 18 | #endif |
| 19 | |
[email protected] | f137d13a | 2009-08-07 22:57:06 | [diff] [blame] | 20 | class PluginReleaseTask : public Task { |
| 21 | public: |
| 22 | void Run() { |
| 23 | ChildProcess::current()->ReleaseProcess(); |
| 24 | } |
| 25 | }; |
| 26 | |
| 27 | // How long we wait before releasing the plugin process. |
| 28 | static const int kPluginReleaseTimeMS = 10000; |
| 29 | |
[email protected] | fa6caa4 | 2009-06-05 05:35:07 | [diff] [blame] | 30 | PluginChannel* PluginChannel::GetPluginChannel( |
[email protected] | 3dfc7a4 | 2009-06-27 01:43:51 | [diff] [blame] | 31 | int process_id, MessageLoop* ipc_message_loop) { |
[email protected] | fa6caa4 | 2009-06-05 05:35:07 | [diff] [blame] | 32 | // map renderer's process id to a (single) channel to that process |
[email protected] | 9a3a293b | 2009-06-04 22:28:16 | [diff] [blame] | 33 | std::string channel_name = StringPrintf( |
[email protected] | fa6caa4 | 2009-06-05 05:35:07 | [diff] [blame] | 34 | "%d.r%d", base::GetCurrentProcId(), process_id); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 35 | |
[email protected] | 4566f13 | 2009-03-12 01:55:13 | [diff] [blame] | 36 | return static_cast<PluginChannel*>(PluginChannelBase::GetChannel( |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 37 | channel_name, |
| 38 | IPC::Channel::MODE_SERVER, |
| 39 | ClassFactory, |
| 40 | ipc_message_loop, |
[email protected] | 4566f13 | 2009-03-12 01:55:13 | [diff] [blame] | 41 | false)); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 42 | } |
| 43 | |
[email protected] | 3dfc7a4 | 2009-06-27 01:43:51 | [diff] [blame] | 44 | PluginChannel::PluginChannel() |
| 45 | : renderer_handle_(0), |
| 46 | #if defined(OS_POSIX) |
| 47 | renderer_fd_(-1), |
| 48 | #endif |
| 49 | in_send_(0), |
| 50 | off_the_record_(false) { |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 51 | SendUnblockingOnlyDuringDispatch(); |
[email protected] | 51d70e0 | 2009-03-27 20:45:59 | [diff] [blame] | 52 | ChildProcess::current()->AddRefProcess(); |
[email protected] | bf24d2c | 2009-02-24 23:07:45 | [diff] [blame] | 53 | const CommandLine* command_line = CommandLine::ForCurrentProcess(); |
| 54 | log_messages_ = command_line->HasSwitch(switches::kLogPluginMessages); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 55 | } |
| 56 | |
| 57 | PluginChannel::~PluginChannel() { |
[email protected] | 157e5d2 | 2009-04-23 18:43:35 | [diff] [blame] | 58 | if (renderer_handle_) |
| 59 | base::CloseProcessHandle(renderer_handle_); |
[email protected] | 3dfc7a4 | 2009-06-27 01:43:51 | [diff] [blame] | 60 | #if defined(OS_POSIX) |
[email protected] | f0ef2da | 2009-07-08 01:26:34 | [diff] [blame] | 61 | // If we still have the renderer FD, close it. |
[email protected] | 3dfc7a4 | 2009-06-27 01:43:51 | [diff] [blame] | 62 | if (renderer_fd_ != -1) { |
| 63 | close(renderer_fd_); |
| 64 | } |
| 65 | #endif |
[email protected] | f137d13a | 2009-08-07 22:57:06 | [diff] [blame] | 66 | MessageLoop::current()->PostDelayedTask(FROM_HERE, new PluginReleaseTask(), |
| 67 | kPluginReleaseTimeMS); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 68 | } |
| 69 | |
| 70 | bool PluginChannel::Send(IPC::Message* msg) { |
| 71 | in_send_++; |
[email protected] | bf24d2c | 2009-02-24 23:07:45 | [diff] [blame] | 72 | if (log_messages_) { |
| 73 | LOG(INFO) << "sending message @" << msg << " on channel @" << this |
| 74 | << " with type " << msg->type(); |
| 75 | } |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 76 | bool result = PluginChannelBase::Send(msg); |
| 77 | in_send_--; |
| 78 | return result; |
| 79 | } |
| 80 | |
[email protected] | bf24d2c | 2009-02-24 23:07:45 | [diff] [blame] | 81 | void PluginChannel::OnMessageReceived(const IPC::Message& msg) { |
| 82 | if (log_messages_) { |
| 83 | LOG(INFO) << "received message @" << &msg << " on channel @" << this |
| 84 | << " with type " << msg.type(); |
| 85 | } |
| 86 | PluginChannelBase::OnMessageReceived(msg); |
| 87 | } |
| 88 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 89 | void PluginChannel::OnControlMessageReceived(const IPC::Message& msg) { |
| 90 | IPC_BEGIN_MESSAGE_MAP(PluginChannel, msg) |
| 91 | IPC_MESSAGE_HANDLER(PluginMsg_CreateInstance, OnCreateInstance) |
[email protected] | f09c718 | 2009-03-10 12:54:04 | [diff] [blame] | 92 | IPC_MESSAGE_HANDLER_DELAY_REPLY(PluginMsg_DestroyInstance, |
| 93 | OnDestroyInstance) |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 94 | IPC_MESSAGE_HANDLER(PluginMsg_GenerateRouteID, OnGenerateRouteID) |
| 95 | IPC_MESSAGE_UNHANDLED_ERROR() |
| 96 | IPC_END_MESSAGE_MAP() |
| 97 | } |
| 98 | |
| 99 | void PluginChannel::OnCreateInstance(const std::string& mime_type, |
| 100 | int* instance_id) { |
| 101 | *instance_id = GenerateRouteID(); |
| 102 | scoped_refptr<WebPluginDelegateStub> stub = new WebPluginDelegateStub( |
| 103 | mime_type, *instance_id, this); |
| 104 | AddRoute(*instance_id, stub, false); |
| 105 | plugin_stubs_.push_back(stub); |
| 106 | } |
| 107 | |
| 108 | void PluginChannel::OnDestroyInstance(int instance_id, |
| 109 | IPC::Message* reply_msg) { |
| 110 | for (size_t i = 0; i < plugin_stubs_.size(); ++i) { |
| 111 | if (plugin_stubs_[i]->instance_id() == instance_id) { |
| 112 | plugin_stubs_.erase(plugin_stubs_.begin() + i); |
| 113 | RemoveRoute(instance_id); |
| 114 | Send(reply_msg); |
| 115 | return; |
| 116 | } |
| 117 | } |
| 118 | |
| 119 | NOTREACHED() << "Couldn't find WebPluginDelegateStub to destroy"; |
| 120 | } |
| 121 | |
| 122 | void PluginChannel::OnGenerateRouteID(int* route_id) { |
| 123 | *route_id = GenerateRouteID(); |
| 124 | } |
| 125 | |
| 126 | int PluginChannel::GenerateRouteID() { |
[email protected] | 157e5d2 | 2009-04-23 18:43:35 | [diff] [blame] | 127 | static int last_id = 0; |
| 128 | return ++last_id; |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 129 | } |
| 130 | |
[email protected] | 4566f13 | 2009-03-12 01:55:13 | [diff] [blame] | 131 | void PluginChannel::OnChannelConnected(int32 peer_pid) { |
[email protected] | 6c6cc80 | 2009-04-03 17:01:36 | [diff] [blame] | 132 | base::ProcessHandle handle; |
| 133 | if (!base::OpenProcessHandle(peer_pid, &handle)) { |
| 134 | NOTREACHED(); |
| 135 | } |
[email protected] | 157e5d2 | 2009-04-23 18:43:35 | [diff] [blame] | 136 | renderer_handle_ = handle; |
[email protected] | 4566f13 | 2009-03-12 01:55:13 | [diff] [blame] | 137 | PluginChannelBase::OnChannelConnected(peer_pid); |
| 138 | } |
| 139 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 140 | void PluginChannel::OnChannelError() { |
[email protected] | 157e5d2 | 2009-04-23 18:43:35 | [diff] [blame] | 141 | base::CloseProcessHandle(renderer_handle_); |
| 142 | renderer_handle_ = 0; |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 143 | PluginChannelBase::OnChannelError(); |
| 144 | CleanUp(); |
| 145 | } |
| 146 | |
| 147 | void PluginChannel::CleanUp() { |
| 148 | // We need to clean up the stubs so that they call NPPDestroy. This will |
| 149 | // also lead to them releasing their reference on this object so that it can |
| 150 | // be deleted. |
| 151 | for (size_t i = 0; i < plugin_stubs_.size(); ++i) |
| 152 | RemoveRoute(plugin_stubs_[i]->instance_id()); |
| 153 | |
| 154 | // Need to addref this object temporarily because otherwise removing the last |
| 155 | // stub will cause the destructor of this object to be called, however at |
| 156 | // that point plugin_stubs_ will have one element and its destructor will be |
| 157 | // called twice. |
| 158 | scoped_refptr<PluginChannel> me(this); |
| 159 | |
| 160 | plugin_stubs_.clear(); |
license.bot | bf09a50 | 2008-08-24 00:55:55 | [diff] [blame] | 161 | } |
[email protected] | 3dfc7a4 | 2009-06-27 01:43:51 | [diff] [blame] | 162 | |
| 163 | bool PluginChannel::Init(MessageLoop* ipc_message_loop, bool create_pipe_now) { |
| 164 | #if defined(OS_POSIX) |
| 165 | // This gets called when the PluginChannel is initially created. At this |
| 166 | // point, create the socketpair and assign the plugin side FD to the channel |
| 167 | // name. Keep the renderer side FD as a member variable in the PluginChannel |
| 168 | // to be able to transmit it through IPC. |
| 169 | int plugin_fd; |
| 170 | IPC::SocketPair(&plugin_fd, &renderer_fd_); |
| 171 | IPC::AddChannelSocket(channel_name(), plugin_fd); |
| 172 | #endif |
| 173 | return PluginChannelBase::Init(ipc_message_loop, create_pipe_now); |
| 174 | } |