Disable ContentSettingBubbleModelTest.RPHAllow which is flaky.
[chromium-blink-merge.git] / content / renderer / pepper / pepper_plugin_delegate_impl.cc
blob6abd88bb6d2167bfe58ac4e0460709c042ad7c2d
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"
7 #include <cmath>
8 #include <cstddef>
9 #include <map>
10 #include <queue>
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;
99 namespace content {
101 namespace {
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 {
108 public:
109 HostDispatcherWrapper(webkit::ppapi::PluginModule* module,
110 base::ProcessId peer_pid,
111 int plugin_child_id,
112 const ppapi::PpapiPermissions& perms,
113 bool is_external)
114 : module_(module),
115 peer_pid_(peer_pid),
116 plugin_child_id_(plugin_child_id),
117 permissions_(perms),
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())
127 return false;
129 #if defined(OS_POSIX)
130 DCHECK_NE(-1, channel_handle.socket.fd);
131 if (channel_handle.socket.fd == -1)
132 return false;
133 #endif
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(),
140 peer_pid_,
141 channel_handle,
142 true, // Client.
143 preferences)) {
144 dispatcher_.reset();
145 dispatcher_delegate_.reset();
146 return false;
148 dispatcher_->channel()->SetRestrictDispatchChannelGroup(
149 kRendererRestrictDispatchGroup_Pepper);
150 return true;
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.
166 if (host) {
167 RenderView* render_view = host->GetRenderViewForInstance(instance);
168 webkit::ppapi::PluginInstance* plugin_instance =
169 host->GetPluginInstance(instance);
170 render_view->Send(new ViewHostMsg_DidCreateOutOfProcessPepperInstance(
171 plugin_child_id_,
172 instance,
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()),
178 is_external_));
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.
187 if (host) {
188 RenderView* render_view = host->GetRenderViewForInstance(instance);
189 render_view->Send(new ViewHostMsg_DidDeleteOutOfProcessPepperInstance(
190 plugin_child_id_,
191 instance,
192 is_external_));
195 virtual base::ProcessId GetPeerProcessId() OVERRIDE {
196 return peer_pid_;
199 ppapi::proxy::HostDispatcher* dispatcher() { return dispatcher_.get(); }
201 private:
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_;
212 bool is_external_;
214 scoped_ptr<ppapi::proxy::HostDispatcher> dispatcher_;
215 scoped_ptr<ppapi::proxy::ProxyChannel::Delegate> dispatcher_delegate_;
218 class QuotaCallbackTranslator : public QuotaDispatcher::Callback {
219 public:
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 {
226 NOTREACHED();
228 virtual void DidFail(quota::QuotaStatusCode error) OVERRIDE {
229 callback_.Run(0);
231 private:
232 PluginCallback callback_;
235 class PluginInstanceLockTarget : public MouseLockDispatcher::LockTarget {
236 public:
237 PluginInstanceLockTarget(webkit::ppapi::PluginInstance* plugin)
238 : plugin_(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);
251 return true;
254 private:
255 webkit::ppapi::PluginInstance* plugin_;
258 void DoNotifyCloseFile(int file_open_id, base::PlatformFileError /* unused */) {
259 ChildThread::current()->file_system_dispatcher()->NotifyCloseFile(
260 file_open_id);
263 class AsyncOpenFileSystemURLCallbackTranslator
264 : public fileapi::FileSystemCallbackDispatcher {
265 public:
266 AsyncOpenFileSystemURLCallbackTranslator(
267 const webkit::ppapi::PluginDelegate::AsyncOpenFileSystemURLCallback&
268 callback)
269 : callback_(callback) {
272 virtual ~AsyncOpenFileSystemURLCallbackTranslator() {}
274 virtual void DidSucceed() OVERRIDE {
275 NOTREACHED();
277 virtual void DidReadMetadata(
278 const base::PlatformFileInfo& file_info,
279 const base::FilePath& platform_path) OVERRIDE {
280 NOTREACHED();
282 virtual void DidCreateSnapshotFile(
283 const base::PlatformFileInfo& file_info,
284 const base::FilePath& platform_path) OVERRIDE {
285 NOTREACHED();
287 virtual void DidReadDirectory(
288 const std::vector<base::FileUtilProxy::Entry>& entries,
289 bool has_more) OVERRIDE {
290 NOTREACHED();
292 virtual void DidOpenFileSystem(const std::string& name,
293 const GURL& root) OVERRIDE {
294 NOTREACHED();
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 {
306 NOTREACHED();
309 virtual void DidOpenFile(base::PlatformFile file,
310 int file_open_id,
311 quota::QuotaLimitType quota_policy) OVERRIDE {
312 callback_.Run(base::PLATFORM_FILE_OK,
313 base::PassPlatformFile(&file),
314 quota_policy,
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));
324 private:
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(
341 module, perms);
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)
351 return NULL;
352 return static_cast<HostType*>(ppapi_host->GetResourceHost(resource));
355 } // namespace
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) {
378 if (!pepper_module)
379 return NULL;
380 return new webkit::ppapi::WebPluginImpl(
381 pepper_module.get(), params, AsWeakPtr());
384 return NULL;
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);
397 if (module) {
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);
404 return module;
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);
412 if (!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(
437 info->name, path,
438 PepperPluginRegistry::GetInstance(),
439 permissions);
440 PepperPluginRegistry::GetInstance()->AddLiveModule(path, module);
442 if (!CreateOutOfProcessModule(module,
443 path,
444 permissions,
445 channel_handle,
446 peer_pid,
447 plugin_child_id,
448 false)) // is_external = false
449 return scoped_refptr<webkit::ppapi::PluginModule>();
451 return module;
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,
464 path,
465 permissions,
466 channel_handle,
467 peer_pid,
468 plugin_child_id,
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);
483 int request_id =
484 pending_connect_broker_.Add(new scoped_refptr<PepperBrokerImpl>(broker));
486 // Have the browser start the broker process for us.
487 IPC::Message* msg =
488 new ViewHostMsg_OpenChannelToPpapiBroker(render_view_->routing_id(),
489 request_id,
490 broker_path);
491 if (!render_view_->Send(msg)) {
492 pending_connect_broker_.Remove(request_id);
493 return scoped_refptr<PepperBrokerImpl>();
496 return broker;
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,
505 int plugin_child_id,
506 bool is_external) {
507 scoped_refptr<PepperHungPluginFilter> hung_filter(
508 new PepperHungPluginFilter(path,
509 render_view_->routing_id(),
510 plugin_child_id));
511 scoped_ptr<HostDispatcherWrapper> dispatcher(
512 new HostDispatcherWrapper(module,
513 peer_pid,
514 plugin_child_id,
515 permissions,
516 is_external));
517 if (!dispatcher->Init(
518 channel_handle,
519 webkit::ppapi::PluginModule::GetLocalGetInterfaceFunc(),
520 GetPreferences(),
521 hung_filter.get()))
522 return NULL;
524 RendererPpapiHostImpl* host_impl =
525 RendererPpapiHostImpl::CreateOnModuleForOutOfProcess(
526 module, dispatcher->dispatcher(), permissions);
527 render_view_->PpapiPluginCreated(host_impl);
529 module->InitAsProxied(dispatcher.release());
530 return host_impl;
533 void PepperPluginDelegateImpl::OnPpapiBrokerChannelCreated(
534 int request_id,
535 base::ProcessId broker_pid,
536 const IPC::ChannelHandle& handle) {
537 scoped_refptr<PepperBrokerImpl>* broker_ptr =
538 pending_connect_broker_.Lookup(request_id);
539 if (broker_ptr) {
540 scoped_refptr<PepperBrokerImpl> broker = *broker_ptr;
541 pending_connect_broker_.Remove(request_id);
542 broker->OnBrokerChannelConnected(broker_pid, handle);
543 } else {
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());
562 return true;
566 return false;
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
572 // us.
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,
623 TransportDIB** dib,
624 gfx::Rect* location,
625 gfx::Rect* clip,
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,
635 clip, scale_factor))
636 return *i;
638 return NULL;
641 void PepperPluginDelegateImpl::PluginFocusChanged(
642 webkit::ppapi::PluginInstance* instance,
643 bool focused) {
644 if (focused)
645 focused_plugin_ = instance;
646 else if (focused_plugin_ == instance)
647 focused_plugin_ = NULL;
648 if (render_view_)
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,
679 int selection_start,
680 int selection_end) {
681 if (render_view_) {
682 render_view_->SimulateImeSetComposition(
683 text, underlines, selection_start, selection_end);
687 void PepperPluginDelegateImpl::SimulateImeConfirmComposition(
688 const string16& text) {
689 if (render_view_)
690 render_view_->SimulateImeConfirmComposition(text, ui::Range());
693 void PepperPluginDelegateImpl::OnImeSetComposition(
694 const string16& text,
695 const std::vector<WebKit::WebCompositionUnderline>& underlines,
696 int selection_start,
697 int selection_end) {
698 if (!IsPluginAcceptingCompositionEvents()) {
699 composition_text_ = text;
700 } else {
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())
728 return;
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);
743 } else {
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_)
767 return;
768 return focused_plugin_->GetSurroundingText(text, range);
771 bool PepperPluginDelegateImpl::IsPluginAcceptingCompositionEvents() const {
772 if (!focused_plugin_)
773 return false;
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() {
841 #ifdef ENABLE_GPU
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
844 // modules.
845 const WebPreferences& prefs = render_view_->webkit_preferences();
846 if (!prefs.accelerated_compositing_for_plugins_enabled)
847 return NULL;
848 return new PlatformContext3DImpl;
849 #else
850 return NULL;
851 #endif
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,
875 int total,
876 bool final_result) {
877 render_view_->reportFindInPageMatchCount(identifier, total, final_result);
880 void PepperPluginDelegateImpl::SelectedFindResultChanged(int identifier,
881 int index) {
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) {
921 DCHECK(client);
923 webkit::ppapi::PluginModule* plugin_module =
924 webkit::ppapi::ResourceHelper::GetPluginModule(client);
925 if (!plugin_module)
926 return NULL;
928 scoped_refptr<PepperBrokerImpl> broker =
929 static_cast<PepperBrokerImpl*>(plugin_module->GetBroker());
930 if (!broker) {
931 broker = CreateBroker(plugin_module);
932 if (!broker)
933 return NULL;
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(),
941 request_id,
942 client->GetDocumentUrl(),
943 plugin_module->path()))) {
944 return NULL;
947 // Adds a reference, ensuring that the broker is not deleted when
948 // |broker| goes out of scope.
949 broker->AddPendingConnect(client);
951 return broker;
954 void PepperPluginDelegateImpl::OnPpapiBrokerPermissionResult(
955 int request_id,
956 bool result) {
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;
962 if (!client)
963 return;
965 webkit::ppapi::PluginModule* plugin_module =
966 webkit::ppapi::ResourceHelper::GetPluginModule(client);
967 if (!plugin_module)
968 return;
970 PepperBrokerImpl* broker =
971 static_cast<PepperBrokerImpl*>(plugin_module->GetBroker());
972 broker->OnBrokerPermissionResult(client, result);
975 bool PepperPluginDelegateImpl::AsyncOpenFile(
976 const base::FilePath& path,
977 int flags,
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,
989 int message_id) {
990 AsyncOpenFileCallback* callback =
991 pending_async_open_files_.Lookup(message_id);
992 DCHECK(callback);
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());
999 delete callback;
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(
1053 const GURL& path,
1054 bool recursive,
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(
1063 const GURL& path,
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(
1071 const GURL& path,
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(
1082 const GURL& path,
1083 int64_t length,
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(
1091 const GURL& path,
1092 fileapi::FileSystemCallbackDispatcher* dispatcher) {
1093 FileSystemDispatcher* file_system_dispatcher =
1094 ChildThread::current()->file_system_dispatcher();
1095 return file_system_dispatcher->Remove(path, false /* recursive */,
1096 dispatcher);
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(
1132 const GURL& path,
1133 int flags,
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(
1140 callback));
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));
1158 return socket_id;
1161 void PepperPluginDelegateImpl::TCPSocketConnect(
1162 webkit::ppapi::PPB_TCPSocket_Private_Impl* socket,
1163 uint32 socket_id,
1164 const std::string& host,
1165 uint16_t port) {
1166 RegisterTCPSocket(socket, socket_id);
1167 render_view_->Send(
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,
1174 uint32 socket_id,
1175 const PP_NetAddress_Private& addr) {
1176 RegisterTCPSocket(socket, socket_id);
1177 render_view_->Send(
1178 new PpapiHostMsg_PPBTCPSocket_ConnectWithNetAddress(
1179 render_view_->routing_id(), socket_id, addr));
1182 void PepperPluginDelegateImpl::TCPSocketSSLHandshake(
1183 uint32 socket_id,
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));
1196 render_view_->Send(
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(
1215 uint32 socket_id,
1216 PP_TCPSocketOption_Private name,
1217 bool value) {
1218 DCHECK(tcp_sockets_.Lookup(socket_id));
1219 render_view_->Send(
1220 new PpapiHostMsg_PPBTCPSocket_SetBoolOption(socket_id, name, value));
1223 void PepperPluginDelegateImpl::RegisterTCPSocket(
1224 webkit::ppapi::PPB_TCPSocket_Private_Impl* socket,
1225 uint32 socket_id) {
1226 tcp_sockets_.AddWithID(socket, socket_id);
1229 void PepperPluginDelegateImpl::TCPServerSocketListen(
1230 PP_Resource socket_resource,
1231 const PP_NetAddress_Private& addr,
1232 int32_t backlog) {
1233 render_view_->Send(
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,
1246 uint32 socket_id) {
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) {
1259 return false;
1261 socket_dispatcher->AddNetworkListObserver(observer);
1262 return true;
1263 #else
1264 return false;
1265 #endif
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);
1275 #endif
1278 bool PepperPluginDelegateImpl::X509CertificateParseDER(
1279 const std::vector<char>& der,
1280 ppapi::PPB_X509Certificate_Fields* fields) {
1281 bool succeeded = false;
1282 render_view_->Send(
1283 new PpapiHostMsg_PPBX509Certificate_ParseDER(der, &succeeded, fields));
1284 return succeeded;
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(
1331 size_t size) {
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) {
1391 int request_id =
1392 device_enumeration_event_handler_->RegisterEnumerateDevicesCallback(
1393 callback);
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),
1399 GURL());
1400 #else
1401 MessageLoop::current()->PostTask(
1402 FROM_HERE,
1403 base::Bind(
1404 &PepperDeviceEnumerationEventHandler::OnDevicesEnumerationFailed,
1405 device_enumeration_event_handler_->AsWeakPtr(), request_id));
1406 #endif
1408 return request_id;
1411 void PepperPluginDelegateImpl::StopEnumerateDevices(int request_id) {
1412 device_enumeration_event_handler_->UnregisterEnumerateDevicesCallback(
1413 request_id);
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(
1419 FROM_HERE,
1420 base::Bind(
1421 &MediaStreamDispatcher::StopEnumerateDevices,
1422 render_view_->media_stream_dispatcher()->AsWeakPtr(),
1423 request_id, device_enumeration_event_handler_.get()->AsWeakPtr()));
1424 #endif
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()
1444 return handled;
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,
1455 uint32 socket_id,
1456 bool succeeded,
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);
1461 if (socket)
1462 socket->OnConnectCompleted(succeeded, local_addr, remote_addr);
1463 if (!succeeded)
1464 tcp_sockets_.Remove(socket_id);
1467 void PepperPluginDelegateImpl::OnTCPSocketSSLHandshakeACK(
1468 uint32 plugin_dispatcher_id,
1469 uint32 socket_id,
1470 bool succeeded,
1471 const ppapi::PPB_X509Certificate_Fields& certificate_fields) {
1472 webkit::ppapi::PPB_TCPSocket_Private_Impl* socket =
1473 tcp_sockets_.Lookup(socket_id);
1474 if (socket)
1475 socket->OnSSLHandshakeCompleted(succeeded, certificate_fields);
1478 void PepperPluginDelegateImpl::OnTCPSocketReadACK(uint32 plugin_dispatcher_id,
1479 uint32 socket_id,
1480 bool succeeded,
1481 const std::string& data) {
1482 webkit::ppapi::PPB_TCPSocket_Private_Impl* socket =
1483 tcp_sockets_.Lookup(socket_id);
1484 if (socket)
1485 socket->OnReadCompleted(succeeded, data);
1488 void PepperPluginDelegateImpl::OnTCPSocketWriteACK(uint32 plugin_dispatcher_id,
1489 uint32 socket_id,
1490 bool succeeded,
1491 int32_t bytes_written) {
1492 webkit::ppapi::PPB_TCPSocket_Private_Impl* socket =
1493 tcp_sockets_.Lookup(socket_id);
1494 if (socket)
1495 socket->OnWriteCompleted(succeeded, bytes_written);
1498 void PepperPluginDelegateImpl::OnTCPSocketSetBoolOptionACK(
1499 uint32 plugin_dispatcher_id,
1500 uint32 socket_id,
1501 bool succeeded) {
1502 webkit::ppapi::PPB_TCPSocket_Private_Impl* socket =
1503 tcp_sockets_.Lookup(socket_id);
1504 if (socket)
1505 socket->OnSetOptionCompleted(succeeded);
1508 void PepperPluginDelegateImpl::OnTCPServerSocketListenACK(
1509 uint32 plugin_dispatcher_id,
1510 PP_Resource socket_resource,
1511 uint32 socket_id,
1512 int32_t status) {
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);
1535 if (socket) {
1536 bool succeeded = (accepted_socket_id != 0);
1537 socket->OnAcceptCompleted(succeeded,
1538 accepted_socket_id,
1539 local_addr,
1540 remote_addr);
1541 } else if (accepted_socket_id != 0) {
1542 render_view_->Send(
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) {
1554 int request_id =
1555 device_enumeration_event_handler_->RegisterOpenDeviceCallback(callback);
1557 #if defined(ENABLE_WEBRTC)
1558 render_view_->media_stream_dispatcher()->OpenDevice(
1559 request_id,
1560 device_enumeration_event_handler_.get()->AsWeakPtr(),
1561 device_id,
1562 PepperDeviceEnumerationEventHandler::FromPepperDeviceType(type),
1563 GURL());
1564 #else
1565 MessageLoop::current()->PostTask(
1566 FROM_HERE,
1567 base::Bind(&PepperDeviceEnumerationEventHandler::OnDeviceOpenFailed,
1568 device_enumeration_event_handler_->AsWeakPtr(), request_id));
1569 #endif
1571 return request_id;
1574 void PepperPluginDelegateImpl::CloseDevice(const std::string& label) {
1575 #if defined(ENABLE_WEBRTC)
1576 render_view_->media_stream_dispatcher()->CloseDevice(label);
1577 #endif
1580 int PepperPluginDelegateImpl::GetSessionID(PP_DeviceType_Dev type,
1581 const std::string& label) {
1582 #if defined(ENABLE_WEBRTC)
1583 switch (type) {
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,
1590 default:
1591 NOTREACHED();
1592 return 0;
1594 #else
1595 return 0;
1596 #endif
1599 MouseLockDispatcher::LockTarget*
1600 PepperPluginDelegateImpl::GetOrCreateLockTargetAdapter(
1601 webkit::ppapi::PluginInstance* instance) {
1602 MouseLockDispatcher::LockTarget* target = mouse_lock_instances_[instance];
1603 if (target)
1604 return target;
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);
1616 delete 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();
1628 } else {
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(
1638 handle,
1639 target_process_id,
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