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/ppb_instance_proxy.h"
6
7#include "base/memory/ref_counted.h"
8#include "build/build_config.h"
9#include "ppapi/c/pp_errors.h"
10#include "ppapi/c/pp_time.h"
11#include "ppapi/c/pp_var.h"
12#include "ppapi/c/ppb_audio_config.h"
13#include "ppapi/c/ppb_instance.h"
14#include "ppapi/c/ppb_messaging.h"
15#include "ppapi/c/ppb_mouse_lock.h"
16#include "ppapi/c/private/pp_content_decryptor.h"
17#include "ppapi/proxy/broker_resource.h"
18#include "ppapi/proxy/browser_font_singleton_resource.h"
19#include "ppapi/proxy/content_decryptor_private_serializer.h"
20#include "ppapi/proxy/enter_proxy.h"
21#include "ppapi/proxy/extensions_common_resource.h"
22#include "ppapi/proxy/flash_clipboard_resource.h"
23#include "ppapi/proxy/flash_file_resource.h"
24#include "ppapi/proxy/flash_fullscreen_resource.h"
25#include "ppapi/proxy/flash_resource.h"
26#include "ppapi/proxy/gamepad_resource.h"
27#include "ppapi/proxy/host_dispatcher.h"
28#include "ppapi/proxy/isolated_file_system_private_resource.h"
29#include "ppapi/proxy/network_proxy_resource.h"
30#include "ppapi/proxy/pdf_resource.h"
31#include "ppapi/proxy/plugin_dispatcher.h"
32#include "ppapi/proxy/ppapi_messages.h"
33#include "ppapi/proxy/serialized_var.h"
34#include "ppapi/proxy/truetype_font_singleton_resource.h"
35#include "ppapi/shared_impl/ppapi_globals.h"
36#include "ppapi/shared_impl/ppb_url_util_shared.h"
37#include "ppapi/shared_impl/ppb_view_shared.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// Windows headers interfere with this file.
45#ifdef PostMessage
46#undef PostMessage
47#endif
48
49using ppapi::thunk::EnterInstanceNoLock;
50using ppapi::thunk::EnterResourceNoLock;
51using ppapi::thunk::PPB_Graphics2D_API;
52using ppapi::thunk::PPB_Graphics3D_API;
53using ppapi::thunk::PPB_Instance_API;
54
55namespace ppapi {
56namespace proxy {
57
58namespace {
59
60const char kSerializationError[] = "Failed to convert a PostMessage "
61    "argument from a PP_Var to a Javascript value. It may have cycles or be of "
62    "an unsupported type.";
63
64InterfaceProxy* CreateInstanceProxy(Dispatcher* dispatcher) {
65  return new PPB_Instance_Proxy(dispatcher);
66}
67
68void RequestSurroundingText(PP_Instance instance) {
69  PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
70  if (!dispatcher)
71    return;  // Instance has gone away while message was pending.
72
73  InstanceData* data = dispatcher->GetInstanceData(instance);
74  DCHECK(data);  // Should have it, since we still have a dispatcher.
75  data->is_request_surrounding_text_pending = false;
76  if (!data->should_do_request_surrounding_text)
77    return;
78
79  // Just fake out a RequestSurroundingText message to the proxy for the PPP
80  // interface.
81  InterfaceProxy* proxy = dispatcher->GetInterfaceProxy(API_ID_PPP_TEXT_INPUT);
82  if (!proxy)
83    return;
84  proxy->OnMessageReceived(PpapiMsg_PPPTextInput_RequestSurroundingText(
85      API_ID_PPP_TEXT_INPUT, instance,
86      PPB_Instance_Shared::kExtraCharsForTextInput));
87}
88
89}  // namespace
90
91PPB_Instance_Proxy::PPB_Instance_Proxy(Dispatcher* dispatcher)
92    : InterfaceProxy(dispatcher),
93      callback_factory_(this) {
94}
95
96PPB_Instance_Proxy::~PPB_Instance_Proxy() {
97}
98
99// static
100const InterfaceProxy::Info* PPB_Instance_Proxy::GetInfoPrivate() {
101  static const Info info = {
102    ppapi::thunk::GetPPB_Instance_Private_0_1_Thunk(),
103    PPB_INSTANCE_PRIVATE_INTERFACE_0_1,
104    API_ID_NONE,  // 1_0 is the canonical one.
105    false,
106    &CreateInstanceProxy,
107  };
108  return &info;
109}
110
111bool PPB_Instance_Proxy::OnMessageReceived(const IPC::Message& msg) {
112  // Prevent the dispatcher from going away during a call to ExecuteScript.
113  // This must happen OUTSIDE of ExecuteScript since the SerializedVars use
114  // the dispatcher upon return of the function (converting the
115  // SerializedVarReturnValue/OutParam to a SerializedVar in the destructor).
116#if !defined(OS_NACL)
117  ScopedModuleReference death_grip(dispatcher());
118#endif
119
120  bool handled = true;
121  IPC_BEGIN_MESSAGE_MAP(PPB_Instance_Proxy, msg)
122#if !defined(OS_NACL)
123    // Plugin -> Host messages.
124    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_GetWindowObject,
125                        OnHostMsgGetWindowObject)
126    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_GetOwnerElementObject,
127                        OnHostMsgGetOwnerElementObject)
128    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_BindGraphics,
129                        OnHostMsgBindGraphics)
130    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_IsFullFrame,
131                        OnHostMsgIsFullFrame)
132    IPC_MESSAGE_HANDLER(
133        PpapiHostMsg_PPBInstance_GetAudioHardwareOutputSampleRate,
134        OnHostMsgGetAudioHardwareOutputSampleRate)
135    IPC_MESSAGE_HANDLER(
136        PpapiHostMsg_PPBInstance_GetAudioHardwareOutputBufferSize,
137        OnHostMsgGetAudioHardwareOutputBufferSize)
138    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_ExecuteScript,
139                        OnHostMsgExecuteScript)
140    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_GetDefaultCharSet,
141                        OnHostMsgGetDefaultCharSet)
142    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_PostMessage,
143                        OnHostMsgPostMessage)
144    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_SetFullscreen,
145                        OnHostMsgSetFullscreen)
146    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_GetScreenSize,
147                        OnHostMsgGetScreenSize)
148    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_RequestInputEvents,
149                        OnHostMsgRequestInputEvents)
150    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_ClearInputEvents,
151                        OnHostMsgClearInputEvents)
152    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_LockMouse,
153                        OnHostMsgLockMouse)
154    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_UnlockMouse,
155                        OnHostMsgUnlockMouse)
156    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_SetCursor,
157                        OnHostMsgSetCursor)
158    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_SetTextInputType,
159                        OnHostMsgSetTextInputType)
160    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_UpdateCaretPosition,
161                        OnHostMsgUpdateCaretPosition)
162    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_CancelCompositionText,
163                        OnHostMsgCancelCompositionText)
164    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_UpdateSurroundingText,
165                        OnHostMsgUpdateSurroundingText)
166    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_GetDocumentURL,
167                        OnHostMsgGetDocumentURL)
168    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_ResolveRelativeToDocument,
169                        OnHostMsgResolveRelativeToDocument)
170    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_DocumentCanRequest,
171                        OnHostMsgDocumentCanRequest)
172    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_DocumentCanAccessDocument,
173                        OnHostMsgDocumentCanAccessDocument)
174    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_GetPluginInstanceURL,
175                        OnHostMsgGetPluginInstanceURL)
176    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_GetPluginReferrerURL,
177                        OnHostMsgGetPluginReferrerURL)
178    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_SessionCreated,
179                        OnHostMsgSessionCreated)
180    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_SessionMessage,
181                        OnHostMsgSessionMessage)
182    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_SessionReady,
183                        OnHostMsgSessionReady)
184    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_SessionClosed,
185                        OnHostMsgSessionClosed)
186    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_SessionError,
187                        OnHostMsgSessionError)
188    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_DeliverBlock,
189                        OnHostMsgDeliverBlock)
190    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_DecoderInitializeDone,
191                        OnHostMsgDecoderInitializeDone)
192    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_DecoderDeinitializeDone,
193                        OnHostMsgDecoderDeinitializeDone)
194    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_DecoderResetDone,
195                        OnHostMsgDecoderResetDone)
196    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_DeliverFrame,
197                        OnHostMsgDeliverFrame)
198    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_DeliverSamples,
199                        OnHostMsgDeliverSamples)
200#endif  // !defined(OS_NACL)
201
202    // Host -> Plugin messages.
203    IPC_MESSAGE_HANDLER(PpapiMsg_PPBInstance_MouseLockComplete,
204                        OnPluginMsgMouseLockComplete)
205
206    IPC_MESSAGE_UNHANDLED(handled = false)
207  IPC_END_MESSAGE_MAP()
208  return handled;
209}
210
211PP_Bool PPB_Instance_Proxy::BindGraphics(PP_Instance instance,
212                                         PP_Resource device) {
213  // If device is 0, pass a null HostResource. This signals the host to unbind
214  // all devices.
215  HostResource host_resource;
216  PP_Resource pp_resource = 0;
217  if (device) {
218    Resource* resource =
219        PpapiGlobals::Get()->GetResourceTracker()->GetResource(device);
220    if (!resource || resource->pp_instance() != instance)
221      return PP_FALSE;
222    host_resource = resource->host_resource();
223    pp_resource = resource->pp_resource();
224  } else {
225    // Passing 0 means unbinding all devices.
226    dispatcher()->Send(new PpapiHostMsg_PPBInstance_BindGraphics(
227        API_ID_PPB_INSTANCE, instance, 0));
228    return PP_TRUE;
229  }
230
231  // We need to pass different resource to Graphics 2D and 3D right now.  Once
232  // 3D is migrated to the new design, we should be able to unify this.
233  EnterResourceNoLock<PPB_Graphics2D_API> enter_2d(device, false);
234  EnterResourceNoLock<PPB_Graphics3D_API> enter_3d(device, false);
235  if (enter_2d.succeeded()) {
236    dispatcher()->Send(new PpapiHostMsg_PPBInstance_BindGraphics(
237        API_ID_PPB_INSTANCE, instance, pp_resource));
238    return PP_TRUE;
239  } else if (enter_3d.succeeded()) {
240    dispatcher()->Send(new PpapiHostMsg_PPBInstance_BindGraphics(
241        API_ID_PPB_INSTANCE, instance, host_resource.host_resource()));
242    return PP_TRUE;
243  }
244  return PP_FALSE;
245}
246
247PP_Bool PPB_Instance_Proxy::IsFullFrame(PP_Instance instance) {
248  PP_Bool result = PP_FALSE;
249  dispatcher()->Send(new PpapiHostMsg_PPBInstance_IsFullFrame(
250      API_ID_PPB_INSTANCE, instance, &result));
251  return result;
252}
253
254const ViewData* PPB_Instance_Proxy::GetViewData(PP_Instance instance) {
255  InstanceData* data = static_cast<PluginDispatcher*>(dispatcher())->
256      GetInstanceData(instance);
257  if (!data)
258    return NULL;
259  return &data->view;
260}
261
262PP_Bool PPB_Instance_Proxy::FlashIsFullscreen(PP_Instance instance) {
263  // This function is only used for proxying in the renderer process. It is not
264  // implemented in the plugin process.
265  NOTREACHED();
266  return PP_FALSE;
267}
268
269PP_Var PPB_Instance_Proxy::GetWindowObject(PP_Instance instance) {
270  ReceiveSerializedVarReturnValue result;
271  dispatcher()->Send(new PpapiHostMsg_PPBInstance_GetWindowObject(
272      API_ID_PPB_INSTANCE, instance, &result));
273  return result.Return(dispatcher());
274}
275
276PP_Var PPB_Instance_Proxy::GetOwnerElementObject(PP_Instance instance) {
277  ReceiveSerializedVarReturnValue result;
278  dispatcher()->Send(new PpapiHostMsg_PPBInstance_GetOwnerElementObject(
279      API_ID_PPB_INSTANCE, instance, &result));
280  return result.Return(dispatcher());
281}
282
283PP_Var PPB_Instance_Proxy::ExecuteScript(PP_Instance instance,
284                                         PP_Var script,
285                                         PP_Var* exception) {
286  ReceiveSerializedException se(dispatcher(), exception);
287  if (se.IsThrown())
288    return PP_MakeUndefined();
289
290  ReceiveSerializedVarReturnValue result;
291  dispatcher()->Send(new PpapiHostMsg_PPBInstance_ExecuteScript(
292      API_ID_PPB_INSTANCE, instance,
293      SerializedVarSendInput(dispatcher(), script), &se, &result));
294  return result.Return(dispatcher());
295}
296
297uint32_t PPB_Instance_Proxy::GetAudioHardwareOutputSampleRate(
298    PP_Instance instance) {
299  uint32_t result = PP_AUDIOSAMPLERATE_NONE;
300  dispatcher()->Send(
301      new PpapiHostMsg_PPBInstance_GetAudioHardwareOutputSampleRate(
302          API_ID_PPB_INSTANCE, instance, &result));
303  return result;
304}
305
306uint32_t PPB_Instance_Proxy::GetAudioHardwareOutputBufferSize(
307    PP_Instance instance) {
308  uint32_t result = 0;
309  dispatcher()->Send(
310      new PpapiHostMsg_PPBInstance_GetAudioHardwareOutputBufferSize(
311          API_ID_PPB_INSTANCE, instance, &result));
312  return result;
313}
314
315PP_Var PPB_Instance_Proxy::GetDefaultCharSet(PP_Instance instance) {
316  PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
317  if (!dispatcher)
318    return PP_MakeUndefined();
319
320  ReceiveSerializedVarReturnValue result;
321  dispatcher->Send(new PpapiHostMsg_PPBInstance_GetDefaultCharSet(
322      API_ID_PPB_INSTANCE, instance, &result));
323  return result.Return(dispatcher);
324}
325
326void PPB_Instance_Proxy::NumberOfFindResultsChanged(PP_Instance instance,
327                                                    int32_t total,
328                                                    PP_Bool final_result) {
329  NOTIMPLEMENTED();  // Not proxied yet.
330}
331
332void PPB_Instance_Proxy::SelectedFindResultChanged(PP_Instance instance,
333                                                   int32_t index) {
334  NOTIMPLEMENTED();  // Not proxied yet.
335}
336
337PP_Bool PPB_Instance_Proxy::IsFullscreen(PP_Instance instance) {
338  InstanceData* data = static_cast<PluginDispatcher*>(dispatcher())->
339      GetInstanceData(instance);
340  if (!data)
341    return PP_FALSE;
342  return PP_FromBool(data->view.is_fullscreen);
343}
344
345PP_Bool PPB_Instance_Proxy::SetFullscreen(PP_Instance instance,
346                                          PP_Bool fullscreen) {
347  PP_Bool result = PP_FALSE;
348  dispatcher()->Send(new PpapiHostMsg_PPBInstance_SetFullscreen(
349      API_ID_PPB_INSTANCE, instance, fullscreen, &result));
350  return result;
351}
352
353PP_Bool PPB_Instance_Proxy::GetScreenSize(PP_Instance instance,
354                                          PP_Size* size) {
355  PP_Bool result = PP_FALSE;
356  dispatcher()->Send(new PpapiHostMsg_PPBInstance_GetScreenSize(
357      API_ID_PPB_INSTANCE, instance, &result, size));
358  return result;
359}
360
361Resource* PPB_Instance_Proxy::GetSingletonResource(PP_Instance instance,
362                                                   SingletonResourceID id) {
363  InstanceData* data = static_cast<PluginDispatcher*>(dispatcher())->
364      GetInstanceData(instance);
365
366  InstanceData::SingletonResourceMap::iterator it =
367      data->singleton_resources.find(id);
368  if (it != data->singleton_resources.end())
369    return it->second.get();
370
371  scoped_refptr<Resource> new_singleton;
372  Connection connection(PluginGlobals::Get()->GetBrowserSender(), dispatcher());
373
374  switch (id) {
375    case BROKER_SINGLETON_ID:
376      new_singleton = new BrokerResource(connection, instance);
377      break;
378    case EXTENSIONS_COMMON_SINGLETON_ID:
379      new_singleton = new ExtensionsCommonResource(connection, instance);
380      break;
381    case GAMEPAD_SINGLETON_ID:
382      new_singleton = new GamepadResource(connection, instance);
383      break;
384    case ISOLATED_FILESYSTEM_SINGLETON_ID:
385      new_singleton =
386          new IsolatedFileSystemPrivateResource(connection, instance);
387      break;
388    case NETWORK_PROXY_SINGLETON_ID:
389      new_singleton = new NetworkProxyResource(connection, instance);
390      break;
391    case TRUETYPE_FONT_SINGLETON_ID:
392      new_singleton = new TrueTypeFontSingletonResource(connection, instance);
393      break;
394// Flash/trusted resources aren't needed for NaCl.
395#if !defined(OS_NACL) && !defined(NACL_WIN64)
396    case BROWSER_FONT_SINGLETON_ID:
397      new_singleton = new BrowserFontSingletonResource(connection, instance);
398      break;
399    case FLASH_CLIPBOARD_SINGLETON_ID:
400      new_singleton = new FlashClipboardResource(connection, instance);
401      break;
402    case FLASH_FILE_SINGLETON_ID:
403      new_singleton = new FlashFileResource(connection, instance);
404      break;
405    case FLASH_FULLSCREEN_SINGLETON_ID:
406      new_singleton = new FlashFullscreenResource(connection, instance);
407      break;
408    case FLASH_SINGLETON_ID:
409      new_singleton = new FlashResource(connection, instance,
410          static_cast<PluginDispatcher*>(dispatcher()));
411      break;
412    case PDF_SINGLETON_ID:
413      new_singleton = new PDFResource(connection, instance);
414      break;
415#else
416    case BROWSER_FONT_SINGLETON_ID:
417    case FLASH_CLIPBOARD_SINGLETON_ID:
418    case FLASH_FILE_SINGLETON_ID:
419    case FLASH_FULLSCREEN_SINGLETON_ID:
420    case FLASH_SINGLETON_ID:
421    case PDF_SINGLETON_ID:
422      NOTREACHED();
423      break;
424#endif  // !defined(OS_NACL) && !defined(NACL_WIN64)
425  }
426
427  if (!new_singleton.get()) {
428    // Getting here implies that a constructor is missing in the above switch.
429    NOTREACHED();
430    return NULL;
431  }
432
433  data->singleton_resources[id] = new_singleton;
434  return new_singleton.get();
435}
436
437int32_t PPB_Instance_Proxy::RequestInputEvents(PP_Instance instance,
438                                               uint32_t event_classes) {
439  dispatcher()->Send(new PpapiHostMsg_PPBInstance_RequestInputEvents(
440      API_ID_PPB_INSTANCE, instance, false, event_classes));
441
442  // We always register for the classes we can handle, this function validates
443  // the flags so we can notify it if anything was invalid, without requiring
444  // a sync reply.
445  return ValidateRequestInputEvents(false, event_classes);
446}
447
448int32_t PPB_Instance_Proxy::RequestFilteringInputEvents(
449    PP_Instance instance,
450    uint32_t event_classes) {
451  dispatcher()->Send(new PpapiHostMsg_PPBInstance_RequestInputEvents(
452      API_ID_PPB_INSTANCE, instance, true, event_classes));
453
454  // We always register for the classes we can handle, this function validates
455  // the flags so we can notify it if anything was invalid, without requiring
456  // a sync reply.
457  return ValidateRequestInputEvents(true, event_classes);
458}
459
460void PPB_Instance_Proxy::ClearInputEventRequest(PP_Instance instance,
461                                                uint32_t event_classes) {
462  dispatcher()->Send(new PpapiHostMsg_PPBInstance_ClearInputEvents(
463      API_ID_PPB_INSTANCE, instance, event_classes));
464}
465
466void PPB_Instance_Proxy::ZoomChanged(PP_Instance instance,
467                                     double factor) {
468  // Not proxied yet.
469  NOTIMPLEMENTED();
470}
471
472void PPB_Instance_Proxy::ZoomLimitsChanged(PP_Instance instance,
473                                           double minimum_factor,
474                                           double maximium_factor) {
475  // Not proxied yet.
476  NOTIMPLEMENTED();
477}
478
479PP_Var PPB_Instance_Proxy::GetDocumentURL(PP_Instance instance,
480                                          PP_URLComponents_Dev* components) {
481  ReceiveSerializedVarReturnValue result;
482  PP_URLComponents_Dev url_components;
483  dispatcher()->Send(new PpapiHostMsg_PPBInstance_GetDocumentURL(
484      API_ID_PPB_INSTANCE, instance, &url_components, &result));
485  if (components)
486    *components = url_components;
487  return result.Return(dispatcher());
488}
489
490#if !defined(OS_NACL)
491PP_Var PPB_Instance_Proxy::ResolveRelativeToDocument(
492    PP_Instance instance,
493    PP_Var relative,
494    PP_URLComponents_Dev* components) {
495  ReceiveSerializedVarReturnValue result;
496  dispatcher()->Send(new PpapiHostMsg_PPBInstance_ResolveRelativeToDocument(
497      API_ID_PPB_INSTANCE, instance,
498      SerializedVarSendInput(dispatcher(), relative),
499      &result));
500  return PPB_URLUtil_Shared::ConvertComponentsAndReturnURL(
501      result.Return(dispatcher()),
502      components);
503}
504
505PP_Bool PPB_Instance_Proxy::DocumentCanRequest(PP_Instance instance,
506                                               PP_Var url) {
507  PP_Bool result = PP_FALSE;
508  dispatcher()->Send(new PpapiHostMsg_PPBInstance_DocumentCanRequest(
509      API_ID_PPB_INSTANCE, instance,
510      SerializedVarSendInput(dispatcher(), url),
511      &result));
512  return result;
513}
514
515PP_Bool PPB_Instance_Proxy::DocumentCanAccessDocument(PP_Instance instance,
516                                                      PP_Instance target) {
517  PP_Bool result = PP_FALSE;
518  dispatcher()->Send(new PpapiHostMsg_PPBInstance_DocumentCanAccessDocument(
519      API_ID_PPB_INSTANCE, instance, target, &result));
520  return result;
521}
522
523PP_Var PPB_Instance_Proxy::GetPluginInstanceURL(
524      PP_Instance instance,
525      PP_URLComponents_Dev* components) {
526  ReceiveSerializedVarReturnValue result;
527  dispatcher()->Send(new PpapiHostMsg_PPBInstance_GetPluginInstanceURL(
528      API_ID_PPB_INSTANCE, instance, &result));
529  return PPB_URLUtil_Shared::ConvertComponentsAndReturnURL(
530      result.Return(dispatcher()),
531      components);
532}
533
534PP_Var PPB_Instance_Proxy::GetPluginReferrerURL(
535      PP_Instance instance,
536      PP_URLComponents_Dev* components) {
537  ReceiveSerializedVarReturnValue result;
538  dispatcher()->Send(new PpapiHostMsg_PPBInstance_GetPluginReferrerURL(
539      API_ID_PPB_INSTANCE, instance, &result));
540  return PPB_URLUtil_Shared::ConvertComponentsAndReturnURL(
541      result.Return(dispatcher()),
542      components);
543}
544
545void PPB_Instance_Proxy::SessionCreated(PP_Instance instance,
546                                        uint32_t session_id,
547                                        PP_Var web_session_id) {
548  dispatcher()->Send(new PpapiHostMsg_PPBInstance_SessionCreated(
549      API_ID_PPB_INSTANCE,
550      instance,
551      session_id,
552      SerializedVarSendInput(dispatcher(), web_session_id)));
553}
554
555void PPB_Instance_Proxy::SessionMessage(PP_Instance instance,
556                                        uint32_t session_id,
557                                        PP_Var message,
558                                        PP_Var destination_url) {
559  dispatcher()->Send(new PpapiHostMsg_PPBInstance_SessionMessage(
560      API_ID_PPB_INSTANCE,
561      instance,
562      session_id,
563      SerializedVarSendInput(dispatcher(), message),
564      SerializedVarSendInput(dispatcher(), destination_url)));
565}
566
567void PPB_Instance_Proxy::SessionReady(PP_Instance instance,
568                                      uint32_t session_id) {
569  dispatcher()->Send(new PpapiHostMsg_PPBInstance_SessionReady(
570      API_ID_PPB_INSTANCE, instance, session_id));
571}
572
573void PPB_Instance_Proxy::SessionClosed(PP_Instance instance,
574                                       uint32_t session_id) {
575  dispatcher()->Send(new PpapiHostMsg_PPBInstance_SessionClosed(
576      API_ID_PPB_INSTANCE, instance, session_id));
577}
578
579void PPB_Instance_Proxy::SessionError(PP_Instance instance,
580                                      uint32_t session_id,
581                                      int32_t media_error,
582                                      int32_t system_code) {
583  dispatcher()->Send(new PpapiHostMsg_PPBInstance_SessionError(
584      API_ID_PPB_INSTANCE, instance, session_id, media_error, system_code));
585}
586
587void PPB_Instance_Proxy::DeliverBlock(PP_Instance instance,
588                                      PP_Resource decrypted_block,
589                                      const PP_DecryptedBlockInfo* block_info) {
590  PP_Resource decrypted_block_host_resource = 0;
591
592  if (decrypted_block) {
593    Resource* object =
594        PpapiGlobals::Get()->GetResourceTracker()->GetResource(decrypted_block);
595    if (!object || object->pp_instance() != instance) {
596      NOTREACHED();
597      return;
598    }
599    decrypted_block_host_resource = object->host_resource().host_resource();
600  }
601
602  std::string serialized_block_info;
603  if (!SerializeBlockInfo(*block_info, &serialized_block_info)) {
604    NOTREACHED();
605    return;
606  }
607
608  dispatcher()->Send(
609      new PpapiHostMsg_PPBInstance_DeliverBlock(API_ID_PPB_INSTANCE,
610          instance,
611          decrypted_block_host_resource,
612          serialized_block_info));
613}
614
615void PPB_Instance_Proxy::DecoderInitializeDone(
616    PP_Instance instance,
617    PP_DecryptorStreamType decoder_type,
618    uint32_t request_id,
619    PP_Bool success) {
620  dispatcher()->Send(
621      new PpapiHostMsg_PPBInstance_DecoderInitializeDone(
622          API_ID_PPB_INSTANCE,
623          instance,
624          decoder_type,
625          request_id,
626          success));
627}
628
629void PPB_Instance_Proxy::DecoderDeinitializeDone(
630    PP_Instance instance,
631    PP_DecryptorStreamType decoder_type,
632    uint32_t request_id) {
633  dispatcher()->Send(
634      new PpapiHostMsg_PPBInstance_DecoderDeinitializeDone(
635          API_ID_PPB_INSTANCE,
636          instance,
637          decoder_type,
638          request_id));
639}
640
641void PPB_Instance_Proxy::DecoderResetDone(PP_Instance instance,
642                                          PP_DecryptorStreamType decoder_type,
643                                          uint32_t request_id) {
644  dispatcher()->Send(
645      new PpapiHostMsg_PPBInstance_DecoderResetDone(
646          API_ID_PPB_INSTANCE,
647          instance,
648          decoder_type,
649          request_id));
650}
651
652void PPB_Instance_Proxy::DeliverFrame(PP_Instance instance,
653                                      PP_Resource decrypted_frame,
654                                      const PP_DecryptedFrameInfo* frame_info) {
655  PP_Resource host_resource = 0;
656  if (decrypted_frame != 0) {
657    ResourceTracker* tracker = PpapiGlobals::Get()->GetResourceTracker();
658    Resource* object = tracker->GetResource(decrypted_frame);
659
660    if (!object || object->pp_instance() != instance) {
661      NOTREACHED();
662      return;
663    }
664
665    host_resource = object->host_resource().host_resource();
666  }
667
668  std::string serialized_frame_info;
669  if (!SerializeBlockInfo(*frame_info, &serialized_frame_info)) {
670    NOTREACHED();
671    return;
672  }
673
674  dispatcher()->Send(
675      new PpapiHostMsg_PPBInstance_DeliverFrame(API_ID_PPB_INSTANCE,
676                                                instance,
677                                                host_resource,
678                                                serialized_frame_info));
679}
680
681void PPB_Instance_Proxy::DeliverSamples(
682    PP_Instance instance,
683    PP_Resource decrypted_samples,
684    const PP_DecryptedSampleInfo* sample_info) {
685  PP_Resource host_resource = 0;
686  if (decrypted_samples != 0) {
687    ResourceTracker* tracker = PpapiGlobals::Get()->GetResourceTracker();
688    Resource* object = tracker->GetResource(decrypted_samples);
689
690    if (!object || object->pp_instance() != instance) {
691      NOTREACHED();
692      return;
693    }
694
695    host_resource = object->host_resource().host_resource();
696  }
697
698  std::string serialized_sample_info;
699  if (!SerializeBlockInfo(*sample_info, &serialized_sample_info)) {
700    NOTREACHED();
701    return;
702  }
703
704  dispatcher()->Send(
705      new PpapiHostMsg_PPBInstance_DeliverSamples(API_ID_PPB_INSTANCE,
706                                                  instance,
707                                                  host_resource,
708                                                  serialized_sample_info));
709}
710#endif  // !defined(OS_NACL)
711
712void PPB_Instance_Proxy::PostMessage(PP_Instance instance,
713                                     PP_Var message) {
714  dispatcher()->Send(new PpapiHostMsg_PPBInstance_PostMessage(
715      API_ID_PPB_INSTANCE,
716      instance, SerializedVarSendInputShmem(dispatcher(), message,
717                                            instance)));
718}
719
720PP_Bool PPB_Instance_Proxy::SetCursor(PP_Instance instance,
721                                      PP_MouseCursor_Type type,
722                                      PP_Resource image,
723                                      const PP_Point* hot_spot) {
724  // Some of these parameters are important for security. This check is in the
725  // plugin process just for the convenience of the caller (since we don't
726  // bother returning errors from the other process with a sync message). The
727  // parameters will be validated again in the renderer.
728  if (!ValidateSetCursorParams(type, image, hot_spot))
729    return PP_FALSE;
730
731  HostResource image_host_resource;
732  if (image) {
733    Resource* cursor_image =
734        PpapiGlobals::Get()->GetResourceTracker()->GetResource(image);
735    if (!cursor_image || cursor_image->pp_instance() != instance)
736      return PP_FALSE;
737    image_host_resource = cursor_image->host_resource();
738  }
739
740  dispatcher()->Send(new PpapiHostMsg_PPBInstance_SetCursor(
741      API_ID_PPB_INSTANCE, instance, static_cast<int32_t>(type),
742      image_host_resource, hot_spot ? *hot_spot : PP_MakePoint(0, 0)));
743  return PP_TRUE;
744}
745
746int32_t PPB_Instance_Proxy::LockMouse(PP_Instance instance,
747                                      scoped_refptr<TrackedCallback> callback) {
748  // Save the mouse callback on the instance data.
749  InstanceData* data = static_cast<PluginDispatcher*>(dispatcher())->
750      GetInstanceData(instance);
751  if (!data)
752    return PP_ERROR_BADARGUMENT;
753  if (TrackedCallback::IsPending(data->mouse_lock_callback))
754    return PP_ERROR_INPROGRESS;  // Already have a pending callback.
755  data->mouse_lock_callback = callback;
756
757  dispatcher()->Send(new PpapiHostMsg_PPBInstance_LockMouse(
758      API_ID_PPB_INSTANCE, instance));
759  return PP_OK_COMPLETIONPENDING;
760}
761
762void PPB_Instance_Proxy::UnlockMouse(PP_Instance instance) {
763  dispatcher()->Send(new PpapiHostMsg_PPBInstance_UnlockMouse(
764      API_ID_PPB_INSTANCE, instance));
765}
766
767void PPB_Instance_Proxy::SetTextInputType(PP_Instance instance,
768                                          PP_TextInput_Type type) {
769  CancelAnyPendingRequestSurroundingText(instance);
770  dispatcher()->Send(new PpapiHostMsg_PPBInstance_SetTextInputType(
771      API_ID_PPB_INSTANCE, instance, type));
772}
773
774void PPB_Instance_Proxy::UpdateCaretPosition(PP_Instance instance,
775                                             const PP_Rect& caret,
776                                             const PP_Rect& bounding_box) {
777  dispatcher()->Send(new PpapiHostMsg_PPBInstance_UpdateCaretPosition(
778      API_ID_PPB_INSTANCE, instance, caret, bounding_box));
779}
780
781void PPB_Instance_Proxy::CancelCompositionText(PP_Instance instance) {
782  CancelAnyPendingRequestSurroundingText(instance);
783  dispatcher()->Send(new PpapiHostMsg_PPBInstance_CancelCompositionText(
784      API_ID_PPB_INSTANCE, instance));
785}
786
787void PPB_Instance_Proxy::SelectionChanged(PP_Instance instance) {
788  // The "right" way to do this is to send the message to the host. However,
789  // all it will do is call RequestSurroundingText with a hardcoded number of
790  // characters in response, which is an entire IPC round-trip.
791  //
792  // We can avoid this round-trip by just implementing the
793  // RequestSurroundingText logic in the plugin process. If the logic in the
794  // host becomes more complex (like a more adaptive number of characters),
795  // we'll need to reevanuate whether we want to do the round trip instead.
796  //
797  // Be careful to post a task to avoid reentering the plugin.
798
799  InstanceData* data =
800      static_cast<PluginDispatcher*>(dispatcher())->GetInstanceData(instance);
801  if (!data)
802    return;
803  data->should_do_request_surrounding_text = true;
804
805  if (!data->is_request_surrounding_text_pending) {
806    base::MessageLoop::current()->PostTask(
807        FROM_HERE,
808        RunWhileLocked(base::Bind(&RequestSurroundingText, instance)));
809    data->is_request_surrounding_text_pending = true;
810  }
811}
812
813void PPB_Instance_Proxy::UpdateSurroundingText(PP_Instance instance,
814                                               const char* text,
815                                               uint32_t caret,
816                                               uint32_t anchor) {
817  dispatcher()->Send(new PpapiHostMsg_PPBInstance_UpdateSurroundingText(
818      API_ID_PPB_INSTANCE, instance, text, caret, anchor));
819}
820
821#if !defined(OS_NACL)
822void PPB_Instance_Proxy::OnHostMsgGetWindowObject(
823    PP_Instance instance,
824    SerializedVarReturnValue result) {
825  if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
826    return;
827  EnterInstanceNoLock enter(instance);
828  if (enter.succeeded())
829    result.Return(dispatcher(), enter.functions()->GetWindowObject(instance));
830}
831
832void PPB_Instance_Proxy::OnHostMsgGetOwnerElementObject(
833    PP_Instance instance,
834    SerializedVarReturnValue result) {
835  if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
836    return;
837  EnterInstanceNoLock enter(instance);
838  if (enter.succeeded()) {
839    result.Return(dispatcher(),
840                  enter.functions()->GetOwnerElementObject(instance));
841  }
842}
843
844void PPB_Instance_Proxy::OnHostMsgBindGraphics(PP_Instance instance,
845                                               PP_Resource device) {
846  // Note that we ignroe the return value here. Otherwise, this would need to
847  // be a slow sync call, and the plugin side of the proxy will have already
848  // validated the resources, so we shouldn't see errors here that weren't
849  // already caught.
850  EnterInstanceNoLock enter(instance);
851  if (enter.succeeded())
852    enter.functions()->BindGraphics(instance, device);
853}
854
855void PPB_Instance_Proxy::OnHostMsgGetAudioHardwareOutputSampleRate(
856    PP_Instance instance, uint32_t* result) {
857  EnterInstanceNoLock enter(instance);
858  if (enter.succeeded())
859    *result = enter.functions()->GetAudioHardwareOutputSampleRate(instance);
860}
861
862void PPB_Instance_Proxy::OnHostMsgGetAudioHardwareOutputBufferSize(
863    PP_Instance instance, uint32_t* result) {
864  EnterInstanceNoLock enter(instance);
865  if (enter.succeeded())
866    *result = enter.functions()->GetAudioHardwareOutputBufferSize(instance);
867}
868
869void PPB_Instance_Proxy::OnHostMsgIsFullFrame(PP_Instance instance,
870                                              PP_Bool* result) {
871  EnterInstanceNoLock enter(instance);
872  if (enter.succeeded())
873    *result = enter.functions()->IsFullFrame(instance);
874}
875
876void PPB_Instance_Proxy::OnHostMsgExecuteScript(
877    PP_Instance instance,
878    SerializedVarReceiveInput script,
879    SerializedVarOutParam out_exception,
880    SerializedVarReturnValue result) {
881  if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
882    return;
883  EnterInstanceNoLock enter(instance);
884  if (enter.failed())
885    return;
886
887  if (dispatcher()->IsPlugin())
888    NOTREACHED();
889  else
890    static_cast<HostDispatcher*>(dispatcher())->set_allow_plugin_reentrancy();
891
892  result.Return(dispatcher(), enter.functions()->ExecuteScript(
893      instance,
894      script.Get(dispatcher()),
895      out_exception.OutParam(dispatcher())));
896}
897
898void PPB_Instance_Proxy::OnHostMsgGetDefaultCharSet(
899    PP_Instance instance,
900    SerializedVarReturnValue result) {
901  if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
902    return;
903  EnterInstanceNoLock enter(instance);
904  if (enter.succeeded())
905    result.Return(dispatcher(), enter.functions()->GetDefaultCharSet(instance));
906}
907
908void PPB_Instance_Proxy::OnHostMsgSetFullscreen(PP_Instance instance,
909                                                PP_Bool fullscreen,
910                                                PP_Bool* result) {
911  EnterInstanceNoLock enter(instance);
912  if (enter.succeeded())
913    *result = enter.functions()->SetFullscreen(instance, fullscreen);
914}
915
916
917void PPB_Instance_Proxy::OnHostMsgGetScreenSize(PP_Instance instance,
918                                                PP_Bool* result,
919                                                PP_Size* size) {
920  EnterInstanceNoLock enter(instance);
921  if (enter.succeeded())
922    *result = enter.functions()->GetScreenSize(instance, size);
923}
924
925void PPB_Instance_Proxy::OnHostMsgRequestInputEvents(PP_Instance instance,
926                                                     bool is_filtering,
927                                                     uint32_t event_classes) {
928  EnterInstanceNoLock enter(instance);
929  if (enter.succeeded()) {
930    if (is_filtering)
931      enter.functions()->RequestFilteringInputEvents(instance, event_classes);
932    else
933      enter.functions()->RequestInputEvents(instance, event_classes);
934  }
935}
936
937void PPB_Instance_Proxy::OnHostMsgClearInputEvents(PP_Instance instance,
938                                                   uint32_t event_classes) {
939  EnterInstanceNoLock enter(instance);
940  if (enter.succeeded())
941    enter.functions()->ClearInputEventRequest(instance, event_classes);
942}
943
944void PPB_Instance_Proxy::OnHostMsgPostMessage(
945    PP_Instance instance,
946    SerializedVarReceiveInput message) {
947  EnterInstanceNoLock enter(instance);
948  if (!message.is_valid_var()) {
949    PpapiGlobals::Get()->LogWithSource(
950        instance, PP_LOGLEVEL_ERROR, std::string(), kSerializationError);
951    return;
952  }
953
954  if (enter.succeeded())
955    enter.functions()->PostMessage(instance,
956                                   message.GetForInstance(dispatcher(),
957                                                          instance));
958}
959
960void PPB_Instance_Proxy::OnHostMsgLockMouse(PP_Instance instance) {
961  // Need to be careful to always issue the callback.
962  pp::CompletionCallback cb = callback_factory_.NewCallback(
963      &PPB_Instance_Proxy::MouseLockCompleteInHost, instance);
964
965  EnterInstanceNoLock enter(instance, cb.pp_completion_callback());
966  if (enter.succeeded())
967    enter.SetResult(enter.functions()->LockMouse(instance, enter.callback()));
968}
969
970void PPB_Instance_Proxy::OnHostMsgUnlockMouse(PP_Instance instance) {
971  EnterInstanceNoLock enter(instance);
972  if (enter.succeeded())
973    enter.functions()->UnlockMouse(instance);
974}
975
976void PPB_Instance_Proxy::OnHostMsgGetDocumentURL(
977    PP_Instance instance,
978    PP_URLComponents_Dev* components,
979    SerializedVarReturnValue result) {
980  if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
981    return;
982  EnterInstanceNoLock enter(instance);
983  if (enter.succeeded()) {
984    PP_Var document_url = enter.functions()->GetDocumentURL(instance,
985                                                            components);
986    result.Return(dispatcher(), document_url);
987  }
988}
989
990void PPB_Instance_Proxy::OnHostMsgResolveRelativeToDocument(
991    PP_Instance instance,
992    SerializedVarReceiveInput relative,
993    SerializedVarReturnValue result) {
994  if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
995    return;
996  EnterInstanceNoLock enter(instance);
997  if (enter.succeeded()) {
998    result.Return(dispatcher(),
999                  enter.functions()->ResolveRelativeToDocument(
1000                      instance, relative.Get(dispatcher()), NULL));
1001  }
1002}
1003
1004void PPB_Instance_Proxy::OnHostMsgDocumentCanRequest(
1005    PP_Instance instance,
1006    SerializedVarReceiveInput url,
1007    PP_Bool* result) {
1008  if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
1009    return;
1010  EnterInstanceNoLock enter(instance);
1011  if (enter.succeeded()) {
1012    *result = enter.functions()->DocumentCanRequest(instance,
1013                                                    url.Get(dispatcher()));
1014  }
1015}
1016
1017void PPB_Instance_Proxy::OnHostMsgDocumentCanAccessDocument(PP_Instance active,
1018                                                            PP_Instance target,
1019                                                            PP_Bool* result) {
1020  if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
1021    return;
1022  EnterInstanceNoLock enter(active);
1023  if (enter.succeeded())
1024    *result = enter.functions()->DocumentCanAccessDocument(active, target);
1025}
1026
1027void PPB_Instance_Proxy::OnHostMsgGetPluginInstanceURL(
1028    PP_Instance instance,
1029    SerializedVarReturnValue result) {
1030  if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
1031    return;
1032  EnterInstanceNoLock enter(instance);
1033  if (enter.succeeded()) {
1034    result.Return(dispatcher(),
1035                  enter.functions()->GetPluginInstanceURL(instance, NULL));
1036  }
1037}
1038
1039void PPB_Instance_Proxy::OnHostMsgGetPluginReferrerURL(
1040    PP_Instance instance,
1041    SerializedVarReturnValue result) {
1042  if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
1043    return;
1044  EnterInstanceNoLock enter(instance);
1045  if (enter.succeeded()) {
1046    result.Return(dispatcher(),
1047                  enter.functions()->GetPluginReferrerURL(instance, NULL));
1048  }
1049}
1050
1051void PPB_Instance_Proxy::OnHostMsgSessionCreated(
1052    PP_Instance instance,
1053    uint32_t session_id,
1054    SerializedVarReceiveInput web_session_id) {
1055  if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
1056    return;
1057  EnterInstanceNoLock enter(instance);
1058  if (enter.succeeded()) {
1059    enter.functions()->SessionCreated(
1060        instance, session_id, web_session_id.Get(dispatcher()));
1061  }
1062}
1063
1064void PPB_Instance_Proxy::OnHostMsgSessionMessage(
1065    PP_Instance instance,
1066    uint32_t session_id,
1067    SerializedVarReceiveInput message,
1068    SerializedVarReceiveInput destination_url) {
1069  if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
1070    return;
1071  EnterInstanceNoLock enter(instance);
1072  if (enter.succeeded()) {
1073    enter.functions()->SessionMessage(instance,
1074                                      session_id,
1075                                      message.Get(dispatcher()),
1076                                      destination_url.Get(dispatcher()));
1077  }
1078}
1079
1080void PPB_Instance_Proxy::OnHostMsgSessionReady(PP_Instance instance,
1081                                               uint32_t session_id) {
1082  if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
1083    return;
1084  EnterInstanceNoLock enter(instance);
1085  if (enter.succeeded()) {
1086    enter.functions()->SessionReady(instance, session_id);
1087  }
1088}
1089
1090void PPB_Instance_Proxy::OnHostMsgSessionClosed(PP_Instance instance,
1091                                                uint32_t session_id) {
1092  if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
1093    return;
1094  EnterInstanceNoLock enter(instance);
1095  if (enter.succeeded()) {
1096    enter.functions()->SessionClosed(instance, session_id);
1097  }
1098}
1099
1100void PPB_Instance_Proxy::OnHostMsgSessionError(PP_Instance instance,
1101                                               uint32_t session_id,
1102                                               int32_t media_error,
1103                                               int32_t system_error) {
1104  if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
1105    return;
1106  EnterInstanceNoLock enter(instance);
1107  if (enter.succeeded()) {
1108    enter.functions()->SessionError(
1109        instance, session_id, media_error, system_error);
1110  }
1111}
1112
1113void PPB_Instance_Proxy::OnHostMsgDeliverBlock(
1114    PP_Instance instance,
1115    PP_Resource decrypted_block,
1116    const std::string& serialized_block_info) {
1117  if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
1118    return;
1119  PP_DecryptedBlockInfo block_info;
1120  if (!DeserializeBlockInfo(serialized_block_info, &block_info))
1121    return;
1122
1123  EnterInstanceNoLock enter(instance);
1124  if (enter.succeeded())
1125    enter.functions()->DeliverBlock(instance, decrypted_block, &block_info);
1126}
1127
1128void PPB_Instance_Proxy::OnHostMsgDecoderInitializeDone(
1129    PP_Instance instance,
1130    PP_DecryptorStreamType decoder_type,
1131    uint32_t request_id,
1132    PP_Bool success) {
1133  if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
1134    return;
1135  EnterInstanceNoLock enter(instance);
1136  if (enter.succeeded()) {
1137    enter.functions()->DecoderInitializeDone(instance,
1138                                             decoder_type,
1139                                             request_id,
1140                                             success);
1141  }
1142}
1143
1144void PPB_Instance_Proxy::OnHostMsgDecoderDeinitializeDone(
1145    PP_Instance instance,
1146    PP_DecryptorStreamType decoder_type,
1147    uint32_t request_id) {
1148  if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
1149    return;
1150  EnterInstanceNoLock enter(instance);
1151  if (enter.succeeded())
1152    enter.functions()->DecoderDeinitializeDone(instance,
1153                                               decoder_type,
1154                                               request_id);
1155}
1156
1157void PPB_Instance_Proxy::OnHostMsgDecoderResetDone(
1158    PP_Instance instance,
1159    PP_DecryptorStreamType decoder_type,
1160    uint32_t request_id) {
1161  if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
1162    return;
1163  EnterInstanceNoLock enter(instance);
1164  if (enter.succeeded())
1165    enter.functions()->DecoderResetDone(instance, decoder_type, request_id);
1166}
1167
1168void PPB_Instance_Proxy::OnHostMsgDeliverFrame(
1169    PP_Instance instance,
1170    PP_Resource decrypted_frame,
1171    const std::string& serialized_frame_info) {
1172  if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
1173    return;
1174  PP_DecryptedFrameInfo frame_info;
1175  if (!DeserializeBlockInfo(serialized_frame_info, &frame_info))
1176    return;
1177
1178  EnterInstanceNoLock enter(instance);
1179  if (enter.succeeded())
1180    enter.functions()->DeliverFrame(instance, decrypted_frame, &frame_info);
1181}
1182
1183void PPB_Instance_Proxy::OnHostMsgDeliverSamples(
1184    PP_Instance instance,
1185    PP_Resource audio_frames,
1186    const std::string& serialized_sample_info) {
1187  if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
1188    return;
1189  PP_DecryptedSampleInfo sample_info;
1190  if (!DeserializeBlockInfo(serialized_sample_info, &sample_info))
1191    return;
1192
1193  EnterInstanceNoLock enter(instance);
1194  if (enter.succeeded())
1195    enter.functions()->DeliverSamples(instance, audio_frames, &sample_info);
1196}
1197
1198void PPB_Instance_Proxy::OnHostMsgSetCursor(
1199    PP_Instance instance,
1200    int32_t type,
1201    const ppapi::HostResource& custom_image,
1202    const PP_Point& hot_spot) {
1203  // This API serves PPB_CursorControl_Dev and PPB_MouseCursor, so is public.
1204  EnterInstanceNoLock enter(instance);
1205  if (enter.succeeded()) {
1206    enter.functions()->SetCursor(
1207        instance, static_cast<PP_MouseCursor_Type>(type),
1208        custom_image.host_resource(), &hot_spot);
1209  }
1210}
1211
1212void PPB_Instance_Proxy::OnHostMsgSetTextInputType(PP_Instance instance,
1213                                                   PP_TextInput_Type type) {
1214  if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
1215    return;
1216  EnterInstanceNoLock enter(instance);
1217  if (enter.succeeded())
1218    enter.functions()->SetTextInputType(instance, type);
1219}
1220
1221void PPB_Instance_Proxy::OnHostMsgUpdateCaretPosition(
1222    PP_Instance instance,
1223    const PP_Rect& caret,
1224    const PP_Rect& bounding_box) {
1225  if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
1226    return;
1227  EnterInstanceNoLock enter(instance);
1228  if (enter.succeeded())
1229    enter.functions()->UpdateCaretPosition(instance, caret, bounding_box);
1230}
1231
1232void PPB_Instance_Proxy::OnHostMsgCancelCompositionText(PP_Instance instance) {
1233  EnterInstanceNoLock enter(instance);
1234  if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
1235    return;
1236  if (enter.succeeded())
1237    enter.functions()->CancelCompositionText(instance);
1238}
1239
1240void PPB_Instance_Proxy::OnHostMsgUpdateSurroundingText(
1241    PP_Instance instance,
1242    const std::string& text,
1243    uint32_t caret,
1244    uint32_t anchor) {
1245  if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
1246    return;
1247  EnterInstanceNoLock enter(instance);
1248  if (enter.succeeded()) {
1249    enter.functions()->UpdateSurroundingText(instance, text.c_str(), caret,
1250                                             anchor);
1251  }
1252}
1253#endif  // !defined(OS_NACL)
1254
1255void PPB_Instance_Proxy::OnPluginMsgMouseLockComplete(PP_Instance instance,
1256                                                      int32_t result) {
1257  if (!dispatcher()->IsPlugin())
1258    return;
1259
1260  // Save the mouse callback on the instance data.
1261  InstanceData* data = static_cast<PluginDispatcher*>(dispatcher())->
1262      GetInstanceData(instance);
1263  if (!data)
1264    return;  // Instance was probably deleted.
1265  if (!TrackedCallback::IsPending(data->mouse_lock_callback)) {
1266    NOTREACHED();
1267    return;
1268  }
1269  data->mouse_lock_callback->Run(result);
1270}
1271
1272#if !defined(OS_NACL)
1273void PPB_Instance_Proxy::MouseLockCompleteInHost(int32_t result,
1274                                                 PP_Instance instance) {
1275  dispatcher()->Send(new PpapiMsg_PPBInstance_MouseLockComplete(
1276      API_ID_PPB_INSTANCE, instance, result));
1277}
1278#endif  // !defined(OS_NACL)
1279
1280void PPB_Instance_Proxy::CancelAnyPendingRequestSurroundingText(
1281    PP_Instance instance) {
1282  InstanceData* data = static_cast<PluginDispatcher*>(dispatcher())->
1283      GetInstanceData(instance);
1284  if (!data)
1285    return;  // Instance was probably deleted.
1286  data->should_do_request_surrounding_text = false;
1287}
1288
1289}  // namespace proxy
1290}  // namespace ppapi
1291