1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ppapi/proxy/ppb_instance_proxy.h"
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/file_mapping_resource.h"
23 #include "ppapi/proxy/flash_clipboard_resource.h"
24 #include "ppapi/proxy/flash_file_resource.h"
25 #include "ppapi/proxy/flash_fullscreen_resource.h"
26 #include "ppapi/proxy/flash_resource.h"
27 #include "ppapi/proxy/gamepad_resource.h"
28 #include "ppapi/proxy/host_dispatcher.h"
29 #include "ppapi/proxy/isolated_file_system_private_resource.h"
30 #include "ppapi/proxy/network_proxy_resource.h"
31 #include "ppapi/proxy/pdf_resource.h"
32 #include "ppapi/proxy/plugin_dispatcher.h"
33 #include "ppapi/proxy/ppapi_messages.h"
34 #include "ppapi/proxy/serialized_var.h"
35 #include "ppapi/proxy/truetype_font_singleton_resource.h"
36 #include "ppapi/proxy/uma_private_resource.h"
37 #include "ppapi/shared_impl/ppapi_globals.h"
38 #include "ppapi/shared_impl/ppb_url_util_shared.h"
39 #include "ppapi/shared_impl/ppb_view_shared.h"
40 #include "ppapi/shared_impl/var.h"
41 #include "ppapi/thunk/enter.h"
42 #include "ppapi/thunk/ppb_graphics_2d_api.h"
43 #include "ppapi/thunk/ppb_graphics_3d_api.h"
44 #include "ppapi/thunk/thunk.h"
46 // Windows headers interfere with this file.
51 using ppapi::thunk::EnterInstanceNoLock;
52 using ppapi::thunk::EnterResourceNoLock;
53 using ppapi::thunk::PPB_Graphics2D_API;
54 using ppapi::thunk::PPB_Graphics3D_API;
55 using ppapi::thunk::PPB_Instance_API;
62 const char kSerializationError[] = "Failed to convert a PostMessage "
63 "argument from a PP_Var to a Javascript value. It may have cycles or be of "
64 "an unsupported type.";
66 void RequestSurroundingText(PP_Instance instance) {
67 PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
69 return; // Instance has gone away while message was pending.
71 InstanceData* data = dispatcher->GetInstanceData(instance);
72 DCHECK(data); // Should have it, since we still have a dispatcher.
73 data->is_request_surrounding_text_pending = false;
74 if (!data->should_do_request_surrounding_text)
77 // Just fake out a RequestSurroundingText message to the proxy for the PPP
79 InterfaceProxy* proxy = dispatcher->GetInterfaceProxy(API_ID_PPP_TEXT_INPUT);
82 proxy->OnMessageReceived(PpapiMsg_PPPTextInput_RequestSurroundingText(
83 API_ID_PPP_TEXT_INPUT, instance,
84 PPB_Instance_Shared::kExtraCharsForTextInput));
89 PPB_Instance_Proxy::PPB_Instance_Proxy(Dispatcher* dispatcher)
90 : InterfaceProxy(dispatcher),
91 callback_factory_(this) {
94 PPB_Instance_Proxy::~PPB_Instance_Proxy() {
97 bool PPB_Instance_Proxy::OnMessageReceived(const IPC::Message& msg) {
98 // Prevent the dispatcher from going away during a call to ExecuteScript.
99 // This must happen OUTSIDE of ExecuteScript since the SerializedVars use
100 // the dispatcher upon return of the function (converting the
101 // SerializedVarReturnValue/OutParam to a SerializedVar in the destructor).
102 #if !defined(OS_NACL)
103 ScopedModuleReference death_grip(dispatcher());
107 IPC_BEGIN_MESSAGE_MAP(PPB_Instance_Proxy, msg)
108 #if !defined(OS_NACL)
109 // Plugin -> Host messages.
110 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_GetWindowObject,
111 OnHostMsgGetWindowObject)
112 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_GetOwnerElementObject,
113 OnHostMsgGetOwnerElementObject)
114 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_BindGraphics,
115 OnHostMsgBindGraphics)
116 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_IsFullFrame,
117 OnHostMsgIsFullFrame)
119 PpapiHostMsg_PPBInstance_GetAudioHardwareOutputSampleRate,
120 OnHostMsgGetAudioHardwareOutputSampleRate)
122 PpapiHostMsg_PPBInstance_GetAudioHardwareOutputBufferSize,
123 OnHostMsgGetAudioHardwareOutputBufferSize)
124 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_ExecuteScript,
125 OnHostMsgExecuteScript)
126 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_GetDefaultCharSet,
127 OnHostMsgGetDefaultCharSet)
128 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_PostMessage,
129 OnHostMsgPostMessage)
130 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_SetFullscreen,
131 OnHostMsgSetFullscreen)
132 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_GetScreenSize,
133 OnHostMsgGetScreenSize)
134 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_RequestInputEvents,
135 OnHostMsgRequestInputEvents)
136 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_ClearInputEvents,
137 OnHostMsgClearInputEvents)
138 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_LockMouse,
140 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_UnlockMouse,
141 OnHostMsgUnlockMouse)
142 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_SetCursor,
144 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_SetTextInputType,
145 OnHostMsgSetTextInputType)
146 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_UpdateCaretPosition,
147 OnHostMsgUpdateCaretPosition)
148 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_CancelCompositionText,
149 OnHostMsgCancelCompositionText)
150 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_UpdateSurroundingText,
151 OnHostMsgUpdateSurroundingText)
152 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_GetDocumentURL,
153 OnHostMsgGetDocumentURL)
154 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_ResolveRelativeToDocument,
155 OnHostMsgResolveRelativeToDocument)
156 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_DocumentCanRequest,
157 OnHostMsgDocumentCanRequest)
158 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_DocumentCanAccessDocument,
159 OnHostMsgDocumentCanAccessDocument)
160 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_GetPluginInstanceURL,
161 OnHostMsgGetPluginInstanceURL)
162 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_GetPluginReferrerURL,
163 OnHostMsgGetPluginReferrerURL)
164 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_SessionCreated,
165 OnHostMsgSessionCreated)
166 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_SessionMessage,
167 OnHostMsgSessionMessage)
168 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_SessionReady,
169 OnHostMsgSessionReady)
170 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_SessionClosed,
171 OnHostMsgSessionClosed)
172 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_SessionError,
173 OnHostMsgSessionError)
174 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_DeliverBlock,
175 OnHostMsgDeliverBlock)
176 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_DecoderInitializeDone,
177 OnHostMsgDecoderInitializeDone)
178 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_DecoderDeinitializeDone,
179 OnHostMsgDecoderDeinitializeDone)
180 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_DecoderResetDone,
181 OnHostMsgDecoderResetDone)
182 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_DeliverFrame,
183 OnHostMsgDeliverFrame)
184 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_DeliverSamples,
185 OnHostMsgDeliverSamples)
186 #endif // !defined(OS_NACL)
188 // Host -> Plugin messages.
189 IPC_MESSAGE_HANDLER(PpapiMsg_PPBInstance_MouseLockComplete,
190 OnPluginMsgMouseLockComplete)
192 IPC_MESSAGE_UNHANDLED(handled = false)
193 IPC_END_MESSAGE_MAP()
197 PP_Bool PPB_Instance_Proxy::BindGraphics(PP_Instance instance,
198 PP_Resource device) {
199 // If device is 0, pass a null HostResource. This signals the host to unbind
201 HostResource host_resource;
202 PP_Resource pp_resource = 0;
205 PpapiGlobals::Get()->GetResourceTracker()->GetResource(device);
206 if (!resource || resource->pp_instance() != instance)
208 host_resource = resource->host_resource();
209 pp_resource = resource->pp_resource();
211 // Passing 0 means unbinding all devices.
212 dispatcher()->Send(new PpapiHostMsg_PPBInstance_BindGraphics(
213 API_ID_PPB_INSTANCE, instance, 0));
217 // We need to pass different resource to Graphics 2D and 3D right now. Once
218 // 3D is migrated to the new design, we should be able to unify this.
219 EnterResourceNoLock<PPB_Graphics2D_API> enter_2d(device, false);
220 EnterResourceNoLock<PPB_Graphics3D_API> enter_3d(device, false);
221 if (enter_2d.succeeded()) {
222 dispatcher()->Send(new PpapiHostMsg_PPBInstance_BindGraphics(
223 API_ID_PPB_INSTANCE, instance, pp_resource));
225 } else if (enter_3d.succeeded()) {
226 dispatcher()->Send(new PpapiHostMsg_PPBInstance_BindGraphics(
227 API_ID_PPB_INSTANCE, instance, host_resource.host_resource()));
233 PP_Bool PPB_Instance_Proxy::IsFullFrame(PP_Instance instance) {
234 PP_Bool result = PP_FALSE;
235 dispatcher()->Send(new PpapiHostMsg_PPBInstance_IsFullFrame(
236 API_ID_PPB_INSTANCE, instance, &result));
240 const ViewData* PPB_Instance_Proxy::GetViewData(PP_Instance instance) {
241 InstanceData* data = static_cast<PluginDispatcher*>(dispatcher())->
242 GetInstanceData(instance);
248 PP_Bool PPB_Instance_Proxy::FlashIsFullscreen(PP_Instance instance) {
249 // This function is only used for proxying in the renderer process. It is not
250 // implemented in the plugin process.
255 PP_Var PPB_Instance_Proxy::GetWindowObject(PP_Instance instance) {
256 ReceiveSerializedVarReturnValue result;
257 dispatcher()->Send(new PpapiHostMsg_PPBInstance_GetWindowObject(
258 API_ID_PPB_INSTANCE, instance, &result));
259 return result.Return(dispatcher());
262 PP_Var PPB_Instance_Proxy::GetOwnerElementObject(PP_Instance instance) {
263 ReceiveSerializedVarReturnValue result;
264 dispatcher()->Send(new PpapiHostMsg_PPBInstance_GetOwnerElementObject(
265 API_ID_PPB_INSTANCE, instance, &result));
266 return result.Return(dispatcher());
269 PP_Var PPB_Instance_Proxy::ExecuteScript(PP_Instance instance,
272 ReceiveSerializedException se(dispatcher(), exception);
274 return PP_MakeUndefined();
276 ReceiveSerializedVarReturnValue result;
277 dispatcher()->Send(new PpapiHostMsg_PPBInstance_ExecuteScript(
278 API_ID_PPB_INSTANCE, instance,
279 SerializedVarSendInput(dispatcher(), script), &se, &result));
280 return result.Return(dispatcher());
283 uint32_t PPB_Instance_Proxy::GetAudioHardwareOutputSampleRate(
284 PP_Instance instance) {
285 uint32_t result = PP_AUDIOSAMPLERATE_NONE;
287 new PpapiHostMsg_PPBInstance_GetAudioHardwareOutputSampleRate(
288 API_ID_PPB_INSTANCE, instance, &result));
292 uint32_t PPB_Instance_Proxy::GetAudioHardwareOutputBufferSize(
293 PP_Instance instance) {
296 new PpapiHostMsg_PPBInstance_GetAudioHardwareOutputBufferSize(
297 API_ID_PPB_INSTANCE, instance, &result));
301 PP_Var PPB_Instance_Proxy::GetDefaultCharSet(PP_Instance instance) {
302 PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
304 return PP_MakeUndefined();
306 ReceiveSerializedVarReturnValue result;
307 dispatcher->Send(new PpapiHostMsg_PPBInstance_GetDefaultCharSet(
308 API_ID_PPB_INSTANCE, instance, &result));
309 return result.Return(dispatcher);
312 void PPB_Instance_Proxy::NumberOfFindResultsChanged(PP_Instance instance,
314 PP_Bool final_result) {
315 NOTIMPLEMENTED(); // Not proxied yet.
318 void PPB_Instance_Proxy::SelectedFindResultChanged(PP_Instance instance,
320 NOTIMPLEMENTED(); // Not proxied yet.
323 PP_Bool PPB_Instance_Proxy::IsFullscreen(PP_Instance instance) {
324 InstanceData* data = static_cast<PluginDispatcher*>(dispatcher())->
325 GetInstanceData(instance);
328 return PP_FromBool(data->view.is_fullscreen);
331 PP_Bool PPB_Instance_Proxy::SetFullscreen(PP_Instance instance,
332 PP_Bool fullscreen) {
333 PP_Bool result = PP_FALSE;
334 dispatcher()->Send(new PpapiHostMsg_PPBInstance_SetFullscreen(
335 API_ID_PPB_INSTANCE, instance, fullscreen, &result));
339 PP_Bool PPB_Instance_Proxy::GetScreenSize(PP_Instance instance,
341 PP_Bool result = PP_FALSE;
342 dispatcher()->Send(new PpapiHostMsg_PPBInstance_GetScreenSize(
343 API_ID_PPB_INSTANCE, instance, &result, size));
347 Resource* PPB_Instance_Proxy::GetSingletonResource(PP_Instance instance,
348 SingletonResourceID id) {
349 InstanceData* data = static_cast<PluginDispatcher*>(dispatcher())->
350 GetInstanceData(instance);
352 InstanceData::SingletonResourceMap::iterator it =
353 data->singleton_resources.find(id);
354 if (it != data->singleton_resources.end())
355 return it->second.get();
357 scoped_refptr<Resource> new_singleton;
358 Connection connection(PluginGlobals::Get()->GetBrowserSender(), dispatcher());
361 case BROKER_SINGLETON_ID:
362 new_singleton = new BrokerResource(connection, instance);
364 case EXTENSIONS_COMMON_SINGLETON_ID:
365 new_singleton = new ExtensionsCommonResource(connection, instance);
367 case FILE_MAPPING_SINGLETON_ID:
368 new_singleton = new FileMappingResource(connection, instance);
370 case GAMEPAD_SINGLETON_ID:
371 new_singleton = new GamepadResource(connection, instance);
373 case ISOLATED_FILESYSTEM_SINGLETON_ID:
375 new IsolatedFileSystemPrivateResource(connection, instance);
377 case NETWORK_PROXY_SINGLETON_ID:
378 new_singleton = new NetworkProxyResource(connection, instance);
380 case TRUETYPE_FONT_SINGLETON_ID:
381 new_singleton = new TrueTypeFontSingletonResource(connection, instance);
383 case UMA_SINGLETON_ID:
384 new_singleton = new UMAPrivateResource(connection, instance);
386 // Flash/trusted resources aren't needed for NaCl.
387 #if !defined(OS_NACL) && !defined(NACL_WIN64)
388 case BROWSER_FONT_SINGLETON_ID:
389 new_singleton = new BrowserFontSingletonResource(connection, instance);
391 case FLASH_CLIPBOARD_SINGLETON_ID:
392 new_singleton = new FlashClipboardResource(connection, instance);
394 case FLASH_FILE_SINGLETON_ID:
395 new_singleton = new FlashFileResource(connection, instance);
397 case FLASH_FULLSCREEN_SINGLETON_ID:
398 new_singleton = new FlashFullscreenResource(connection, instance);
400 case FLASH_SINGLETON_ID:
401 new_singleton = new FlashResource(connection, instance,
402 static_cast<PluginDispatcher*>(dispatcher()));
404 case PDF_SINGLETON_ID:
405 new_singleton = new PDFResource(connection, instance);
408 case BROWSER_FONT_SINGLETON_ID:
409 case FLASH_CLIPBOARD_SINGLETON_ID:
410 case FLASH_FILE_SINGLETON_ID:
411 case FLASH_FULLSCREEN_SINGLETON_ID:
412 case FLASH_SINGLETON_ID:
413 case PDF_SINGLETON_ID:
416 #endif // !defined(OS_NACL) && !defined(NACL_WIN64)
419 if (!new_singleton.get()) {
420 // Getting here implies that a constructor is missing in the above switch.
425 data->singleton_resources[id] = new_singleton;
426 return new_singleton.get();
429 int32_t PPB_Instance_Proxy::RequestInputEvents(PP_Instance instance,
430 uint32_t event_classes) {
431 dispatcher()->Send(new PpapiHostMsg_PPBInstance_RequestInputEvents(
432 API_ID_PPB_INSTANCE, instance, false, event_classes));
434 // We always register for the classes we can handle, this function validates
435 // the flags so we can notify it if anything was invalid, without requiring
437 return ValidateRequestInputEvents(false, event_classes);
440 int32_t PPB_Instance_Proxy::RequestFilteringInputEvents(
441 PP_Instance instance,
442 uint32_t event_classes) {
443 dispatcher()->Send(new PpapiHostMsg_PPBInstance_RequestInputEvents(
444 API_ID_PPB_INSTANCE, instance, true, event_classes));
446 // We always register for the classes we can handle, this function validates
447 // the flags so we can notify it if anything was invalid, without requiring
449 return ValidateRequestInputEvents(true, event_classes);
452 void PPB_Instance_Proxy::ClearInputEventRequest(PP_Instance instance,
453 uint32_t event_classes) {
454 dispatcher()->Send(new PpapiHostMsg_PPBInstance_ClearInputEvents(
455 API_ID_PPB_INSTANCE, instance, event_classes));
458 void PPB_Instance_Proxy::ZoomChanged(PP_Instance instance,
464 void PPB_Instance_Proxy::ZoomLimitsChanged(PP_Instance instance,
465 double minimum_factor,
466 double maximium_factor) {
471 PP_Var PPB_Instance_Proxy::GetDocumentURL(PP_Instance instance,
472 PP_URLComponents_Dev* components) {
473 ReceiveSerializedVarReturnValue result;
474 PP_URLComponents_Dev url_components;
475 dispatcher()->Send(new PpapiHostMsg_PPBInstance_GetDocumentURL(
476 API_ID_PPB_INSTANCE, instance, &url_components, &result));
478 *components = url_components;
479 return result.Return(dispatcher());
482 #if !defined(OS_NACL)
483 PP_Var PPB_Instance_Proxy::ResolveRelativeToDocument(
484 PP_Instance instance,
486 PP_URLComponents_Dev* components) {
487 ReceiveSerializedVarReturnValue result;
488 dispatcher()->Send(new PpapiHostMsg_PPBInstance_ResolveRelativeToDocument(
489 API_ID_PPB_INSTANCE, instance,
490 SerializedVarSendInput(dispatcher(), relative),
492 return PPB_URLUtil_Shared::ConvertComponentsAndReturnURL(
493 result.Return(dispatcher()),
497 PP_Bool PPB_Instance_Proxy::DocumentCanRequest(PP_Instance instance,
499 PP_Bool result = PP_FALSE;
500 dispatcher()->Send(new PpapiHostMsg_PPBInstance_DocumentCanRequest(
501 API_ID_PPB_INSTANCE, instance,
502 SerializedVarSendInput(dispatcher(), url),
507 PP_Bool PPB_Instance_Proxy::DocumentCanAccessDocument(PP_Instance instance,
508 PP_Instance target) {
509 PP_Bool result = PP_FALSE;
510 dispatcher()->Send(new PpapiHostMsg_PPBInstance_DocumentCanAccessDocument(
511 API_ID_PPB_INSTANCE, instance, target, &result));
515 PP_Var PPB_Instance_Proxy::GetPluginInstanceURL(
516 PP_Instance instance,
517 PP_URLComponents_Dev* components) {
518 ReceiveSerializedVarReturnValue result;
519 dispatcher()->Send(new PpapiHostMsg_PPBInstance_GetPluginInstanceURL(
520 API_ID_PPB_INSTANCE, instance, &result));
521 return PPB_URLUtil_Shared::ConvertComponentsAndReturnURL(
522 result.Return(dispatcher()),
526 PP_Var PPB_Instance_Proxy::GetPluginReferrerURL(
527 PP_Instance instance,
528 PP_URLComponents_Dev* components) {
529 ReceiveSerializedVarReturnValue result;
530 dispatcher()->Send(new PpapiHostMsg_PPBInstance_GetPluginReferrerURL(
531 API_ID_PPB_INSTANCE, instance, &result));
532 return PPB_URLUtil_Shared::ConvertComponentsAndReturnURL(
533 result.Return(dispatcher()),
537 void PPB_Instance_Proxy::SessionCreated(PP_Instance instance,
539 PP_Var web_session_id) {
540 dispatcher()->Send(new PpapiHostMsg_PPBInstance_SessionCreated(
544 SerializedVarSendInput(dispatcher(), web_session_id)));
547 void PPB_Instance_Proxy::SessionMessage(PP_Instance instance,
550 PP_Var destination_url) {
551 dispatcher()->Send(new PpapiHostMsg_PPBInstance_SessionMessage(
555 SerializedVarSendInput(dispatcher(), message),
556 SerializedVarSendInput(dispatcher(), destination_url)));
559 void PPB_Instance_Proxy::SessionReady(PP_Instance instance,
560 uint32_t session_id) {
561 dispatcher()->Send(new PpapiHostMsg_PPBInstance_SessionReady(
562 API_ID_PPB_INSTANCE, instance, session_id));
565 void PPB_Instance_Proxy::SessionClosed(PP_Instance instance,
566 uint32_t session_id) {
567 dispatcher()->Send(new PpapiHostMsg_PPBInstance_SessionClosed(
568 API_ID_PPB_INSTANCE, instance, session_id));
571 void PPB_Instance_Proxy::SessionError(PP_Instance instance,
574 int32_t system_code) {
575 dispatcher()->Send(new PpapiHostMsg_PPBInstance_SessionError(
576 API_ID_PPB_INSTANCE, instance, session_id, media_error, system_code));
579 void PPB_Instance_Proxy::DeliverBlock(PP_Instance instance,
580 PP_Resource decrypted_block,
581 const PP_DecryptedBlockInfo* block_info) {
582 PP_Resource decrypted_block_host_resource = 0;
584 if (decrypted_block) {
586 PpapiGlobals::Get()->GetResourceTracker()->GetResource(decrypted_block);
587 if (!object || object->pp_instance() != instance) {
591 decrypted_block_host_resource = object->host_resource().host_resource();
594 std::string serialized_block_info;
595 if (!SerializeBlockInfo(*block_info, &serialized_block_info)) {
601 new PpapiHostMsg_PPBInstance_DeliverBlock(API_ID_PPB_INSTANCE,
603 decrypted_block_host_resource,
604 serialized_block_info));
607 void PPB_Instance_Proxy::DecoderInitializeDone(
608 PP_Instance instance,
609 PP_DecryptorStreamType decoder_type,
613 new PpapiHostMsg_PPBInstance_DecoderInitializeDone(
621 void PPB_Instance_Proxy::DecoderDeinitializeDone(
622 PP_Instance instance,
623 PP_DecryptorStreamType decoder_type,
624 uint32_t request_id) {
626 new PpapiHostMsg_PPBInstance_DecoderDeinitializeDone(
633 void PPB_Instance_Proxy::DecoderResetDone(PP_Instance instance,
634 PP_DecryptorStreamType decoder_type,
635 uint32_t request_id) {
637 new PpapiHostMsg_PPBInstance_DecoderResetDone(
644 void PPB_Instance_Proxy::DeliverFrame(PP_Instance instance,
645 PP_Resource decrypted_frame,
646 const PP_DecryptedFrameInfo* frame_info) {
647 PP_Resource host_resource = 0;
648 if (decrypted_frame != 0) {
649 ResourceTracker* tracker = PpapiGlobals::Get()->GetResourceTracker();
650 Resource* object = tracker->GetResource(decrypted_frame);
652 if (!object || object->pp_instance() != instance) {
657 host_resource = object->host_resource().host_resource();
660 std::string serialized_frame_info;
661 if (!SerializeBlockInfo(*frame_info, &serialized_frame_info)) {
667 new PpapiHostMsg_PPBInstance_DeliverFrame(API_ID_PPB_INSTANCE,
670 serialized_frame_info));
673 void PPB_Instance_Proxy::DeliverSamples(
674 PP_Instance instance,
675 PP_Resource decrypted_samples,
676 const PP_DecryptedSampleInfo* sample_info) {
677 PP_Resource host_resource = 0;
678 if (decrypted_samples != 0) {
679 ResourceTracker* tracker = PpapiGlobals::Get()->GetResourceTracker();
680 Resource* object = tracker->GetResource(decrypted_samples);
682 if (!object || object->pp_instance() != instance) {
687 host_resource = object->host_resource().host_resource();
690 std::string serialized_sample_info;
691 if (!SerializeBlockInfo(*sample_info, &serialized_sample_info)) {
697 new PpapiHostMsg_PPBInstance_DeliverSamples(API_ID_PPB_INSTANCE,
700 serialized_sample_info));
702 #endif // !defined(OS_NACL)
704 void PPB_Instance_Proxy::PostMessage(PP_Instance instance,
706 dispatcher()->Send(new PpapiHostMsg_PPBInstance_PostMessage(
708 instance, SerializedVarSendInputShmem(dispatcher(), message,
712 PP_Bool PPB_Instance_Proxy::SetCursor(PP_Instance instance,
713 PP_MouseCursor_Type type,
715 const PP_Point* hot_spot) {
716 // Some of these parameters are important for security. This check is in the
717 // plugin process just for the convenience of the caller (since we don't
718 // bother returning errors from the other process with a sync message). The
719 // parameters will be validated again in the renderer.
720 if (!ValidateSetCursorParams(type, image, hot_spot))
723 HostResource image_host_resource;
725 Resource* cursor_image =
726 PpapiGlobals::Get()->GetResourceTracker()->GetResource(image);
727 if (!cursor_image || cursor_image->pp_instance() != instance)
729 image_host_resource = cursor_image->host_resource();
732 dispatcher()->Send(new PpapiHostMsg_PPBInstance_SetCursor(
733 API_ID_PPB_INSTANCE, instance, static_cast<int32_t>(type),
734 image_host_resource, hot_spot ? *hot_spot : PP_MakePoint(0, 0)));
738 int32_t PPB_Instance_Proxy::LockMouse(PP_Instance instance,
739 scoped_refptr<TrackedCallback> callback) {
740 // Save the mouse callback on the instance data.
741 InstanceData* data = static_cast<PluginDispatcher*>(dispatcher())->
742 GetInstanceData(instance);
744 return PP_ERROR_BADARGUMENT;
745 if (TrackedCallback::IsPending(data->mouse_lock_callback))
746 return PP_ERROR_INPROGRESS; // Already have a pending callback.
747 data->mouse_lock_callback = callback;
749 dispatcher()->Send(new PpapiHostMsg_PPBInstance_LockMouse(
750 API_ID_PPB_INSTANCE, instance));
751 return PP_OK_COMPLETIONPENDING;
754 void PPB_Instance_Proxy::UnlockMouse(PP_Instance instance) {
755 dispatcher()->Send(new PpapiHostMsg_PPBInstance_UnlockMouse(
756 API_ID_PPB_INSTANCE, instance));
759 void PPB_Instance_Proxy::SetTextInputType(PP_Instance instance,
760 PP_TextInput_Type type) {
761 CancelAnyPendingRequestSurroundingText(instance);
762 dispatcher()->Send(new PpapiHostMsg_PPBInstance_SetTextInputType(
763 API_ID_PPB_INSTANCE, instance, type));
766 void PPB_Instance_Proxy::UpdateCaretPosition(PP_Instance instance,
767 const PP_Rect& caret,
768 const PP_Rect& bounding_box) {
769 dispatcher()->Send(new PpapiHostMsg_PPBInstance_UpdateCaretPosition(
770 API_ID_PPB_INSTANCE, instance, caret, bounding_box));
773 void PPB_Instance_Proxy::CancelCompositionText(PP_Instance instance) {
774 CancelAnyPendingRequestSurroundingText(instance);
775 dispatcher()->Send(new PpapiHostMsg_PPBInstance_CancelCompositionText(
776 API_ID_PPB_INSTANCE, instance));
779 void PPB_Instance_Proxy::SelectionChanged(PP_Instance instance) {
780 // The "right" way to do this is to send the message to the host. However,
781 // all it will do is call RequestSurroundingText with a hardcoded number of
782 // characters in response, which is an entire IPC round-trip.
784 // We can avoid this round-trip by just implementing the
785 // RequestSurroundingText logic in the plugin process. If the logic in the
786 // host becomes more complex (like a more adaptive number of characters),
787 // we'll need to reevanuate whether we want to do the round trip instead.
789 // Be careful to post a task to avoid reentering the plugin.
792 static_cast<PluginDispatcher*>(dispatcher())->GetInstanceData(instance);
795 data->should_do_request_surrounding_text = true;
797 if (!data->is_request_surrounding_text_pending) {
798 base::MessageLoop::current()->PostTask(
800 RunWhileLocked(base::Bind(&RequestSurroundingText, instance)));
801 data->is_request_surrounding_text_pending = true;
805 void PPB_Instance_Proxy::UpdateSurroundingText(PP_Instance instance,
809 dispatcher()->Send(new PpapiHostMsg_PPBInstance_UpdateSurroundingText(
810 API_ID_PPB_INSTANCE, instance, text, caret, anchor));
813 #if !defined(OS_NACL)
814 void PPB_Instance_Proxy::OnHostMsgGetWindowObject(
815 PP_Instance instance,
816 SerializedVarReturnValue result) {
817 if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
819 EnterInstanceNoLock enter(instance);
820 if (enter.succeeded())
821 result.Return(dispatcher(), enter.functions()->GetWindowObject(instance));
824 void PPB_Instance_Proxy::OnHostMsgGetOwnerElementObject(
825 PP_Instance instance,
826 SerializedVarReturnValue result) {
827 if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
829 EnterInstanceNoLock enter(instance);
830 if (enter.succeeded()) {
831 result.Return(dispatcher(),
832 enter.functions()->GetOwnerElementObject(instance));
836 void PPB_Instance_Proxy::OnHostMsgBindGraphics(PP_Instance instance,
837 PP_Resource device) {
838 // Note that we ignroe the return value here. Otherwise, this would need to
839 // be a slow sync call, and the plugin side of the proxy will have already
840 // validated the resources, so we shouldn't see errors here that weren't
842 EnterInstanceNoLock enter(instance);
843 if (enter.succeeded())
844 enter.functions()->BindGraphics(instance, device);
847 void PPB_Instance_Proxy::OnHostMsgGetAudioHardwareOutputSampleRate(
848 PP_Instance instance, uint32_t* result) {
849 EnterInstanceNoLock enter(instance);
850 if (enter.succeeded())
851 *result = enter.functions()->GetAudioHardwareOutputSampleRate(instance);
854 void PPB_Instance_Proxy::OnHostMsgGetAudioHardwareOutputBufferSize(
855 PP_Instance instance, uint32_t* result) {
856 EnterInstanceNoLock enter(instance);
857 if (enter.succeeded())
858 *result = enter.functions()->GetAudioHardwareOutputBufferSize(instance);
861 void PPB_Instance_Proxy::OnHostMsgIsFullFrame(PP_Instance instance,
863 EnterInstanceNoLock enter(instance);
864 if (enter.succeeded())
865 *result = enter.functions()->IsFullFrame(instance);
868 void PPB_Instance_Proxy::OnHostMsgExecuteScript(
869 PP_Instance instance,
870 SerializedVarReceiveInput script,
871 SerializedVarOutParam out_exception,
872 SerializedVarReturnValue result) {
873 if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
875 EnterInstanceNoLock enter(instance);
879 if (dispatcher()->IsPlugin())
882 static_cast<HostDispatcher*>(dispatcher())->set_allow_plugin_reentrancy();
884 result.Return(dispatcher(), enter.functions()->ExecuteScript(
886 script.Get(dispatcher()),
887 out_exception.OutParam(dispatcher())));
890 void PPB_Instance_Proxy::OnHostMsgGetDefaultCharSet(
891 PP_Instance instance,
892 SerializedVarReturnValue result) {
893 if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
895 EnterInstanceNoLock enter(instance);
896 if (enter.succeeded())
897 result.Return(dispatcher(), enter.functions()->GetDefaultCharSet(instance));
900 void PPB_Instance_Proxy::OnHostMsgSetFullscreen(PP_Instance instance,
903 EnterInstanceNoLock enter(instance);
904 if (enter.succeeded())
905 *result = enter.functions()->SetFullscreen(instance, fullscreen);
909 void PPB_Instance_Proxy::OnHostMsgGetScreenSize(PP_Instance instance,
912 EnterInstanceNoLock enter(instance);
913 if (enter.succeeded())
914 *result = enter.functions()->GetScreenSize(instance, size);
917 void PPB_Instance_Proxy::OnHostMsgRequestInputEvents(PP_Instance instance,
919 uint32_t event_classes) {
920 EnterInstanceNoLock enter(instance);
921 if (enter.succeeded()) {
923 enter.functions()->RequestFilteringInputEvents(instance, event_classes);
925 enter.functions()->RequestInputEvents(instance, event_classes);
929 void PPB_Instance_Proxy::OnHostMsgClearInputEvents(PP_Instance instance,
930 uint32_t event_classes) {
931 EnterInstanceNoLock enter(instance);
932 if (enter.succeeded())
933 enter.functions()->ClearInputEventRequest(instance, event_classes);
936 void PPB_Instance_Proxy::OnHostMsgPostMessage(
937 PP_Instance instance,
938 SerializedVarReceiveInput message) {
939 EnterInstanceNoLock enter(instance);
940 if (!message.is_valid_var()) {
941 PpapiGlobals::Get()->LogWithSource(
942 instance, PP_LOGLEVEL_ERROR, std::string(), kSerializationError);
946 if (enter.succeeded())
947 enter.functions()->PostMessage(instance,
948 message.GetForInstance(dispatcher(),
952 void PPB_Instance_Proxy::OnHostMsgLockMouse(PP_Instance instance) {
953 // Need to be careful to always issue the callback.
954 pp::CompletionCallback cb = callback_factory_.NewCallback(
955 &PPB_Instance_Proxy::MouseLockCompleteInHost, instance);
957 EnterInstanceNoLock enter(instance, cb.pp_completion_callback());
958 if (enter.succeeded())
959 enter.SetResult(enter.functions()->LockMouse(instance, enter.callback()));
962 void PPB_Instance_Proxy::OnHostMsgUnlockMouse(PP_Instance instance) {
963 EnterInstanceNoLock enter(instance);
964 if (enter.succeeded())
965 enter.functions()->UnlockMouse(instance);
968 void PPB_Instance_Proxy::OnHostMsgGetDocumentURL(
969 PP_Instance instance,
970 PP_URLComponents_Dev* components,
971 SerializedVarReturnValue result) {
972 if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
974 EnterInstanceNoLock enter(instance);
975 if (enter.succeeded()) {
976 PP_Var document_url = enter.functions()->GetDocumentURL(instance,
978 result.Return(dispatcher(), document_url);
982 void PPB_Instance_Proxy::OnHostMsgResolveRelativeToDocument(
983 PP_Instance instance,
984 SerializedVarReceiveInput relative,
985 SerializedVarReturnValue result) {
986 if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
988 EnterInstanceNoLock enter(instance);
989 if (enter.succeeded()) {
990 result.Return(dispatcher(),
991 enter.functions()->ResolveRelativeToDocument(
992 instance, relative.Get(dispatcher()), NULL));
996 void PPB_Instance_Proxy::OnHostMsgDocumentCanRequest(
997 PP_Instance instance,
998 SerializedVarReceiveInput url,
1000 if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
1002 EnterInstanceNoLock enter(instance);
1003 if (enter.succeeded()) {
1004 *result = enter.functions()->DocumentCanRequest(instance,
1005 url.Get(dispatcher()));
1009 void PPB_Instance_Proxy::OnHostMsgDocumentCanAccessDocument(PP_Instance active,
1012 if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
1014 EnterInstanceNoLock enter(active);
1015 if (enter.succeeded())
1016 *result = enter.functions()->DocumentCanAccessDocument(active, target);
1019 void PPB_Instance_Proxy::OnHostMsgGetPluginInstanceURL(
1020 PP_Instance instance,
1021 SerializedVarReturnValue result) {
1022 if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
1024 EnterInstanceNoLock enter(instance);
1025 if (enter.succeeded()) {
1026 result.Return(dispatcher(),
1027 enter.functions()->GetPluginInstanceURL(instance, NULL));
1031 void PPB_Instance_Proxy::OnHostMsgGetPluginReferrerURL(
1032 PP_Instance instance,
1033 SerializedVarReturnValue result) {
1034 if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
1036 EnterInstanceNoLock enter(instance);
1037 if (enter.succeeded()) {
1038 result.Return(dispatcher(),
1039 enter.functions()->GetPluginReferrerURL(instance, NULL));
1043 void PPB_Instance_Proxy::OnHostMsgSessionCreated(
1044 PP_Instance instance,
1045 uint32_t session_id,
1046 SerializedVarReceiveInput web_session_id) {
1047 if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
1049 EnterInstanceNoLock enter(instance);
1050 if (enter.succeeded()) {
1051 enter.functions()->SessionCreated(
1052 instance, session_id, web_session_id.Get(dispatcher()));
1056 void PPB_Instance_Proxy::OnHostMsgSessionMessage(
1057 PP_Instance instance,
1058 uint32_t session_id,
1059 SerializedVarReceiveInput message,
1060 SerializedVarReceiveInput destination_url) {
1061 if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
1063 EnterInstanceNoLock enter(instance);
1064 if (enter.succeeded()) {
1065 enter.functions()->SessionMessage(instance,
1067 message.Get(dispatcher()),
1068 destination_url.Get(dispatcher()));
1072 void PPB_Instance_Proxy::OnHostMsgSessionReady(PP_Instance instance,
1073 uint32_t session_id) {
1074 if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
1076 EnterInstanceNoLock enter(instance);
1077 if (enter.succeeded()) {
1078 enter.functions()->SessionReady(instance, session_id);
1082 void PPB_Instance_Proxy::OnHostMsgSessionClosed(PP_Instance instance,
1083 uint32_t session_id) {
1084 if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
1086 EnterInstanceNoLock enter(instance);
1087 if (enter.succeeded()) {
1088 enter.functions()->SessionClosed(instance, session_id);
1092 void PPB_Instance_Proxy::OnHostMsgSessionError(PP_Instance instance,
1093 uint32_t session_id,
1094 int32_t media_error,
1095 int32_t system_error) {
1096 if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
1098 EnterInstanceNoLock enter(instance);
1099 if (enter.succeeded()) {
1100 enter.functions()->SessionError(
1101 instance, session_id, media_error, system_error);
1105 void PPB_Instance_Proxy::OnHostMsgDeliverBlock(
1106 PP_Instance instance,
1107 PP_Resource decrypted_block,
1108 const std::string& serialized_block_info) {
1109 if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
1111 PP_DecryptedBlockInfo block_info;
1112 if (!DeserializeBlockInfo(serialized_block_info, &block_info))
1115 EnterInstanceNoLock enter(instance);
1116 if (enter.succeeded())
1117 enter.functions()->DeliverBlock(instance, decrypted_block, &block_info);
1120 void PPB_Instance_Proxy::OnHostMsgDecoderInitializeDone(
1121 PP_Instance instance,
1122 PP_DecryptorStreamType decoder_type,
1123 uint32_t request_id,
1125 if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
1127 EnterInstanceNoLock enter(instance);
1128 if (enter.succeeded()) {
1129 enter.functions()->DecoderInitializeDone(instance,
1136 void PPB_Instance_Proxy::OnHostMsgDecoderDeinitializeDone(
1137 PP_Instance instance,
1138 PP_DecryptorStreamType decoder_type,
1139 uint32_t request_id) {
1140 if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
1142 EnterInstanceNoLock enter(instance);
1143 if (enter.succeeded())
1144 enter.functions()->DecoderDeinitializeDone(instance,
1149 void PPB_Instance_Proxy::OnHostMsgDecoderResetDone(
1150 PP_Instance instance,
1151 PP_DecryptorStreamType decoder_type,
1152 uint32_t request_id) {
1153 if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
1155 EnterInstanceNoLock enter(instance);
1156 if (enter.succeeded())
1157 enter.functions()->DecoderResetDone(instance, decoder_type, request_id);
1160 void PPB_Instance_Proxy::OnHostMsgDeliverFrame(
1161 PP_Instance instance,
1162 PP_Resource decrypted_frame,
1163 const std::string& serialized_frame_info) {
1164 if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
1166 PP_DecryptedFrameInfo frame_info;
1167 if (!DeserializeBlockInfo(serialized_frame_info, &frame_info))
1170 EnterInstanceNoLock enter(instance);
1171 if (enter.succeeded())
1172 enter.functions()->DeliverFrame(instance, decrypted_frame, &frame_info);
1175 void PPB_Instance_Proxy::OnHostMsgDeliverSamples(
1176 PP_Instance instance,
1177 PP_Resource audio_frames,
1178 const std::string& serialized_sample_info) {
1179 if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
1181 PP_DecryptedSampleInfo sample_info;
1182 if (!DeserializeBlockInfo(serialized_sample_info, &sample_info))
1185 EnterInstanceNoLock enter(instance);
1186 if (enter.succeeded())
1187 enter.functions()->DeliverSamples(instance, audio_frames, &sample_info);
1190 void PPB_Instance_Proxy::OnHostMsgSetCursor(
1191 PP_Instance instance,
1193 const ppapi::HostResource& custom_image,
1194 const PP_Point& hot_spot) {
1195 // This API serves PPB_CursorControl_Dev and PPB_MouseCursor, so is public.
1196 EnterInstanceNoLock enter(instance);
1197 if (enter.succeeded()) {
1198 enter.functions()->SetCursor(
1199 instance, static_cast<PP_MouseCursor_Type>(type),
1200 custom_image.host_resource(), &hot_spot);
1204 void PPB_Instance_Proxy::OnHostMsgSetTextInputType(PP_Instance instance,
1205 PP_TextInput_Type type) {
1206 if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
1208 EnterInstanceNoLock enter(instance);
1209 if (enter.succeeded())
1210 enter.functions()->SetTextInputType(instance, type);
1213 void PPB_Instance_Proxy::OnHostMsgUpdateCaretPosition(
1214 PP_Instance instance,
1215 const PP_Rect& caret,
1216 const PP_Rect& bounding_box) {
1217 if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
1219 EnterInstanceNoLock enter(instance);
1220 if (enter.succeeded())
1221 enter.functions()->UpdateCaretPosition(instance, caret, bounding_box);
1224 void PPB_Instance_Proxy::OnHostMsgCancelCompositionText(PP_Instance instance) {
1225 EnterInstanceNoLock enter(instance);
1226 if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
1228 if (enter.succeeded())
1229 enter.functions()->CancelCompositionText(instance);
1232 void PPB_Instance_Proxy::OnHostMsgUpdateSurroundingText(
1233 PP_Instance instance,
1234 const std::string& text,
1237 if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
1239 EnterInstanceNoLock enter(instance);
1240 if (enter.succeeded()) {
1241 enter.functions()->UpdateSurroundingText(instance, text.c_str(), caret,
1245 #endif // !defined(OS_NACL)
1247 void PPB_Instance_Proxy::OnPluginMsgMouseLockComplete(PP_Instance instance,
1249 if (!dispatcher()->IsPlugin())
1252 // Save the mouse callback on the instance data.
1253 InstanceData* data = static_cast<PluginDispatcher*>(dispatcher())->
1254 GetInstanceData(instance);
1256 return; // Instance was probably deleted.
1257 if (!TrackedCallback::IsPending(data->mouse_lock_callback)) {
1261 data->mouse_lock_callback->Run(result);
1264 #if !defined(OS_NACL)
1265 void PPB_Instance_Proxy::MouseLockCompleteInHost(int32_t result,
1266 PP_Instance instance) {
1267 dispatcher()->Send(new PpapiMsg_PPBInstance_MouseLockComplete(
1268 API_ID_PPB_INSTANCE, instance, result));
1270 #endif // !defined(OS_NACL)
1272 void PPB_Instance_Proxy::CancelAnyPendingRequestSurroundingText(
1273 PP_Instance instance) {
1274 InstanceData* data = static_cast<PluginDispatcher*>(dispatcher())->
1275 GetInstanceData(instance);
1277 return; // Instance was probably deleted.
1278 data->should_do_request_surrounding_text = false;
1281 } // namespace proxy
1282 } // namespace ppapi