- add sources.
[platform/framework/web/crosswalk.git] / src / ppapi / proxy / ppp_instance_proxy.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 "ppapi/proxy/ppp_instance_proxy.h"
6
7 #include <algorithm>
8
9 #include "base/bind.h"
10 #include "ppapi/c/pp_var.h"
11 #include "ppapi/c/ppb_core.h"
12 #include "ppapi/c/ppb_fullscreen.h"
13 #include "ppapi/c/ppp_instance.h"
14 #include "ppapi/proxy/host_dispatcher.h"
15 #include "ppapi/proxy/plugin_dispatcher.h"
16 #include "ppapi/proxy/plugin_globals.h"
17 #include "ppapi/proxy/plugin_proxy_delegate.h"
18 #include "ppapi/proxy/plugin_resource_tracker.h"
19 #include "ppapi/proxy/ppapi_messages.h"
20 #include "ppapi/proxy/url_loader_resource.h"
21 #include "ppapi/shared_impl/ppapi_globals.h"
22 #include "ppapi/shared_impl/ppb_view_shared.h"
23 #include "ppapi/shared_impl/resource_tracker.h"
24 #include "ppapi/shared_impl/scoped_pp_resource.h"
25 #include "ppapi/thunk/enter.h"
26 #include "ppapi/thunk/ppb_flash_fullscreen_api.h"
27 #include "ppapi/thunk/ppb_view_api.h"
28
29 namespace ppapi {
30 namespace proxy {
31
32 using thunk::EnterInstanceAPINoLock;
33 using thunk::EnterInstanceNoLock;
34 using thunk::EnterResourceNoLock;
35 using thunk::PPB_Flash_Fullscreen_API;
36 using thunk::PPB_Instance_API;
37 using thunk::PPB_View_API;
38
39 namespace {
40
41 #if !defined(OS_NACL)
42 PP_Bool DidCreate(PP_Instance instance,
43                   uint32_t argc,
44                   const char* argn[],
45                   const char* argv[]) {
46   std::vector<std::string> argn_vect;
47   std::vector<std::string> argv_vect;
48   for (uint32_t i = 0; i < argc; i++) {
49     argn_vect.push_back(std::string(argn[i]));
50     argv_vect.push_back(std::string(argv[i]));
51   }
52
53   PP_Bool result = PP_FALSE;
54   HostDispatcher::GetForInstance(instance)->Send(
55       new PpapiMsg_PPPInstance_DidCreate(API_ID_PPP_INSTANCE, instance,
56                                          argn_vect, argv_vect, &result));
57   return result;
58 }
59
60 void DidDestroy(PP_Instance instance) {
61   HostDispatcher::GetForInstance(instance)->Send(
62       new PpapiMsg_PPPInstance_DidDestroy(API_ID_PPP_INSTANCE, instance));
63 }
64
65 void DidChangeView(PP_Instance instance, PP_Resource view_resource) {
66   HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
67
68   EnterResourceNoLock<PPB_View_API> enter_view(view_resource, false);
69   if (enter_view.failed()) {
70     NOTREACHED();
71     return;
72   }
73
74   PP_Bool flash_fullscreen = PP_FALSE;
75   EnterInstanceNoLock enter_instance(instance);
76   if (!enter_instance.failed())
77     flash_fullscreen = enter_instance.functions()->FlashIsFullscreen(instance);
78   dispatcher->Send(new PpapiMsg_PPPInstance_DidChangeView(
79       API_ID_PPP_INSTANCE, instance, enter_view.object()->GetData(),
80       flash_fullscreen));
81 }
82
83 void DidChangeFocus(PP_Instance instance, PP_Bool has_focus) {
84   HostDispatcher::GetForInstance(instance)->Send(
85       new PpapiMsg_PPPInstance_DidChangeFocus(API_ID_PPP_INSTANCE,
86                                               instance, has_focus));
87 }
88
89 PP_Bool HandleDocumentLoad(PP_Instance instance, PP_Resource url_loader) {
90   // This should never get called. Out-of-process document loads are handled
91   // specially.
92   NOTREACHED();
93   return PP_FALSE;
94 }
95
96 static const PPP_Instance_1_1 instance_interface = {
97   &DidCreate,
98   &DidDestroy,
99   &DidChangeView,
100   &DidChangeFocus,
101   &HandleDocumentLoad
102 };
103 #endif  // !defined(OS_NACL)
104
105 }  // namespace
106
107 PPP_Instance_Proxy::PPP_Instance_Proxy(Dispatcher* dispatcher)
108     : InterfaceProxy(dispatcher) {
109   if (dispatcher->IsPlugin()) {
110     // The PPP_Instance proxy works by always proxying the 1.1 version of the
111     // interface, and then detecting in the plugin process which one to use.
112     // PPP_Instance_Combined handles dispatching to whatever interface is
113     // supported.
114     //
115     // This means that if the plugin supports either 1.0 or 1.1 version of
116     // the interface, we want to say it supports the 1.1 version since we'll
117     // convert it here. This magic conversion code is hardcoded into
118     // PluginDispatcher::OnMsgSupportsInterface.
119     combined_interface_.reset(PPP_Instance_Combined::Create(
120         base::Bind(dispatcher->local_get_interface())));
121   }
122 }
123
124 PPP_Instance_Proxy::~PPP_Instance_Proxy() {
125 }
126
127 #if !defined(OS_NACL)
128 // static
129 const PPP_Instance* PPP_Instance_Proxy::GetInstanceInterface() {
130   return &instance_interface;
131 }
132 #endif  // !defined(OS_NACL)
133
134 bool PPP_Instance_Proxy::OnMessageReceived(const IPC::Message& msg) {
135   if (!dispatcher()->IsPlugin())
136     return false;
137
138   bool handled = true;
139   IPC_BEGIN_MESSAGE_MAP(PPP_Instance_Proxy, msg)
140     IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidCreate,
141                         OnPluginMsgDidCreate)
142     IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidDestroy,
143                         OnPluginMsgDidDestroy)
144     IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidChangeView,
145                         OnPluginMsgDidChangeView)
146     IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidChangeFocus,
147                         OnPluginMsgDidChangeFocus)
148     IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_HandleDocumentLoad,
149                         OnPluginMsgHandleDocumentLoad)
150     IPC_MESSAGE_UNHANDLED(handled = false)
151   IPC_END_MESSAGE_MAP()
152   return handled;
153 }
154
155 void PPP_Instance_Proxy::OnPluginMsgDidCreate(
156     PP_Instance instance,
157     const std::vector<std::string>& argn,
158     const std::vector<std::string>& argv,
159     PP_Bool* result) {
160   *result = PP_FALSE;
161   if (argn.size() != argv.size())
162     return;
163
164   // Set up the routing associating this new instance with the dispatcher we
165   // just got the message from. This must be done before calling into the
166   // plugin so it can in turn call PPAPI functions.
167   PluginDispatcher* plugin_dispatcher =
168       static_cast<PluginDispatcher*>(dispatcher());
169   plugin_dispatcher->DidCreateInstance(instance);
170   PpapiGlobals::Get()->GetResourceTracker()->DidCreateInstance(instance);
171
172   // Make sure the arrays always have at least one element so we can take the
173   // address below.
174   std::vector<const char*> argn_array(
175       std::max(static_cast<size_t>(1), argn.size()));
176   std::vector<const char*> argv_array(
177       std::max(static_cast<size_t>(1), argn.size()));
178   for (size_t i = 0; i < argn.size(); i++) {
179     argn_array[i] = argn[i].c_str();
180     argv_array[i] = argv[i].c_str();
181   }
182
183   DCHECK(combined_interface_.get());
184   *result = combined_interface_->DidCreate(instance,
185                                            static_cast<uint32_t>(argn.size()),
186                                            &argn_array[0], &argv_array[0]);
187 }
188
189 void PPP_Instance_Proxy::OnPluginMsgDidDestroy(PP_Instance instance) {
190   combined_interface_->DidDestroy(instance);
191
192   PpapiGlobals* globals = PpapiGlobals::Get();
193   globals->GetResourceTracker()->DidDeleteInstance(instance);
194   globals->GetVarTracker()->DidDeleteInstance(instance);
195
196   static_cast<PluginDispatcher*>(dispatcher())->DidDestroyInstance(instance);
197 }
198
199 void PPP_Instance_Proxy::OnPluginMsgDidChangeView(
200     PP_Instance instance,
201     const ViewData& new_data,
202     PP_Bool flash_fullscreen) {
203   PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
204   if (!dispatcher)
205     return;
206   InstanceData* data = dispatcher->GetInstanceData(instance);
207   if (!data)
208     return;
209   data->view = new_data;
210
211 #if !defined(OS_NACL)
212   EnterInstanceAPINoLock<PPB_Flash_Fullscreen_API> enter(instance);
213   if (!enter.failed())
214     enter.functions()->SetLocalIsFullscreen(instance, flash_fullscreen);
215 #endif  // !defined(OS_NACL)
216
217   ScopedPPResource resource(
218       ScopedPPResource::PassRef(),
219       (new PPB_View_Shared(OBJECT_IS_PROXY,
220                            instance, new_data))->GetReference());
221
222   combined_interface_->DidChangeView(instance, resource,
223                                      &new_data.rect,
224                                      &new_data.clip_rect);
225 }
226
227 void PPP_Instance_Proxy::OnPluginMsgDidChangeFocus(PP_Instance instance,
228                                                    PP_Bool has_focus) {
229   combined_interface_->DidChangeFocus(instance, has_focus);
230 }
231
232 void PPP_Instance_Proxy::OnPluginMsgHandleDocumentLoad(
233     PP_Instance instance,
234     int pending_loader_host_id,
235     const URLResponseInfoData& data) {
236   PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
237   if (!dispatcher)
238     return;
239   Connection connection(PluginGlobals::Get()->GetBrowserSender(),
240                         dispatcher);
241
242   scoped_refptr<URLLoaderResource> loader_resource(
243       new URLLoaderResource(connection, instance,
244                             pending_loader_host_id, data));
245
246   PP_Resource loader_pp_resource = loader_resource->GetReference();
247   if (!combined_interface_->HandleDocumentLoad(instance, loader_pp_resource))
248     loader_resource->Close();
249   // We don't pass a ref into the plugin, if it wants one, it will have taken
250   // an additional one.
251   PpapiGlobals::Get()->GetResourceTracker()->ReleaseResource(
252       loader_pp_resource);
253 }
254
255 }  // namespace proxy
256 }  // namespace ppapi