blob: 6264af52a7bf7385d0161b03c1c201c6147d6289 [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)
17#include "chrome/common/ipc_channel_posix.h"
18#endif
19
[email protected]fa6caa42009-06-05 05:35:0720PluginChannel* PluginChannel::GetPluginChannel(
[email protected]3dfc7a42009-06-27 01:43:5121 int process_id, MessageLoop* ipc_message_loop) {
[email protected]fa6caa42009-06-05 05:35:0722 // map renderer's process id to a (single) channel to that process
[email protected]9a3a293b2009-06-04 22:28:1623 std::string channel_name = StringPrintf(
[email protected]fa6caa42009-06-05 05:35:0724 "%d.r%d", base::GetCurrentProcId(), process_id);
initial.commit09911bf2008-07-26 23:55:2925
[email protected]4566f132009-03-12 01:55:1326 return static_cast<PluginChannel*>(PluginChannelBase::GetChannel(
initial.commit09911bf2008-07-26 23:55:2927 channel_name,
28 IPC::Channel::MODE_SERVER,
29 ClassFactory,
30 ipc_message_loop,
[email protected]4566f132009-03-12 01:55:1331 false));
initial.commit09911bf2008-07-26 23:55:2932}
33
[email protected]3dfc7a42009-06-27 01:43:5134PluginChannel::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.commit09911bf2008-07-26 23:55:2941 SendUnblockingOnlyDuringDispatch();
[email protected]51d70e02009-03-27 20:45:5942 ChildProcess::current()->AddRefProcess();
[email protected]bf24d2c2009-02-24 23:07:4543 const CommandLine* command_line = CommandLine::ForCurrentProcess();
44 log_messages_ = command_line->HasSwitch(switches::kLogPluginMessages);
initial.commit09911bf2008-07-26 23:55:2945}
46
47PluginChannel::~PluginChannel() {
[email protected]157e5d22009-04-23 18:43:3548 if (renderer_handle_)
49 base::CloseProcessHandle(renderer_handle_);
[email protected]3dfc7a42009-06-27 01:43:5150#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]51d70e02009-03-27 20:45:5956 ChildProcess::current()->ReleaseProcess();
initial.commit09911bf2008-07-26 23:55:2957}
58
59bool PluginChannel::Send(IPC::Message* msg) {
60 in_send_++;
[email protected]bf24d2c2009-02-24 23:07:4561 if (log_messages_) {
62 LOG(INFO) << "sending message @" << msg << " on channel @" << this
63 << " with type " << msg->type();
64 }
initial.commit09911bf2008-07-26 23:55:2965 bool result = PluginChannelBase::Send(msg);
66 in_send_--;
67 return result;
68}
69
[email protected]bf24d2c2009-02-24 23:07:4570void 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.commit09911bf2008-07-26 23:55:2978void PluginChannel::OnControlMessageReceived(const IPC::Message& msg) {
79 IPC_BEGIN_MESSAGE_MAP(PluginChannel, msg)
80 IPC_MESSAGE_HANDLER(PluginMsg_CreateInstance, OnCreateInstance)
[email protected]f09c7182009-03-10 12:54:0481 IPC_MESSAGE_HANDLER_DELAY_REPLY(PluginMsg_DestroyInstance,
82 OnDestroyInstance)
initial.commit09911bf2008-07-26 23:55:2983 IPC_MESSAGE_HANDLER(PluginMsg_GenerateRouteID, OnGenerateRouteID)
84 IPC_MESSAGE_UNHANDLED_ERROR()
85 IPC_END_MESSAGE_MAP()
86}
87
88void 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
97void 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
111void PluginChannel::OnGenerateRouteID(int* route_id) {
112 *route_id = GenerateRouteID();
113}
114
115int PluginChannel::GenerateRouteID() {
[email protected]157e5d22009-04-23 18:43:35116 static int last_id = 0;
117 return ++last_id;
initial.commit09911bf2008-07-26 23:55:29118}
119
[email protected]4566f132009-03-12 01:55:13120void PluginChannel::OnChannelConnected(int32 peer_pid) {
[email protected]6c6cc802009-04-03 17:01:36121 base::ProcessHandle handle;
122 if (!base::OpenProcessHandle(peer_pid, &handle)) {
123 NOTREACHED();
124 }
[email protected]157e5d22009-04-23 18:43:35125 renderer_handle_ = handle;
[email protected]4566f132009-03-12 01:55:13126 PluginChannelBase::OnChannelConnected(peer_pid);
127}
128
initial.commit09911bf2008-07-26 23:55:29129void PluginChannel::OnChannelError() {
[email protected]157e5d22009-04-23 18:43:35130 base::CloseProcessHandle(renderer_handle_);
131 renderer_handle_ = 0;
initial.commit09911bf2008-07-26 23:55:29132 PluginChannelBase::OnChannelError();
133 CleanUp();
134}
135
136void 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.botbf09a502008-08-24 00:55:55150}
[email protected]3dfc7a42009-06-27 01:43:51151
152bool 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}