OLD | NEW |
---|---|
(Empty) | |
1 // Use of this source code is governed by a BSD-style license that can be | |
2 // found in the LICENSE file. | |
3 | |
4 #include "content/renderer/browser_plugin/guest_to_embedder_channel.h" | |
5 | |
6 #include "base/process_util.h" | |
7 #include "content/common/browser_plugin_messages.h" | |
8 #include "content/common/child_process.h" | |
9 #include "content/renderer/browser_plugin/browser_plugin_var_serialization_rules .h" | |
10 #include "content/renderer/render_thread_impl.h" | |
11 #include "content/renderer/render_view_impl.h" | |
12 #include "ipc/ipc_message_macros.h" | |
jam
2012/05/16 02:22:40
nit: not needed
Fady Samuel
2012/05/16 04:43:54
Done.
| |
13 #include "ppapi/c/pp_bool.h" | |
14 #include "ppapi/c/pp_graphics_3d.h" | |
15 #include "ppapi/proxy/ppapi_command_buffer_proxy.h" | |
16 #include "ppapi/proxy/ppapi_messages.h" | |
17 #include "ppapi/shared_impl/api_id.h" | |
18 #include "ppapi/shared_impl/ppapi_globals.h" | |
19 #include "ppapi/shared_impl/var.h" | |
20 #include "webkit/plugins/ppapi/event_conversion.h" | |
21 | |
22 namespace content { | |
23 | |
24 GuestToEmbedderChannel::GuestToEmbedderChannel( | |
25 const std::string& embedder_channel_name) | |
26 : Dispatcher(NULL), | |
27 embedder_channel_name_(embedder_channel_name) { | |
28 SetSerializationRules(new BrowserPluginVarSerializationRules()); | |
29 } | |
30 | |
31 bool GuestToEmbedderChannel::OnMessageReceived(const IPC::Message& message) { | |
32 bool handled = true; | |
33 bool msg_is_ok = true; | |
34 IPC_BEGIN_MESSAGE_MAP_EX(GuestToEmbedderChannel, message, msg_is_ok) | |
35 IPC_MESSAGE_HANDLER(PpapiMsg_SupportsInterface, OnSupportsInterface) | |
36 IPC_MESSAGE_HANDLER(PpapiMsg_SetPreferences, OnSetPreferences) | |
37 IPC_MESSAGE_HANDLER(PpapiMsg_ReserveInstanceId, OnReserveInstanceId) | |
38 IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidCreate, | |
39 OnDidCreate) | |
40 IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidDestroy, | |
41 OnDidDestroy) | |
42 IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidChangeView, | |
43 OnDidChangeView) | |
44 IPC_MESSAGE_HANDLER(PpapiMsg_PPPInstance_DidChangeFocus, | |
45 OnDidChangeFocus) | |
46 IPC_MESSAGE_HANDLER(PpapiMsg_PPPMessaging_HandleMessage, | |
47 OnHandleMessage) | |
48 IPC_MESSAGE_HANDLER(PpapiMsg_PPPInputEvent_HandleFilteredInputEvent, | |
49 OnHandleFilteredInputEvent) | |
50 IPC_MESSAGE_HANDLER(PpapiMsg_PPPGraphics3D_ContextLost, | |
51 OnContextLost) | |
52 // Have the super handle all other messages. | |
53 IPC_MESSAGE_UNHANDLED(handled = false) | |
54 IPC_END_MESSAGE_MAP_EX() | |
55 | |
56 if (!msg_is_ok) { | |
57 // The message had a handler, but its deserialization failed. | |
58 // Kill the renderer to avoid potential spoofing attacks. | |
59 CHECK(false) << "Unable to deserialize message in ProxyChannel."; | |
jam
2012/05/16 02:22:40
you're in an untrusted process getting IPCs from a
Fady Samuel
2012/05/16 04:43:54
This is a copy-and-paste remnant. Removing.
This
| |
60 } | |
61 return handled; | |
62 } | |
63 | |
64 bool GuestToEmbedderChannel::Send(IPC::Message* message) { | |
65 // We always want guest->host messages to arrive in-order. If some sync | |
66 // and some async messages are sent in response to a synchronous | |
67 // host->guest call, the sync reply will be processed before the async | |
68 // reply, and everything will be confused. | |
69 // | |
70 // Allowing all async messages to unblock the renderer means more reentrancy | |
71 // there but gives correct ordering. | |
72 message->set_unblock(true); | |
73 return ProxyChannel::Send(message); | |
74 } | |
75 | |
76 void GuestToEmbedderChannel::OnChannelError() { | |
77 // We cannot destroy the GuestToEmbedderChannel here because a | |
78 // PpapiCommandBufferProxy may still refer to this object. | |
79 // However, we should not be using this channel again once we get a | |
80 // channel error so when remove it from the channel manager. | |
81 RenderThreadImpl::current()->browser_plugin_channel_manager()-> | |
82 RemoveChannelByName(embedder_channel_name_); | |
83 } | |
84 | |
85 bool GuestToEmbedderChannel::IsPlugin() const { | |
86 return true; | |
87 } | |
88 | |
89 WebGraphicsContext3DCommandBufferImpl* | |
90 GuestToEmbedderChannel::CreateWebGraphicsContext3D( | |
91 RenderViewImpl* render_view, | |
92 const WebKit::WebGraphicsContext3D::Attributes& attributes, | |
93 bool offscreen) { | |
94 scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context( | |
95 new WebGraphicsContext3DCommandBufferImpl( | |
96 0, GURL(), NULL, | |
97 render_view->AsWeakPtr())); | |
98 | |
99 // Special case: RenderView initialization has not yet completed. | |
100 if (!render_view->pp_instance()) | |
101 return context.release(); | |
102 | |
103 if (CreateGraphicsContext(context.get(), | |
104 attributes, | |
105 offscreen, | |
106 render_view)) | |
107 return context.release(); | |
108 | |
109 return NULL; | |
110 } | |
111 | |
112 void GuestToEmbedderChannel::IssueSwapBuffers( | |
113 const ppapi::HostResource& resource) { | |
114 Send(new PpapiHostMsg_PPBGraphics3D_SwapBuffers( | |
115 ppapi::API_ID_PPB_GRAPHICS_3D, resource)); | |
116 } | |
117 | |
118 bool GuestToEmbedderChannel::InitChannel( | |
119 const IPC::ChannelHandle& channel_handle) { | |
120 return ProxyChannel::InitWithChannel(&delegate_, channel_handle, false); | |
121 } | |
122 | |
123 void GuestToEmbedderChannel::OnSupportsInterface( | |
124 const std::string& interface_name, | |
125 bool* result) { | |
126 // TODO: This is a hack to avoid getting GetInstanceObject messages | |
127 // and failing a CHECK. A more correct solution is to implement | |
128 // VarSerializationRules for GuestToEmbedderChannel. | |
129 *result = interface_name.find("PPP_Instance_Private") == std::string::npos; | |
130 } | |
131 | |
132 void GuestToEmbedderChannel::OnSetPreferences(const ppapi::Preferences& prefs) { | |
133 // TODO(fsamuel): Do we care about these preferences? | |
134 // These look like some font stuff from WebPreferences. | |
135 // Perhaps this should be plumbed into our associated RenderView? | |
136 NOTIMPLEMENTED(); | |
137 } | |
138 | |
139 void GuestToEmbedderChannel::OnReserveInstanceId(PP_Instance instance, | |
140 bool* usable) { | |
141 *usable = | |
142 render_view_instances_.find(instance) == render_view_instances_.end(); | |
143 } | |
144 | |
145 void GuestToEmbedderChannel::RequestInputEvents(PP_Instance instance) { | |
146 // Request receipt of input events | |
147 Send(new PpapiHostMsg_PPBInstance_RequestInputEvents( | |
148 ppapi::API_ID_PPB_INSTANCE, instance, true, | |
149 PP_INPUTEVENT_CLASS_MOUSE | | |
150 PP_INPUTEVENT_CLASS_KEYBOARD | | |
151 PP_INPUTEVENT_CLASS_WHEEL | | |
152 PP_INPUTEVENT_CLASS_TOUCH)); | |
153 } | |
154 | |
155 bool GuestToEmbedderChannel::CreateGraphicsContext( | |
156 WebGraphicsContext3DCommandBufferImpl* context, | |
157 const WebKit::WebGraphicsContext3D::Attributes& attributes, | |
158 bool offscreen, | |
159 RenderViewImpl* render_view) { | |
160 std::vector<int32_t> attribs; | |
161 attribs.push_back(PP_GRAPHICS3DATTRIB_NONE); | |
162 | |
163 ppapi::HostResource resource; | |
164 DCHECK(render_view->pp_instance()); | |
165 // TODO(fsamuel): Support child contexts. | |
166 bool success = Send(new PpapiHostMsg_PPBGraphics3D_Create( | |
167 ppapi::API_ID_PPB_GRAPHICS_3D, | |
168 render_view->pp_instance(), | |
169 attribs, | |
170 &resource)); | |
171 if (!success || resource.is_null()) | |
172 return false; | |
173 if (!offscreen) { | |
174 PP_Bool result = PP_FALSE; | |
175 Send(new PpapiHostMsg_PPBInstance_BindGraphics( | |
176 ppapi::API_ID_PPB_INSTANCE, | |
177 render_view->pp_instance(), | |
178 resource, | |
179 &result)); | |
180 if (result != PP_TRUE) | |
181 return false; | |
182 } | |
183 | |
184 CommandBufferProxy* command_buffer = | |
185 new ppapi::proxy::PpapiCommandBufferProxy(resource, this); | |
186 command_buffer->Initialize(); | |
187 context->InitializeWithCommandBuffer( | |
188 command_buffer, | |
189 attributes, | |
190 false /* bind generates resources */); | |
191 render_view->set_host_resource(resource); | |
192 return true; | |
193 } | |
194 | |
195 void GuestToEmbedderChannel::AddGuest( | |
196 PP_Instance instance, | |
197 RenderViewImpl* render_view) { | |
198 DCHECK(instance); | |
199 DCHECK(render_view_instances_.find(instance) == render_view_instances_.end()); | |
200 render_view_instances_[instance] = render_view->AsWeakPtr(); | |
201 } | |
202 | |
203 | |
204 void GuestToEmbedderChannel::RemoveGuest(PP_Instance instance) { | |
205 DCHECK(render_view_instances_.find(instance) != render_view_instances_.end()); | |
206 render_view_instances_.erase(instance); | |
207 } | |
208 | |
209 void GuestToEmbedderChannel::OnDidCreate(PP_Instance instance, | |
210 const std::vector<std::string>& argn, | |
211 const std::vector<std::string>& argv, | |
212 PP_Bool* result) { | |
213 *result = PP_TRUE; | |
214 } | |
215 | |
216 void GuestToEmbedderChannel::OnDidDestroy(PP_Instance instance) { | |
217 RemoveGuest(instance); | |
218 } | |
219 | |
220 void GuestToEmbedderChannel::OnDidChangeView( | |
221 PP_Instance instance, | |
222 const ppapi::ViewData& new_data, | |
223 PP_Bool flash_fullscreen) { | |
224 // We can't do anything with this message if we don't have a render view | |
225 // yet. If we do have a RenderView then we need to tell the associated | |
226 // WebContentsObserver to resize. | |
227 if (render_view_instances_.find(instance) != render_view_instances_.end()) { | |
228 RenderViewImpl* render_view = render_view_instances_[instance]; | |
229 render_view->Send( | |
230 new BrowserPluginHostMsg_ResizeGuest( | |
231 render_view->GetRoutingID(), | |
232 new_data.rect.size.width, | |
233 new_data.rect.size.height)); | |
234 } | |
235 } | |
236 | |
237 void GuestToEmbedderChannel::OnDidChangeFocus(PP_Instance instance, | |
238 PP_Bool has_focus) { | |
239 NOTIMPLEMENTED(); | |
240 } | |
241 | |
242 void GuestToEmbedderChannel::OnHandleMessage( | |
243 PP_Instance instance, | |
244 ppapi::proxy::SerializedVarReceiveInput message_data) { | |
245 InstanceMap::iterator it = render_view_instances_.find(instance); | |
246 if (it == render_view_instances_.end()) | |
247 return; | |
248 | |
249 PP_Var received_var(message_data.Get(this)); | |
250 DCHECK(received_var.type == PP_VARTYPE_STRING); | |
251 ppapi::VarTracker* tracker = ppapi::PpapiGlobals::Get()->GetVarTracker(); | |
252 ppapi::StringVar* var = tracker->GetVar(received_var)->AsStringVar(); | |
253 DCHECK(var); | |
254 | |
255 RenderViewImpl* render_view = it->second; | |
256 render_view->Send( | |
257 new BrowserPluginHostMsg_NavigateFromGuest( | |
258 render_view->GetRoutingID(), | |
259 instance, | |
260 var->value())); | |
261 } | |
262 | |
263 void GuestToEmbedderChannel::OnHandleFilteredInputEvent( | |
264 PP_Instance instance, | |
265 const ppapi::InputEventData& data, | |
266 PP_Bool* result) { | |
267 DCHECK(render_view_instances_.find(instance) != render_view_instances_.end()); | |
268 | |
269 RenderViewImpl* render_view = render_view_instances_[instance]; | |
270 scoped_ptr<WebKit::WebInputEvent> web_input_event( | |
271 webkit::ppapi::CreateWebInputEvent(data)); | |
272 *result = PP_FromBool( | |
273 render_view->GetWebView()->handleInputEvent(*web_input_event)); | |
274 } | |
275 | |
276 void GuestToEmbedderChannel::OnContextLost(PP_Instance instance) { | |
277 InstanceMap::iterator it = render_view_instances_.begin(); | |
278 for (InstanceMap::iterator it = render_view_instances_.begin(); | |
279 it != render_view_instances_.end(); ++it) { | |
280 it->second->GetWebView()->loseCompositorContext(1); | |
281 } | |
282 } | |
283 | |
284 } // namespace content | |
OLD | NEW |