[M108 Aura Migration][NaCl][PPFwk] Add error logs + SVACE/DLOG/Static analysis fix
[platform/framework/web/chromium-efl.git] / ppapi / proxy / ppb_instance_proxy.cc
1 // Copyright 2012 The Chromium Authors
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/ppb_instance_proxy.h"
6
7 #include <utility>
8
9 #include "base/bind.h"
10 #include "base/logging.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/numerics/safe_conversions.h"
13 #include "build/build_config.h"
14 #include "media/base/limits.h"
15 #include "ppapi/c/pp_errors.h"
16 #include "ppapi/c/pp_time.h"
17 #include "ppapi/c/pp_var.h"
18 #include "ppapi/c/ppb_audio_config.h"
19 #include "ppapi/c/ppb_instance.h"
20 #include "ppapi/c/ppb_messaging.h"
21 #include "ppapi/c/ppb_mouse_lock.h"
22 #include "ppapi/proxy/browser_font_singleton_resource.h"
23 #include "ppapi/proxy/enter_proxy.h"
24 #include "ppapi/proxy/gamepad_resource.h"
25 #include "ppapi/proxy/host_dispatcher.h"
26 #include "ppapi/proxy/isolated_file_system_private_resource.h"
27 #include "ppapi/proxy/message_handler.h"
28 #include "ppapi/proxy/network_proxy_resource.h"
29 #include "ppapi/proxy/plugin_dispatcher.h"
30 #include "ppapi/proxy/ppapi_messages.h"
31 #include "ppapi/proxy/serialized_var.h"
32 #include "ppapi/proxy/uma_private_resource.h"
33 #include "ppapi/shared_impl/array_var.h"
34 #include "ppapi/shared_impl/ppapi_globals.h"
35 #include "ppapi/shared_impl/ppb_url_util_shared.h"
36 #include "ppapi/shared_impl/ppb_view_shared.h"
37 #include "ppapi/shared_impl/scoped_pp_var.h"
38 #include "ppapi/shared_impl/var.h"
39 #include "ppapi/thunk/enter.h"
40 #include "ppapi/thunk/ppb_graphics_2d_api.h"
41 #include "ppapi/thunk/ppb_graphics_3d_api.h"
42 #include "ppapi/thunk/thunk.h"
43
44 #if defined(TIZEN_PEPPER_EXTENSIONS)
45 #include "ppapi/proxy/extension_system_resource.h"
46 #include "ppapi/proxy/remote_controller_resource.h"
47 #endif  // defined(TIZEN_PEPPER_EXTENSIONS)
48
49 // Windows headers interfere with this file.
50 #ifdef PostMessage
51 #undef PostMessage
52 #endif
53
54 using ppapi::thunk::EnterInstanceNoLock;
55 using ppapi::thunk::EnterResourceNoLock;
56 using ppapi::thunk::PPB_Graphics2D_API;
57 using ppapi::thunk::PPB_Graphics3D_API;
58 using ppapi::thunk::PPB_Instance_API;
59
60 namespace ppapi {
61 namespace proxy {
62
63 namespace {
64
65 #if !BUILDFLAG(IS_NACL)
66 const char kSerializationError[] = "Failed to convert a PostMessage "
67     "argument from a PP_Var to a Javascript value. It may have cycles or be of "
68     "an unsupported type.";
69 #endif
70
71 void RequestSurroundingText(PP_Instance instance) {
72   PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
73   if (!dispatcher)
74     return;  // Instance has gone away while message was pending.
75
76   InstanceData* data = dispatcher->GetInstanceData(instance);
77   DCHECK(data);  // Should have it, since we still have a dispatcher.
78   data->is_request_surrounding_text_pending = false;
79   if (!data->should_do_request_surrounding_text)
80     return;
81
82   // Just fake out a RequestSurroundingText message to the proxy for the PPP
83   // interface.
84   InterfaceProxy* proxy = dispatcher->GetInterfaceProxy(API_ID_PPP_TEXT_INPUT);
85   if (!proxy)
86     return;
87   proxy->OnMessageReceived(PpapiMsg_PPPTextInput_RequestSurroundingText(
88       API_ID_PPP_TEXT_INPUT, instance,
89       PPB_Instance_Shared::kExtraCharsForTextInput));
90 }
91
92 }  // namespace
93
94 PPB_Instance_Proxy::PPB_Instance_Proxy(Dispatcher* dispatcher)
95     : InterfaceProxy(dispatcher),
96       callback_factory_(this) {
97 }
98
99 PPB_Instance_Proxy::~PPB_Instance_Proxy() {
100 }
101
102 bool PPB_Instance_Proxy::OnMessageReceived(const IPC::Message& msg) {
103   // Prevent the dispatcher from going away during a call to ExecuteScript.
104   // This must happen OUTSIDE of ExecuteScript since the SerializedVars use
105   // the dispatcher upon return of the function (converting the
106   // SerializedVarReturnValue/OutParam to a SerializedVar in the destructor).
107 #if !BUILDFLAG(IS_NACL)
108   ScopedModuleReference death_grip(dispatcher());
109 #endif
110
111   bool handled = true;
112   IPC_BEGIN_MESSAGE_MAP(PPB_Instance_Proxy, msg)
113 #if !BUILDFLAG(IS_NACL)
114     // Plugin -> Host messages.
115     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_GetWindowObject,
116                         OnHostMsgGetWindowObject)
117     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_GetOwnerElementObject,
118                         OnHostMsgGetOwnerElementObject)
119     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_BindGraphics,
120                         OnHostMsgBindGraphics)
121     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_IsFullFrame,
122                         OnHostMsgIsFullFrame)
123     IPC_MESSAGE_HANDLER(
124         PpapiHostMsg_PPBInstance_GetAudioHardwareOutputSampleRate,
125         OnHostMsgGetAudioHardwareOutputSampleRate)
126     IPC_MESSAGE_HANDLER(
127         PpapiHostMsg_PPBInstance_GetAudioHardwareOutputBufferSize,
128         OnHostMsgGetAudioHardwareOutputBufferSize)
129     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_ExecuteScript,
130                         OnHostMsgExecuteScript)
131     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_GetDefaultCharSet,
132                         OnHostMsgGetDefaultCharSet)
133     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_PostMessage,
134                         OnHostMsgPostMessage)
135     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_SetFullscreen,
136                         OnHostMsgSetFullscreen)
137     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_GetScreenSize,
138                         OnHostMsgGetScreenSize)
139     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_RequestInputEvents,
140                         OnHostMsgRequestInputEvents)
141     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_ClearInputEvents,
142                         OnHostMsgClearInputEvents)
143     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_LockMouse,
144                         OnHostMsgLockMouse)
145     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_UnlockMouse,
146                         OnHostMsgUnlockMouse)
147     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_SetCursor,
148                         OnHostMsgSetCursor)
149     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_SetTextInputType,
150                         OnHostMsgSetTextInputType)
151     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_UpdateCaretPosition,
152                         OnHostMsgUpdateCaretPosition)
153     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_CancelCompositionText,
154                         OnHostMsgCancelCompositionText)
155     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_UpdateSurroundingText,
156                         OnHostMsgUpdateSurroundingText)
157     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_GetDocumentURL,
158                         OnHostMsgGetDocumentURL)
159     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_ResolveRelativeToDocument,
160                         OnHostMsgResolveRelativeToDocument)
161     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_DocumentCanRequest,
162                         OnHostMsgDocumentCanRequest)
163     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_DocumentCanAccessDocument,
164                         OnHostMsgDocumentCanAccessDocument)
165     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_GetPluginInstanceURL,
166                         OnHostMsgGetPluginInstanceURL)
167     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_GetPluginReferrerURL,
168                         OnHostMsgGetPluginReferrerURL)
169 #endif  // !BUILDFLAG(IS_NACL)
170
171     // Host -> Plugin messages.
172     IPC_MESSAGE_HANDLER(PpapiMsg_PPBInstance_MouseLockComplete,
173                         OnPluginMsgMouseLockComplete)
174
175     IPC_MESSAGE_UNHANDLED(handled = false)
176   IPC_END_MESSAGE_MAP()
177   return handled;
178 }
179
180 PP_Bool PPB_Instance_Proxy::BindGraphics(PP_Instance instance,
181                                          PP_Resource device) {
182   // If device is 0, pass a null HostResource. This signals the host to unbind
183   // all devices.
184   PP_Resource pp_resource = 0;
185   if (device) {
186     Resource* resource =
187         PpapiGlobals::Get()->GetResourceTracker()->GetResource(device);
188     if (!resource || resource->pp_instance() != instance)
189       return PP_FALSE;
190     // We need to pass different resource to Graphics 2D and 3D right now.  Once
191     // 3D is migrated to the new design, we should be able to unify this.
192     if (resource->AsPPB_Graphics3D_API()) {
193       pp_resource = resource->host_resource().host_resource();
194     } else if (resource->AsPPB_Graphics2D_API()) {
195       pp_resource = resource->pp_resource();
196     } else {
197       // A bad resource.
198       return PP_FALSE;
199     }
200   }
201   dispatcher()->Send(new PpapiHostMsg_PPBInstance_BindGraphics(
202         API_ID_PPB_INSTANCE, instance, pp_resource));
203   return PP_TRUE;
204 }
205
206 PP_Bool PPB_Instance_Proxy::IsFullFrame(PP_Instance instance) {
207   PP_Bool result = PP_FALSE;
208   dispatcher()->Send(new PpapiHostMsg_PPBInstance_IsFullFrame(
209       API_ID_PPB_INSTANCE, instance, &result));
210   return result;
211 }
212
213 const ViewData* PPB_Instance_Proxy::GetViewData(PP_Instance instance) {
214   InstanceData* data = static_cast<PluginDispatcher*>(dispatcher())->
215       GetInstanceData(instance);
216   if (!data)
217     return NULL;
218   return &data->view;
219 }
220
221 PP_Var PPB_Instance_Proxy::GetWindowObject(PP_Instance instance) {
222   ReceiveSerializedVarReturnValue result;
223   dispatcher()->Send(new PpapiHostMsg_PPBInstance_GetWindowObject(
224       API_ID_PPB_INSTANCE, instance, &result));
225   return result.Return(dispatcher());
226 }
227
228 PP_Var PPB_Instance_Proxy::GetOwnerElementObject(PP_Instance instance) {
229   ReceiveSerializedVarReturnValue result;
230   dispatcher()->Send(new PpapiHostMsg_PPBInstance_GetOwnerElementObject(
231       API_ID_PPB_INSTANCE, instance, &result));
232   return result.Return(dispatcher());
233 }
234
235 PP_Var PPB_Instance_Proxy::ExecuteScript(PP_Instance instance,
236                                          PP_Var script,
237                                          PP_Var* exception) {
238   ReceiveSerializedException se(dispatcher(), exception);
239   if (se.IsThrown())
240     return PP_MakeUndefined();
241
242   ReceiveSerializedVarReturnValue result;
243   dispatcher()->Send(new PpapiHostMsg_PPBInstance_ExecuteScript(
244       API_ID_PPB_INSTANCE, instance,
245       SerializedVarSendInput(dispatcher(), script), &se, &result));
246   return result.Return(dispatcher());
247 }
248
249 uint32_t PPB_Instance_Proxy::GetAudioHardwareOutputSampleRate(
250     PP_Instance instance) {
251   uint32_t result = PP_AUDIOSAMPLERATE_NONE;
252   dispatcher()->Send(
253       new PpapiHostMsg_PPBInstance_GetAudioHardwareOutputSampleRate(
254           API_ID_PPB_INSTANCE, instance, &result));
255   return result;
256 }
257
258 uint32_t PPB_Instance_Proxy::GetAudioHardwareOutputBufferSize(
259     PP_Instance instance) {
260   uint32_t result = 0;
261   dispatcher()->Send(
262       new PpapiHostMsg_PPBInstance_GetAudioHardwareOutputBufferSize(
263           API_ID_PPB_INSTANCE, instance, &result));
264   return result;
265 }
266
267 PP_Var PPB_Instance_Proxy::GetDefaultCharSet(PP_Instance instance) {
268   PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
269   if (!dispatcher)
270     return PP_MakeUndefined();
271
272   ReceiveSerializedVarReturnValue result;
273   dispatcher->Send(new PpapiHostMsg_PPBInstance_GetDefaultCharSet(
274       API_ID_PPB_INSTANCE, instance, &result));
275   return result.Return(dispatcher);
276 }
277
278 PP_Bool PPB_Instance_Proxy::IsFullscreen(PP_Instance instance) {
279   InstanceData* data = static_cast<PluginDispatcher*>(dispatcher())->
280       GetInstanceData(instance);
281   if (!data)
282     return PP_FALSE;
283   return PP_FromBool(data->view.is_fullscreen);
284 }
285
286 PP_Bool PPB_Instance_Proxy::SetFullscreen(PP_Instance instance,
287                                           PP_Bool fullscreen) {
288   PP_Bool result = PP_FALSE;
289   dispatcher()->Send(new PpapiHostMsg_PPBInstance_SetFullscreen(
290       API_ID_PPB_INSTANCE, instance, fullscreen, &result));
291   return result;
292 }
293
294 PP_Bool PPB_Instance_Proxy::GetScreenSize(PP_Instance instance,
295                                           PP_Size* size) {
296   PP_Bool result = PP_FALSE;
297   dispatcher()->Send(new PpapiHostMsg_PPBInstance_GetScreenSize(
298       API_ID_PPB_INSTANCE, instance, &result, size));
299   return result;
300 }
301
302 Resource* PPB_Instance_Proxy::GetSingletonResource(PP_Instance instance,
303                                                    SingletonResourceID id) {
304   InstanceData* data = static_cast<PluginDispatcher*>(dispatcher())->
305       GetInstanceData(instance);
306
307   InstanceData::SingletonResourceMap::iterator it =
308       data->singleton_resources.find(id);
309   if (it != data->singleton_resources.end())
310     return it->second.get();
311
312   scoped_refptr<Resource> new_singleton;
313   Connection connection(PluginGlobals::Get()->GetBrowserSender(),
314                         static_cast<PluginDispatcher*>(dispatcher())->sender());
315
316   switch (id) {
317     case GAMEPAD_SINGLETON_ID:
318       new_singleton = new GamepadResource(connection, instance);
319       break;
320     case ISOLATED_FILESYSTEM_SINGLETON_ID:
321       new_singleton =
322           new IsolatedFileSystemPrivateResource(connection, instance);
323       break;
324     case NETWORK_PROXY_SINGLETON_ID:
325       new_singleton = new NetworkProxyResource(connection, instance);
326       break;
327     case UMA_SINGLETON_ID:
328       new_singleton = new UMAPrivateResource(connection, instance);
329       break;
330 // Flash/trusted resources aren't needed for NaCl.
331 #if !BUILDFLAG(IS_NACL) && !defined(NACL_WIN64)
332     case BROWSER_FONT_SINGLETON_ID:
333       new_singleton = new BrowserFontSingletonResource(connection, instance);
334       break;
335     case EXTENSION_SYSTEM_SINGLETON_ID:
336 #if defined(TIZEN_PEPPER_EXTENSIONS)
337       new_singleton = new ExtensionSystemResource(connection, instance);
338 #else
339       NOTREACHED();
340 #endif  // defined(TIZEN_PEPPER_EXTENSIONS)
341       break;
342     case REMOTE_CONTROLLER_SINGLETON_ID:
343 #if defined(TIZEN_PEPPER_EXTENSIONS)
344       new_singleton = new RemoteControllerResource(connection, instance);
345 #else
346       NOTREACHED();
347 #endif  // defined(TIZEN_PEPPER_EXTENSIONS)
348       break;
349 #else
350     case BROWSER_FONT_SINGLETON_ID:
351     case EXTENSION_SYSTEM_SINGLETON_ID:
352     case REMOTE_CONTROLLER_SINGLETON_ID:
353       NOTREACHED();
354       break;
355 #endif  // !BUILDFLAG(IS_NACL) && !defined(NACL_WIN64)
356   }
357
358   if (!new_singleton.get()) {
359     // Getting here implies that a constructor is missing in the above switch.
360     NOTREACHED();
361     return NULL;
362   }
363
364   data->singleton_resources[id] = new_singleton;
365   return new_singleton.get();
366 }
367
368 int32_t PPB_Instance_Proxy::RequestInputEvents(PP_Instance instance,
369                                                uint32_t event_classes) {
370   dispatcher()->Send(new PpapiHostMsg_PPBInstance_RequestInputEvents(
371       API_ID_PPB_INSTANCE, instance, false, event_classes));
372
373   // We always register for the classes we can handle, this function validates
374   // the flags so we can notify it if anything was invalid, without requiring
375   // a sync reply.
376   return ValidateRequestInputEvents(false, event_classes);
377 }
378
379 int32_t PPB_Instance_Proxy::RequestFilteringInputEvents(
380     PP_Instance instance,
381     uint32_t event_classes) {
382   dispatcher()->Send(new PpapiHostMsg_PPBInstance_RequestInputEvents(
383       API_ID_PPB_INSTANCE, instance, true, event_classes));
384
385   // We always register for the classes we can handle, this function validates
386   // the flags so we can notify it if anything was invalid, without requiring
387   // a sync reply.
388   return ValidateRequestInputEvents(true, event_classes);
389 }
390
391 void PPB_Instance_Proxy::ClearInputEventRequest(PP_Instance instance,
392                                                 uint32_t event_classes) {
393   dispatcher()->Send(new PpapiHostMsg_PPBInstance_ClearInputEvents(
394       API_ID_PPB_INSTANCE, instance, event_classes));
395 }
396
397 PP_Var PPB_Instance_Proxy::GetDocumentURL(PP_Instance instance,
398                                           PP_URLComponents_Dev* components) {
399   ReceiveSerializedVarReturnValue result;
400   PP_URLComponents_Dev url_components = {{0}};
401   dispatcher()->Send(new PpapiHostMsg_PPBInstance_GetDocumentURL(
402       API_ID_PPB_INSTANCE, instance, &url_components, &result));
403   if (components)
404     *components = url_components;
405   return result.Return(dispatcher());
406 }
407
408 #if !BUILDFLAG(IS_NACL)
409 PP_Var PPB_Instance_Proxy::ResolveRelativeToDocument(
410     PP_Instance instance,
411     PP_Var relative,
412     PP_URLComponents_Dev* components) {
413   ReceiveSerializedVarReturnValue result;
414   dispatcher()->Send(new PpapiHostMsg_PPBInstance_ResolveRelativeToDocument(
415       API_ID_PPB_INSTANCE, instance,
416       SerializedVarSendInput(dispatcher(), relative),
417       &result));
418   return PPB_URLUtil_Shared::ConvertComponentsAndReturnURL(
419       result.Return(dispatcher()),
420       components);
421 }
422
423 PP_Bool PPB_Instance_Proxy::DocumentCanRequest(PP_Instance instance,
424                                                PP_Var url) {
425   PP_Bool result = PP_FALSE;
426   dispatcher()->Send(new PpapiHostMsg_PPBInstance_DocumentCanRequest(
427       API_ID_PPB_INSTANCE, instance,
428       SerializedVarSendInput(dispatcher(), url),
429       &result));
430   return result;
431 }
432
433 PP_Bool PPB_Instance_Proxy::DocumentCanAccessDocument(PP_Instance instance,
434                                                       PP_Instance target) {
435   PP_Bool result = PP_FALSE;
436   dispatcher()->Send(new PpapiHostMsg_PPBInstance_DocumentCanAccessDocument(
437       API_ID_PPB_INSTANCE, instance, target, &result));
438   return result;
439 }
440
441 PP_Var PPB_Instance_Proxy::GetPluginInstanceURL(
442       PP_Instance instance,
443       PP_URLComponents_Dev* components) {
444   ReceiveSerializedVarReturnValue result;
445   dispatcher()->Send(new PpapiHostMsg_PPBInstance_GetPluginInstanceURL(
446       API_ID_PPB_INSTANCE, instance, &result));
447   return PPB_URLUtil_Shared::ConvertComponentsAndReturnURL(
448       result.Return(dispatcher()),
449       components);
450 }
451
452 PP_Var PPB_Instance_Proxy::GetPluginReferrerURL(
453       PP_Instance instance,
454       PP_URLComponents_Dev* components) {
455   ReceiveSerializedVarReturnValue result;
456   dispatcher()->Send(new PpapiHostMsg_PPBInstance_GetPluginReferrerURL(
457       API_ID_PPB_INSTANCE, instance, &result));
458   return PPB_URLUtil_Shared::ConvertComponentsAndReturnURL(
459       result.Return(dispatcher()),
460       components);
461 }
462 #endif  // !BUILDFLAG(IS_NACL)
463
464 void PPB_Instance_Proxy::PostMessage(PP_Instance instance,
465                                      PP_Var message) {
466   dispatcher()->Send(new PpapiHostMsg_PPBInstance_PostMessage(
467       API_ID_PPB_INSTANCE,
468       instance, SerializedVarSendInputShmem(dispatcher(), message,
469                                             instance)));
470 }
471
472 int32_t PPB_Instance_Proxy::RegisterMessageHandler(
473     PP_Instance instance,
474     void* user_data,
475     const PPP_MessageHandler_0_2* handler,
476     PP_Resource message_loop) {
477   InstanceData* data =
478       static_cast<PluginDispatcher*>(dispatcher())->GetInstanceData(instance);
479   if (!data) {
480     LOG(ERROR) << "Data is NULL";
481     return PP_ERROR_BADARGUMENT;
482   }
483
484   int32_t result = PP_ERROR_FAILED;
485   std::unique_ptr<MessageHandler> message_handler = MessageHandler::Create(
486       instance, handler, user_data, message_loop, &result);
487   if (message_handler)
488     data->message_handler = std::move(message_handler);
489   return result;
490 }
491
492 void PPB_Instance_Proxy::UnregisterMessageHandler(PP_Instance instance) {
493   InstanceData* data =
494       static_cast<PluginDispatcher*>(dispatcher())->GetInstanceData(instance);
495   if (!data)
496     return;
497   data->message_handler.reset();
498 }
499
500 PP_Bool PPB_Instance_Proxy::SetCursor(PP_Instance instance,
501                                       PP_MouseCursor_Type type,
502                                       PP_Resource image,
503                                       const PP_Point* hot_spot) {
504   // Some of these parameters are important for security. This check is in the
505   // plugin process just for the convenience of the caller (since we don't
506   // bother returning errors from the other process with a sync message). The
507   // parameters will be validated again in the renderer.
508   if (!ValidateSetCursorParams(type, image, hot_spot))
509     return PP_FALSE;
510
511   HostResource image_host_resource;
512   if (image) {
513     Resource* cursor_image =
514         PpapiGlobals::Get()->GetResourceTracker()->GetResource(image);
515     if (!cursor_image || cursor_image->pp_instance() != instance)
516       return PP_FALSE;
517     image_host_resource = cursor_image->host_resource();
518   }
519
520   dispatcher()->Send(new PpapiHostMsg_PPBInstance_SetCursor(
521       API_ID_PPB_INSTANCE, instance, static_cast<int32_t>(type),
522       image_host_resource, hot_spot ? *hot_spot : PP_MakePoint(0, 0)));
523   return PP_TRUE;
524 }
525
526 int32_t PPB_Instance_Proxy::LockMouse(PP_Instance instance,
527                                       scoped_refptr<TrackedCallback> callback) {
528   // Save the mouse callback on the instance data.
529   InstanceData* data = static_cast<PluginDispatcher*>(dispatcher())->
530       GetInstanceData(instance);
531   if (!data) {
532     LOG(ERROR) << "Data is NULL";
533     return PP_ERROR_BADARGUMENT;
534   }
535   if (TrackedCallback::IsPending(data->mouse_lock_callback)) {
536     LOG(ERROR) << "Lock mouse is pending";
537     return PP_ERROR_INPROGRESS;  // Already have a pending callback.
538   }
539   data->mouse_lock_callback = callback;
540
541   dispatcher()->Send(new PpapiHostMsg_PPBInstance_LockMouse(
542       API_ID_PPB_INSTANCE, instance));
543   return PP_OK_COMPLETIONPENDING;
544 }
545
546 void PPB_Instance_Proxy::UnlockMouse(PP_Instance instance) {
547   dispatcher()->Send(new PpapiHostMsg_PPBInstance_UnlockMouse(
548       API_ID_PPB_INSTANCE, instance));
549 }
550
551 void PPB_Instance_Proxy::SetTextInputType(PP_Instance instance,
552                                           PP_TextInput_Type type) {
553   CancelAnyPendingRequestSurroundingText(instance);
554   dispatcher()->Send(new PpapiHostMsg_PPBInstance_SetTextInputType(
555       API_ID_PPB_INSTANCE, instance, type));
556 }
557
558 void PPB_Instance_Proxy::UpdateCaretPosition(PP_Instance instance,
559                                              const PP_Rect& caret,
560                                              const PP_Rect& bounding_box) {
561   dispatcher()->Send(new PpapiHostMsg_PPBInstance_UpdateCaretPosition(
562       API_ID_PPB_INSTANCE, instance, caret, bounding_box));
563 }
564
565 void PPB_Instance_Proxy::CancelCompositionText(PP_Instance instance) {
566   CancelAnyPendingRequestSurroundingText(instance);
567   dispatcher()->Send(new PpapiHostMsg_PPBInstance_CancelCompositionText(
568       API_ID_PPB_INSTANCE, instance));
569 }
570
571 void PPB_Instance_Proxy::SelectionChanged(PP_Instance instance) {
572   // The "right" way to do this is to send the message to the host. However,
573   // all it will do is call RequestSurroundingText with a hardcoded number of
574   // characters in response, which is an entire IPC round-trip.
575   //
576   // We can avoid this round-trip by just implementing the
577   // RequestSurroundingText logic in the plugin process. If the logic in the
578   // host becomes more complex (like a more adaptive number of characters),
579   // we'll need to reevanuate whether we want to do the round trip instead.
580   //
581   // Be careful to post a task to avoid reentering the plugin.
582
583   InstanceData* data =
584       static_cast<PluginDispatcher*>(dispatcher())->GetInstanceData(instance);
585   if (!data)
586     return;
587   data->should_do_request_surrounding_text = true;
588
589   if (!data->is_request_surrounding_text_pending) {
590     PpapiGlobals::Get()->GetMainThreadMessageLoop()->PostTask(
591         FROM_HERE,
592         RunWhileLocked(base::BindOnce(&RequestSurroundingText, instance)));
593     data->is_request_surrounding_text_pending = true;
594   }
595 }
596
597 void PPB_Instance_Proxy::UpdateSurroundingText(PP_Instance instance,
598                                                const char* text,
599                                                uint32_t caret,
600                                                uint32_t anchor) {
601   dispatcher()->Send(new PpapiHostMsg_PPBInstance_UpdateSurroundingText(
602       API_ID_PPB_INSTANCE, instance, text, caret, anchor));
603 }
604
605 #if !BUILDFLAG(IS_NACL)
606 void PPB_Instance_Proxy::OnHostMsgGetWindowObject(
607     PP_Instance instance,
608     SerializedVarReturnValue result) {
609   if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
610     return;
611   EnterInstanceNoLock enter(instance);
612   if (enter.succeeded())
613     result.Return(dispatcher(), enter.functions()->GetWindowObject(instance));
614 }
615
616 void PPB_Instance_Proxy::OnHostMsgGetOwnerElementObject(
617     PP_Instance instance,
618     SerializedVarReturnValue result) {
619   if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
620     return;
621   EnterInstanceNoLock enter(instance);
622   if (enter.succeeded()) {
623     result.Return(dispatcher(),
624                   enter.functions()->GetOwnerElementObject(instance));
625   }
626 }
627
628 void PPB_Instance_Proxy::OnHostMsgBindGraphics(PP_Instance instance,
629                                                PP_Resource device) {
630   // Note that we ignroe the return value here. Otherwise, this would need to
631   // be a slow sync call, and the plugin side of the proxy will have already
632   // validated the resources, so we shouldn't see errors here that weren't
633   // already caught.
634   EnterInstanceNoLock enter(instance);
635   if (enter.succeeded())
636     enter.functions()->BindGraphics(instance, device);
637 }
638
639 void PPB_Instance_Proxy::OnHostMsgGetAudioHardwareOutputSampleRate(
640     PP_Instance instance, uint32_t* result) {
641   EnterInstanceNoLock enter(instance);
642   if (enter.succeeded())
643     *result = enter.functions()->GetAudioHardwareOutputSampleRate(instance);
644 }
645
646 void PPB_Instance_Proxy::OnHostMsgGetAudioHardwareOutputBufferSize(
647     PP_Instance instance, uint32_t* result) {
648   EnterInstanceNoLock enter(instance);
649   if (enter.succeeded())
650     *result = enter.functions()->GetAudioHardwareOutputBufferSize(instance);
651 }
652
653 void PPB_Instance_Proxy::OnHostMsgIsFullFrame(PP_Instance instance,
654                                               PP_Bool* result) {
655   EnterInstanceNoLock enter(instance);
656   if (enter.succeeded())
657     *result = enter.functions()->IsFullFrame(instance);
658 }
659
660 void PPB_Instance_Proxy::OnHostMsgExecuteScript(
661     PP_Instance instance,
662     SerializedVarReceiveInput script,
663     SerializedVarOutParam out_exception,
664     SerializedVarReturnValue result) {
665   if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
666     return;
667   EnterInstanceNoLock enter(instance);
668   if (enter.failed())
669     return;
670
671   if (dispatcher()->IsPlugin())
672     NOTREACHED();
673   else
674     static_cast<HostDispatcher*>(dispatcher())->set_allow_plugin_reentrancy();
675
676   result.Return(dispatcher(), enter.functions()->ExecuteScript(
677       instance,
678       script.Get(dispatcher()),
679       out_exception.OutParam(dispatcher())));
680 }
681
682 void PPB_Instance_Proxy::OnHostMsgGetDefaultCharSet(
683     PP_Instance instance,
684     SerializedVarReturnValue result) {
685   if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
686     return;
687   EnterInstanceNoLock enter(instance);
688   if (enter.succeeded())
689     result.Return(dispatcher(), enter.functions()->GetDefaultCharSet(instance));
690 }
691
692 void PPB_Instance_Proxy::OnHostMsgSetFullscreen(PP_Instance instance,
693                                                 PP_Bool fullscreen,
694                                                 PP_Bool* result) {
695   EnterInstanceNoLock enter(instance);
696   if (enter.succeeded())
697     *result = enter.functions()->SetFullscreen(instance, fullscreen);
698 }
699
700
701 void PPB_Instance_Proxy::OnHostMsgGetScreenSize(PP_Instance instance,
702                                                 PP_Bool* result,
703                                                 PP_Size* size) {
704   EnterInstanceNoLock enter(instance);
705   if (enter.succeeded())
706     *result = enter.functions()->GetScreenSize(instance, size);
707 }
708
709 void PPB_Instance_Proxy::OnHostMsgRequestInputEvents(PP_Instance instance,
710                                                      bool is_filtering,
711                                                      uint32_t event_classes) {
712   EnterInstanceNoLock enter(instance);
713   if (enter.succeeded()) {
714     if (is_filtering)
715       enter.functions()->RequestFilteringInputEvents(instance, event_classes);
716     else
717       enter.functions()->RequestInputEvents(instance, event_classes);
718   }
719 }
720
721 void PPB_Instance_Proxy::OnHostMsgClearInputEvents(PP_Instance instance,
722                                                    uint32_t event_classes) {
723   EnterInstanceNoLock enter(instance);
724   if (enter.succeeded())
725     enter.functions()->ClearInputEventRequest(instance, event_classes);
726 }
727
728 void PPB_Instance_Proxy::OnHostMsgPostMessage(
729     PP_Instance instance,
730     SerializedVarReceiveInput message) {
731   EnterInstanceNoLock enter(instance);
732   if (!message.is_valid_var()) {
733     PpapiGlobals::Get()->LogWithSource(
734         instance, PP_LOGLEVEL_ERROR, std::string(), kSerializationError);
735     return;
736   }
737
738   if (enter.succeeded())
739     enter.functions()->PostMessage(instance,
740                                    message.GetForInstance(dispatcher(),
741                                                           instance));
742 }
743
744 void PPB_Instance_Proxy::OnHostMsgLockMouse(PP_Instance instance) {
745   // Need to be careful to always issue the callback.
746   pp::CompletionCallback cb = callback_factory_.NewCallback(
747       &PPB_Instance_Proxy::MouseLockCompleteInHost, instance);
748
749   EnterInstanceNoLock enter(instance, cb.pp_completion_callback());
750   if (enter.succeeded())
751     enter.SetResult(enter.functions()->LockMouse(instance, enter.callback()));
752 }
753
754 void PPB_Instance_Proxy::OnHostMsgUnlockMouse(PP_Instance instance) {
755   EnterInstanceNoLock enter(instance);
756   if (enter.succeeded())
757     enter.functions()->UnlockMouse(instance);
758 }
759
760 void PPB_Instance_Proxy::OnHostMsgGetDocumentURL(
761     PP_Instance instance,
762     PP_URLComponents_Dev* components,
763     SerializedVarReturnValue result) {
764   if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
765     return;
766   EnterInstanceNoLock enter(instance);
767   if (enter.succeeded()) {
768     PP_Var document_url = enter.functions()->GetDocumentURL(instance,
769                                                             components);
770     result.Return(dispatcher(), document_url);
771   }
772 }
773
774 void PPB_Instance_Proxy::OnHostMsgResolveRelativeToDocument(
775     PP_Instance instance,
776     SerializedVarReceiveInput relative,
777     SerializedVarReturnValue result) {
778   if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
779     return;
780   EnterInstanceNoLock enter(instance);
781   if (enter.succeeded()) {
782     result.Return(dispatcher(),
783                   enter.functions()->ResolveRelativeToDocument(
784                       instance, relative.Get(dispatcher()), NULL));
785   }
786 }
787
788 void PPB_Instance_Proxy::OnHostMsgDocumentCanRequest(
789     PP_Instance instance,
790     SerializedVarReceiveInput url,
791     PP_Bool* result) {
792   if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
793     return;
794   EnterInstanceNoLock enter(instance);
795   if (enter.succeeded()) {
796     *result = enter.functions()->DocumentCanRequest(instance,
797                                                     url.Get(dispatcher()));
798   }
799 }
800
801 void PPB_Instance_Proxy::OnHostMsgDocumentCanAccessDocument(PP_Instance active,
802                                                             PP_Instance target,
803                                                             PP_Bool* result) {
804   if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
805     return;
806   EnterInstanceNoLock enter(active);
807   if (enter.succeeded())
808     *result = enter.functions()->DocumentCanAccessDocument(active, target);
809 }
810
811 void PPB_Instance_Proxy::OnHostMsgGetPluginInstanceURL(
812     PP_Instance instance,
813     SerializedVarReturnValue result) {
814   if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
815     return;
816   EnterInstanceNoLock enter(instance);
817   if (enter.succeeded()) {
818     result.Return(dispatcher(),
819                   enter.functions()->GetPluginInstanceURL(instance, NULL));
820   }
821 }
822
823 void PPB_Instance_Proxy::OnHostMsgGetPluginReferrerURL(
824     PP_Instance instance,
825     SerializedVarReturnValue result) {
826   if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
827     return;
828   EnterInstanceNoLock enter(instance);
829   if (enter.succeeded()) {
830     result.Return(dispatcher(),
831                   enter.functions()->GetPluginReferrerURL(instance, NULL));
832   }
833 }
834
835 void PPB_Instance_Proxy::OnHostMsgSetCursor(
836     PP_Instance instance,
837     int32_t type,
838     const ppapi::HostResource& custom_image,
839     const PP_Point& hot_spot) {
840   // This API serves PPB_CursorControl_Dev and PPB_MouseCursor, so is public.
841   EnterInstanceNoLock enter(instance);
842   if (enter.succeeded()) {
843     enter.functions()->SetCursor(
844         instance, static_cast<PP_MouseCursor_Type>(type),
845         custom_image.host_resource(), &hot_spot);
846   }
847 }
848
849 void PPB_Instance_Proxy::OnHostMsgSetTextInputType(PP_Instance instance,
850                                                    PP_TextInput_Type type) {
851   EnterInstanceNoLock enter(instance);
852   if (enter.succeeded())
853     enter.functions()->SetTextInputType(instance, type);
854 }
855
856 void PPB_Instance_Proxy::OnHostMsgUpdateCaretPosition(
857     PP_Instance instance,
858     const PP_Rect& caret,
859     const PP_Rect& bounding_box) {
860   EnterInstanceNoLock enter(instance);
861   if (enter.succeeded())
862     enter.functions()->UpdateCaretPosition(instance, caret, bounding_box);
863 }
864
865 void PPB_Instance_Proxy::OnHostMsgCancelCompositionText(PP_Instance instance) {
866   EnterInstanceNoLock enter(instance);
867   if (enter.succeeded())
868     enter.functions()->CancelCompositionText(instance);
869 }
870
871 void PPB_Instance_Proxy::OnHostMsgUpdateSurroundingText(
872     PP_Instance instance,
873     const std::string& text,
874     uint32_t caret,
875     uint32_t anchor) {
876   EnterInstanceNoLock enter(instance);
877   if (enter.succeeded()) {
878     enter.functions()->UpdateSurroundingText(instance, text.c_str(), caret,
879                                              anchor);
880   }
881 }
882 #endif  // !BUILDFLAG(IS_NACL)
883
884 void PPB_Instance_Proxy::OnPluginMsgMouseLockComplete(PP_Instance instance,
885                                                       int32_t result) {
886   if (!dispatcher()->IsPlugin())
887     return;
888
889   // Save the mouse callback on the instance data.
890   InstanceData* data = static_cast<PluginDispatcher*>(dispatcher())->
891       GetInstanceData(instance);
892   if (!data)
893     return;  // Instance was probably deleted.
894   if (!TrackedCallback::IsPending(data->mouse_lock_callback)) {
895     NOTREACHED();
896     return;
897   }
898   data->mouse_lock_callback->Run(result);
899 }
900
901 #if !BUILDFLAG(IS_NACL)
902 void PPB_Instance_Proxy::MouseLockCompleteInHost(int32_t result,
903                                                  PP_Instance instance) {
904   dispatcher()->Send(new PpapiMsg_PPBInstance_MouseLockComplete(
905       API_ID_PPB_INSTANCE, instance, result));
906 }
907 #endif  // !BUILDFLAG(IS_NACL)
908
909 void PPB_Instance_Proxy::CancelAnyPendingRequestSurroundingText(
910     PP_Instance instance) {
911   InstanceData* data = static_cast<PluginDispatcher*>(dispatcher())->
912       GetInstanceData(instance);
913   if (!data)
914     return;  // Instance was probably deleted.
915   data->should_do_request_surrounding_text = false;
916 }
917
918 }  // namespace proxy
919 }  // namespace ppapi