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