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 "content/renderer/pepper/pepper_plugin_delegate_impl.h"
12 #include "base/bind.h"
13 #include "base/callback.h"
14 #include "base/command_line.h"
15 #include "base/files/file_path.h"
16 #include "base/files/file_util_proxy.h"
17 #include "base/logging.h"
18 #include "base/strings/string_split.h"
19 #include "base/sync_socket.h"
20 #include "base/time.h"
21 #include "content/common/child_process.h"
22 #include "content/common/child_process_messages.h"
23 #include "content/common/child_thread.h"
24 #include "content/common/fileapi/file_system_dispatcher.h"
25 #include "content/common/fileapi/file_system_messages.h"
26 #include "content/common/gpu/client/context_provider_command_buffer.h"
27 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
28 #include "content/common/pepper_messages.h"
29 #include "content/common/pepper_plugin_registry.h"
30 #include "content/common/quota_dispatcher.h"
31 #include "content/common/sandbox_util.h"
32 #include "content/common/view_messages.h"
33 #include "content/public/common/content_switches.h"
34 #include "content/public/common/context_menu_params.h"
35 #include "content/public/common/media_stream_request.h"
36 #include "content/public/common/referrer.h"
37 #include "content/public/renderer/content_renderer_client.h"
38 #include "content/public/renderer/renderer_restrict_dispatch_group.h"
39 #include "content/renderer/gamepad_shared_memory_reader.h"
40 #include "content/renderer/media/media_stream_dispatcher.h"
41 #include "content/renderer/media/pepper_platform_video_decoder_impl.h"
42 #include "content/renderer/p2p/socket_dispatcher.h"
43 #include "content/renderer/pepper/content_renderer_pepper_host_factory.h"
44 #include "content/renderer/pepper/pepper_broker_impl.h"
45 #include "content/renderer/pepper/pepper_device_enumeration_event_handler.h"
46 #include "content/renderer/pepper/pepper_file_system_host.h"
47 #include "content/renderer/pepper/pepper_hung_plugin_filter.h"
48 #include "content/renderer/pepper/pepper_in_process_resource_creation.h"
49 #include "content/renderer/pepper/pepper_platform_audio_input_impl.h"
50 #include "content/renderer/pepper/pepper_platform_audio_output_impl.h"
51 #include "content/renderer/pepper/pepper_platform_context_3d_impl.h"
52 #include "content/renderer/pepper/pepper_platform_image_2d_impl.h"
53 #include "content/renderer/pepper/pepper_platform_video_capture_impl.h"
54 #include "content/renderer/pepper/pepper_proxy_channel_delegate_impl.h"
55 #include "content/renderer/pepper/renderer_ppapi_host_impl.h"
56 #include "content/renderer/render_thread_impl.h"
57 #include "content/renderer/render_view_impl.h"
58 #include "content/renderer/render_widget_fullscreen_pepper.h"
59 #include "content/renderer/webplugin_delegate_proxy.h"
60 #include "googleurl/src/gurl.h"
61 #include "ipc/ipc_channel_handle.h"
62 #include "media/base/audio_hardware_config.h"
63 #include "media/video/capture/video_capture_proxy.h"
64 #include "ppapi/c/dev/pp_video_dev.h"
65 #include "ppapi/c/pp_errors.h"
66 #include "ppapi/c/private/ppb_flash.h"
67 #include "ppapi/host/ppapi_host.h"
68 #include "ppapi/proxy/host_dispatcher.h"
69 #include "ppapi/proxy/ppapi_messages.h"
70 #include "ppapi/shared_impl/file_path.h"
71 #include "ppapi/shared_impl/platform_file.h"
72 #include "ppapi/shared_impl/ppapi_permissions.h"
73 #include "ppapi/shared_impl/ppapi_preferences.h"
74 #include "ppapi/shared_impl/ppb_device_ref_shared.h"
75 #include "ppapi/thunk/enter.h"
76 #include "ppapi/thunk/ppb_tcp_server_socket_private_api.h"
77 #include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h"
78 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
79 #include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h"
80 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
81 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
82 #include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginContainer.h"
83 #include "third_party/WebKit/Source/WebKit/chromium/public/WebScreenInfo.h"
84 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
85 #include "ui/gfx/size.h"
86 #include "webkit/fileapi/file_system_callback_dispatcher.h"
87 #include "webkit/plugins/npapi/webplugin.h"
88 #include "webkit/plugins/ppapi/plugin_module.h"
89 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
90 #include "webkit/plugins/ppapi/ppapi_webplugin_impl.h"
91 #include "webkit/plugins/ppapi/ppb_tcp_server_socket_private_impl.h"
92 #include "webkit/plugins/ppapi/ppb_tcp_socket_private_impl.h"
93 #include "webkit/plugins/ppapi/resource_helper.h"
94 #include "webkit/plugins/webplugininfo.h"
96 using WebKit::WebView
;
97 using WebKit::WebFrame
;
103 // This class wraps a dispatcher and has the same lifetime. A dispatcher has
104 // the same lifetime as a plugin module, which is longer than any particular
105 // RenderView or plugin instance.
106 class HostDispatcherWrapper
107 : public webkit::ppapi::PluginDelegate::OutOfProcessProxy
{
109 HostDispatcherWrapper(webkit::ppapi::PluginModule
* module
,
110 base::ProcessId peer_pid
,
112 const ppapi::PpapiPermissions
& perms
,
116 plugin_child_id_(plugin_child_id
),
118 is_external_(is_external
) {
120 virtual ~HostDispatcherWrapper() {}
122 bool Init(const IPC::ChannelHandle
& channel_handle
,
123 PP_GetInterface_Func local_get_interface
,
124 const ppapi::Preferences
& preferences
,
125 PepperHungPluginFilter
* filter
) {
126 if (channel_handle
.name
.empty())
129 #if defined(OS_POSIX)
130 DCHECK_NE(-1, channel_handle
.socket
.fd
);
131 if (channel_handle
.socket
.fd
== -1)
135 dispatcher_delegate_
.reset(new PepperProxyChannelDelegateImpl
);
136 dispatcher_
.reset(new ppapi::proxy::HostDispatcher(
137 module_
->pp_module(), local_get_interface
, filter
, permissions_
));
139 if (!dispatcher_
->InitHostWithChannel(dispatcher_delegate_
.get(),
145 dispatcher_delegate_
.reset();
148 dispatcher_
->channel()->SetRestrictDispatchChannelGroup(
149 kRendererRestrictDispatchGroup_Pepper
);
153 // OutOfProcessProxy implementation.
154 virtual const void* GetProxiedInterface(const char* name
) OVERRIDE
{
155 return dispatcher_
->GetProxiedInterface(name
);
157 virtual void AddInstance(PP_Instance instance
) OVERRIDE
{
158 ppapi::proxy::HostDispatcher::SetForInstance(instance
, dispatcher_
.get());
160 RendererPpapiHostImpl
* host
=
161 RendererPpapiHostImpl::GetForPPInstance(instance
);
162 // TODO(brettw) remove this null check when the old-style pepper-based
163 // browser tag is removed from this file. Getting this notification should
164 // always give us an instance we can find in the map otherwise, but that
165 // isn't true for browser tag support.
167 RenderView
* render_view
= host
->GetRenderViewForInstance(instance
);
168 webkit::ppapi::PluginInstance
* plugin_instance
=
169 host
->GetPluginInstance(instance
);
170 render_view
->Send(new ViewHostMsg_DidCreateOutOfProcessPepperInstance(
173 PepperRendererInstanceData(
174 0, // The render process id will be supplied in the browser.
175 render_view
->GetRoutingID(),
176 plugin_instance
->container()->element().document().url(),
177 plugin_instance
->plugin_url()),
181 virtual void RemoveInstance(PP_Instance instance
) OVERRIDE
{
182 ppapi::proxy::HostDispatcher::RemoveForInstance(instance
);
184 RendererPpapiHostImpl
* host
=
185 RendererPpapiHostImpl::GetForPPInstance(instance
);
186 // TODO(brettw) remove null check as described in AddInstance.
188 RenderView
* render_view
= host
->GetRenderViewForInstance(instance
);
189 render_view
->Send(new ViewHostMsg_DidDeleteOutOfProcessPepperInstance(
195 virtual base::ProcessId
GetPeerProcessId() OVERRIDE
{
199 ppapi::proxy::HostDispatcher
* dispatcher() { return dispatcher_
.get(); }
202 webkit::ppapi::PluginModule
* module_
;
204 base::ProcessId peer_pid_
;
206 // ID that the browser process uses to idetify the child process for the
207 // plugin. This isn't directly useful from our process (the renderer) except
208 // in messages to the browser to disambiguate plugins.
209 int plugin_child_id_
;
211 ppapi::PpapiPermissions permissions_
;
214 scoped_ptr
<ppapi::proxy::HostDispatcher
> dispatcher_
;
215 scoped_ptr
<ppapi::proxy::ProxyChannel::Delegate
> dispatcher_delegate_
;
218 class QuotaCallbackTranslator
: public QuotaDispatcher::Callback
{
220 typedef webkit::ppapi::PluginDelegate::AvailableSpaceCallback PluginCallback
;
221 explicit QuotaCallbackTranslator(const PluginCallback
& cb
) : callback_(cb
) {}
222 virtual void DidQueryStorageUsageAndQuota(int64 usage
, int64 quota
) OVERRIDE
{
223 callback_
.Run(std::max(static_cast<int64
>(0), quota
- usage
));
225 virtual void DidGrantStorageQuota(int64 granted_quota
) OVERRIDE
{
228 virtual void DidFail(quota::QuotaStatusCode error
) OVERRIDE
{
232 PluginCallback callback_
;
235 class PluginInstanceLockTarget
: public MouseLockDispatcher::LockTarget
{
237 PluginInstanceLockTarget(webkit::ppapi::PluginInstance
* plugin
)
240 virtual void OnLockMouseACK(bool succeeded
) OVERRIDE
{
241 plugin_
->OnLockMouseACK(succeeded
);
244 virtual void OnMouseLockLost() OVERRIDE
{
245 plugin_
->OnMouseLockLost();
248 virtual bool HandleMouseLockedInputEvent(
249 const WebKit::WebMouseEvent
&event
) OVERRIDE
{
250 plugin_
->HandleMouseLockedInputEvent(event
);
255 webkit::ppapi::PluginInstance
* plugin_
;
258 void DoNotifyCloseFile(int file_open_id
, base::PlatformFileError
/* unused */) {
259 ChildThread::current()->file_system_dispatcher()->NotifyCloseFile(
263 class AsyncOpenFileSystemURLCallbackTranslator
264 : public fileapi::FileSystemCallbackDispatcher
{
266 AsyncOpenFileSystemURLCallbackTranslator(
267 const webkit::ppapi::PluginDelegate::AsyncOpenFileSystemURLCallback
&
269 : callback_(callback
) {
272 virtual ~AsyncOpenFileSystemURLCallbackTranslator() {}
274 virtual void DidSucceed() OVERRIDE
{
277 virtual void DidReadMetadata(
278 const base::PlatformFileInfo
& file_info
,
279 const base::FilePath
& platform_path
) OVERRIDE
{
282 virtual void DidCreateSnapshotFile(
283 const base::PlatformFileInfo
& file_info
,
284 const base::FilePath
& platform_path
) OVERRIDE
{
287 virtual void DidReadDirectory(
288 const std::vector
<base::FileUtilProxy::Entry
>& entries
,
289 bool has_more
) OVERRIDE
{
292 virtual void DidOpenFileSystem(const std::string
& name
,
293 const GURL
& root
) OVERRIDE
{
297 virtual void DidFail(base::PlatformFileError error_code
) OVERRIDE
{
298 base::PlatformFile invalid_file
= base::kInvalidPlatformFileValue
;
299 callback_
.Run(error_code
,
300 base::PassPlatformFile(&invalid_file
),
301 quota::kQuotaLimitTypeUnknown
,
302 webkit::ppapi::PluginDelegate::NotifyCloseFileCallback());
305 virtual void DidWrite(int64 bytes
, bool complete
) OVERRIDE
{
309 virtual void DidOpenFile(base::PlatformFile file
,
311 quota::QuotaLimitType quota_policy
) OVERRIDE
{
312 callback_
.Run(base::PLATFORM_FILE_OK
,
313 base::PassPlatformFile(&file
),
315 base::Bind(&DoNotifyCloseFile
, file_open_id
));
316 // Make sure we won't leak file handle if the requester has died.
317 if (file
!= base::kInvalidPlatformFileValue
) {
318 base::FileUtilProxy::Close(
319 RenderThreadImpl::current()->GetFileThreadMessageLoopProxy(), file
,
320 base::Bind(&DoNotifyCloseFile
, file_open_id
));
325 webkit::ppapi::PluginDelegate::AsyncOpenFileSystemURLCallback callback_
;
328 void CreateHostForInProcessModule(RenderViewImpl
* render_view
,
329 webkit::ppapi::PluginModule
* module
,
330 const webkit::WebPluginInfo
& webplugin_info
) {
331 // First time an in-process plugin was used, make a host for it.
332 const PepperPluginInfo
* info
=
333 PepperPluginRegistry::GetInstance()->GetInfoForPlugin(webplugin_info
);
334 DCHECK(!info
->is_out_of_process
);
336 ppapi::PpapiPermissions
perms(
337 PepperPluginRegistry::GetInstance()->GetInfoForPlugin(
338 webplugin_info
)->permissions
);
339 RendererPpapiHostImpl
* host_impl
=
340 RendererPpapiHostImpl::CreateOnModuleForInProcess(
342 render_view
->PpapiPluginCreated(host_impl
);
345 template <typename HostType
>
346 const HostType
* GetRendererResourceHost(
347 PP_Instance instance
, PP_Resource resource
) {
348 const ppapi::host::PpapiHost
* ppapi_host
=
349 RendererPpapiHost::GetForPPInstance(instance
)->GetPpapiHost();
350 if (!resource
|| !ppapi_host
)
352 return static_cast<HostType
*>(ppapi_host
->GetResourceHost(resource
));
357 PepperPluginDelegateImpl::PepperPluginDelegateImpl(RenderViewImpl
* render_view
)
358 : RenderViewObserver(render_view
),
359 render_view_(render_view
),
360 focused_plugin_(NULL
),
361 last_mouse_event_target_(NULL
),
362 device_enumeration_event_handler_(
363 new PepperDeviceEnumerationEventHandler()) {
366 PepperPluginDelegateImpl::~PepperPluginDelegateImpl() {
367 DCHECK(mouse_lock_instances_
.empty());
370 WebKit::WebPlugin
* PepperPluginDelegateImpl::CreatePepperWebPlugin(
371 const webkit::WebPluginInfo
& webplugin_info
,
372 const WebKit::WebPluginParams
& params
) {
373 bool pepper_plugin_was_registered
= false;
374 scoped_refptr
<webkit::ppapi::PluginModule
> pepper_module(
375 CreatePepperPluginModule(webplugin_info
, &pepper_plugin_was_registered
));
377 if (pepper_plugin_was_registered
) {
380 return new webkit::ppapi::WebPluginImpl(
381 pepper_module
.get(), params
, AsWeakPtr());
387 scoped_refptr
<webkit::ppapi::PluginModule
>
388 PepperPluginDelegateImpl::CreatePepperPluginModule(
389 const webkit::WebPluginInfo
& webplugin_info
,
390 bool* pepper_plugin_was_registered
) {
391 *pepper_plugin_was_registered
= true;
393 // See if a module has already been loaded for this plugin.
394 base::FilePath
path(webplugin_info
.path
);
395 scoped_refptr
<webkit::ppapi::PluginModule
> module
=
396 PepperPluginRegistry::GetInstance()->GetLiveModule(path
);
398 if (!module
->GetEmbedderState()) {
399 // If the module exists and no embedder state was associated with it,
400 // then the module was one of the ones preloaded and is an in-process
401 // plugin. We need to associate our host state with it.
402 CreateHostForInProcessModule(render_view_
, module
, webplugin_info
);
407 // In-process plugins will have always been created up-front to avoid the
408 // sandbox restrictions. So getting here implies it doesn't exist or should
409 // be out of process.
410 const PepperPluginInfo
* info
=
411 PepperPluginRegistry::GetInstance()->GetInfoForPlugin(webplugin_info
);
413 *pepper_plugin_was_registered
= false;
414 return scoped_refptr
<webkit::ppapi::PluginModule
>();
415 } else if (!info
->is_out_of_process
) {
416 // In-process plugin not preloaded, it probably couldn't be initialized.
417 return scoped_refptr
<webkit::ppapi::PluginModule
>();
420 ppapi::PpapiPermissions permissions
=
421 ppapi::PpapiPermissions::GetForCommandLine(info
->permissions
);
423 // Out of process: have the browser start the plugin process for us.
424 IPC::ChannelHandle channel_handle
;
425 base::ProcessId peer_pid
;
426 int plugin_child_id
= 0;
427 render_view_
->Send(new ViewHostMsg_OpenChannelToPepperPlugin(
428 path
, &channel_handle
, &peer_pid
, &plugin_child_id
));
429 if (channel_handle
.name
.empty()) {
430 // Couldn't be initialized.
431 return scoped_refptr
<webkit::ppapi::PluginModule
>();
434 // AddLiveModule must be called before any early returns since the
435 // module's destructor will remove itself.
436 module
= new webkit::ppapi::PluginModule(
438 PepperPluginRegistry::GetInstance(),
440 PepperPluginRegistry::GetInstance()->AddLiveModule(path
, module
);
442 if (!CreateOutOfProcessModule(module
,
448 false)) // is_external = false
449 return scoped_refptr
<webkit::ppapi::PluginModule
>();
454 RendererPpapiHost
* PepperPluginDelegateImpl::CreateExternalPluginModule(
455 scoped_refptr
<webkit::ppapi::PluginModule
> module
,
456 const base::FilePath
& path
,
457 ppapi::PpapiPermissions permissions
,
458 const IPC::ChannelHandle
& channel_handle
,
459 base::ProcessId peer_pid
,
460 int plugin_child_id
) {
461 // We don't call PepperPluginRegistry::AddLiveModule, as this module is
462 // managed externally.
463 return CreateOutOfProcessModule(module
,
469 true); // is_external = true
472 scoped_refptr
<PepperBrokerImpl
> PepperPluginDelegateImpl::CreateBroker(
473 webkit::ppapi::PluginModule
* plugin_module
) {
474 DCHECK(plugin_module
);
475 DCHECK(!plugin_module
->GetBroker());
477 // The broker path is the same as the plugin.
478 const base::FilePath
& broker_path
= plugin_module
->path();
480 scoped_refptr
<PepperBrokerImpl
> broker
=
481 new PepperBrokerImpl(plugin_module
, this);
484 pending_connect_broker_
.Add(new scoped_refptr
<PepperBrokerImpl
>(broker
));
486 // Have the browser start the broker process for us.
488 new ViewHostMsg_OpenChannelToPpapiBroker(render_view_
->routing_id(),
491 if (!render_view_
->Send(msg
)) {
492 pending_connect_broker_
.Remove(request_id
);
493 return scoped_refptr
<PepperBrokerImpl
>();
499 RendererPpapiHost
* PepperPluginDelegateImpl::CreateOutOfProcessModule(
500 webkit::ppapi::PluginModule
* module
,
501 const base::FilePath
& path
,
502 ppapi::PpapiPermissions permissions
,
503 const IPC::ChannelHandle
& channel_handle
,
504 base::ProcessId peer_pid
,
507 scoped_refptr
<PepperHungPluginFilter
> hung_filter(
508 new PepperHungPluginFilter(path
,
509 render_view_
->routing_id(),
511 scoped_ptr
<HostDispatcherWrapper
> dispatcher(
512 new HostDispatcherWrapper(module
,
517 if (!dispatcher
->Init(
519 webkit::ppapi::PluginModule::GetLocalGetInterfaceFunc(),
524 RendererPpapiHostImpl
* host_impl
=
525 RendererPpapiHostImpl::CreateOnModuleForOutOfProcess(
526 module
, dispatcher
->dispatcher(), permissions
);
527 render_view_
->PpapiPluginCreated(host_impl
);
529 module
->InitAsProxied(dispatcher
.release());
533 void PepperPluginDelegateImpl::OnPpapiBrokerChannelCreated(
535 base::ProcessId broker_pid
,
536 const IPC::ChannelHandle
& handle
) {
537 scoped_refptr
<PepperBrokerImpl
>* broker_ptr
=
538 pending_connect_broker_
.Lookup(request_id
);
540 scoped_refptr
<PepperBrokerImpl
> broker
= *broker_ptr
;
541 pending_connect_broker_
.Remove(request_id
);
542 broker
->OnBrokerChannelConnected(broker_pid
, handle
);
544 // There is no broker waiting for this channel. Close it so the broker can
545 // clean up and possibly exit.
546 // The easiest way to clean it up is to just put it in an object
547 // and then close them. This failure case is not performance critical.
548 PepperBrokerDispatcherWrapper temp_dispatcher
;
549 temp_dispatcher
.Init(broker_pid
, handle
);
553 // Iterates through pending_connect_broker_ to find the broker.
554 // Cannot use Lookup() directly because pending_connect_broker_ does not store
555 // the raw pointer to the broker. Assumes maximum of one copy of broker exists.
556 bool PepperPluginDelegateImpl::StopWaitingForBrokerConnection(
557 PepperBrokerImpl
* broker
) {
558 for (BrokerMap::iterator
i(&pending_connect_broker_
);
559 !i
.IsAtEnd(); i
.Advance()) {
560 if (i
.GetCurrentValue()->get() == broker
) {
561 pending_connect_broker_
.Remove(i
.GetCurrentKey());
569 void PepperPluginDelegateImpl::ViewWillInitiatePaint() {
570 // Notify all of our instances that we started painting. This is used for
571 // internal bookkeeping only, so we know that the set can not change under
573 for (std::set
<webkit::ppapi::PluginInstance
*>::iterator i
=
574 active_instances_
.begin();
575 i
!= active_instances_
.end(); ++i
)
576 (*i
)->ViewWillInitiatePaint();
579 void PepperPluginDelegateImpl::ViewInitiatedPaint() {
580 // Notify all instances that we painted. The same caveats apply as for
581 // ViewFlushedPaint regarding instances closing themselves, so we take
582 // similar precautions.
583 std::set
<webkit::ppapi::PluginInstance
*> plugins
= active_instances_
;
584 for (std::set
<webkit::ppapi::PluginInstance
*>::iterator i
= plugins
.begin();
585 i
!= plugins
.end(); ++i
) {
586 if (active_instances_
.find(*i
) != active_instances_
.end())
587 (*i
)->ViewInitiatedPaint();
591 void PepperPluginDelegateImpl::ViewFlushedPaint() {
592 // Notify all instances that we flushed. This will call into the plugin, and
593 // we it may ask to close itself as a result. This will, in turn, modify our
594 // set, possibly invalidating the iterator. So we iterate on a copy that
595 // won't change out from under us.
596 std::set
<webkit::ppapi::PluginInstance
*> plugins
= active_instances_
;
597 for (std::set
<webkit::ppapi::PluginInstance
*>::iterator i
= plugins
.begin();
598 i
!= plugins
.end(); ++i
) {
599 // The copy above makes sure our iterator is never invalid if some plugins
600 // are destroyed. But some plugin may decide to close all of its views in
601 // response to a paint in one of them, so we need to make sure each one is
602 // still "current" before using it.
604 // It's possible that a plugin was destroyed, but another one was created
605 // with the same address. In this case, we'll call ViewFlushedPaint on that
606 // new plugin. But that's OK for this particular case since we're just
607 // notifying all of our instances that the view flushed, and the new one is
608 // one of our instances.
610 // What about the case where a new one is created in a callback at a new
611 // address and we don't issue the callback? We're still OK since this
612 // callback is used for flush callbacks and we could not have possibly
613 // started a new paint (ViewWillInitiatePaint) for the new plugin while
614 // processing a previous paint for an existing one.
615 if (active_instances_
.find(*i
) != active_instances_
.end())
616 (*i
)->ViewFlushedPaint();
620 webkit::ppapi::PluginInstance
*
621 PepperPluginDelegateImpl::GetBitmapForOptimizedPluginPaint(
622 const gfx::Rect
& paint_bounds
,
626 float* scale_factor
) {
627 for (std::set
<webkit::ppapi::PluginInstance
*>::iterator i
=
628 active_instances_
.begin();
629 i
!= active_instances_
.end(); ++i
) {
630 webkit::ppapi::PluginInstance
* instance
= *i
;
631 // In Flash fullscreen , the plugin contents should be painted onto the
632 // fullscreen widget instead of the web page.
633 if (!instance
->FlashIsFullscreenOrPending() &&
634 instance
->GetBitmapForOptimizedPluginPaint(paint_bounds
, dib
, location
,
641 void PepperPluginDelegateImpl::PluginFocusChanged(
642 webkit::ppapi::PluginInstance
* instance
,
645 focused_plugin_
= instance
;
646 else if (focused_plugin_
== instance
)
647 focused_plugin_
= NULL
;
649 render_view_
->PpapiPluginFocusChanged();
652 void PepperPluginDelegateImpl::PluginTextInputTypeChanged(
653 webkit::ppapi::PluginInstance
* instance
) {
654 if (focused_plugin_
== instance
&& render_view_
)
655 render_view_
->PpapiPluginTextInputTypeChanged();
658 void PepperPluginDelegateImpl::PluginCaretPositionChanged(
659 webkit::ppapi::PluginInstance
* instance
) {
660 if (focused_plugin_
== instance
&& render_view_
)
661 render_view_
->PpapiPluginCaretPositionChanged();
664 void PepperPluginDelegateImpl::PluginRequestedCancelComposition(
665 webkit::ppapi::PluginInstance
* instance
) {
666 if (focused_plugin_
== instance
&& render_view_
)
667 render_view_
->PpapiPluginCancelComposition();
670 void PepperPluginDelegateImpl::PluginSelectionChanged(
671 webkit::ppapi::PluginInstance
* instance
) {
672 if (focused_plugin_
== instance
&& render_view_
)
673 render_view_
->PpapiPluginSelectionChanged();
676 void PepperPluginDelegateImpl::SimulateImeSetComposition(
677 const string16
& text
,
678 const std::vector
<WebKit::WebCompositionUnderline
>& underlines
,
682 render_view_
->SimulateImeSetComposition(
683 text
, underlines
, selection_start
, selection_end
);
687 void PepperPluginDelegateImpl::SimulateImeConfirmComposition(
688 const string16
& text
) {
690 render_view_
->SimulateImeConfirmComposition(text
, ui::Range());
693 void PepperPluginDelegateImpl::OnImeSetComposition(
694 const string16
& text
,
695 const std::vector
<WebKit::WebCompositionUnderline
>& underlines
,
698 if (!IsPluginAcceptingCompositionEvents()) {
699 composition_text_
= text
;
701 // TODO(kinaba) currently all composition events are sent directly to
702 // plugins. Use DOM event mechanism after WebKit is made aware about
703 // plugins that support composition.
704 // The code below mimics the behavior of WebCore::Editor::setComposition.
706 // Empty -> nonempty: composition started.
707 if (composition_text_
.empty() && !text
.empty())
708 focused_plugin_
->HandleCompositionStart(string16());
709 // Nonempty -> empty: composition canceled.
710 if (!composition_text_
.empty() && text
.empty())
711 focused_plugin_
->HandleCompositionEnd(string16());
712 composition_text_
= text
;
713 // Nonempty: composition is ongoing.
714 if (!composition_text_
.empty()) {
715 focused_plugin_
->HandleCompositionUpdate(composition_text_
, underlines
,
716 selection_start
, selection_end
);
721 void PepperPluginDelegateImpl::OnImeConfirmComposition(const string16
& text
) {
722 // Here, text.empty() has a special meaning. It means to commit the last
723 // update of composition text (see RenderWidgetHost::ImeConfirmComposition()).
724 const string16
& last_text
= text
.empty() ? composition_text_
: text
;
726 // last_text is empty only when both text and composition_text_ is. Ignore it.
727 if (last_text
.empty())
730 if (!IsPluginAcceptingCompositionEvents()) {
731 for (size_t i
= 0; i
< text
.size(); ++i
) {
732 WebKit::WebKeyboardEvent char_event
;
733 char_event
.type
= WebKit::WebInputEvent::Char
;
734 char_event
.timeStampSeconds
= base::Time::Now().ToDoubleT();
735 char_event
.modifiers
= 0;
736 char_event
.windowsKeyCode
= last_text
[i
];
737 char_event
.nativeKeyCode
= last_text
[i
];
738 char_event
.text
[0] = last_text
[i
];
739 char_event
.unmodifiedText
[0] = last_text
[i
];
740 if (render_view_
->webwidget())
741 render_view_
->webwidget()->handleInputEvent(char_event
);
744 // Mimics the order of events sent by WebKit.
745 // See WebCore::Editor::setComposition() for the corresponding code.
746 focused_plugin_
->HandleCompositionEnd(last_text
);
747 focused_plugin_
->HandleTextInput(last_text
);
749 composition_text_
.clear();
752 gfx::Rect
PepperPluginDelegateImpl::GetCaretBounds() const {
753 if (!focused_plugin_
)
754 return gfx::Rect(0, 0, 0, 0);
755 return focused_plugin_
->GetCaretBounds();
758 ui::TextInputType
PepperPluginDelegateImpl::GetTextInputType() const {
759 if (!focused_plugin_
)
760 return ui::TEXT_INPUT_TYPE_NONE
;
761 return focused_plugin_
->text_input_type();
764 void PepperPluginDelegateImpl::GetSurroundingText(string16
* text
,
765 ui::Range
* range
) const {
766 if (!focused_plugin_
)
768 return focused_plugin_
->GetSurroundingText(text
, range
);
771 bool PepperPluginDelegateImpl::IsPluginAcceptingCompositionEvents() const {
772 if (!focused_plugin_
)
774 return focused_plugin_
->IsPluginAcceptingCompositionEvents();
777 bool PepperPluginDelegateImpl::CanComposeInline() const {
778 return IsPluginAcceptingCompositionEvents();
781 void PepperPluginDelegateImpl::PluginCrashed(
782 webkit::ppapi::PluginInstance
* instance
) {
783 render_view_
->PluginCrashed(instance
->module()->path(),
784 instance
->module()->GetPeerProcessId());
785 UnSetAndDeleteLockTargetAdapter(instance
);
788 void PepperPluginDelegateImpl::InstanceCreated(
789 webkit::ppapi::PluginInstance
* instance
) {
790 active_instances_
.insert(instance
);
792 // Set the initial focus.
793 instance
->SetContentAreaFocus(render_view_
->has_focus());
796 void PepperPluginDelegateImpl::InstanceDeleted(
797 webkit::ppapi::PluginInstance
* instance
) {
798 active_instances_
.erase(instance
);
799 UnSetAndDeleteLockTargetAdapter(instance
);
801 if (last_mouse_event_target_
== instance
)
802 last_mouse_event_target_
= NULL
;
803 if (focused_plugin_
== instance
)
804 PluginFocusChanged(instance
, false);
807 scoped_ptr
< ::ppapi::thunk::ResourceCreationAPI
>
808 PepperPluginDelegateImpl::CreateResourceCreationAPI(
809 webkit::ppapi::PluginInstance
* instance
) {
810 RendererPpapiHostImpl
* host_impl
= static_cast<RendererPpapiHostImpl
*>(
811 instance
->module()->GetEmbedderState());
812 return host_impl
->CreateInProcessResourceCreationAPI(instance
);
815 SkBitmap
* PepperPluginDelegateImpl::GetSadPluginBitmap() {
816 return GetContentClient()->renderer()->GetSadPluginBitmap();
819 WebKit::WebPlugin
* PepperPluginDelegateImpl::CreatePluginReplacement(
820 const base::FilePath
& file_path
) {
821 return GetContentClient()->renderer()->CreatePluginReplacement(
822 render_view_
, file_path
);
825 webkit::ppapi::PluginDelegate::PlatformImage2D
*
826 PepperPluginDelegateImpl::CreateImage2D(int width
, int height
) {
827 return PepperPlatformImage2DImpl::Create(width
, height
);
830 webkit::ppapi::PluginDelegate::PlatformGraphics2D
*
831 PepperPluginDelegateImpl::GetGraphics2D(
832 webkit::ppapi::PluginInstance
* instance
,
833 PP_Resource resource
) {
834 RendererPpapiHostImpl
* host_impl
= static_cast<RendererPpapiHostImpl
*>(
835 instance
->module()->GetEmbedderState());
836 return host_impl
->GetPlatformGraphics2D(resource
);
839 webkit::ppapi::PluginDelegate::PlatformContext3D
*
840 PepperPluginDelegateImpl::CreateContext3D() {
842 // If accelerated compositing of plugins is disabled, fail to create a 3D
843 // context, because it won't be visible. This allows graceful fallback in the
845 const WebPreferences
& prefs
= render_view_
->webkit_preferences();
846 if (!prefs
.accelerated_compositing_for_plugins_enabled
)
848 return new PlatformContext3DImpl
;
854 void PepperPluginDelegateImpl::ReparentContext(
855 webkit::ppapi::PluginDelegate::PlatformContext3D
* context
) {
856 static_cast<PlatformContext3DImpl
*>(context
)->
857 SetParentAndCreateBackingTextureIfNeeded();
860 webkit::ppapi::PluginDelegate::PlatformVideoCapture
*
861 PepperPluginDelegateImpl::CreateVideoCapture(
862 const std::string
& device_id
,
863 PlatformVideoCaptureEventHandler
* handler
) {
864 return new PepperPlatformVideoCaptureImpl(AsWeakPtr(), device_id
, handler
);
867 webkit::ppapi::PluginDelegate::PlatformVideoDecoder
*
868 PepperPluginDelegateImpl::CreateVideoDecoder(
869 media::VideoDecodeAccelerator::Client
* client
,
870 int32 command_buffer_route_id
) {
871 return new PlatformVideoDecoderImpl(client
, command_buffer_route_id
);
874 void PepperPluginDelegateImpl::NumberOfFindResultsChanged(int identifier
,
877 render_view_
->reportFindInPageMatchCount(identifier
, total
, final_result
);
880 void PepperPluginDelegateImpl::SelectedFindResultChanged(int identifier
,
882 render_view_
->reportFindInPageSelection(
883 identifier
, index
+ 1, WebKit::WebRect());
886 uint32_t PepperPluginDelegateImpl::GetAudioHardwareOutputSampleRate() {
887 RenderThreadImpl
* thread
= RenderThreadImpl::current();
888 return thread
->GetAudioHardwareConfig()->GetOutputSampleRate();
891 uint32_t PepperPluginDelegateImpl::GetAudioHardwareOutputBufferSize() {
892 RenderThreadImpl
* thread
= RenderThreadImpl::current();
893 return thread
->GetAudioHardwareConfig()->GetOutputBufferSize();
896 webkit::ppapi::PluginDelegate::PlatformAudioOutput
*
897 PepperPluginDelegateImpl::CreateAudioOutput(
898 uint32_t sample_rate
,
899 uint32_t sample_count
,
900 webkit::ppapi::PluginDelegate::PlatformAudioOutputClient
* client
) {
901 return PepperPlatformAudioOutputImpl::Create(
902 static_cast<int>(sample_rate
), static_cast<int>(sample_count
),
903 GetRoutingID(), client
);
906 webkit::ppapi::PluginDelegate::PlatformAudioInput
*
907 PepperPluginDelegateImpl::CreateAudioInput(
908 const std::string
& device_id
,
909 uint32_t sample_rate
,
910 uint32_t sample_count
,
911 webkit::ppapi::PluginDelegate::PlatformAudioInputClient
* client
) {
912 return PepperPlatformAudioInputImpl::Create(
913 AsWeakPtr(), device_id
, static_cast<int>(sample_rate
),
914 static_cast<int>(sample_count
), client
);
917 // If a broker has not already been created for this plugin, creates one.
918 webkit::ppapi::PluginDelegate::Broker
*
919 PepperPluginDelegateImpl::ConnectToBroker(
920 webkit::ppapi::PPB_Broker_Impl
* client
) {
923 webkit::ppapi::PluginModule
* plugin_module
=
924 webkit::ppapi::ResourceHelper::GetPluginModule(client
);
928 scoped_refptr
<PepperBrokerImpl
> broker
=
929 static_cast<PepperBrokerImpl
*>(plugin_module
->GetBroker());
931 broker
= CreateBroker(plugin_module
);
936 int request_id
= pending_permission_requests_
.Add(
937 new base::WeakPtr
<webkit::ppapi::PPB_Broker_Impl
>(client
->AsWeakPtr()));
938 if (!render_view_
->Send(
939 new ViewHostMsg_RequestPpapiBrokerPermission(
940 render_view_
->routing_id(),
942 client
->GetDocumentUrl(),
943 plugin_module
->path()))) {
947 // Adds a reference, ensuring that the broker is not deleted when
948 // |broker| goes out of scope.
949 broker
->AddPendingConnect(client
);
954 void PepperPluginDelegateImpl::OnPpapiBrokerPermissionResult(
957 scoped_ptr
<base::WeakPtr
<webkit::ppapi::PPB_Broker_Impl
> > client_ptr(
958 pending_permission_requests_
.Lookup(request_id
));
959 DCHECK(client_ptr
.get());
960 pending_permission_requests_
.Remove(request_id
);
961 base::WeakPtr
<webkit::ppapi::PPB_Broker_Impl
> client
= *client_ptr
;
965 webkit::ppapi::PluginModule
* plugin_module
=
966 webkit::ppapi::ResourceHelper::GetPluginModule(client
);
970 PepperBrokerImpl
* broker
=
971 static_cast<PepperBrokerImpl
*>(plugin_module
->GetBroker());
972 broker
->OnBrokerPermissionResult(client
, result
);
975 bool PepperPluginDelegateImpl::AsyncOpenFile(
976 const base::FilePath
& path
,
978 const AsyncOpenFileCallback
& callback
) {
979 int message_id
= pending_async_open_files_
.Add(
980 new AsyncOpenFileCallback(callback
));
981 IPC::Message
* msg
= new ViewHostMsg_AsyncOpenFile(
982 render_view_
->routing_id(), path
, flags
, message_id
);
983 return render_view_
->Send(msg
);
986 void PepperPluginDelegateImpl::OnAsyncFileOpened(
987 base::PlatformFileError error_code
,
988 base::PlatformFile file
,
990 AsyncOpenFileCallback
* callback
=
991 pending_async_open_files_
.Lookup(message_id
);
993 pending_async_open_files_
.Remove(message_id
);
994 callback
->Run(error_code
, base::PassPlatformFile(&file
));
995 // Make sure we won't leak file handle if the requester has died.
996 if (file
!= base::kInvalidPlatformFileValue
)
997 base::FileUtilProxy::Close(GetFileThreadMessageLoopProxy(), file
,
998 base::FileUtilProxy::StatusCallback());
1002 void PepperPluginDelegateImpl::OnSetFocus(bool has_focus
) {
1003 for (std::set
<webkit::ppapi::PluginInstance
*>::iterator i
=
1004 active_instances_
.begin();
1005 i
!= active_instances_
.end(); ++i
)
1006 (*i
)->SetContentAreaFocus(has_focus
);
1009 void PepperPluginDelegateImpl::PageVisibilityChanged(bool is_visible
) {
1010 for (std::set
<webkit::ppapi::PluginInstance
*>::iterator i
=
1011 active_instances_
.begin();
1012 i
!= active_instances_
.end(); ++i
)
1013 (*i
)->PageVisibilityChanged(is_visible
);
1016 bool PepperPluginDelegateImpl::IsPluginFocused() const {
1017 return focused_plugin_
!= NULL
;
1020 void PepperPluginDelegateImpl::WillHandleMouseEvent() {
1021 // This method is called for every mouse event that the render view receives.
1022 // And then the mouse event is forwarded to WebKit, which dispatches it to the
1023 // event target. Potentially a Pepper plugin will receive the event.
1024 // In order to tell whether a plugin gets the last mouse event and which it
1025 // is, we set |last_mouse_event_target_| to NULL here. If a plugin gets the
1026 // event, it will notify us via DidReceiveMouseEvent() and set itself as
1027 // |last_mouse_event_target_|.
1028 last_mouse_event_target_
= NULL
;
1031 bool PepperPluginDelegateImpl::IsFileSystemOpened(PP_Instance instance
,
1032 PP_Resource resource
) const {
1033 const PepperFileSystemHost
* host
=
1034 GetRendererResourceHost
<PepperFileSystemHost
>(instance
, resource
);
1035 return host
&& host
->IsOpened();
1038 PP_FileSystemType
PepperPluginDelegateImpl::GetFileSystemType(
1039 PP_Instance instance
, PP_Resource resource
) const {
1040 const PepperFileSystemHost
* host
=
1041 GetRendererResourceHost
<PepperFileSystemHost
>(instance
, resource
);
1042 return host
? host
->GetType() : PP_FILESYSTEMTYPE_INVALID
;
1045 GURL
PepperPluginDelegateImpl::GetFileSystemRootUrl(
1046 PP_Instance instance
, PP_Resource resource
) const {
1047 const PepperFileSystemHost
* host
=
1048 GetRendererResourceHost
<PepperFileSystemHost
>(instance
, resource
);
1049 return host
? host
->GetRootUrl() : GURL();
1052 bool PepperPluginDelegateImpl::MakeDirectory(
1055 fileapi::FileSystemCallbackDispatcher
* dispatcher
) {
1056 FileSystemDispatcher
* file_system_dispatcher
=
1057 ChildThread::current()->file_system_dispatcher();
1058 return file_system_dispatcher
->Create(
1059 path
, false, true, recursive
, dispatcher
);
1062 bool PepperPluginDelegateImpl::Query(
1064 fileapi::FileSystemCallbackDispatcher
* dispatcher
) {
1065 FileSystemDispatcher
* file_system_dispatcher
=
1066 ChildThread::current()->file_system_dispatcher();
1067 return file_system_dispatcher
->ReadMetadata(path
, dispatcher
);
1070 bool PepperPluginDelegateImpl::Touch(
1072 const base::Time
& last_access_time
,
1073 const base::Time
& last_modified_time
,
1074 fileapi::FileSystemCallbackDispatcher
* dispatcher
) {
1075 FileSystemDispatcher
* file_system_dispatcher
=
1076 ChildThread::current()->file_system_dispatcher();
1077 return file_system_dispatcher
->TouchFile(path
, last_access_time
,
1078 last_modified_time
, dispatcher
);
1081 bool PepperPluginDelegateImpl::SetLength(
1084 fileapi::FileSystemCallbackDispatcher
* dispatcher
) {
1085 FileSystemDispatcher
* file_system_dispatcher
=
1086 ChildThread::current()->file_system_dispatcher();
1087 return file_system_dispatcher
->Truncate(path
, length
, NULL
, dispatcher
);
1090 bool PepperPluginDelegateImpl::Delete(
1092 fileapi::FileSystemCallbackDispatcher
* dispatcher
) {
1093 FileSystemDispatcher
* file_system_dispatcher
=
1094 ChildThread::current()->file_system_dispatcher();
1095 return file_system_dispatcher
->Remove(path
, false /* recursive */,
1099 bool PepperPluginDelegateImpl::Rename(
1100 const GURL
& file_path
,
1101 const GURL
& new_file_path
,
1102 fileapi::FileSystemCallbackDispatcher
* dispatcher
) {
1103 FileSystemDispatcher
* file_system_dispatcher
=
1104 ChildThread::current()->file_system_dispatcher();
1105 return file_system_dispatcher
->Move(file_path
, new_file_path
, dispatcher
);
1108 bool PepperPluginDelegateImpl::ReadDirectory(
1109 const GURL
& directory_path
,
1110 fileapi::FileSystemCallbackDispatcher
* dispatcher
) {
1111 FileSystemDispatcher
* file_system_dispatcher
=
1112 ChildThread::current()->file_system_dispatcher();
1113 return file_system_dispatcher
->ReadDirectory(directory_path
, dispatcher
);
1116 void PepperPluginDelegateImpl::QueryAvailableSpace(
1117 const GURL
& origin
, quota::StorageType type
,
1118 const AvailableSpaceCallback
& callback
) {
1119 ChildThread::current()->quota_dispatcher()->QueryStorageUsageAndQuota(
1120 origin
, type
, new QuotaCallbackTranslator(callback
));
1123 void PepperPluginDelegateImpl::WillUpdateFile(const GURL
& path
) {
1124 ChildThread::current()->Send(new FileSystemHostMsg_WillUpdate(path
));
1127 void PepperPluginDelegateImpl::DidUpdateFile(const GURL
& path
, int64_t delta
) {
1128 ChildThread::current()->Send(new FileSystemHostMsg_DidUpdate(path
, delta
));
1131 bool PepperPluginDelegateImpl::AsyncOpenFileSystemURL(
1134 const AsyncOpenFileSystemURLCallback
& callback
) {
1136 FileSystemDispatcher
* file_system_dispatcher
=
1137 ChildThread::current()->file_system_dispatcher();
1138 return file_system_dispatcher
->OpenFile(path
, flags
,
1139 new AsyncOpenFileSystemURLCallbackTranslator(
1143 void PepperPluginDelegateImpl::SyncGetFileSystemPlatformPath(
1144 const GURL
& url
, base::FilePath
* platform_path
) {
1145 RenderThreadImpl::current()->Send(new FileSystemHostMsg_SyncGetPlatformPath(
1146 url
, platform_path
));
1149 scoped_refptr
<base::MessageLoopProxy
>
1150 PepperPluginDelegateImpl::GetFileThreadMessageLoopProxy() {
1151 return RenderThreadImpl::current()->GetFileThreadMessageLoopProxy();
1154 uint32
PepperPluginDelegateImpl::TCPSocketCreate() {
1155 uint32 socket_id
= 0;
1156 render_view_
->Send(new PpapiHostMsg_PPBTCPSocket_Create(
1157 render_view_
->routing_id(), 0, &socket_id
));
1161 void PepperPluginDelegateImpl::TCPSocketConnect(
1162 webkit::ppapi::PPB_TCPSocket_Private_Impl
* socket
,
1164 const std::string
& host
,
1166 RegisterTCPSocket(socket
, socket_id
);
1168 new PpapiHostMsg_PPBTCPSocket_Connect(
1169 render_view_
->routing_id(), socket_id
, host
, port
));
1172 void PepperPluginDelegateImpl::TCPSocketConnectWithNetAddress(
1173 webkit::ppapi::PPB_TCPSocket_Private_Impl
* socket
,
1175 const PP_NetAddress_Private
& addr
) {
1176 RegisterTCPSocket(socket
, socket_id
);
1178 new PpapiHostMsg_PPBTCPSocket_ConnectWithNetAddress(
1179 render_view_
->routing_id(), socket_id
, addr
));
1182 void PepperPluginDelegateImpl::TCPSocketSSLHandshake(
1184 const std::string
& server_name
,
1185 uint16_t server_port
,
1186 const std::vector
<std::vector
<char> >& trusted_certs
,
1187 const std::vector
<std::vector
<char> >& untrusted_certs
) {
1188 DCHECK(tcp_sockets_
.Lookup(socket_id
));
1189 render_view_
->Send(new PpapiHostMsg_PPBTCPSocket_SSLHandshake(
1190 socket_id
, server_name
, server_port
, trusted_certs
, untrusted_certs
));
1193 void PepperPluginDelegateImpl::TCPSocketRead(uint32 socket_id
,
1194 int32_t bytes_to_read
) {
1195 DCHECK(tcp_sockets_
.Lookup(socket_id
));
1197 new PpapiHostMsg_PPBTCPSocket_Read(socket_id
, bytes_to_read
));
1200 void PepperPluginDelegateImpl::TCPSocketWrite(uint32 socket_id
,
1201 const std::string
& buffer
) {
1202 DCHECK(tcp_sockets_
.Lookup(socket_id
));
1203 render_view_
->Send(new PpapiHostMsg_PPBTCPSocket_Write(socket_id
, buffer
));
1206 void PepperPluginDelegateImpl::TCPSocketDisconnect(uint32 socket_id
) {
1207 // There is no DCHECK(tcp_sockets_.Lookup(socket_id)) because this method
1208 // can be called before TCPSocketConnect or TCPSocketConnectWithNetAddress.
1209 render_view_
->Send(new PpapiHostMsg_PPBTCPSocket_Disconnect(socket_id
));
1210 if (tcp_sockets_
.Lookup(socket_id
))
1211 tcp_sockets_
.Remove(socket_id
);
1214 void PepperPluginDelegateImpl::TCPSocketSetBoolOption(
1216 PP_TCPSocketOption_Private name
,
1218 DCHECK(tcp_sockets_
.Lookup(socket_id
));
1220 new PpapiHostMsg_PPBTCPSocket_SetBoolOption(socket_id
, name
, value
));
1223 void PepperPluginDelegateImpl::RegisterTCPSocket(
1224 webkit::ppapi::PPB_TCPSocket_Private_Impl
* socket
,
1226 tcp_sockets_
.AddWithID(socket
, socket_id
);
1229 void PepperPluginDelegateImpl::TCPServerSocketListen(
1230 PP_Resource socket_resource
,
1231 const PP_NetAddress_Private
& addr
,
1234 new PpapiHostMsg_PPBTCPServerSocket_Listen(
1235 render_view_
->routing_id(), 0, socket_resource
, addr
, backlog
));
1238 void PepperPluginDelegateImpl::TCPServerSocketAccept(uint32 server_socket_id
) {
1239 DCHECK(tcp_server_sockets_
.Lookup(server_socket_id
));
1240 render_view_
->Send(new PpapiHostMsg_PPBTCPServerSocket_Accept(
1241 render_view_
->routing_id(), server_socket_id
));
1244 void PepperPluginDelegateImpl::TCPServerSocketStopListening(
1245 PP_Resource socket_resource
,
1247 if (socket_id
!= 0) {
1248 render_view_
->Send(new PpapiHostMsg_PPBTCPServerSocket_Destroy(socket_id
));
1249 tcp_server_sockets_
.Remove(socket_id
);
1253 bool PepperPluginDelegateImpl::AddNetworkListObserver(
1254 webkit_glue::NetworkListObserver
* observer
) {
1255 #if defined(ENABLE_WEBRTC)
1256 P2PSocketDispatcher
* socket_dispatcher
=
1257 RenderThreadImpl::current()->p2p_socket_dispatcher();
1258 if (!socket_dispatcher
) {
1261 socket_dispatcher
->AddNetworkListObserver(observer
);
1268 void PepperPluginDelegateImpl::RemoveNetworkListObserver(
1269 webkit_glue::NetworkListObserver
* observer
) {
1270 #if defined(ENABLE_WEBRTC)
1271 P2PSocketDispatcher
* socket_dispatcher
=
1272 RenderThreadImpl::current()->p2p_socket_dispatcher();
1273 if (socket_dispatcher
)
1274 socket_dispatcher
->RemoveNetworkListObserver(observer
);
1278 bool PepperPluginDelegateImpl::X509CertificateParseDER(
1279 const std::vector
<char>& der
,
1280 ppapi::PPB_X509Certificate_Fields
* fields
) {
1281 bool succeeded
= false;
1283 new PpapiHostMsg_PPBX509Certificate_ParseDER(der
, &succeeded
, fields
));
1287 webkit::ppapi::FullscreenContainer
*
1288 PepperPluginDelegateImpl::CreateFullscreenContainer(
1289 webkit::ppapi::PluginInstance
* instance
) {
1290 return render_view_
->CreatePepperFullscreenContainer(instance
);
1293 gfx::Size
PepperPluginDelegateImpl::GetScreenSize() {
1294 WebKit::WebScreenInfo info
= render_view_
->screenInfo();
1295 return gfx::Size(info
.rect
.width
, info
.rect
.height
);
1298 std::string
PepperPluginDelegateImpl::GetDefaultEncoding() {
1299 return render_view_
->webkit_preferences().default_encoding
;
1302 void PepperPluginDelegateImpl::ZoomLimitsChanged(double minimum_factor
,
1303 double maximum_factor
) {
1304 double minimum_level
= WebView::zoomFactorToZoomLevel(minimum_factor
);
1305 double maximum_level
= WebView::zoomFactorToZoomLevel(maximum_factor
);
1306 render_view_
->webview()->zoomLimitsChanged(minimum_level
, maximum_level
);
1309 void PepperPluginDelegateImpl::DidStartLoading() {
1310 render_view_
->DidStartLoadingForPlugin();
1313 void PepperPluginDelegateImpl::DidStopLoading() {
1314 render_view_
->DidStopLoadingForPlugin();
1317 void PepperPluginDelegateImpl::SetContentRestriction(int restrictions
) {
1318 render_view_
->Send(new ViewHostMsg_UpdateContentRestrictions(
1319 render_view_
->routing_id(), restrictions
));
1322 void PepperPluginDelegateImpl::SaveURLAs(const GURL
& url
) {
1323 WebFrame
* frame
= render_view_
->webview()->mainFrame();
1324 Referrer
referrer(frame
->document().url(),
1325 frame
->document().referrerPolicy());
1326 render_view_
->Send(new ViewHostMsg_SaveURLAs(
1327 render_view_
->routing_id(), url
, referrer
));
1330 base::SharedMemory
* PepperPluginDelegateImpl::CreateAnonymousSharedMemory(
1332 return RenderThread::Get()->HostAllocateSharedMemoryBuffer(size
).release();
1335 ppapi::Preferences
PepperPluginDelegateImpl::GetPreferences() {
1336 return ppapi::Preferences(render_view_
->webkit_preferences());
1339 bool PepperPluginDelegateImpl::LockMouse(
1340 webkit::ppapi::PluginInstance
* instance
) {
1341 return GetMouseLockDispatcher(instance
)->LockMouse(
1342 GetOrCreateLockTargetAdapter(instance
));
1345 void PepperPluginDelegateImpl::UnlockMouse(
1346 webkit::ppapi::PluginInstance
* instance
) {
1347 GetMouseLockDispatcher(instance
)->UnlockMouse(
1348 GetOrCreateLockTargetAdapter(instance
));
1351 bool PepperPluginDelegateImpl::IsMouseLocked(
1352 webkit::ppapi::PluginInstance
* instance
) {
1353 return GetMouseLockDispatcher(instance
)->IsMouseLockedTo(
1354 GetOrCreateLockTargetAdapter(instance
));
1357 void PepperPluginDelegateImpl::DidChangeCursor(
1358 webkit::ppapi::PluginInstance
* instance
,
1359 const WebKit::WebCursorInfo
& cursor
) {
1360 // Update the cursor appearance immediately if the requesting plugin is the
1361 // one which receives the last mouse event. Otherwise, the new cursor won't be
1362 // picked up until the plugin gets the next input event. That is bad if, e.g.,
1363 // the plugin would like to set an invisible cursor when there isn't any user
1364 // input for a while.
1365 if (instance
== last_mouse_event_target_
)
1366 render_view_
->didChangeCursor(cursor
);
1369 void PepperPluginDelegateImpl::DidReceiveMouseEvent(
1370 webkit::ppapi::PluginInstance
* instance
) {
1371 last_mouse_event_target_
= instance
;
1374 bool PepperPluginDelegateImpl::IsInFullscreenMode() {
1375 return render_view_
->is_fullscreen();
1378 void PepperPluginDelegateImpl::SampleGamepads(WebKit::WebGamepads
* data
) {
1379 if (!gamepad_shared_memory_reader_
)
1380 gamepad_shared_memory_reader_
.reset(new GamepadSharedMemoryReader
);
1381 gamepad_shared_memory_reader_
->SampleGamepads(*data
);
1384 bool PepperPluginDelegateImpl::IsPageVisible() const {
1385 return !render_view_
->is_hidden();
1388 int PepperPluginDelegateImpl::EnumerateDevices(
1389 PP_DeviceType_Dev type
,
1390 const EnumerateDevicesCallback
& callback
) {
1392 device_enumeration_event_handler_
->RegisterEnumerateDevicesCallback(
1395 #if defined(ENABLE_WEBRTC)
1396 render_view_
->media_stream_dispatcher()->EnumerateDevices(
1397 request_id
, device_enumeration_event_handler_
.get()->AsWeakPtr(),
1398 PepperDeviceEnumerationEventHandler::FromPepperDeviceType(type
),
1401 MessageLoop::current()->PostTask(
1404 &PepperDeviceEnumerationEventHandler::OnDevicesEnumerationFailed
,
1405 device_enumeration_event_handler_
->AsWeakPtr(), request_id
));
1411 void PepperPluginDelegateImpl::StopEnumerateDevices(int request_id
) {
1412 device_enumeration_event_handler_
->UnregisterEnumerateDevicesCallback(
1415 #if defined(ENABLE_WEBRTC)
1416 // Need to post task since this function might be called inside the callback
1417 // of EnumerateDevices.
1418 MessageLoop::current()->PostTask(
1421 &MediaStreamDispatcher::StopEnumerateDevices
,
1422 render_view_
->media_stream_dispatcher()->AsWeakPtr(),
1423 request_id
, device_enumeration_event_handler_
.get()->AsWeakPtr()));
1427 bool PepperPluginDelegateImpl::OnMessageReceived(const IPC::Message
& message
) {
1428 bool handled
= true;
1429 IPC_BEGIN_MESSAGE_MAP(PepperPluginDelegateImpl
, message
)
1430 IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPSocket_ConnectACK
,
1431 OnTCPSocketConnectACK
)
1432 IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPSocket_SSLHandshakeACK
,
1433 OnTCPSocketSSLHandshakeACK
)
1434 IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPSocket_ReadACK
, OnTCPSocketReadACK
)
1435 IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPSocket_WriteACK
, OnTCPSocketWriteACK
)
1436 IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPSocket_SetBoolOptionACK
,
1437 OnTCPSocketSetBoolOptionACK
)
1438 IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPServerSocket_ListenACK
,
1439 OnTCPServerSocketListenACK
)
1440 IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPServerSocket_AcceptACK
,
1441 OnTCPServerSocketAcceptACK
)
1442 IPC_MESSAGE_UNHANDLED(handled
= false)
1443 IPC_END_MESSAGE_MAP()
1447 void PepperPluginDelegateImpl::OnDestruct() {
1448 // Nothing to do here. Default implementation in RenderViewObserver does
1449 // 'delete this' but it's not suitable for PepperPluginDelegateImpl because
1450 // it's non-pointer member in RenderViewImpl.
1453 void PepperPluginDelegateImpl::OnTCPSocketConnectACK(
1454 uint32 plugin_dispatcher_id
,
1457 const PP_NetAddress_Private
& local_addr
,
1458 const PP_NetAddress_Private
& remote_addr
) {
1459 webkit::ppapi::PPB_TCPSocket_Private_Impl
* socket
=
1460 tcp_sockets_
.Lookup(socket_id
);
1462 socket
->OnConnectCompleted(succeeded
, local_addr
, remote_addr
);
1464 tcp_sockets_
.Remove(socket_id
);
1467 void PepperPluginDelegateImpl::OnTCPSocketSSLHandshakeACK(
1468 uint32 plugin_dispatcher_id
,
1471 const ppapi::PPB_X509Certificate_Fields
& certificate_fields
) {
1472 webkit::ppapi::PPB_TCPSocket_Private_Impl
* socket
=
1473 tcp_sockets_
.Lookup(socket_id
);
1475 socket
->OnSSLHandshakeCompleted(succeeded
, certificate_fields
);
1478 void PepperPluginDelegateImpl::OnTCPSocketReadACK(uint32 plugin_dispatcher_id
,
1481 const std::string
& data
) {
1482 webkit::ppapi::PPB_TCPSocket_Private_Impl
* socket
=
1483 tcp_sockets_
.Lookup(socket_id
);
1485 socket
->OnReadCompleted(succeeded
, data
);
1488 void PepperPluginDelegateImpl::OnTCPSocketWriteACK(uint32 plugin_dispatcher_id
,
1491 int32_t bytes_written
) {
1492 webkit::ppapi::PPB_TCPSocket_Private_Impl
* socket
=
1493 tcp_sockets_
.Lookup(socket_id
);
1495 socket
->OnWriteCompleted(succeeded
, bytes_written
);
1498 void PepperPluginDelegateImpl::OnTCPSocketSetBoolOptionACK(
1499 uint32 plugin_dispatcher_id
,
1502 webkit::ppapi::PPB_TCPSocket_Private_Impl
* socket
=
1503 tcp_sockets_
.Lookup(socket_id
);
1505 socket
->OnSetOptionCompleted(succeeded
);
1508 void PepperPluginDelegateImpl::OnTCPServerSocketListenACK(
1509 uint32 plugin_dispatcher_id
,
1510 PP_Resource socket_resource
,
1513 ppapi::thunk::EnterResource
<ppapi::thunk::PPB_TCPServerSocket_Private_API
>
1514 enter(socket_resource
, true);
1515 if (enter
.succeeded()) {
1516 ppapi::PPB_TCPServerSocket_Shared
* socket
=
1517 static_cast<ppapi::PPB_TCPServerSocket_Shared
*>(enter
.object());
1518 if (status
== PP_OK
)
1519 tcp_server_sockets_
.AddWithID(socket
, socket_id
);
1520 socket
->OnListenCompleted(socket_id
, status
);
1521 } else if (socket_id
!= 0 && status
== PP_OK
) {
1522 // StopListening was called before completion of Listen.
1523 render_view_
->Send(new PpapiHostMsg_PPBTCPServerSocket_Destroy(socket_id
));
1527 void PepperPluginDelegateImpl::OnTCPServerSocketAcceptACK(
1528 uint32 plugin_dispatcher_id
,
1529 uint32 server_socket_id
,
1530 uint32 accepted_socket_id
,
1531 const PP_NetAddress_Private
& local_addr
,
1532 const PP_NetAddress_Private
& remote_addr
) {
1533 ppapi::PPB_TCPServerSocket_Shared
* socket
=
1534 tcp_server_sockets_
.Lookup(server_socket_id
);
1536 bool succeeded
= (accepted_socket_id
!= 0);
1537 socket
->OnAcceptCompleted(succeeded
,
1541 } else if (accepted_socket_id
!= 0) {
1543 new PpapiHostMsg_PPBTCPSocket_Disconnect(accepted_socket_id
));
1547 int PepperPluginDelegateImpl::GetRoutingID() const {
1548 return render_view_
->routing_id();
1551 int PepperPluginDelegateImpl::OpenDevice(PP_DeviceType_Dev type
,
1552 const std::string
& device_id
,
1553 const OpenDeviceCallback
& callback
) {
1555 device_enumeration_event_handler_
->RegisterOpenDeviceCallback(callback
);
1557 #if defined(ENABLE_WEBRTC)
1558 render_view_
->media_stream_dispatcher()->OpenDevice(
1560 device_enumeration_event_handler_
.get()->AsWeakPtr(),
1562 PepperDeviceEnumerationEventHandler::FromPepperDeviceType(type
),
1565 MessageLoop::current()->PostTask(
1567 base::Bind(&PepperDeviceEnumerationEventHandler::OnDeviceOpenFailed
,
1568 device_enumeration_event_handler_
->AsWeakPtr(), request_id
));
1574 void PepperPluginDelegateImpl::CloseDevice(const std::string
& label
) {
1575 #if defined(ENABLE_WEBRTC)
1576 render_view_
->media_stream_dispatcher()->CloseDevice(label
);
1580 int PepperPluginDelegateImpl::GetSessionID(PP_DeviceType_Dev type
,
1581 const std::string
& label
) {
1582 #if defined(ENABLE_WEBRTC)
1584 case PP_DEVICETYPE_DEV_AUDIOCAPTURE
:
1585 return render_view_
->media_stream_dispatcher()->audio_session_id(label
,
1587 case PP_DEVICETYPE_DEV_VIDEOCAPTURE
:
1588 return render_view_
->media_stream_dispatcher()->video_session_id(label
,
1599 MouseLockDispatcher::LockTarget
*
1600 PepperPluginDelegateImpl::GetOrCreateLockTargetAdapter(
1601 webkit::ppapi::PluginInstance
* instance
) {
1602 MouseLockDispatcher::LockTarget
* target
= mouse_lock_instances_
[instance
];
1606 return mouse_lock_instances_
[instance
] =
1607 new PluginInstanceLockTarget(instance
);
1610 void PepperPluginDelegateImpl::UnSetAndDeleteLockTargetAdapter(
1611 webkit::ppapi::PluginInstance
* instance
) {
1612 LockTargetMap::iterator it
= mouse_lock_instances_
.find(instance
);
1613 if (it
!= mouse_lock_instances_
.end()) {
1614 MouseLockDispatcher::LockTarget
* target
= it
->second
;
1615 GetMouseLockDispatcher(instance
)->OnLockTargetDestroyed(target
);
1617 mouse_lock_instances_
.erase(it
);
1621 MouseLockDispatcher
* PepperPluginDelegateImpl::GetMouseLockDispatcher(
1622 webkit::ppapi::PluginInstance
* instance
) {
1623 if (instance
->flash_fullscreen()) {
1624 RenderWidgetFullscreenPepper
* container
=
1625 static_cast<RenderWidgetFullscreenPepper
*>(
1626 instance
->fullscreen_container());
1627 return container
->mouse_lock_dispatcher();
1629 return render_view_
->mouse_lock_dispatcher();
1633 IPC::PlatformFileForTransit
PepperPluginDelegateImpl::ShareHandleWithRemote(
1634 base::PlatformFile handle
,
1635 base::ProcessId target_process_id
,
1636 bool should_close_source
) const {
1637 return BrokerGetFileHandleForProcess(
1640 should_close_source
);
1643 bool PepperPluginDelegateImpl::IsRunningInProcess(PP_Instance instance
) const {
1644 RendererPpapiHostImpl
* host
=
1645 RendererPpapiHostImpl::GetForPPInstance(instance
);
1646 return host
&& host
->IsRunningInProcess();
1649 } // namespace content