Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / renderer / pepper / pepper_in_process_router.cc
1 // 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"
8 #include "base/message_loop/message_loop.h"
9 #include "content/public/renderer/render_thread.h"
10 #include "content/renderer/pepper/renderer_ppapi_host_impl.h"
11 #include "content/renderer/render_frame_impl.h"
12 #include "ipc/ipc_message.h"
13 #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
18 using ppapi::UnpackMessage;
19
20 namespace content {
21
22 class PepperInProcessRouter::Channel : public IPC::Sender {
23  public:
24   Channel(const base::Callback<bool(IPC::Message*)>& callback)
25       : callback_(callback) {}
26
27   ~Channel() override {}
28
29   bool Send(IPC::Message* message) override { return callback_.Run(message); }
30
31  private:
32   base::Callback<bool(IPC::Message*)> callback_;
33 };
34
35 PepperInProcessRouter::PepperInProcessRouter(RendererPpapiHostImpl* host_impl)
36     : host_impl_(host_impl),
37       pending_message_id_(0),
38       reply_result_(false),
39       weak_factory_(this) {
40   browser_channel_.reset(new Channel(base::Bind(
41       &PepperInProcessRouter::SendToBrowser, base::Unretained(this))));
42   host_to_plugin_router_.reset(new Channel(base::Bind(
43       &PepperInProcessRouter::SendToPlugin, base::Unretained(this))));
44   plugin_to_host_router_.reset(new Channel(
45       base::Bind(&PepperInProcessRouter::SendToHost, base::Unretained(this))));
46 }
47
48 PepperInProcessRouter::~PepperInProcessRouter() {}
49
50 IPC::Sender* PepperInProcessRouter::GetPluginToRendererSender() {
51   return plugin_to_host_router_.get();
52 }
53
54 IPC::Sender* PepperInProcessRouter::GetRendererToPluginSender() {
55   return host_to_plugin_router_.get();
56 }
57
58 ppapi::proxy::Connection PepperInProcessRouter::GetPluginConnection(
59     PP_Instance instance) {
60   int routing_id = 0;
61   RenderFrame* frame = host_impl_->GetRenderFrameForInstance(instance);
62   if (frame)
63     routing_id = frame->GetRoutingID();
64   return ppapi::proxy::Connection(
65       browser_channel_.get(), plugin_to_host_router_.get(), routing_id);
66 }
67
68 // static
69 bool PepperInProcessRouter::OnPluginMsgReceived(const IPC::Message& msg) {
70   // Emulate the proxy by dispatching the relevant message here.
71   ppapi::proxy::ResourceMessageReplyParams reply_params;
72   IPC::Message nested_msg;
73
74   if (msg.type() == PpapiPluginMsg_ResourceReply::ID) {
75     // Resource reply from the renderer (no routing id).
76     if (!UnpackMessage<PpapiPluginMsg_ResourceReply>(
77             msg, &reply_params, &nested_msg)) {
78       NOTREACHED();
79       return false;
80     }
81   } else if (msg.type() == PpapiHostMsg_InProcessResourceReply::ID) {
82     // Resource reply from the browser (has a routing id).
83     if (!UnpackMessage<PpapiHostMsg_InProcessResourceReply>(
84             msg, &reply_params, &nested_msg)) {
85       NOTREACHED();
86       return false;
87     }
88   } else {
89     return false;
90   }
91   ppapi::Resource* resource =
92       ppapi::PpapiGlobals::Get()->GetResourceTracker()->GetResource(
93           reply_params.pp_resource());
94   // If the resource doesn't exist, it may have been destroyed so just ignore
95   // the message.
96   if (resource)
97     resource->OnReplyReceived(reply_params, nested_msg);
98   return true;
99 }
100
101 bool PepperInProcessRouter::SendToHost(IPC::Message* msg) {
102   scoped_ptr<IPC::Message> message(msg);
103
104   if (!message->is_sync()) {
105     // If this is a resource destroyed message, post a task to dispatch it.
106     // Dispatching it synchronously can cause the host to re-enter the proxy
107     // code while we're still in the resource destructor, leading to a crash.
108     // http://crbug.com/276368.
109     // This won't cause message reordering problems because the resource
110     // destroyed message is always the last one sent for a resource.
111     if (message->type() == PpapiHostMsg_ResourceDestroyed::ID) {
112       base::MessageLoop::current()->PostTask(
113           FROM_HERE,
114           base::Bind(&PepperInProcessRouter::DispatchHostMsg,
115                      weak_factory_.GetWeakPtr(),
116                      base::Owned(message.release())));
117       return true;
118     } else {
119       bool result = host_impl_->GetPpapiHost()->OnMessageReceived(*message);
120       DCHECK(result) << "The message was not handled by the host.";
121       return true;
122     }
123   }
124
125   pending_message_id_ = IPC::SyncMessage::GetMessageId(*message);
126   reply_deserializer_.reset(
127       static_cast<IPC::SyncMessage*>(message.get())->GetReplyDeserializer());
128   reply_result_ = false;
129
130   bool result = host_impl_->GetPpapiHost()->OnMessageReceived(*message);
131   DCHECK(result) << "The message was not handled by the host.";
132
133   pending_message_id_ = 0;
134   reply_deserializer_.reset(NULL);
135   return reply_result_;
136 }
137
138 bool PepperInProcessRouter::SendToPlugin(IPC::Message* msg) {
139   scoped_ptr<IPC::Message> message(msg);
140   CHECK(!msg->is_sync());
141   if (IPC::SyncMessage::IsMessageReplyTo(*message, pending_message_id_)) {
142     if (!msg->is_reply_error())
143       reply_result_ = reply_deserializer_->SerializeOutputParameters(*message);
144   } else {
145     CHECK(!pending_message_id_);
146     // Dispatch plugin messages from the message loop.
147     base::MessageLoop::current()->PostTask(
148         FROM_HERE,
149         base::Bind(&PepperInProcessRouter::DispatchPluginMsg,
150                    weak_factory_.GetWeakPtr(),
151                    base::Owned(message.release())));
152   }
153   return true;
154 }
155
156 void PepperInProcessRouter::DispatchHostMsg(IPC::Message* msg) {
157   bool handled = host_impl_->GetPpapiHost()->OnMessageReceived(*msg);
158   DCHECK(handled);
159 }
160
161 void PepperInProcessRouter::DispatchPluginMsg(IPC::Message* msg) {
162   bool handled = OnPluginMsgReceived(*msg);
163   DCHECK(handled);
164 }
165
166 bool PepperInProcessRouter::SendToBrowser(IPC::Message* msg) {
167   return RenderThread::Get()->Send(msg);
168 }
169
170 }  // namespace content