blob: 45755e1d4d84a155b8a11d65fba34d0fae20b875 [file] [log] [blame]
[email protected]93df81e2012-08-10 22:22:461// Copyright (c) 2012 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.
4
5#include "content/renderer/pepper/pepper_in_process_router.h"
6
7#include "base/bind.h"
[email protected]aaf68892013-07-18 00:11:308#include "base/message_loop/message_loop.h"
[email protected]0d586af2013-07-31 21:58:069#include "content/public/renderer/render_thread.h"
[email protected]93df81e2012-08-10 22:22:4610#include "content/renderer/pepper/renderer_ppapi_host_impl.h"
[email protected]fb44cb0a2013-12-04 00:45:5511#include "content/renderer/render_frame_impl.h"
[email protected]93df81e2012-08-10 22:22:4612#include "ipc/ipc_message.h"
[email protected]93df81e2012-08-10 22:22:4613#include "ipc/ipc_sender.h"
14#include "ppapi/proxy/ppapi_messages.h"
15#include "ppapi/shared_impl/ppapi_globals.h"
16#include "ppapi/shared_impl/resource_tracker.h"
17
[email protected]0d586af2013-07-31 21:58:0618using ppapi::UnpackMessage;
19
[email protected]93df81e2012-08-10 22:22:4620namespace content {
21
[email protected]5c96d9da2012-10-09 20:15:3422class PepperInProcessRouter::Channel : public IPC::Sender {
[email protected]93df81e2012-08-10 22:22:4623 public:
[email protected]5c96d9da2012-10-09 20:15:3424 Channel(const base::Callback<bool(IPC::Message*)>& callback)
25 : callback_(callback) {}
[email protected]93df81e2012-08-10 22:22:4626
[email protected]5c96d9da2012-10-09 20:15:3427 virtual ~Channel() {}
28
29 virtual bool Send(IPC::Message* message) OVERRIDE {
30 return callback_.Run(message);
[email protected]93df81e2012-08-10 22:22:4631 }
[email protected]93df81e2012-08-10 22:22:4632
33 private:
[email protected]5c96d9da2012-10-09 20:15:3434 base::Callback<bool(IPC::Message*)> callback_;
[email protected]93df81e2012-08-10 22:22:4635};
36
[email protected]93df81e2012-08-10 22:22:4637PepperInProcessRouter::PepperInProcessRouter(
38 RendererPpapiHostImpl* host_impl)
[email protected]5c96d9da2012-10-09 20:15:3439 : host_impl_(host_impl),
40 pending_message_id_(0),
41 reply_result_(false),
[email protected]69e797f2013-04-30 01:10:2242 weak_factory_(this) {
[email protected]0d586af2013-07-31 21:58:0643 browser_channel_.reset(
44 new Channel(base::Bind(&PepperInProcessRouter::SendToBrowser,
[email protected]5c96d9da2012-10-09 20:15:3445 base::Unretained(this))));
46 host_to_plugin_router_.reset(
47 new Channel(base::Bind(&PepperInProcessRouter::SendToPlugin,
48 base::Unretained(this))));
49 plugin_to_host_router_.reset(
50 new Channel(base::Bind(&PepperInProcessRouter::SendToHost,
51 base::Unretained(this))));
[email protected]93df81e2012-08-10 22:22:4652}
53
54PepperInProcessRouter::~PepperInProcessRouter() {
55}
56
57IPC::Sender* PepperInProcessRouter::GetPluginToRendererSender() {
58 return plugin_to_host_router_.get();
59}
60
61IPC::Sender* PepperInProcessRouter::GetRendererToPluginSender() {
62 return host_to_plugin_router_.get();
63}
64
[email protected]8dd2d2c2013-07-23 21:19:3165ppapi::proxy::Connection PepperInProcessRouter::GetPluginConnection(
66 PP_Instance instance) {
67 int routing_id = 0;
[email protected]fb44cb0a2013-12-04 00:45:5568 RenderFrame* frame = host_impl_->GetRenderFrameForInstance(instance);
69 if (frame)
[email protected]60eca4eb2013-12-06 00:02:1670 routing_id = frame->GetRoutingID();
[email protected]0d586af2013-07-31 21:58:0671 return ppapi::proxy::Connection(browser_channel_.get(),
[email protected]8dd2d2c2013-07-23 21:19:3172 plugin_to_host_router_.get(),
73 routing_id);
[email protected]93df81e2012-08-10 22:22:4674}
75
[email protected]0d586af2013-07-31 21:58:0676// static
77bool PepperInProcessRouter::OnPluginMsgReceived(const IPC::Message& msg) {
78 // Emulate the proxy by dispatching the relevant message here.
79 ppapi::proxy::ResourceMessageReplyParams reply_params;
80 IPC::Message nested_msg;
81
82 if (msg.type() == PpapiPluginMsg_ResourceReply::ID) {
83 // Resource reply from the renderer (no routing id).
84 if (!UnpackMessage<PpapiPluginMsg_ResourceReply>(msg, &reply_params,
85 &nested_msg)) {
86 NOTREACHED();
87 return false;
88 }
89 } else if (msg.type() == PpapiHostMsg_InProcessResourceReply::ID) {
90 // Resource reply from the browser (has a routing id).
91 if (!UnpackMessage<PpapiHostMsg_InProcessResourceReply>(msg, &reply_params,
92 &nested_msg)) {
93 NOTREACHED();
94 return false;
95 }
96 } else {
97 return false;
98 }
99 ppapi::Resource* resource =
100 ppapi::PpapiGlobals::Get()->GetResourceTracker()->GetResource(
101 reply_params.pp_resource());
102 // If the resource doesn't exist, it may have been destroyed so just ignore
103 // the message.
104 if (resource)
105 resource->OnReplyReceived(reply_params, nested_msg);
106 return true;
107}
108
[email protected]5c96d9da2012-10-09 20:15:34109bool PepperInProcessRouter::SendToHost(IPC::Message* msg) {
110 scoped_ptr<IPC::Message> message(msg);
111
112 if (!message->is_sync()) {
[email protected]165bae72013-09-11 20:08:06113 // If this is a resource destroyed message, post a task to dispatch it.
114 // Dispatching it synchronously can cause the host to re-enter the proxy
115 // code while we're still in the resource destructor, leading to a crash.
116 // http://crbug.com/276368.
117 // This won't cause message reordering problems because the resource
118 // destroyed message is always the last one sent for a resource.
119 if (message->type() == PpapiHostMsg_ResourceDestroyed::ID) {
120 base::MessageLoop::current()->PostTask(
121 FROM_HERE,
122 base::Bind(&PepperInProcessRouter::DispatchHostMsg,
123 weak_factory_.GetWeakPtr(),
124 base::Owned(message.release())));
125 return true;
126 } else {
127 bool result = host_impl_->GetPpapiHost()->OnMessageReceived(*message);
128 DCHECK(result) << "The message was not handled by the host.";
129 return true;
130 }
[email protected]5c96d9da2012-10-09 20:15:34131 }
132
133 pending_message_id_ = IPC::SyncMessage::GetMessageId(*message);
134 reply_deserializer_.reset(
135 static_cast<IPC::SyncMessage*>(message.get())->GetReplyDeserializer());
136 reply_result_ = false;
137
138 bool result = host_impl_->GetPpapiHost()->OnMessageReceived(*message);
139 DCHECK(result) << "The message was not handled by the host.";
140
141 pending_message_id_ = 0;
142 reply_deserializer_.reset(NULL);
143 return reply_result_;
144}
145
146bool PepperInProcessRouter::SendToPlugin(IPC::Message* msg) {
147 scoped_ptr<IPC::Message> message(msg);
[email protected]c27f1152012-10-16 20:23:48148 CHECK(!msg->is_sync());
149 if (IPC::SyncMessage::IsMessageReplyTo(*message, pending_message_id_)) {
[email protected]5c96d9da2012-10-09 20:15:34150 if (!msg->is_reply_error())
151 reply_result_ = reply_deserializer_->SerializeOutputParameters(*message);
152 } else {
153 CHECK(!pending_message_id_);
154 // Dispatch plugin messages from the message loop.
[email protected]dd32b1272013-05-04 14:17:11155 base::MessageLoop::current()->PostTask(
[email protected]5c96d9da2012-10-09 20:15:34156 FROM_HERE,
157 base::Bind(&PepperInProcessRouter::DispatchPluginMsg,
[email protected]dd32b1272013-05-04 14:17:11158 weak_factory_.GetWeakPtr(),
159 base::Owned(message.release())));
[email protected]5c96d9da2012-10-09 20:15:34160 }
161 return true;
162}
163
[email protected]165bae72013-09-11 20:08:06164void PepperInProcessRouter::DispatchHostMsg(IPC::Message* msg) {
165 bool handled = host_impl_->GetPpapiHost()->OnMessageReceived(*msg);
166 DCHECK(handled);
167}
168
[email protected]5c96d9da2012-10-09 20:15:34169void PepperInProcessRouter::DispatchPluginMsg(IPC::Message* msg) {
[email protected]0d586af2013-07-31 21:58:06170 bool handled = OnPluginMsgReceived(*msg);
171 DCHECK(handled);
[email protected]5c96d9da2012-10-09 20:15:34172}
173
[email protected]0d586af2013-07-31 21:58:06174bool PepperInProcessRouter::SendToBrowser(IPC::Message *msg) {
175 return RenderThread::Get()->Send(msg);
[email protected]5c96d9da2012-10-09 20:15:34176}
177
[email protected]93df81e2012-08-10 22:22:46178} // namespace content