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.
5 #include "ppapi/proxy/ppp_instance_proxy.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_resource_tracker.h"
17 #include "ppapi/proxy/ppapi_messages.h"
18 #include "ppapi/proxy/ppb_url_loader_proxy.h"
19 #include "ppapi/shared_impl/ppapi_globals.h"
20 #include "ppapi/shared_impl/ppb_view_shared.h"
21 #include "ppapi/shared_impl/scoped_pp_resource.h"
22 #include "ppapi/thunk/enter.h"
23 #include "ppapi/thunk/ppb_flash_fullscreen_api.h"
24 #include "ppapi/thunk/ppb_view_api.h"
29 using thunk::EnterInstanceAPINoLock
;
30 using thunk::EnterInstanceNoLock
;
31 using thunk::EnterResourceNoLock
;
32 using thunk::PPB_Flash_Fullscreen_API
;
33 using thunk::PPB_Instance_API
;
34 using thunk::PPB_View_API
;
39 PP_Bool
DidCreate(PP_Instance instance
,
43 std::vector
<std::string
> argn_vect
;
44 std::vector
<std::string
> argv_vect
;
45 for (uint32_t i
= 0; i
< argc
; i
++) {
46 argn_vect
.push_back(std::string(argn
[i
]));
47 argv_vect
.push_back(std::string(argv
[i
]));
50 PP_Bool result
= PP_FALSE
;
51 HostDispatcher::GetForInstance(instance
)->Send(
52 new PpapiMsg_PPPInstance_DidCreate(API_ID_PPP_INSTANCE
, instance
,
53 argn_vect
, argv_vect
, &result
));
57 void DidDestroy(PP_Instance instance
) {
58 HostDispatcher::GetForInstance(instance
)->Send(
59 new PpapiMsg_PPPInstance_DidDestroy(API_ID_PPP_INSTANCE
, instance
));
62 void DidChangeView(PP_Instance instance
, PP_Resource view_resource
) {
63 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
65 EnterResourceNoLock
<PPB_View_API
> enter_view(view_resource
, false);
66 if (enter_view
.failed()) {
71 PP_Bool flash_fullscreen
= PP_FALSE
;
72 EnterInstanceNoLock
enter_instance(instance
);
73 if (!enter_instance
.failed())
74 flash_fullscreen
= enter_instance
.functions()->FlashIsFullscreen(instance
);
75 dispatcher
->Send(new PpapiMsg_PPPInstance_DidChangeView(
76 API_ID_PPP_INSTANCE
, instance
, enter_view
.object()->GetData(),
80 void DidChangeFocus(PP_Instance instance
, PP_Bool has_focus
) {
81 HostDispatcher::GetForInstance(instance
)->Send(
82 new PpapiMsg_PPPInstance_DidChangeFocus(API_ID_PPP_INSTANCE
,
83 instance
, has_focus
));
86 PP_Bool
HandleDocumentLoad(PP_Instance instance
,
87 PP_Resource url_loader
) {
88 PP_Bool result
= PP_FALSE
;
89 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
91 // Set up the URLLoader for proxying.
93 PPB_URLLoader_Proxy
* url_loader_proxy
= static_cast<PPB_URLLoader_Proxy
*>(
94 dispatcher
->GetInterfaceProxy(API_ID_PPB_URL_LOADER
));
95 url_loader_proxy
->PrepareURLLoaderForSendingToPlugin(url_loader
);
97 // PluginResourceTracker in the plugin process assumes that resources that it
98 // tracks have been addrefed on behalf of the plugin at the renderer side. So
99 // we explicitly do it for |url_loader| here.
101 // Please also see comments in PPP_Instance_Proxy::OnMsgHandleDocumentLoad()
102 // about releasing of this extra reference.
103 const PPB_Core
* core
= reinterpret_cast<const PPB_Core
*>(
104 dispatcher
->local_get_interface()(PPB_CORE_INTERFACE
));
109 core
->AddRefResource(url_loader
);
111 HostResource serialized_loader
;
112 serialized_loader
.SetHostResource(instance
, url_loader
);
113 dispatcher
->Send(new PpapiMsg_PPPInstance_HandleDocumentLoad(
114 API_ID_PPP_INSTANCE
, instance
, serialized_loader
, &result
));
118 static const PPP_Instance_1_1 instance_interface
= {
125 #endif // !defined(OS_NACL)
129 PPP_Instance_Proxy::PPP_Instance_Proxy(Dispatcher
* dispatcher
)
130 : InterfaceProxy(dispatcher
) {
131 if (dispatcher
->IsPlugin()) {
132 // The PPP_Instance proxy works by always proxying the 1.1 version of the
133 // interface, and then detecting in the plugin process which one to use.
134 // PPP_Instance_Combined handles dispatching to whatever interface is
137 // This means that if the plugin supports either 1.0 or 1.1 version of
138 // the interface, we want to say it supports the 1.1 version since we'll
139 // convert it here. This magic conversion code is hardcoded into
140 // PluginDispatcher::OnMsgSupportsInterface.
141 combined_interface_
.reset(PPP_Instance_Combined::Create(
142 base::Bind(dispatcher
->local_get_interface())));
146 PPP_Instance_Proxy::~PPP_Instance_Proxy() {
149 #if !defined(OS_NACL)
151 const PPP_Instance
* PPP_Instance_Proxy::GetInstanceInterface() {
152 return &instance_interface
;
154 #endif // !defined(OS_NACL)
156 bool PPP_Instance_Proxy::OnMessageReceived(const IPC::Message
& msg
) {
158 IPC_BEGIN_MESSAGE_MAP(PPP_Instance_Proxy
, msg
)
159 IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidCreate
,
160 OnPluginMsgDidCreate
)
161 IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidDestroy
,
162 OnPluginMsgDidDestroy
)
163 IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidChangeView
,
164 OnPluginMsgDidChangeView
)
165 IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidChangeFocus
,
166 OnPluginMsgDidChangeFocus
)
167 IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_HandleDocumentLoad
,
168 OnPluginMsgHandleDocumentLoad
)
169 IPC_MESSAGE_UNHANDLED(handled
= false)
170 IPC_END_MESSAGE_MAP()
174 void PPP_Instance_Proxy::OnPluginMsgDidCreate(
175 PP_Instance instance
,
176 const std::vector
<std::string
>& argn
,
177 const std::vector
<std::string
>& argv
,
180 if (argn
.size() != argv
.size())
183 // Set up the routing associating this new instance with the dispatcher we
184 // just got the message from. This must be done before calling into the
185 // plugin so it can in turn call PPAPI functions.
186 PluginDispatcher
* plugin_dispatcher
=
187 static_cast<PluginDispatcher
*>(dispatcher());
188 plugin_dispatcher
->DidCreateInstance(instance
);
189 PpapiGlobals::Get()->GetResourceTracker()->DidCreateInstance(instance
);
191 // Make sure the arrays always have at least one element so we can take the
193 std::vector
<const char*> argn_array(
194 std::max(static_cast<size_t>(1), argn
.size()));
195 std::vector
<const char*> argv_array(
196 std::max(static_cast<size_t>(1), argn
.size()));
197 for (size_t i
= 0; i
< argn
.size(); i
++) {
198 argn_array
[i
] = argn
[i
].c_str();
199 argv_array
[i
] = argv
[i
].c_str();
202 DCHECK(combined_interface_
.get());
203 *result
= combined_interface_
->DidCreate(instance
,
204 static_cast<uint32_t>(argn
.size()),
205 &argn_array
[0], &argv_array
[0]);
208 void PPP_Instance_Proxy::OnPluginMsgDidDestroy(PP_Instance instance
) {
209 combined_interface_
->DidDestroy(instance
);
211 PpapiGlobals
* globals
= PpapiGlobals::Get();
212 globals
->GetResourceTracker()->DidDeleteInstance(instance
);
213 globals
->GetVarTracker()->DidDeleteInstance(instance
);
215 static_cast<PluginDispatcher
*>(dispatcher())->DidDestroyInstance(instance
);
218 void PPP_Instance_Proxy::OnPluginMsgDidChangeView(
219 PP_Instance instance
,
220 const ViewData
& new_data
,
221 PP_Bool flash_fullscreen
) {
222 PluginDispatcher
* dispatcher
= PluginDispatcher::GetForInstance(instance
);
225 InstanceData
* data
= dispatcher
->GetInstanceData(instance
);
228 data
->view
= new_data
;
230 #if !defined(OS_NACL)
231 EnterInstanceAPINoLock
<PPB_Flash_Fullscreen_API
> enter(instance
);
233 enter
.functions()->SetLocalIsFullscreen(instance
, flash_fullscreen
);
234 #endif // !defined(OS_NACL)
236 ScopedPPResource
resource(
237 ScopedPPResource::PassRef(),
238 (new PPB_View_Shared(OBJECT_IS_PROXY
,
239 instance
, new_data
))->GetReference());
241 combined_interface_
->DidChangeView(instance
, resource
,
243 &new_data
.clip_rect
);
246 void PPP_Instance_Proxy::OnPluginMsgDidChangeFocus(PP_Instance instance
,
248 combined_interface_
->DidChangeFocus(instance
, has_focus
);
251 void PPP_Instance_Proxy::OnPluginMsgHandleDocumentLoad(
252 PP_Instance instance
,
253 const HostResource
& url_loader
,
255 PP_Resource plugin_loader
=
256 PPB_URLLoader_Proxy::TrackPluginResource(url_loader
);
257 *result
= combined_interface_
->HandleDocumentLoad(instance
, plugin_loader
);
259 // This balances the one reference that TrackPluginResource() initialized it
260 // with. The plugin will normally take an additional reference which will keep
261 // the resource alive in the plugin (and the one reference in the renderer
262 // representing all plugin references).
263 // Once all references at the plugin side are released, the renderer side will
264 // be notified and release the reference added in HandleDocumentLoad() above.
265 PpapiGlobals::Get()->GetResourceTracker()->ReleaseResource(plugin_loader
);