Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(156)

Side by Side Diff: content/renderer/pepper/pepper_plugin_delegate_impl.cc

Issue 20987009: Rename PepperPluginDelegateImpl to PepperHelperImpl after getting rid of the PluginDelegate interfa… (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/renderer/pepper/pepper_plugin_delegate_impl.h"
6
7 #include <cmath>
8 #include <cstddef>
9 #include <map>
10 #include <queue>
11
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/platform_file.h"
19 #include "base/strings/string_split.h"
20 #include "base/sync_socket.h"
21 #include "base/time/time.h"
22 #include "content/child/child_process.h"
23 #include "content/child/npapi/webplugin.h"
24 #include "content/common/child_process_messages.h"
25 #include "content/common/gpu/client/context_provider_command_buffer.h"
26 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
27 #include "content/common/pepper_messages.h"
28 #include "content/common/view_messages.h"
29 #include "content/public/common/content_switches.h"
30 #include "content/public/common/context_menu_params.h"
31 #include "content/public/common/media_stream_request.h"
32 #include "content/public/common/page_zoom.h"
33 #include "content/public/common/referrer.h"
34 #include "content/public/common/webplugininfo.h"
35 #include "content/public/renderer/content_renderer_client.h"
36 #include "content/renderer/gamepad_shared_memory_reader.h"
37 #include "content/renderer/media/media_stream_dispatcher.h"
38 #include "content/renderer/p2p/socket_dispatcher.h"
39 #include "content/renderer/pepper/content_renderer_pepper_host_factory.h"
40 #include "content/renderer/pepper/host_dispatcher_wrapper.h"
41 #include "content/renderer/pepper/pepper_broker.h"
42 #include "content/renderer/pepper/pepper_browser_connection.h"
43 #include "content/renderer/pepper/pepper_file_system_host.h"
44 #include "content/renderer/pepper/pepper_graphics_2d_host.h"
45 #include "content/renderer/pepper/pepper_hung_plugin_filter.h"
46 #include "content/renderer/pepper/pepper_in_process_resource_creation.h"
47 #include "content/renderer/pepper/pepper_in_process_router.h"
48 #include "content/renderer/pepper/pepper_plugin_instance_impl.h"
49 #include "content/renderer/pepper/pepper_plugin_registry.h"
50 #include "content/renderer/pepper/pepper_url_loader_host.h"
51 #include "content/renderer/pepper/pepper_webplugin_impl.h"
52 #include "content/renderer/pepper/plugin_module.h"
53 #include "content/renderer/pepper/ppb_tcp_server_socket_private_impl.h"
54 #include "content/renderer/pepper/ppb_tcp_socket_private_impl.h"
55 #include "content/renderer/pepper/renderer_ppapi_host_impl.h"
56 #include "content/renderer/pepper/resource_helper.h"
57 #include "content/renderer/pepper/url_response_info_util.h"
58 #include "content/renderer/render_thread_impl.h"
59 #include "content/renderer/render_view_impl.h"
60 #include "content/renderer/render_widget_fullscreen_pepper.h"
61 #include "content/renderer/webplugin_delegate_proxy.h"
62 #include "ipc/ipc_channel_handle.h"
63 #include "ipc/ipc_platform_file.h"
64 #include "media/video/capture/video_capture_proxy.h"
65 #include "ppapi/c/dev/pp_video_dev.h"
66 #include "ppapi/c/pp_errors.h"
67 #include "ppapi/c/private/ppb_flash.h"
68 #include "ppapi/proxy/ppapi_messages.h"
69 #include "ppapi/proxy/url_loader_resource.h"
70 #include "ppapi/shared_impl/api_id.h"
71 #include "ppapi/shared_impl/file_path.h"
72 #include "ppapi/shared_impl/platform_file.h"
73 #include "ppapi/shared_impl/ppapi_globals.h"
74 #include "ppapi/shared_impl/ppapi_preferences.h"
75 #include "ppapi/shared_impl/ppb_device_ref_shared.h"
76 #include "ppapi/shared_impl/ppp_instance_combined.h"
77 #include "ppapi/shared_impl/resource_tracker.h"
78 #include "ppapi/shared_impl/socket_option_data.h"
79 #include "ppapi/thunk/enter.h"
80 #include "ppapi/thunk/ppb_tcp_server_socket_private_api.h"
81 #include "third_party/WebKit/public/web/WebCursorInfo.h"
82 #include "third_party/WebKit/public/web/WebFrame.h"
83 #include "third_party/WebKit/public/web/WebInputEvent.h"
84 #include "third_party/WebKit/public/web/WebScreenInfo.h"
85 #include "third_party/WebKit/public/web/WebView.h"
86 #include "ui/gfx/size.h"
87 #include "url/gurl.h"
88
89 using WebKit::WebFrame;
90
91 namespace content {
92
93 namespace {
94
95 void CreateHostForInProcessModule(RenderViewImpl* render_view,
96 PluginModule* module,
97 const WebPluginInfo& webplugin_info) {
98 // First time an in-process plugin was used, make a host for it.
99 const PepperPluginInfo* info =
100 PepperPluginRegistry::GetInstance()->GetInfoForPlugin(webplugin_info);
101 DCHECK(!info->is_out_of_process);
102
103 ppapi::PpapiPermissions perms(
104 PepperPluginRegistry::GetInstance()->GetInfoForPlugin(
105 webplugin_info)->permissions);
106 RendererPpapiHostImpl* host_impl =
107 RendererPpapiHostImpl::CreateOnModuleForInProcess(
108 module, perms);
109 render_view->PpapiPluginCreated(host_impl);
110 }
111
112 } // namespace
113
114 PepperPluginDelegateImpl::PepperPluginDelegateImpl(RenderViewImpl* render_view)
115 : RenderViewObserver(render_view),
116 render_view_(render_view),
117 pepper_browser_connection_(this),
118 focused_plugin_(NULL),
119 last_mouse_event_target_(NULL) {
120 }
121
122 PepperPluginDelegateImpl::~PepperPluginDelegateImpl() {
123 }
124
125 WebKit::WebPlugin* PepperPluginDelegateImpl::CreatePepperWebPlugin(
126 const WebPluginInfo& webplugin_info,
127 const WebKit::WebPluginParams& params) {
128 bool pepper_plugin_was_registered = false;
129 scoped_refptr<PluginModule> pepper_module(
130 CreatePepperPluginModule(webplugin_info, &pepper_plugin_was_registered));
131
132 if (pepper_plugin_was_registered) {
133 if (!pepper_module.get())
134 return NULL;
135 return new PepperWebPluginImpl(
136 pepper_module.get(), params, AsWeakPtr(), render_view_->AsWeakPtr());
137 }
138
139 return NULL;
140 }
141
142 scoped_refptr<PluginModule> PepperPluginDelegateImpl::CreatePepperPluginModule(
143 const WebPluginInfo& webplugin_info,
144 bool* pepper_plugin_was_registered) {
145 *pepper_plugin_was_registered = true;
146
147 // See if a module has already been loaded for this plugin.
148 base::FilePath path(webplugin_info.path);
149 scoped_refptr<PluginModule> module =
150 PepperPluginRegistry::GetInstance()->GetLiveModule(path);
151 if (module.get()) {
152 if (!module->renderer_ppapi_host()) {
153 // If the module exists and no embedder state was associated with it,
154 // then the module was one of the ones preloaded and is an in-process
155 // plugin. We need to associate our host state with it.
156 CreateHostForInProcessModule(render_view_, module.get(), webplugin_info);
157 }
158 return module;
159 }
160
161 // In-process plugins will have always been created up-front to avoid the
162 // sandbox restrictions. So getting here implies it doesn't exist or should
163 // be out of process.
164 const PepperPluginInfo* info =
165 PepperPluginRegistry::GetInstance()->GetInfoForPlugin(webplugin_info);
166 if (!info) {
167 *pepper_plugin_was_registered = false;
168 return scoped_refptr<PluginModule>();
169 } else if (!info->is_out_of_process) {
170 // In-process plugin not preloaded, it probably couldn't be initialized.
171 return scoped_refptr<PluginModule>();
172 }
173
174 ppapi::PpapiPermissions permissions =
175 ppapi::PpapiPermissions::GetForCommandLine(info->permissions);
176
177 // Out of process: have the browser start the plugin process for us.
178 IPC::ChannelHandle channel_handle;
179 base::ProcessId peer_pid;
180 int plugin_child_id = 0;
181 Send(new ViewHostMsg_OpenChannelToPepperPlugin(
182 path, &channel_handle, &peer_pid, &plugin_child_id));
183 if (channel_handle.name.empty()) {
184 // Couldn't be initialized.
185 return scoped_refptr<PluginModule>();
186 }
187
188 // AddLiveModule must be called before any early returns since the
189 // module's destructor will remove itself.
190 module = new PluginModule(info->name, path, permissions);
191 PepperPluginRegistry::GetInstance()->AddLiveModule(path, module.get());
192
193 if (!CreateOutOfProcessModule(module.get(),
194 path,
195 permissions,
196 channel_handle,
197 peer_pid,
198 plugin_child_id,
199 false)) // is_external = false
200 return scoped_refptr<PluginModule>();
201
202 return module;
203 }
204
205 scoped_refptr<PepperBroker> PepperPluginDelegateImpl::CreateBroker(
206 PluginModule* plugin_module) {
207 DCHECK(plugin_module);
208 DCHECK(!plugin_module->GetBroker());
209
210 // The broker path is the same as the plugin.
211 const base::FilePath& broker_path = plugin_module->path();
212
213 scoped_refptr<PepperBroker> broker = new PepperBroker(plugin_module, this);
214
215 int request_id =
216 pending_connect_broker_.Add(new scoped_refptr<PepperBroker>(broker));
217
218 // Have the browser start the broker process for us.
219 Send(new ViewHostMsg_OpenChannelToPpapiBroker(
220 routing_id(), request_id, broker_path));
221
222 return broker;
223 }
224
225 RendererPpapiHost* PepperPluginDelegateImpl::CreateOutOfProcessModule(
226 PluginModule* module,
227 const base::FilePath& path,
228 ppapi::PpapiPermissions permissions,
229 const IPC::ChannelHandle& channel_handle,
230 base::ProcessId peer_pid,
231 int plugin_child_id,
232 bool is_external) {
233 scoped_refptr<PepperHungPluginFilter> hung_filter(
234 new PepperHungPluginFilter(path, routing_id(), plugin_child_id));
235 scoped_ptr<HostDispatcherWrapper> dispatcher(
236 new HostDispatcherWrapper(module,
237 peer_pid,
238 plugin_child_id,
239 permissions,
240 is_external));
241 if (!dispatcher->Init(
242 channel_handle,
243 PluginModule::GetLocalGetInterfaceFunc(),
244 ppapi::Preferences(render_view_->webkit_preferences()),
245 hung_filter.get()))
246 return NULL;
247
248 RendererPpapiHostImpl* host_impl =
249 RendererPpapiHostImpl::CreateOnModuleForOutOfProcess(
250 module, dispatcher->dispatcher(), permissions);
251 render_view_->PpapiPluginCreated(host_impl);
252
253 module->InitAsProxied(dispatcher.release());
254 return host_impl;
255 }
256
257 void PepperPluginDelegateImpl::OnPpapiBrokerChannelCreated(
258 int request_id,
259 base::ProcessId broker_pid,
260 const IPC::ChannelHandle& handle) {
261 scoped_refptr<PepperBroker>* broker_ptr =
262 pending_connect_broker_.Lookup(request_id);
263 if (broker_ptr) {
264 scoped_refptr<PepperBroker> broker = *broker_ptr;
265 pending_connect_broker_.Remove(request_id);
266 broker->OnBrokerChannelConnected(broker_pid, handle);
267 } else {
268 // There is no broker waiting for this channel. Close it so the broker can
269 // clean up and possibly exit.
270 // The easiest way to clean it up is to just put it in an object
271 // and then close them. This failure case is not performance critical.
272 PepperBrokerDispatcherWrapper temp_dispatcher;
273 temp_dispatcher.Init(broker_pid, handle);
274 }
275 }
276
277 // Iterates through pending_connect_broker_ to find the broker.
278 // Cannot use Lookup() directly because pending_connect_broker_ does not store
279 // the raw pointer to the broker. Assumes maximum of one copy of broker exists.
280 bool PepperPluginDelegateImpl::StopWaitingForBrokerConnection(
281 PepperBroker* broker) {
282 for (BrokerMap::iterator i(&pending_connect_broker_);
283 !i.IsAtEnd(); i.Advance()) {
284 if (i.GetCurrentValue()->get() == broker) {
285 pending_connect_broker_.Remove(i.GetCurrentKey());
286 return true;
287 }
288 }
289
290 return false;
291 }
292
293 void PepperPluginDelegateImpl::ViewWillInitiatePaint() {
294 // Notify all of our instances that we started painting. This is used for
295 // internal bookkeeping only, so we know that the set can not change under
296 // us.
297 for (std::set<PepperPluginInstanceImpl*>::iterator i =
298 active_instances_.begin();
299 i != active_instances_.end(); ++i)
300 (*i)->ViewWillInitiatePaint();
301 }
302
303 void PepperPluginDelegateImpl::ViewInitiatedPaint() {
304 // Notify all instances that we painted. The same caveats apply as for
305 // ViewFlushedPaint regarding instances closing themselves, so we take
306 // similar precautions.
307 std::set<PepperPluginInstanceImpl*> plugins = active_instances_;
308 for (std::set<PepperPluginInstanceImpl*>::iterator i = plugins.begin();
309 i != plugins.end(); ++i) {
310 if (active_instances_.find(*i) != active_instances_.end())
311 (*i)->ViewInitiatedPaint();
312 }
313 }
314
315 void PepperPluginDelegateImpl::ViewFlushedPaint() {
316 // Notify all instances that we flushed. This will call into the plugin, and
317 // we it may ask to close itself as a result. This will, in turn, modify our
318 // set, possibly invalidating the iterator. So we iterate on a copy that
319 // won't change out from under us.
320 std::set<PepperPluginInstanceImpl*> plugins = active_instances_;
321 for (std::set<PepperPluginInstanceImpl*>::iterator i = plugins.begin();
322 i != plugins.end(); ++i) {
323 // The copy above makes sure our iterator is never invalid if some plugins
324 // are destroyed. But some plugin may decide to close all of its views in
325 // response to a paint in one of them, so we need to make sure each one is
326 // still "current" before using it.
327 //
328 // It's possible that a plugin was destroyed, but another one was created
329 // with the same address. In this case, we'll call ViewFlushedPaint on that
330 // new plugin. But that's OK for this particular case since we're just
331 // notifying all of our instances that the view flushed, and the new one is
332 // one of our instances.
333 //
334 // What about the case where a new one is created in a callback at a new
335 // address and we don't issue the callback? We're still OK since this
336 // callback is used for flush callbacks and we could not have possibly
337 // started a new paint (ViewWillInitiatePaint) for the new plugin while
338 // processing a previous paint for an existing one.
339 if (active_instances_.find(*i) != active_instances_.end())
340 (*i)->ViewFlushedPaint();
341 }
342 }
343
344 PepperPluginInstanceImpl* PepperPluginDelegateImpl::
345 GetBitmapForOptimizedPluginPaint(
346 const gfx::Rect& paint_bounds,
347 TransportDIB** dib,
348 gfx::Rect* location,
349 gfx::Rect* clip,
350 float* scale_factor) {
351 for (std::set<PepperPluginInstanceImpl*>::iterator i =
352 active_instances_.begin();
353 i != active_instances_.end(); ++i) {
354 PepperPluginInstanceImpl* instance = *i;
355 // In Flash fullscreen , the plugin contents should be painted onto the
356 // fullscreen widget instead of the web page.
357 if (!instance->FlashIsFullscreenOrPending() &&
358 instance->GetBitmapForOptimizedPluginPaint(paint_bounds, dib, location,
359 clip, scale_factor))
360 return *i;
361 }
362 return NULL;
363 }
364
365 void PepperPluginDelegateImpl::PluginFocusChanged(
366 PepperPluginInstanceImpl* instance,
367 bool focused) {
368 if (focused)
369 focused_plugin_ = instance;
370 else if (focused_plugin_ == instance)
371 focused_plugin_ = NULL;
372 if (render_view_)
373 render_view_->PpapiPluginFocusChanged();
374 }
375
376 void PepperPluginDelegateImpl::PluginTextInputTypeChanged(
377 PepperPluginInstanceImpl* instance) {
378 if (focused_plugin_ == instance && render_view_)
379 render_view_->PpapiPluginTextInputTypeChanged();
380 }
381
382 void PepperPluginDelegateImpl::PluginCaretPositionChanged(
383 PepperPluginInstanceImpl* instance) {
384 if (focused_plugin_ == instance && render_view_)
385 render_view_->PpapiPluginCaretPositionChanged();
386 }
387
388 void PepperPluginDelegateImpl::PluginRequestedCancelComposition(
389 PepperPluginInstanceImpl* instance) {
390 if (focused_plugin_ == instance && render_view_)
391 render_view_->PpapiPluginCancelComposition();
392 }
393
394 void PepperPluginDelegateImpl::PluginSelectionChanged(
395 PepperPluginInstanceImpl* instance) {
396 if (focused_plugin_ == instance && render_view_)
397 render_view_->PpapiPluginSelectionChanged();
398 }
399
400 void PepperPluginDelegateImpl::OnImeSetComposition(
401 const string16& text,
402 const std::vector<WebKit::WebCompositionUnderline>& underlines,
403 int selection_start,
404 int selection_end) {
405 if (!IsPluginAcceptingCompositionEvents()) {
406 composition_text_ = text;
407 } else {
408 // TODO(kinaba) currently all composition events are sent directly to
409 // plugins. Use DOM event mechanism after WebKit is made aware about
410 // plugins that support composition.
411 // The code below mimics the behavior of WebCore::Editor::setComposition.
412
413 // Empty -> nonempty: composition started.
414 if (composition_text_.empty() && !text.empty())
415 focused_plugin_->HandleCompositionStart(string16());
416 // Nonempty -> empty: composition canceled.
417 if (!composition_text_.empty() && text.empty())
418 focused_plugin_->HandleCompositionEnd(string16());
419 composition_text_ = text;
420 // Nonempty: composition is ongoing.
421 if (!composition_text_.empty()) {
422 focused_plugin_->HandleCompositionUpdate(composition_text_, underlines,
423 selection_start, selection_end);
424 }
425 }
426 }
427
428 void PepperPluginDelegateImpl::OnImeConfirmComposition(const string16& text) {
429 // Here, text.empty() has a special meaning. It means to commit the last
430 // update of composition text (see RenderWidgetHost::ImeConfirmComposition()).
431 const string16& last_text = text.empty() ? composition_text_ : text;
432
433 // last_text is empty only when both text and composition_text_ is. Ignore it.
434 if (last_text.empty())
435 return;
436
437 if (!IsPluginAcceptingCompositionEvents()) {
438 for (size_t i = 0; i < text.size(); ++i) {
439 WebKit::WebKeyboardEvent char_event;
440 char_event.type = WebKit::WebInputEvent::Char;
441 char_event.timeStampSeconds = base::Time::Now().ToDoubleT();
442 char_event.modifiers = 0;
443 char_event.windowsKeyCode = last_text[i];
444 char_event.nativeKeyCode = last_text[i];
445 char_event.text[0] = last_text[i];
446 char_event.unmodifiedText[0] = last_text[i];
447 if (render_view_->webwidget())
448 render_view_->webwidget()->handleInputEvent(char_event);
449 }
450 } else {
451 // Mimics the order of events sent by WebKit.
452 // See WebCore::Editor::setComposition() for the corresponding code.
453 focused_plugin_->HandleCompositionEnd(last_text);
454 focused_plugin_->HandleTextInput(last_text);
455 }
456 composition_text_.clear();
457 }
458
459 gfx::Rect PepperPluginDelegateImpl::GetCaretBounds() const {
460 if (!focused_plugin_)
461 return gfx::Rect(0, 0, 0, 0);
462 return focused_plugin_->GetCaretBounds();
463 }
464
465 ui::TextInputType PepperPluginDelegateImpl::GetTextInputType() const {
466 if (!focused_plugin_)
467 return ui::TEXT_INPUT_TYPE_NONE;
468 return focused_plugin_->text_input_type();
469 }
470
471 void PepperPluginDelegateImpl::GetSurroundingText(string16* text,
472 ui::Range* range) const {
473 if (!focused_plugin_)
474 return;
475 return focused_plugin_->GetSurroundingText(text, range);
476 }
477
478 bool PepperPluginDelegateImpl::IsPluginAcceptingCompositionEvents() const {
479 if (!focused_plugin_)
480 return false;
481 return focused_plugin_->IsPluginAcceptingCompositionEvents();
482 }
483
484 bool PepperPluginDelegateImpl::CanComposeInline() const {
485 return IsPluginAcceptingCompositionEvents();
486 }
487
488 void PepperPluginDelegateImpl::InstanceCreated(
489 PepperPluginInstanceImpl* instance) {
490 active_instances_.insert(instance);
491
492 // Set the initial focus.
493 instance->SetContentAreaFocus(render_view_->has_focus());
494 }
495
496 void PepperPluginDelegateImpl::InstanceDeleted(
497 PepperPluginInstanceImpl* instance) {
498 active_instances_.erase(instance);
499
500 if (last_mouse_event_target_ == instance)
501 last_mouse_event_target_ = NULL;
502 if (focused_plugin_ == instance)
503 PluginFocusChanged(instance, false);
504 }
505
506 // If a broker has not already been created for this plugin, creates one.
507 PepperBroker* PepperPluginDelegateImpl::ConnectToBroker(
508 PPB_Broker_Impl* client) {
509 DCHECK(client);
510
511 PluginModule* plugin_module = ResourceHelper::GetPluginModule(client);
512 if (!plugin_module)
513 return NULL;
514
515 scoped_refptr<PepperBroker> broker =
516 static_cast<PepperBroker*>(plugin_module->GetBroker());
517 if (!broker.get())
518 broker = CreateBroker(plugin_module);
519
520 int request_id = pending_permission_requests_.Add(
521 new base::WeakPtr<PPB_Broker_Impl>(client->AsWeakPtr()));
522 Send(new ViewHostMsg_RequestPpapiBrokerPermission(
523 routing_id(),
524 request_id,
525 client->GetDocumentUrl(),
526 plugin_module->path()));
527
528 // Adds a reference, ensuring that the broker is not deleted when
529 // |broker| goes out of scope.
530 broker->AddPendingConnect(client);
531
532 return broker.get();
533 }
534
535 void PepperPluginDelegateImpl::OnPpapiBrokerPermissionResult(
536 int request_id,
537 bool result) {
538 scoped_ptr<base::WeakPtr<PPB_Broker_Impl> > client_ptr(
539 pending_permission_requests_.Lookup(request_id));
540 DCHECK(client_ptr.get());
541 pending_permission_requests_.Remove(request_id);
542 base::WeakPtr<PPB_Broker_Impl> client = *client_ptr;
543 if (!client.get())
544 return;
545
546 PluginModule* plugin_module = ResourceHelper::GetPluginModule(client.get());
547 if (!plugin_module)
548 return;
549
550 PepperBroker* broker = static_cast<PepperBroker*>(plugin_module->GetBroker());
551 broker->OnBrokerPermissionResult(client.get(), result);
552 }
553
554 bool PepperPluginDelegateImpl::AsyncOpenFile(
555 const base::FilePath& path,
556 int flags,
557 const AsyncOpenFileCallback& callback) {
558 int message_id = pending_async_open_files_.Add(
559 new AsyncOpenFileCallback(callback));
560 return Send(new ViewHostMsg_AsyncOpenFile(
561 routing_id(), path, flags, message_id));
562 }
563
564 void PepperPluginDelegateImpl::OnAsyncFileOpened(
565 base::PlatformFileError error_code,
566 IPC::PlatformFileForTransit file_for_transit,
567 int message_id) {
568 AsyncOpenFileCallback* callback =
569 pending_async_open_files_.Lookup(message_id);
570 DCHECK(callback);
571 pending_async_open_files_.Remove(message_id);
572
573 base::PlatformFile file =
574 IPC::PlatformFileForTransitToPlatformFile(file_for_transit);
575 callback->Run(error_code, base::PassPlatformFile(&file));
576 // Make sure we won't leak file handle if the requester has died.
577 if (file != base::kInvalidPlatformFileValue) {
578 base::FileUtilProxy::Close(
579 RenderThreadImpl::current()->GetFileThreadMessageLoopProxy().get(),
580 file,
581 base::FileUtilProxy::StatusCallback());
582 }
583 delete callback;
584 }
585
586 void PepperPluginDelegateImpl::OnSetFocus(bool has_focus) {
587 for (std::set<PepperPluginInstanceImpl*>::iterator i =
588 active_instances_.begin();
589 i != active_instances_.end(); ++i)
590 (*i)->SetContentAreaFocus(has_focus);
591 }
592
593 void PepperPluginDelegateImpl::PageVisibilityChanged(bool is_visible) {
594 for (std::set<PepperPluginInstanceImpl*>::iterator i =
595 active_instances_.begin();
596 i != active_instances_.end(); ++i)
597 (*i)->PageVisibilityChanged(is_visible);
598 }
599
600 bool PepperPluginDelegateImpl::IsPluginFocused() const {
601 return focused_plugin_ != NULL;
602 }
603
604 void PepperPluginDelegateImpl::WillHandleMouseEvent() {
605 // This method is called for every mouse event that the render view receives.
606 // And then the mouse event is forwarded to WebKit, which dispatches it to the
607 // event target. Potentially a Pepper plugin will receive the event.
608 // In order to tell whether a plugin gets the last mouse event and which it
609 // is, we set |last_mouse_event_target_| to NULL here. If a plugin gets the
610 // event, it will notify us via DidReceiveMouseEvent() and set itself as
611 // |last_mouse_event_target_|.
612 last_mouse_event_target_ = NULL;
613 }
614
615 void PepperPluginDelegateImpl::RegisterTCPSocket(
616 PPB_TCPSocket_Private_Impl* socket,
617 uint32 socket_id) {
618 tcp_sockets_.AddWithID(socket, socket_id);
619 }
620
621 void PepperPluginDelegateImpl::UnregisterTCPSocket(uint32 socket_id) {
622 // There is no DCHECK(tcp_sockets_.Lookup(socket_id)) because this method
623 // can be called before TCPSocketConnect or TCPSocketConnectWithNetAddress.
624 if (tcp_sockets_.Lookup(socket_id))
625 tcp_sockets_.Remove(socket_id);
626 }
627
628 void PepperPluginDelegateImpl::TCPServerSocketStopListening(uint32 socket_id) {
629 tcp_server_sockets_.Remove(socket_id);
630 }
631
632 void PepperPluginDelegateImpl::HandleDocumentLoad(
633 PepperPluginInstanceImpl* instance,
634 const WebKit::WebURLResponse& response) {
635 DCHECK(!instance->document_loader());
636
637 PP_Instance pp_instance = instance->pp_instance();
638 RendererPpapiHostImpl* host_impl = instance->module()->renderer_ppapi_host();
639
640 // Create a loader resource host for this load. Note that we have to set
641 // the document_loader before issuing the in-process
642 // PPP_Instance.HandleDocumentLoad call below, since this may reentrantly
643 // call into the instance and expect it to be valid.
644 PepperURLLoaderHost* loader_host =
645 new PepperURLLoaderHost(host_impl, true, pp_instance, 0);
646 instance->set_document_loader(loader_host);
647 loader_host->didReceiveResponse(NULL, response);
648
649 // This host will be pending until the resource object attaches to it.
650 int pending_host_id = host_impl->GetPpapiHost()->AddPendingResourceHost(
651 scoped_ptr<ppapi::host::ResourceHost>(loader_host));
652 DCHECK(pending_host_id);
653 ppapi::URLResponseInfoData data =
654 DataFromWebURLResponse(pp_instance, response);
655
656 if (host_impl->in_process_router()) {
657 // Running in-process, we can just create the resource and call the
658 // PPP_Instance function directly.
659 scoped_refptr<ppapi::proxy::URLLoaderResource> loader_resource(
660 new ppapi::proxy::URLLoaderResource(
661 host_impl->in_process_router()->GetPluginConnection(pp_instance),
662 pp_instance, pending_host_id, data));
663
664 PP_Resource loader_pp_resource = loader_resource->GetReference();
665 if (!instance->instance_interface()->HandleDocumentLoad(
666 instance->pp_instance(), loader_pp_resource))
667 loader_resource->Close();
668 // We don't pass a ref into the plugin, if it wants one, it will have taken
669 // an additional one.
670 ppapi::PpapiGlobals::Get()->GetResourceTracker()->ReleaseResource(
671 loader_pp_resource);
672
673 // Danger! If the plugin doesn't take a ref in HandleDocumentLoad, the
674 // resource host will be destroyed as soon as our scoped_refptr for the
675 // resource goes out of scope.
676 //
677 // Null it out so people don't accidentally add code below that uses it.
678 loader_host = NULL;
679 } else {
680 // Running out-of-process. Initiate an IPC call to notify the plugin
681 // process.
682 ppapi::proxy::HostDispatcher* dispatcher =
683 ppapi::proxy::HostDispatcher::GetForInstance(pp_instance);
684 dispatcher->Send(new PpapiMsg_PPPInstance_HandleDocumentLoad(
685 ppapi::API_ID_PPP_INSTANCE, pp_instance, pending_host_id, data));
686 }
687 }
688
689 RendererPpapiHost* PepperPluginDelegateImpl::CreateExternalPluginModule(
690 scoped_refptr<PluginModule> module,
691 const base::FilePath& path,
692 ppapi::PpapiPermissions permissions,
693 const IPC::ChannelHandle& channel_handle,
694 base::ProcessId peer_pid,
695 int plugin_child_id) {
696 // We don't call PepperPluginRegistry::AddLiveModule, as this module is
697 // managed externally.
698 return CreateOutOfProcessModule(module.get(),
699 path,
700 permissions,
701 channel_handle,
702 peer_pid,
703 plugin_child_id,
704 true); // is_external = true
705 }
706
707 void PepperPluginDelegateImpl::DidChangeCursor(
708 PepperPluginInstanceImpl* instance,
709 const WebKit::WebCursorInfo& cursor) {
710 // Update the cursor appearance immediately if the requesting plugin is the
711 // one which receives the last mouse event. Otherwise, the new cursor won't be
712 // picked up until the plugin gets the next input event. That is bad if, e.g.,
713 // the plugin would like to set an invisible cursor when there isn't any user
714 // input for a while.
715 if (instance == last_mouse_event_target_)
716 render_view_->didChangeCursor(cursor);
717 }
718
719 void PepperPluginDelegateImpl::DidReceiveMouseEvent(
720 PepperPluginInstanceImpl* instance) {
721 last_mouse_event_target_ = instance;
722 }
723
724 void PepperPluginDelegateImpl::SampleGamepads(WebKit::WebGamepads* data) {
725 if (!gamepad_shared_memory_reader_)
726 gamepad_shared_memory_reader_.reset(new GamepadSharedMemoryReader);
727 gamepad_shared_memory_reader_->SampleGamepads(*data);
728 }
729
730 bool PepperPluginDelegateImpl::OnMessageReceived(const IPC::Message& message) {
731 if (pepper_browser_connection_.OnMessageReceived(message))
732 return true;
733
734 bool handled = true;
735 IPC_BEGIN_MESSAGE_MAP(PepperPluginDelegateImpl, message)
736 IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPSocket_ConnectACK,
737 OnTCPSocketConnectACK)
738 IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPSocket_SSLHandshakeACK,
739 OnTCPSocketSSLHandshakeACK)
740 IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPSocket_ReadACK, OnTCPSocketReadACK)
741 IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPSocket_WriteACK, OnTCPSocketWriteACK)
742 IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPSocket_SetOptionACK,
743 OnTCPSocketSetOptionACK)
744 IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPServerSocket_ListenACK,
745 OnTCPServerSocketListenACK)
746 IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPServerSocket_AcceptACK,
747 OnTCPServerSocketAcceptACK)
748 IPC_MESSAGE_HANDLER(ViewMsg_PpapiBrokerChannelCreated,
749 OnPpapiBrokerChannelCreated)
750 IPC_MESSAGE_HANDLER(ViewMsg_AsyncOpenFile_ACK, OnAsyncFileOpened)
751 IPC_MESSAGE_HANDLER(ViewMsg_PpapiBrokerPermissionResult,
752 OnPpapiBrokerPermissionResult)
753 IPC_MESSAGE_UNHANDLED(handled = false)
754 IPC_END_MESSAGE_MAP()
755 return handled;
756 }
757
758 void PepperPluginDelegateImpl::OnDestruct() {
759 // Nothing to do here. Default implementation in RenderViewObserver does
760 // 'delete this' but it's not suitable for PepperPluginDelegateImpl because
761 // it's non-pointer member in RenderViewImpl.
762 }
763
764 void PepperPluginDelegateImpl::OnTCPSocketConnectACK(
765 uint32 plugin_dispatcher_id,
766 uint32 socket_id,
767 int32_t result,
768 const PP_NetAddress_Private& local_addr,
769 const PP_NetAddress_Private& remote_addr) {
770 PPB_TCPSocket_Private_Impl* socket = tcp_sockets_.Lookup(socket_id);
771 if (socket)
772 socket->OnConnectCompleted(result, local_addr, remote_addr);
773 if (result != PP_OK)
774 tcp_sockets_.Remove(socket_id);
775 }
776
777 void PepperPluginDelegateImpl::OnTCPSocketSSLHandshakeACK(
778 uint32 plugin_dispatcher_id,
779 uint32 socket_id,
780 bool succeeded,
781 const ppapi::PPB_X509Certificate_Fields& certificate_fields) {
782 PPB_TCPSocket_Private_Impl* socket = tcp_sockets_.Lookup(socket_id);
783 if (socket)
784 socket->OnSSLHandshakeCompleted(succeeded, certificate_fields);
785 }
786
787 void PepperPluginDelegateImpl::OnTCPSocketReadACK(uint32 plugin_dispatcher_id,
788 uint32 socket_id,
789 int32_t result,
790 const std::string& data) {
791 PPB_TCPSocket_Private_Impl* socket = tcp_sockets_.Lookup(socket_id);
792 if (socket)
793 socket->OnReadCompleted(result, data);
794 }
795
796 void PepperPluginDelegateImpl::OnTCPSocketWriteACK(uint32 plugin_dispatcher_id,
797 uint32 socket_id,
798 int32_t result) {
799 PPB_TCPSocket_Private_Impl* socket = tcp_sockets_.Lookup(socket_id);
800 if (socket)
801 socket->OnWriteCompleted(result);
802 }
803
804 void PepperPluginDelegateImpl::OnTCPSocketSetOptionACK(
805 uint32 plugin_dispatcher_id,
806 uint32 socket_id,
807 int32_t result) {
808 PPB_TCPSocket_Private_Impl* socket = tcp_sockets_.Lookup(socket_id);
809 if (socket)
810 socket->OnSetOptionCompleted(result);
811 }
812
813 void PepperPluginDelegateImpl::OnTCPServerSocketListenACK(
814 uint32 plugin_dispatcher_id,
815 PP_Resource socket_resource,
816 uint32 socket_id,
817 const PP_NetAddress_Private& local_addr,
818 int32_t status) {
819 ppapi::thunk::EnterResource<ppapi::thunk::PPB_TCPServerSocket_Private_API>
820 enter(socket_resource, true);
821 if (enter.succeeded()) {
822 ppapi::PPB_TCPServerSocket_Shared* socket =
823 static_cast<ppapi::PPB_TCPServerSocket_Shared*>(enter.object());
824 if (status == PP_OK)
825 tcp_server_sockets_.AddWithID(socket, socket_id);
826 socket->OnListenCompleted(socket_id, local_addr, status);
827 } else if (socket_id != 0 && status == PP_OK) {
828 // StopListening was called before completion of Listen.
829 Send(new PpapiHostMsg_PPBTCPServerSocket_Destroy(socket_id));
830 }
831 }
832
833 void PepperPluginDelegateImpl::OnTCPServerSocketAcceptACK(
834 uint32 plugin_dispatcher_id,
835 uint32 server_socket_id,
836 uint32 accepted_socket_id,
837 const PP_NetAddress_Private& local_addr,
838 const PP_NetAddress_Private& remote_addr) {
839 ppapi::PPB_TCPServerSocket_Shared* socket =
840 tcp_server_sockets_.Lookup(server_socket_id);
841 if (socket) {
842 bool succeeded = (accepted_socket_id != 0);
843 socket->OnAcceptCompleted(succeeded,
844 accepted_socket_id,
845 local_addr,
846 remote_addr);
847 } else if (accepted_socket_id != 0) {
848 Send(new PpapiHostMsg_PPBTCPSocket_Disconnect(accepted_socket_id));
849 }
850 }
851
852 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/pepper/pepper_plugin_delegate_impl.h ('k') | content/renderer/pepper/pepper_plugin_instance_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698