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