blob: 04d9afcfdc30fa996bd95c8e49c9f81e670a1064 [file] [log] [blame]
license.botbf09a502008-08-24 00:55:551// 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.commit09911bf2008-07-26 23:55:294
initial.commit09911bf2008-07-26 23:55:295#include "chrome/plugin/plugin_channel.h"
6
[email protected]bf24d2c2009-02-24 23:07:457#include "base/command_line.h"
[email protected]4566f132009-03-12 01:55:138#include "base/process_util.h"
initial.commit09911bf2008-07-26 23:55:299#include "base/string_util.h"
[email protected]d2e884d2009-06-22 20:37:5210#include "build/build_config.h"
[email protected]51d70e02009-03-27 20:45:5911#include "chrome/common/child_process.h"
12#include "chrome/common/plugin_messages.h"
[email protected]bf24d2c2009-02-24 23:07:4513#include "chrome/common/chrome_switches.h"
[email protected]8930d472009-02-21 08:05:2814#include "chrome/plugin/plugin_thread.h"
initial.commit09911bf2008-07-26 23:55:2915
[email protected]d2e884d2009-06-22 20:37:5216#if defined(OS_POSIX)
[email protected]946d1b22009-07-22 23:57:2117#include "ipc/ipc_channel_posix.h"
[email protected]d2e884d2009-06-22 20:37:5218#endif
19
[email protected]f137d13a2009-08-07 22:57:0620class 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.
28static const int kPluginReleaseTimeMS = 10000;
29
[email protected]fa6caa42009-06-05 05:35:0730PluginChannel* PluginChannel::GetPluginChannel(
[email protected]3dfc7a42009-06-27 01:43:5131 int process_id, MessageLoop* ipc_message_loop) {
[email protected]fa6caa42009-06-05 05:35:0732 // map renderer's process id to a (single) channel to that process
[email protected]9a3a293b2009-06-04 22:28:1633 std::string channel_name = StringPrintf(
[email protected]fa6caa42009-06-05 05:35:0734 "%d.r%d", base::GetCurrentProcId(), process_id);
initial.commit09911bf2008-07-26 23:55:2935
[email protected]4566f132009-03-12 01:55:1336 return static_cast<PluginChannel*>(PluginChannelBase::GetChannel(
initial.commit09911bf2008-07-26 23:55:2937 channel_name,
38 IPC::Channel::MODE_SERVER,
39 ClassFactory,
40 ipc_message_loop,
[email protected]4566f132009-03-12 01:55:1341 false));
initial.commit09911bf2008-07-26 23:55:2942}
43
[email protected]3dfc7a42009-06-27 01:43:5144PluginChannel::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.commit09911bf2008-07-26 23:55:2951 SendUnblockingOnlyDuringDispatch();
[email protected]51d70e02009-03-27 20:45:5952 ChildProcess::current()->AddRefProcess();
[email protected]bf24d2c2009-02-24 23:07:4553 const CommandLine* command_line = CommandLine::ForCurrentProcess();
54 log_messages_ = command_line->HasSwitch(switches::kLogPluginMessages);
initial.commit09911bf2008-07-26 23:55:2955}
56
57PluginChannel::~PluginChannel() {
[email protected]157e5d22009-04-23 18:43:3558 if (renderer_handle_)
59 base::CloseProcessHandle(renderer_handle_);
[email protected]3dfc7a42009-06-27 01:43:5160#if defined(OS_POSIX)
[email protected]f0ef2da2009-07-08 01:26:3461 // If we still have the renderer FD, close it.
[email protected]3dfc7a42009-06-27 01:43:5162 if (renderer_fd_ != -1) {
63 close(renderer_fd_);
64 }
65#endif
[email protected]f137d13a2009-08-07 22:57:0666 MessageLoop::current()->PostDelayedTask(FROM_HERE, new PluginReleaseTask(),
67 kPluginReleaseTimeMS);
initial.commit09911bf2008-07-26 23:55:2968}
69
70bool PluginChannel::Send(IPC::Message* msg) {
71 in_send_++;
[email protected]bf24d2c2009-02-24 23:07:4572 if (log_messages_) {
73 LOG(INFO) << "sending message @" << msg << " on channel @" << this
74 << " with type " << msg->type();
75 }
initial.commit09911bf2008-07-26 23:55:2976 bool result = PluginChannelBase::Send(msg);
77 in_send_--;
78 return result;
79}
80
[email protected]bf24d2c2009-02-24 23:07:4581void 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.commit09911bf2008-07-26 23:55:2989void PluginChannel::OnControlMessageReceived(const IPC::Message& msg) {
90 IPC_BEGIN_MESSAGE_MAP(PluginChannel, msg)
91 IPC_MESSAGE_HANDLER(PluginMsg_CreateInstance, OnCreateInstance)
[email protected]f09c7182009-03-10 12:54:0492 IPC_MESSAGE_HANDLER_DELAY_REPLY(PluginMsg_DestroyInstance,
93 OnDestroyInstance)
initial.commit09911bf2008-07-26 23:55:2994 IPC_MESSAGE_HANDLER(PluginMsg_GenerateRouteID, OnGenerateRouteID)
95 IPC_MESSAGE_UNHANDLED_ERROR()
96 IPC_END_MESSAGE_MAP()
97}
98
99void 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
108void 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
122void PluginChannel::OnGenerateRouteID(int* route_id) {
123 *route_id = GenerateRouteID();
124}
125
126int PluginChannel::GenerateRouteID() {
[email protected]157e5d22009-04-23 18:43:35127 static int last_id = 0;
128 return ++last_id;
initial.commit09911bf2008-07-26 23:55:29129}
130
[email protected]4566f132009-03-12 01:55:13131void PluginChannel::OnChannelConnected(int32 peer_pid) {
[email protected]6c6cc802009-04-03 17:01:36132 base::ProcessHandle handle;
133 if (!base::OpenProcessHandle(peer_pid, &handle)) {
134 NOTREACHED();
135 }
[email protected]157e5d22009-04-23 18:43:35136 renderer_handle_ = handle;
[email protected]4566f132009-03-12 01:55:13137 PluginChannelBase::OnChannelConnected(peer_pid);
138}
139
initial.commit09911bf2008-07-26 23:55:29140void PluginChannel::OnChannelError() {
[email protected]157e5d22009-04-23 18:43:35141 base::CloseProcessHandle(renderer_handle_);
142 renderer_handle_ = 0;
initial.commit09911bf2008-07-26 23:55:29143 PluginChannelBase::OnChannelError();
144 CleanUp();
145}
146
147void 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.botbf09a502008-08-24 00:55:55161}
[email protected]3dfc7a42009-06-27 01:43:51162
163bool 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}