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_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"
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
;
42 PP_Bool
DidCreate(PP_Instance instance
,
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
]));
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
));
60 void DidDestroy(PP_Instance instance
) {
61 HostDispatcher::GetForInstance(instance
)->Send(
62 new PpapiMsg_PPPInstance_DidDestroy(API_ID_PPP_INSTANCE
, instance
));
65 void DidChangeView(PP_Instance instance
, PP_Resource view_resource
) {
66 HostDispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
68 EnterResourceNoLock
<PPB_View_API
> enter_view(view_resource
, false);
69 if (enter_view
.failed()) {
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(),
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
));
89 PP_Bool
HandleDocumentLoad(PP_Instance instance
, PP_Resource url_loader
) {
90 // This should never get called. Out-of-process document loads are handled
96 static const PPP_Instance_1_1 instance_interface
= {
103 #endif // !defined(OS_NACL)
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
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())));
124 PPP_Instance_Proxy::~PPP_Instance_Proxy() {
127 #if !defined(OS_NACL)
129 const PPP_Instance
* PPP_Instance_Proxy::GetInstanceInterface() {
130 return &instance_interface
;
132 #endif // !defined(OS_NACL)
134 bool PPP_Instance_Proxy::OnMessageReceived(const IPC::Message
& msg
) {
135 if (!dispatcher()->IsPlugin())
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()
155 void PPP_Instance_Proxy::OnPluginMsgDidCreate(
156 PP_Instance instance
,
157 const std::vector
<std::string
>& argn
,
158 const std::vector
<std::string
>& argv
,
161 if (argn
.size() != argv
.size())
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
);
172 // Make sure the arrays always have at least one element so we can take the
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();
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]);
189 void PPP_Instance_Proxy::OnPluginMsgDidDestroy(PP_Instance instance
) {
190 combined_interface_
->DidDestroy(instance
);
192 PpapiGlobals
* globals
= PpapiGlobals::Get();
193 globals
->GetResourceTracker()->DidDeleteInstance(instance
);
194 globals
->GetVarTracker()->DidDeleteInstance(instance
);
196 static_cast<PluginDispatcher
*>(dispatcher())->DidDestroyInstance(instance
);
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
);
206 InstanceData
* data
= dispatcher
->GetInstanceData(instance
);
209 data
->view
= new_data
;
211 #if !defined(OS_NACL)
212 EnterInstanceAPINoLock
<PPB_Flash_Fullscreen_API
> enter(instance
);
214 enter
.functions()->SetLocalIsFullscreen(instance
, flash_fullscreen
);
215 #endif // !defined(OS_NACL)
217 ScopedPPResource
resource(
218 ScopedPPResource::PassRef(),
219 (new PPB_View_Shared(OBJECT_IS_PROXY
,
220 instance
, new_data
))->GetReference());
222 combined_interface_
->DidChangeView(instance
, resource
,
224 &new_data
.clip_rect
);
227 void PPP_Instance_Proxy::OnPluginMsgDidChangeFocus(PP_Instance instance
,
229 combined_interface_
->DidChangeFocus(instance
, has_focus
);
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
);
239 Connection
connection(PluginGlobals::Get()->GetBrowserSender(),
242 scoped_refptr
<URLLoaderResource
> loader_resource(
243 new URLLoaderResource(connection
, instance
,
244 pending_loader_host_id
, data
));
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(