[content shell] implement testRunner.overridePreference
[chromium-blink-merge.git] / content / renderer / webplugin_delegate_proxy.cc
bloba05cfec1914393331e77a7567596fa37c183f70f
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/webplugin_delegate_proxy.h"
7 #if defined(TOOLKIT_GTK)
8 #include <gtk/gtk.h>
9 #elif defined(USE_X11)
10 #include <cairo/cairo.h>
11 #endif
13 #include <algorithm>
15 #include "base/auto_reset.h"
16 #include "base/basictypes.h"
17 #include "base/command_line.h"
18 #include "base/file_util.h"
19 #include "base/logging.h"
20 #include "base/memory/ref_counted.h"
21 #include "base/memory/scoped_ptr.h"
22 #include "base/process.h"
23 #include "base/string_split.h"
24 #include "base/string_util.h"
25 #include "base/utf_string_conversions.h"
26 #include "base/version.h"
27 #include "content/common/child_process.h"
28 #include "content/common/npobject_proxy.h"
29 #include "content/common/npobject_stub.h"
30 #include "content/common/npobject_util.h"
31 #include "content/common/plugin_messages.h"
32 #include "content/common/view_messages.h"
33 #include "content/public/renderer/content_renderer_client.h"
34 #include "content/renderer/plugin_channel_host.h"
35 #include "content/renderer/render_thread_impl.h"
36 #include "content/renderer/render_view_impl.h"
37 #include "ipc/ipc_channel_handle.h"
38 #include "net/base/mime_util.h"
39 #include "skia/ext/platform_canvas.h"
40 #include "third_party/WebKit/Source/WebKit/chromium/public/WebBindings.h"
41 #include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h"
42 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
43 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
44 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
45 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebDragData.h"
46 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h"
47 #include "ui/gfx/blit.h"
48 #include "ui/gfx/canvas.h"
49 #include "ui/gfx/native_widget_types.h"
50 #include "ui/gfx/size.h"
51 #include "ui/gfx/skia_util.h"
52 #include "webkit/glue/webkit_glue.h"
53 #include "webkit/plugins/npapi/webplugin.h"
54 #include "webkit/plugins/plugin_constants.h"
55 #include "webkit/plugins/sad_plugin.h"
57 #if defined(OS_POSIX)
58 #include "ipc/ipc_channel_posix.h"
59 #endif
61 #if defined(OS_MACOSX)
62 #include "base/mac/mac_util.h"
63 #endif
65 #if defined(OS_WIN)
66 #include "content/public/common/sandbox_init.h"
67 #endif
69 using WebKit::WebBindings;
70 using WebKit::WebCursorInfo;
71 using WebKit::WebDragData;
72 using WebKit::WebInputEvent;
73 using WebKit::WebString;
74 using WebKit::WebView;
76 namespace content {
78 namespace {
80 class ScopedLogLevel {
81 public:
82 explicit ScopedLogLevel(int level);
83 ~ScopedLogLevel();
85 private:
86 int old_level_;
88 DISALLOW_COPY_AND_ASSIGN(ScopedLogLevel);
91 ScopedLogLevel::ScopedLogLevel(int level)
92 : old_level_(logging::GetMinLogLevel()) {
93 logging::SetMinLogLevel(level);
96 ScopedLogLevel::~ScopedLogLevel() {
97 logging::SetMinLogLevel(old_level_);
100 // Proxy for WebPluginResourceClient. The object owns itself after creation,
101 // deleting itself after its callback has been called.
102 class ResourceClientProxy : public webkit::npapi::WebPluginResourceClient {
103 public:
104 ResourceClientProxy(PluginChannelHost* channel, int instance_id)
105 : channel_(channel), instance_id_(instance_id), resource_id_(0),
106 multibyte_response_expected_(false) {
109 ~ResourceClientProxy() {
112 void Initialize(unsigned long resource_id, const GURL& url, int notify_id) {
113 resource_id_ = resource_id;
114 channel_->Send(new PluginMsg_HandleURLRequestReply(
115 instance_id_, resource_id, url, notify_id));
118 void InitializeForSeekableStream(unsigned long resource_id,
119 int range_request_id) {
120 resource_id_ = resource_id;
121 multibyte_response_expected_ = true;
122 channel_->Send(new PluginMsg_HTTPRangeRequestReply(
123 instance_id_, resource_id, range_request_id));
126 // PluginResourceClient implementation:
127 void WillSendRequest(const GURL& url, int http_status_code) {
128 DCHECK(channel_ != NULL);
129 channel_->Send(new PluginMsg_WillSendRequest(instance_id_, resource_id_,
130 url, http_status_code));
133 void DidReceiveResponse(const std::string& mime_type,
134 const std::string& headers,
135 uint32 expected_length,
136 uint32 last_modified,
137 bool request_is_seekable) {
138 DCHECK(channel_ != NULL);
139 PluginMsg_DidReceiveResponseParams params;
140 params.id = resource_id_;
141 params.mime_type = mime_type;
142 params.headers = headers;
143 params.expected_length = expected_length;
144 params.last_modified = last_modified;
145 params.request_is_seekable = request_is_seekable;
146 // Grab a reference on the underlying channel so it does not get
147 // deleted from under us.
148 scoped_refptr<PluginChannelHost> channel_ref(channel_);
149 channel_->Send(new PluginMsg_DidReceiveResponse(instance_id_, params));
152 void DidReceiveData(const char* buffer, int length, int data_offset) {
153 DCHECK(channel_ != NULL);
154 DCHECK_GT(length, 0);
155 std::vector<char> data;
156 data.resize(static_cast<size_t>(length));
157 memcpy(&data.front(), buffer, length);
158 // Grab a reference on the underlying channel so it does not get
159 // deleted from under us.
160 scoped_refptr<PluginChannelHost> channel_ref(channel_);
161 channel_->Send(new PluginMsg_DidReceiveData(instance_id_, resource_id_,
162 data, data_offset));
165 void DidFinishLoading() {
166 DCHECK(channel_ != NULL);
167 channel_->Send(new PluginMsg_DidFinishLoading(instance_id_, resource_id_));
168 channel_ = NULL;
169 MessageLoop::current()->DeleteSoon(FROM_HERE, this);
172 void DidFail() {
173 DCHECK(channel_ != NULL);
174 channel_->Send(new PluginMsg_DidFail(instance_id_, resource_id_));
175 channel_ = NULL;
176 MessageLoop::current()->DeleteSoon(FROM_HERE, this);
179 bool IsMultiByteResponseExpected() {
180 return multibyte_response_expected_;
183 int ResourceId() {
184 return resource_id_;
187 private:
188 scoped_refptr<PluginChannelHost> channel_;
189 int instance_id_;
190 unsigned long resource_id_;
191 // Set to true if the response expected is a multibyte response.
192 // For e.g. response for a HTTP byte range request.
193 bool multibyte_response_expected_;
196 } // namespace
198 WebPluginDelegateProxy::WebPluginDelegateProxy(
199 const std::string& mime_type,
200 const base::WeakPtr<RenderViewImpl>& render_view)
201 : render_view_(render_view),
202 plugin_(NULL),
203 uses_shared_bitmaps_(false),
204 #if defined(OS_MACOSX)
205 uses_compositor_(false),
206 #elif defined(OS_WIN)
207 dummy_activation_window_(NULL),
208 #endif
209 window_(gfx::kNullPluginWindow),
210 mime_type_(mime_type),
211 instance_id_(MSG_ROUTING_NONE),
212 npobject_(NULL),
213 sad_plugin_(NULL),
214 invalidate_pending_(false),
215 front_buffer_index_(0),
216 page_url_(render_view_->webview()->mainFrame()->document().url()) {
219 WebPluginDelegateProxy::~WebPluginDelegateProxy() {
220 if (npobject_)
221 WebBindings::releaseObject(npobject_);
224 WebPluginDelegateProxy::SharedBitmap::SharedBitmap() {}
226 WebPluginDelegateProxy::SharedBitmap::~SharedBitmap() {}
228 void WebPluginDelegateProxy::PluginDestroyed() {
229 #if defined(OS_MACOSX) || defined(OS_WIN)
230 // Ensure that the renderer doesn't think the plugin still has focus.
231 if (render_view_)
232 render_view_->PluginFocusChanged(false, instance_id_);
233 #endif
235 #if defined(OS_WIN)
236 if (dummy_activation_window_ && render_view_) {
237 render_view_->Send(new ViewHostMsg_WindowlessPluginDummyWindowDestroyed(
238 render_view_->routing_id(), dummy_activation_window_));
240 dummy_activation_window_ = NULL;
241 #endif
243 if (window_)
244 WillDestroyWindow();
246 if (render_view_)
247 render_view_->UnregisterPluginDelegate(this);
249 if (channel_host_) {
250 Send(new PluginMsg_DestroyInstance(instance_id_));
252 // Must remove the route after sending the destroy message, since
253 // RemoveRoute can lead to all the outstanding NPObjects being told the
254 // channel went away if this was the last instance.
255 channel_host_->RemoveRoute(instance_id_);
257 // Release the channel host now. If we are is the last reference to the
258 // channel, this avoids a race where this renderer asks a new connection to
259 // the same plugin between now and the time 'this' is actually deleted.
260 // Destroying the channel host is what releases the channel name -> FD
261 // association on POSIX, and if we ask for a new connection before it is
262 // released, the plugin will give us a new FD, and we'll assert when trying
263 // to associate it with the channel name.
264 channel_host_ = NULL;
267 if (window_script_object_) {
268 // Release the window script object, if the plugin didn't already.
269 // If we don't do this then it will linger until the last plugin instance is
270 // destroyed. In the meantime, though, the frame that it refers to may have
271 // been destroyed by WebKit, at which point WebKit will forcibly deallocate
272 // the window script object. The window script object stub is unique to the
273 // plugin instance, so this won't affect other instances.
274 window_script_object_->DeleteSoon();
277 plugin_ = NULL;
279 MessageLoop::current()->DeleteSoon(FROM_HERE, this);
282 bool WebPluginDelegateProxy::Initialize(
283 const GURL& url,
284 const std::vector<std::string>& arg_names,
285 const std::vector<std::string>& arg_values,
286 webkit::npapi::WebPlugin* plugin,
287 bool load_manually) {
288 // TODO(shess): Attempt to work around http://crbug.com/97285 and
289 // http://crbug.com/141055 by retrying the connection. Reports seem
290 // to indicate that the plugin hasn't crashed, and that the problem
291 // is not 100% persistent.
292 const size_t kAttempts = 2;
294 bool result = false;
295 scoped_refptr<PluginChannelHost> channel_host;
296 int instance_id = 0;
298 for (size_t attempt = 0; !result && attempt < kAttempts; attempt++) {
299 #if defined(OS_MACOSX)
300 // TODO(shess): Debugging for http://crbug.com/97285 . See comment
301 // in plugin_channel_host.cc.
302 scoped_ptr<base::AutoReset<bool> > track_nested_removes(
303 new base::AutoReset<bool>(PluginChannelHost::GetRemoveTrackingFlag(),
304 true));
305 #endif
307 IPC::ChannelHandle channel_handle;
308 if (!RenderThreadImpl::current()->Send(new ViewHostMsg_OpenChannelToPlugin(
309 render_view_->routing_id(), url, page_url_, mime_type_,
310 &channel_handle, &info_))) {
311 continue;
314 if (channel_handle.name.empty()) {
315 // We got an invalid handle. Either the plugin couldn't be found (which
316 // shouldn't happen, since if we got here the plugin should exist) or the
317 // plugin crashed on initialization.
318 if (!info_.path.empty()) {
319 render_view_->PluginCrashed(info_.path);
320 LOG(ERROR) << "Plug-in crashed on start";
322 // Return true so that the plugin widget is created and we can paint the
323 // crashed plugin there.
324 return true;
326 LOG(ERROR) << "Plug-in couldn't be found";
327 return false;
330 channel_host =
331 PluginChannelHost::GetPluginChannelHost(
332 channel_handle, ChildProcess::current()->io_message_loop_proxy());
333 if (!channel_host.get()) {
334 LOG(ERROR) << "Couldn't get PluginChannelHost";
335 continue;
337 #if defined(OS_MACOSX)
338 track_nested_removes.reset();
339 #endif
342 // TODO(bauerb): Debugging for http://crbug.com/141055.
343 ScopedLogLevel log_level(-2); // Equivalent to --v=2
344 result = channel_host->Send(new PluginMsg_CreateInstance(
345 mime_type_, &instance_id));
346 if (!result) {
347 LOG(ERROR) << "Couldn't send PluginMsg_CreateInstance";
348 continue;
353 // Failed too often, give up.
354 if (!result)
355 return false;
357 channel_host_ = channel_host;
358 instance_id_ = instance_id;
360 channel_host_->AddRoute(instance_id_, this, NULL);
362 // Now tell the PluginInstance in the plugin process to initialize.
363 PluginMsg_Init_Params params;
364 params.url = url;
365 params.page_url = page_url_;
366 params.arg_names = arg_names;
367 params.arg_values = arg_values;
368 params.host_render_view_routing_id = render_view_->routing_id();
369 params.load_manually = load_manually;
371 plugin_ = plugin;
373 result = false;
374 Send(new PluginMsg_Init(instance_id_, params, &result));
376 if (!result)
377 LOG(ERROR) << "PluginMsg_Init returned false";
379 render_view_->RegisterPluginDelegate(this);
381 return result;
384 bool WebPluginDelegateProxy::Send(IPC::Message* msg) {
385 if (!channel_host_) {
386 DLOG(WARNING) << "dropping message because channel host is null";
387 delete msg;
388 return false;
391 return channel_host_->Send(msg);
394 void WebPluginDelegateProxy::SendJavaScriptStream(const GURL& url,
395 const std::string& result,
396 bool success,
397 int notify_id) {
398 Send(new PluginMsg_SendJavaScriptStream(
399 instance_id_, url, result, success, notify_id));
402 void WebPluginDelegateProxy::DidReceiveManualResponse(
403 const GURL& url, const std::string& mime_type,
404 const std::string& headers, uint32 expected_length,
405 uint32 last_modified) {
406 PluginMsg_DidReceiveResponseParams params;
407 params.id = 0;
408 params.mime_type = mime_type;
409 params.headers = headers;
410 params.expected_length = expected_length;
411 params.last_modified = last_modified;
412 Send(new PluginMsg_DidReceiveManualResponse(instance_id_, url, params));
415 void WebPluginDelegateProxy::DidReceiveManualData(const char* buffer,
416 int length) {
417 DCHECK_GT(length, 0);
418 std::vector<char> data;
419 data.resize(static_cast<size_t>(length));
420 memcpy(&data.front(), buffer, length);
421 Send(new PluginMsg_DidReceiveManualData(instance_id_, data));
424 void WebPluginDelegateProxy::DidFinishManualLoading() {
425 Send(new PluginMsg_DidFinishManualLoading(instance_id_));
428 void WebPluginDelegateProxy::DidManualLoadFail() {
429 Send(new PluginMsg_DidManualLoadFail(instance_id_));
432 bool WebPluginDelegateProxy::OnMessageReceived(const IPC::Message& msg) {
433 GetContentClient()->SetActiveURL(page_url_);
435 bool handled = true;
436 IPC_BEGIN_MESSAGE_MAP(WebPluginDelegateProxy, msg)
437 IPC_MESSAGE_HANDLER(PluginHostMsg_SetWindow, OnSetWindow)
438 #if defined(OS_WIN)
439 IPC_MESSAGE_HANDLER(PluginHostMsg_SetWindowlessData, OnSetWindowlessData)
440 IPC_MESSAGE_HANDLER(PluginHostMsg_NotifyIMEStatus, OnNotifyIMEStatus)
441 #endif
442 IPC_MESSAGE_HANDLER(PluginHostMsg_CancelResource, OnCancelResource)
443 IPC_MESSAGE_HANDLER(PluginHostMsg_InvalidateRect, OnInvalidateRect)
444 IPC_MESSAGE_HANDLER(PluginHostMsg_GetWindowScriptNPObject,
445 OnGetWindowScriptNPObject)
446 IPC_MESSAGE_HANDLER(PluginHostMsg_GetPluginElement, OnGetPluginElement)
447 IPC_MESSAGE_HANDLER(PluginHostMsg_ResolveProxy, OnResolveProxy)
448 IPC_MESSAGE_HANDLER(PluginHostMsg_SetCookie, OnSetCookie)
449 IPC_MESSAGE_HANDLER(PluginHostMsg_GetCookies, OnGetCookies)
450 IPC_MESSAGE_HANDLER(PluginHostMsg_URLRequest, OnHandleURLRequest)
451 IPC_MESSAGE_HANDLER(PluginHostMsg_CancelDocumentLoad, OnCancelDocumentLoad)
452 IPC_MESSAGE_HANDLER(PluginHostMsg_InitiateHTTPRangeRequest,
453 OnInitiateHTTPRangeRequest)
454 IPC_MESSAGE_HANDLER(PluginHostMsg_DeferResourceLoading,
455 OnDeferResourceLoading)
457 #if defined(OS_MACOSX)
458 IPC_MESSAGE_HANDLER(PluginHostMsg_FocusChanged,
459 OnFocusChanged);
460 IPC_MESSAGE_HANDLER(PluginHostMsg_StartIme,
461 OnStartIme);
462 IPC_MESSAGE_HANDLER(PluginHostMsg_BindFakePluginWindowHandle,
463 OnBindFakePluginWindowHandle);
464 // Used only on 10.6 and later.
465 IPC_MESSAGE_HANDLER(PluginHostMsg_AcceleratedSurfaceSetIOSurface,
466 OnAcceleratedSurfaceSetIOSurface)
467 // Used on 10.5 and earlier.
468 IPC_MESSAGE_HANDLER(PluginHostMsg_AcceleratedSurfaceSetTransportDIB,
469 OnAcceleratedSurfaceSetTransportDIB)
470 IPC_MESSAGE_HANDLER(PluginHostMsg_AllocTransportDIB,
471 OnAcceleratedSurfaceAllocTransportDIB)
472 IPC_MESSAGE_HANDLER(PluginHostMsg_FreeTransportDIB,
473 OnAcceleratedSurfaceFreeTransportDIB)
474 IPC_MESSAGE_HANDLER(PluginHostMsg_AcceleratedSurfaceBuffersSwapped,
475 OnAcceleratedSurfaceBuffersSwapped)
476 // Used only on 10.6 and later.
477 IPC_MESSAGE_HANDLER(PluginHostMsg_AcceleratedPluginEnabledRendering,
478 OnAcceleratedPluginEnabledRendering)
479 IPC_MESSAGE_HANDLER(PluginHostMsg_AcceleratedPluginAllocatedIOSurface,
480 OnAcceleratedPluginAllocatedIOSurface)
481 IPC_MESSAGE_HANDLER(PluginHostMsg_AcceleratedPluginSwappedIOSurface,
482 OnAcceleratedPluginSwappedIOSurface)
483 #endif
484 IPC_MESSAGE_HANDLER(PluginHostMsg_URLRedirectResponse,
485 OnURLRedirectResponse)
486 IPC_MESSAGE_UNHANDLED(handled = false)
487 IPC_END_MESSAGE_MAP()
488 DCHECK(handled);
489 return handled;
492 void WebPluginDelegateProxy::OnChannelError() {
493 if (plugin_) {
494 if (window_) {
495 // The actual WebPluginDelegate never got a chance to tell the WebPlugin
496 // its window was going away. Do it on its behalf.
497 WillDestroyWindow();
499 plugin_->Invalidate();
501 if (!channel_host_->expecting_shutdown())
502 render_view_->PluginCrashed(info_.path);
504 #if defined(OS_MACOSX) || defined(OS_WIN)
505 // Ensure that the renderer doesn't think the plugin still has focus.
506 if (render_view_)
507 render_view_->PluginFocusChanged(false, instance_id_);
508 #endif
511 static void CopyTransportDIBHandleForMessage(
512 const TransportDIB::Handle& handle_in,
513 TransportDIB::Handle* handle_out,
514 base::ProcessId peer_pid) {
515 #if defined(OS_MACOSX)
516 // On Mac, TransportDIB::Handle is typedef'ed to FileDescriptor, and
517 // FileDescriptor message fields needs to remain valid until the message is
518 // sent or else the sendmsg() call will fail.
519 if ((handle_out->fd = HANDLE_EINTR(dup(handle_in.fd))) < 0) {
520 PLOG(ERROR) << "dup()";
521 return;
523 handle_out->auto_close = true;
524 #elif defined(OS_WIN)
525 // On Windows we need to duplicate the handle for the plugin process.
526 *handle_out = NULL;
527 BrokerDuplicateHandle(handle_in, peer_pid, handle_out,
528 FILE_MAP_READ | FILE_MAP_WRITE, 0);
529 DCHECK(*handle_out != NULL);
530 #else
531 // Don't need to do anything special for other platforms.
532 *handle_out = handle_in;
533 #endif
536 void WebPluginDelegateProxy::SendUpdateGeometry(
537 bool bitmaps_changed) {
538 PluginMsg_UpdateGeometry_Param param;
539 param.window_rect = plugin_rect_;
540 param.clip_rect = clip_rect_;
541 param.windowless_buffer0 = TransportDIB::DefaultHandleValue();
542 param.windowless_buffer1 = TransportDIB::DefaultHandleValue();
543 param.windowless_buffer_index = back_buffer_index();
545 #if defined(OS_POSIX)
546 // If we're using POSIX mmap'd TransportDIBs, sending the handle across
547 // IPC establishes a new mapping rather than just sending a window ID,
548 // so only do so if we've actually changed the shared memory bitmaps.
549 if (bitmaps_changed)
550 #endif
552 if (transport_stores_[0].dib.get())
553 CopyTransportDIBHandleForMessage(transport_stores_[0].dib->handle(),
554 &param.windowless_buffer0,
555 channel_host_->peer_pid());
557 if (transport_stores_[1].dib.get())
558 CopyTransportDIBHandleForMessage(transport_stores_[1].dib->handle(),
559 &param.windowless_buffer1,
560 channel_host_->peer_pid());
563 IPC::Message* msg;
564 #if defined(OS_WIN)
565 if (UseSynchronousGeometryUpdates()) {
566 msg = new PluginMsg_UpdateGeometrySync(instance_id_, param);
567 } else // NOLINT
568 #endif
570 msg = new PluginMsg_UpdateGeometry(instance_id_, param);
571 msg->set_unblock(true);
574 Send(msg);
577 void WebPluginDelegateProxy::UpdateGeometry(const gfx::Rect& window_rect,
578 const gfx::Rect& clip_rect) {
579 // window_rect becomes either a window in native windowing system
580 // coords, or a backing buffer. In either case things will go bad
581 // if the rectangle is very large.
582 if (window_rect.width() < 0 || window_rect.width() > kMaxPluginSideLength ||
583 window_rect.height() < 0 || window_rect.height() > kMaxPluginSideLength ||
584 // We know this won't overflow due to above checks.
585 static_cast<uint32>(window_rect.width()) *
586 static_cast<uint32>(window_rect.height()) > kMaxPluginSize) {
587 return;
590 plugin_rect_ = window_rect;
591 clip_rect_ = clip_rect;
593 bool bitmaps_changed = false;
595 if (uses_shared_bitmaps_) {
596 if (!front_buffer_canvas() ||
597 (window_rect.width() != front_buffer_canvas()->getDevice()->width() ||
598 window_rect.height() != front_buffer_canvas()->getDevice()->height()))
600 bitmaps_changed = true;
602 // Create a shared memory section that the plugin paints into
603 // asynchronously.
604 ResetWindowlessBitmaps();
605 if (!window_rect.IsEmpty()) {
606 if (!CreateSharedBitmap(&transport_stores_[0].dib,
607 &transport_stores_[0].canvas) ||
608 !CreateSharedBitmap(&transport_stores_[1].dib,
609 &transport_stores_[1].canvas)) {
610 DCHECK(false);
611 ResetWindowlessBitmaps();
612 return;
618 SendUpdateGeometry(bitmaps_changed);
621 void WebPluginDelegateProxy::ResetWindowlessBitmaps() {
622 transport_stores_[0].dib.reset();
623 transport_stores_[1].dib.reset();
625 transport_stores_[0].canvas.reset();
626 transport_stores_[1].canvas.reset();
627 transport_store_painted_ = gfx::Rect();
628 front_buffer_diff_ = gfx::Rect();
631 static size_t BitmapSizeForPluginRect(const gfx::Rect& plugin_rect) {
632 const size_t stride =
633 skia::PlatformCanvasStrideForWidth(plugin_rect.width());
634 return stride * plugin_rect.height();
637 #if !defined(OS_WIN)
638 bool WebPluginDelegateProxy::CreateLocalBitmap(
639 std::vector<uint8>* memory,
640 scoped_ptr<skia::PlatformCanvas>* canvas) {
641 const size_t size = BitmapSizeForPluginRect(plugin_rect_);
642 memory->resize(size);
643 if (memory->size() != size)
644 return false;
645 canvas->reset(skia::CreatePlatformCanvas(
646 plugin_rect_.width(), plugin_rect_.height(), true, &((*memory)[0]),
647 skia::CRASH_ON_FAILURE));
648 return true;
650 #endif
652 bool WebPluginDelegateProxy::CreateSharedBitmap(
653 scoped_ptr<TransportDIB>* memory,
654 scoped_ptr<skia::PlatformCanvas>* canvas) {
655 const size_t size = BitmapSizeForPluginRect(plugin_rect_);
656 #if defined(OS_POSIX) && !defined(OS_MACOSX)
657 memory->reset(TransportDIB::Create(size, 0));
658 if (!memory->get())
659 return false;
660 #endif
661 #if defined(OS_MACOSX)
662 TransportDIB::Handle handle;
663 IPC::Message* msg = new ViewHostMsg_AllocTransportDIB(size, false, &handle);
664 if (!RenderThreadImpl::current()->Send(msg))
665 return false;
666 if (handle.fd < 0)
667 return false;
668 memory->reset(TransportDIB::Map(handle));
669 #else
670 static uint32 sequence_number = 0;
671 memory->reset(TransportDIB::Create(size, sequence_number++));
672 #endif
673 canvas->reset((*memory)->GetPlatformCanvas(plugin_rect_.width(),
674 plugin_rect_.height()));
675 return !!canvas->get();
678 #if defined(OS_MACOSX)
679 // Flips |rect| vertically within an enclosing rect with height |height|.
680 // Intended for converting rects between flipped and non-flipped contexts.
681 static void FlipRectVerticallyWithHeight(gfx::Rect* rect, int height) {
682 rect->set_y(height - rect->bottom());
684 #endif
686 void WebPluginDelegateProxy::Paint(WebKit::WebCanvas* canvas,
687 const gfx::Rect& damaged_rect) {
688 // Limit the damaged rectangle to whatever is contained inside the plugin
689 // rectangle, as that's the rectangle that we'll actually draw.
690 gfx::Rect rect = gfx::IntersectRects(damaged_rect, plugin_rect_);
692 // If the plugin is no longer connected (channel crashed) draw a crashed
693 // plugin bitmap
694 if (!channel_host_ || !channel_host_->channel_valid()) {
695 PaintSadPlugin(canvas, rect);
696 return;
699 if (!uses_shared_bitmaps_)
700 return;
702 // We got a paint before the plugin's coordinates, so there's no buffer to
703 // copy from.
704 if (!front_buffer_canvas())
705 return;
707 gfx::Rect offset_rect = rect;
708 offset_rect.Offset(-plugin_rect_.x(), -plugin_rect_.y());
710 // transport_store_painted_ is really a bounding box, so in principle this
711 // check could falsely indicate that we don't need to paint offset_rect, but
712 // in practice it works fine.
713 if (!transport_store_painted_.Contains(offset_rect)) {
714 Send(new PluginMsg_Paint(instance_id_, offset_rect));
715 // Since the plugin is not blocked on the renderer in this context, there is
716 // a chance that it will begin repainting the back-buffer before we complete
717 // capturing the data. Buffer flipping would increase that risk because
718 // geometry update is asynchronous, so we don't want to use buffer flipping
719 // here.
720 UpdateFrontBuffer(offset_rect, false);
723 const SkBitmap& bitmap =
724 front_buffer_canvas()->getDevice()->accessBitmap(false);
725 SkPaint paint;
726 paint.setXfermodeMode(SkXfermode::kSrcATop_Mode);
727 SkIRect src_rect = gfx::RectToSkIRect(offset_rect);
728 canvas->drawBitmapRect(bitmap,
729 &src_rect,
730 gfx::RectToSkRect(rect),
731 &paint);
733 if (invalidate_pending_) {
734 // Only send the PaintAck message if this paint is in response to an
735 // invalidate from the plugin, since this message acts as an access token
736 // to ensure only one process is using the transport dib at a time.
737 invalidate_pending_ = false;
738 Send(new PluginMsg_DidPaint(instance_id_));
742 NPObject* WebPluginDelegateProxy::GetPluginScriptableObject() {
743 if (npobject_)
744 return WebBindings::retainObject(npobject_);
746 int route_id = MSG_ROUTING_NONE;
747 Send(new PluginMsg_GetPluginScriptableObject(instance_id_, &route_id));
748 if (route_id == MSG_ROUTING_NONE)
749 return NULL;
751 npobject_ = NPObjectProxy::Create(
752 channel_host_.get(), route_id, 0, page_url_);
754 return WebBindings::retainObject(npobject_);
757 bool WebPluginDelegateProxy::GetFormValue(string16* value) {
758 bool success = false;
759 Send(new PluginMsg_GetFormValue(instance_id_, value, &success));
760 return success;
763 void WebPluginDelegateProxy::DidFinishLoadWithReason(
764 const GURL& url, NPReason reason, int notify_id) {
765 Send(new PluginMsg_DidFinishLoadWithReason(
766 instance_id_, url, reason, notify_id));
769 void WebPluginDelegateProxy::SetFocus(bool focused) {
770 Send(new PluginMsg_SetFocus(instance_id_, focused));
771 #if defined(OS_WIN)
772 if (render_view_)
773 render_view_->PluginFocusChanged(focused, instance_id_);
774 #endif
777 bool WebPluginDelegateProxy::HandleInputEvent(
778 const WebInputEvent& event,
779 WebCursorInfo* cursor_info) {
780 bool handled;
781 WebCursor cursor;
782 // A windowless plugin can enter a modal loop in the context of a
783 // NPP_HandleEvent call, in which case we need to pump messages to
784 // the plugin. We pass of the corresponding event handle to the
785 // plugin process, which is set if the plugin does enter a modal loop.
786 IPC::SyncMessage* message = new PluginMsg_HandleInputEvent(
787 instance_id_, &event, &handled, &cursor);
788 message->set_pump_messages_event(modal_loop_pump_messages_event_.get());
789 Send(message);
790 cursor.GetCursorInfo(cursor_info);
791 return handled;
794 int WebPluginDelegateProxy::GetProcessId() {
795 return channel_host_->peer_pid();
798 void WebPluginDelegateProxy::SetContentAreaFocus(bool has_focus) {
799 IPC::Message* msg = new PluginMsg_SetContentAreaFocus(instance_id_,
800 has_focus);
801 // Make sure focus events are delivered in the right order relative to
802 // sync messages they might interact with (Paint, HandleEvent, etc.).
803 msg->set_unblock(true);
804 Send(msg);
807 #if defined(OS_WIN)
808 void WebPluginDelegateProxy::ImeCompositionUpdated(
809 const string16& text,
810 const std::vector<int>& clauses,
811 const std::vector<int>& target,
812 int cursor_position,
813 int plugin_id) {
814 // Dispatch the raw IME data if this plug-in is the focused one.
815 if (instance_id_ != plugin_id)
816 return;
818 IPC::Message* msg = new PluginMsg_ImeCompositionUpdated(instance_id_,
819 text, clauses, target, cursor_position);
820 msg->set_unblock(true);
821 Send(msg);
824 void WebPluginDelegateProxy::ImeCompositionCompleted(const string16& text,
825 int plugin_id) {
826 // Dispatch the IME text if this plug-in is the focused one.
827 if (instance_id_ != plugin_id)
828 return;
830 IPC::Message* msg = new PluginMsg_ImeCompositionCompleted(instance_id_, text);
831 msg->set_unblock(true);
832 Send(msg);
834 #endif
836 #if defined(OS_MACOSX)
837 void WebPluginDelegateProxy::SetWindowFocus(bool window_has_focus) {
838 IPC::Message* msg = new PluginMsg_SetWindowFocus(instance_id_,
839 window_has_focus);
840 // Make sure focus events are delivered in the right order relative to
841 // sync messages they might interact with (Paint, HandleEvent, etc.).
842 msg->set_unblock(true);
843 Send(msg);
846 void WebPluginDelegateProxy::SetContainerVisibility(bool is_visible) {
847 IPC::Message* msg;
848 if (is_visible) {
849 gfx::Rect window_frame = render_view_->rootWindowRect();
850 gfx::Rect view_frame = render_view_->windowRect();
851 WebKit::WebView* webview = render_view_->webview();
852 msg = new PluginMsg_ContainerShown(instance_id_, window_frame, view_frame,
853 webview && webview->isActive());
854 } else {
855 msg = new PluginMsg_ContainerHidden(instance_id_);
857 // Make sure visibility events are delivered in the right order relative to
858 // sync messages they might interact with (Paint, HandleEvent, etc.).
859 msg->set_unblock(true);
860 Send(msg);
863 void WebPluginDelegateProxy::WindowFrameChanged(gfx::Rect window_frame,
864 gfx::Rect view_frame) {
865 IPC::Message* msg = new PluginMsg_WindowFrameChanged(instance_id_,
866 window_frame,
867 view_frame);
868 // Make sure frame events are delivered in the right order relative to
869 // sync messages they might interact with (e.g., HandleEvent).
870 msg->set_unblock(true);
871 Send(msg);
873 void WebPluginDelegateProxy::ImeCompositionCompleted(const string16& text,
874 int plugin_id) {
875 // If the message isn't intended for this plugin, there's nothing to do.
876 if (instance_id_ != plugin_id)
877 return;
879 IPC::Message* msg = new PluginMsg_ImeCompositionCompleted(instance_id_,
880 text);
881 // Order relative to other key events is important.
882 msg->set_unblock(true);
883 Send(msg);
885 #endif // OS_MACOSX
887 void WebPluginDelegateProxy::OnSetWindow(gfx::PluginWindowHandle window) {
888 #if defined(OS_MACOSX)
889 uses_shared_bitmaps_ = !window && !uses_compositor_;
890 #else
891 uses_shared_bitmaps_ = !window;
892 #endif
893 window_ = window;
894 if (plugin_)
895 plugin_->SetWindow(window);
898 void WebPluginDelegateProxy::WillDestroyWindow() {
899 DCHECK(window_);
900 plugin_->WillDestroyWindow(window_);
901 #if defined(OS_MACOSX)
902 if (window_) {
903 // This is actually a "fake" window handle only for the GPU
904 // plugin. Deallocate it on the browser side.
905 if (render_view_)
906 render_view_->DestroyFakePluginWindowHandle(window_);
908 #endif
909 window_ = gfx::kNullPluginWindow;
912 #if defined(OS_WIN)
913 void WebPluginDelegateProxy::OnSetWindowlessData(
914 HANDLE modal_loop_pump_messages_event,
915 gfx::NativeViewId dummy_activation_window) {
916 DCHECK(modal_loop_pump_messages_event_ == NULL);
917 DCHECK(dummy_activation_window_ == NULL);
919 dummy_activation_window_ = dummy_activation_window;
920 render_view_->Send(new ViewHostMsg_WindowlessPluginDummyWindowCreated(
921 render_view_->routing_id(), dummy_activation_window_));
923 // Bug 25583: this can be null because some "virus scanners" block the
924 // DuplicateHandle call in the plugin process.
925 if (!modal_loop_pump_messages_event)
926 return;
928 modal_loop_pump_messages_event_.reset(
929 new base::WaitableEvent(modal_loop_pump_messages_event));
932 void WebPluginDelegateProxy::OnNotifyIMEStatus(int input_type,
933 const gfx::Rect& caret_rect) {
934 if (!render_view_)
935 return;
937 ViewHostMsg_TextInputState_Params params;
938 params.type = static_cast<ui::TextInputType>(input_type);
939 params.can_compose_inline = true;
940 render_view_->Send(new ViewHostMsg_TextInputStateChanged(
941 render_view_->routing_id(),
942 params));
944 render_view_->Send(new ViewHostMsg_SelectionBoundsChanged(
945 render_view_->routing_id(),
946 caret_rect, WebKit::WebTextDirectionLeftToRight,
947 caret_rect, WebKit::WebTextDirectionLeftToRight));
949 #endif
951 void WebPluginDelegateProxy::OnCancelResource(int id) {
952 if (plugin_)
953 plugin_->CancelResource(id);
956 void WebPluginDelegateProxy::OnInvalidateRect(const gfx::Rect& rect) {
957 if (!plugin_)
958 return;
960 // Clip the invalidation rect to the plugin bounds; the plugin may have been
961 // resized since the invalidate message was sent.
962 gfx::Rect clipped_rect =
963 gfx::IntersectRects(rect, gfx::Rect(plugin_rect_.size()));
965 invalidate_pending_ = true;
966 // The plugin is blocked on the renderer because the invalidate message it has
967 // sent us is synchronous, so we can use buffer flipping here if the caller
968 // allows it.
969 UpdateFrontBuffer(clipped_rect, true);
970 plugin_->InvalidateRect(clipped_rect);
973 void WebPluginDelegateProxy::OnGetWindowScriptNPObject(
974 int route_id, bool* success) {
975 *success = false;
976 NPObject* npobject = NULL;
977 if (plugin_)
978 npobject = plugin_->GetWindowScriptNPObject();
980 if (!npobject)
981 return;
983 // The stub will delete itself when the proxy tells it that it's released, or
984 // otherwise when the channel is closed.
985 window_script_object_ = (new NPObjectStub(
986 npobject, channel_host_.get(), route_id, 0, page_url_))->AsWeakPtr();
987 *success = true;
990 void WebPluginDelegateProxy::OnResolveProxy(const GURL& url,
991 bool* result,
992 std::string* proxy_list) {
993 *result = false;
994 RenderThreadImpl::current()->Send(
995 new ViewHostMsg_ResolveProxy(url, result, proxy_list));
998 void WebPluginDelegateProxy::OnGetPluginElement(int route_id, bool* success) {
999 *success = false;
1000 NPObject* npobject = NULL;
1001 if (plugin_)
1002 npobject = plugin_->GetPluginElement();
1003 if (!npobject)
1004 return;
1006 // The stub will delete itself when the proxy tells it that it's released, or
1007 // otherwise when the channel is closed.
1008 new NPObjectStub(
1009 npobject, channel_host_.get(), route_id, 0, page_url_);
1010 *success = true;
1013 void WebPluginDelegateProxy::OnSetCookie(const GURL& url,
1014 const GURL& first_party_for_cookies,
1015 const std::string& cookie) {
1016 if (plugin_)
1017 plugin_->SetCookie(url, first_party_for_cookies, cookie);
1020 void WebPluginDelegateProxy::OnGetCookies(const GURL& url,
1021 const GURL& first_party_for_cookies,
1022 std::string* cookies) {
1023 DCHECK(cookies);
1024 if (plugin_)
1025 *cookies = plugin_->GetCookies(url, first_party_for_cookies);
1028 void WebPluginDelegateProxy::PaintSadPlugin(WebKit::WebCanvas* native_context,
1029 const gfx::Rect& rect) {
1030 // Lazily load the sad plugin image.
1031 if (!sad_plugin_)
1032 sad_plugin_ = GetContentClient()->renderer()->GetSadPluginBitmap();
1033 if (sad_plugin_)
1034 webkit::PaintSadPlugin(native_context, plugin_rect_, *sad_plugin_);
1037 void WebPluginDelegateProxy::CopyFromBackBufferToFrontBuffer(
1038 const gfx::Rect& rect) {
1039 #if defined(OS_MACOSX)
1040 // Blitting the bits directly is much faster than going through CG, and since
1041 // the goal is just to move the raw pixels between two bitmaps with the same
1042 // pixel format (no compositing, color correction, etc.), it's safe.
1043 const size_t stride =
1044 skia::PlatformCanvasStrideForWidth(plugin_rect_.width());
1045 const size_t chunk_size = 4 * rect.width();
1046 DCHECK(back_buffer_dib() != NULL);
1047 uint8* source_data = static_cast<uint8*>(back_buffer_dib()->memory()) +
1048 rect.y() * stride + 4 * rect.x();
1049 DCHECK(front_buffer_dib() != NULL);
1050 uint8* target_data = static_cast<uint8*>(front_buffer_dib()->memory()) +
1051 rect.y() * stride + 4 * rect.x();
1052 for (int row = 0; row < rect.height(); ++row) {
1053 memcpy(target_data, source_data, chunk_size);
1054 source_data += stride;
1055 target_data += stride;
1057 #else
1058 BlitCanvasToCanvas(front_buffer_canvas(),
1059 rect,
1060 back_buffer_canvas(),
1061 rect.origin());
1062 #endif
1065 void WebPluginDelegateProxy::UpdateFrontBuffer(
1066 const gfx::Rect& rect,
1067 bool allow_buffer_flipping) {
1068 if (!front_buffer_canvas()) {
1069 return;
1072 #if defined(OS_WIN)
1073 // If SendUpdateGeometry() would block on the plugin process then we don't
1074 // want to use buffer flipping at all since it would add extra locking.
1075 // (Alternatively we could probably safely use async updates for buffer
1076 // flipping all the time since the size is not changing.)
1077 if (UseSynchronousGeometryUpdates()) {
1078 allow_buffer_flipping = false;
1080 #endif
1082 // Plugin has just painted "rect" into the back-buffer, so the front-buffer
1083 // no longer holds the latest content for that rectangle.
1084 front_buffer_diff_.Subtract(rect);
1085 if (allow_buffer_flipping && front_buffer_diff_.IsEmpty()) {
1086 // Back-buffer contains the latest content for all areas; simply flip
1087 // the buffers.
1088 front_buffer_index_ = back_buffer_index();
1089 SendUpdateGeometry(false);
1090 // The front-buffer now holds newer content for this region than the
1091 // back-buffer.
1092 front_buffer_diff_ = rect;
1093 } else {
1094 // Back-buffer contains the latest content for "rect" but the front-buffer
1095 // contains the latest content for some other areas (or buffer flipping not
1096 // allowed); fall back to copying the data.
1097 CopyFromBackBufferToFrontBuffer(rect);
1099 transport_store_painted_.Union(rect);
1102 void WebPluginDelegateProxy::OnHandleURLRequest(
1103 const PluginHostMsg_URLRequest_Params& params) {
1104 const char* data = NULL;
1105 if (params.buffer.size())
1106 data = &params.buffer[0];
1108 const char* target = NULL;
1109 if (params.target.length())
1110 target = params.target.c_str();
1112 plugin_->HandleURLRequest(
1113 params.url.c_str(), params.method.c_str(), target, data,
1114 static_cast<unsigned int>(params.buffer.size()), params.notify_id,
1115 params.popups_allowed, params.notify_redirects);
1118 webkit::npapi::WebPluginResourceClient*
1119 WebPluginDelegateProxy::CreateResourceClient(
1120 unsigned long resource_id, const GURL& url, int notify_id) {
1121 if (!channel_host_)
1122 return NULL;
1124 ResourceClientProxy* proxy = new ResourceClientProxy(channel_host_,
1125 instance_id_);
1126 proxy->Initialize(resource_id, url, notify_id);
1127 return proxy;
1130 webkit::npapi::WebPluginResourceClient*
1131 WebPluginDelegateProxy::CreateSeekableResourceClient(
1132 unsigned long resource_id, int range_request_id) {
1133 if (!channel_host_)
1134 return NULL;
1136 ResourceClientProxy* proxy = new ResourceClientProxy(channel_host_,
1137 instance_id_);
1138 proxy->InitializeForSeekableStream(resource_id, range_request_id);
1139 return proxy;
1142 #if defined(OS_MACOSX)
1143 void WebPluginDelegateProxy::OnFocusChanged(bool focused) {
1144 if (render_view_)
1145 render_view_->PluginFocusChanged(focused, instance_id_);
1148 void WebPluginDelegateProxy::OnStartIme() {
1149 if (render_view_)
1150 render_view_->StartPluginIme();
1153 void WebPluginDelegateProxy::OnBindFakePluginWindowHandle(bool opaque) {
1154 BindFakePluginWindowHandle(opaque);
1157 // Synthesize a fake window handle for the plug-in to identify the instance
1158 // to the browser, allowing mapping to a surface for hardware acceleration
1159 // of plug-in content. The browser generates the handle which is then set on
1160 // the plug-in. Returns true if it successfully sets the window handle on the
1161 // plug-in.
1162 bool WebPluginDelegateProxy::BindFakePluginWindowHandle(bool opaque) {
1163 gfx::PluginWindowHandle fake_window = gfx::kNullPluginWindow;
1164 if (render_view_)
1165 fake_window = render_view_->AllocateFakePluginWindowHandle(opaque, false);
1166 // If we aren't running on 10.6, this allocation will fail.
1167 if (!fake_window)
1168 return false;
1169 OnSetWindow(fake_window);
1170 if (!Send(new PluginMsg_SetFakeAcceleratedSurfaceWindowHandle(instance_id_,
1171 fake_window))) {
1172 return false;
1175 // Since this isn't a real window, it doesn't get initial size and location
1176 // information the way a real windowed plugin would, so we need to feed it its
1177 // starting geometry.
1178 webkit::npapi::WebPluginGeometry geom;
1179 geom.window = fake_window;
1180 geom.window_rect = plugin_rect_;
1181 geom.clip_rect = clip_rect_;
1182 geom.rects_valid = true;
1183 geom.visible = true;
1184 render_view_->DidMovePlugin(geom);
1185 // Invalidate the plugin region to ensure that the move event actually gets
1186 // dispatched (for a plugin on an otherwise static page).
1187 render_view_->didInvalidateRect(WebKit::WebRect(plugin_rect_.x(),
1188 plugin_rect_.y(),
1189 plugin_rect_.width(),
1190 plugin_rect_.height()));
1192 return true;
1194 #endif
1196 gfx::PluginWindowHandle WebPluginDelegateProxy::GetPluginWindowHandle() {
1197 return window_;
1200 void WebPluginDelegateProxy::OnCancelDocumentLoad() {
1201 plugin_->CancelDocumentLoad();
1204 void WebPluginDelegateProxy::OnInitiateHTTPRangeRequest(
1205 const std::string& url,
1206 const std::string& range_info,
1207 int range_request_id) {
1208 plugin_->InitiateHTTPRangeRequest(
1209 url.c_str(), range_info.c_str(), range_request_id);
1212 void WebPluginDelegateProxy::OnDeferResourceLoading(unsigned long resource_id,
1213 bool defer) {
1214 plugin_->SetDeferResourceLoading(resource_id, defer);
1217 #if defined(OS_MACOSX)
1218 void WebPluginDelegateProxy::OnAcceleratedSurfaceSetIOSurface(
1219 gfx::PluginWindowHandle window,
1220 int32 width,
1221 int32 height,
1222 uint64 io_surface_identifier) {
1223 if (render_view_)
1224 render_view_->AcceleratedSurfaceSetIOSurface(window, width, height,
1225 io_surface_identifier);
1228 void WebPluginDelegateProxy::OnAcceleratedSurfaceSetTransportDIB(
1229 gfx::PluginWindowHandle window,
1230 int32 width,
1231 int32 height,
1232 TransportDIB::Handle transport_dib) {
1233 if (render_view_)
1234 render_view_->AcceleratedSurfaceSetTransportDIB(window, width, height,
1235 transport_dib);
1238 void WebPluginDelegateProxy::OnAcceleratedSurfaceAllocTransportDIB(
1239 size_t size,
1240 TransportDIB::Handle* dib_handle) {
1241 if (render_view_)
1242 *dib_handle = render_view_->AcceleratedSurfaceAllocTransportDIB(size);
1243 else
1244 *dib_handle = TransportDIB::DefaultHandleValue();
1247 void WebPluginDelegateProxy::OnAcceleratedSurfaceFreeTransportDIB(
1248 TransportDIB::Id dib_id) {
1249 if (render_view_)
1250 render_view_->AcceleratedSurfaceFreeTransportDIB(dib_id);
1253 void WebPluginDelegateProxy::OnAcceleratedSurfaceBuffersSwapped(
1254 gfx::PluginWindowHandle window, uint64 surface_handle) {
1255 if (render_view_)
1256 render_view_->AcceleratedSurfaceBuffersSwapped(window, surface_handle);
1259 void WebPluginDelegateProxy::OnAcceleratedPluginEnabledRendering() {
1260 uses_compositor_ = true;
1261 OnSetWindow(gfx::kNullPluginWindow);
1264 void WebPluginDelegateProxy::OnAcceleratedPluginAllocatedIOSurface(
1265 int32 width,
1266 int32 height,
1267 uint32 surface_id) {
1268 if (plugin_)
1269 plugin_->AcceleratedPluginAllocatedIOSurface(width, height, surface_id);
1272 void WebPluginDelegateProxy::OnAcceleratedPluginSwappedIOSurface() {
1273 if (plugin_)
1274 plugin_->AcceleratedPluginSwappedIOSurface();
1276 #endif
1278 #if defined(OS_WIN)
1279 bool WebPluginDelegateProxy::UseSynchronousGeometryUpdates() {
1280 // Need to update geometry synchronously with WMP, otherwise if a site
1281 // scripts the plugin to start playing while it's in the middle of handling
1282 // an update geometry message, videos don't play. See urls in bug 20260.
1283 if (info_.name.find(ASCIIToUTF16("Windows Media Player")) != string16::npos)
1284 return true;
1286 // The move networks plugin needs to be informed of geometry updates
1287 // synchronously.
1288 std::vector<webkit::WebPluginMimeType>::iterator index;
1289 for (index = info_.mime_types.begin(); index != info_.mime_types.end();
1290 index++) {
1291 if (index->mime_type == "application/x-vnd.moveplayer.qm" ||
1292 index->mime_type == "application/x-vnd.moveplay2.qm" ||
1293 index->mime_type == "application/x-vnd.movenetworks.qm" ||
1294 index->mime_type == "application/x-vnd.mnplayer.qm") {
1295 return true;
1298 return false;
1300 #endif
1302 void WebPluginDelegateProxy::OnURLRedirectResponse(bool allow,
1303 int resource_id) {
1304 if (!plugin_)
1305 return;
1307 plugin_->URLRedirectResponse(allow, resource_id);
1310 } // namespace content