blob: 3704bc7b07094779b4ba1060a5f663a2d1cad626 [file] [log] [blame]
[email protected]a5f73fea2012-02-15 18:09:171// Copyright (c) 2012 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
[email protected]3c5c6d82011-03-16 17:23:585#include "content/plugin/webplugin_proxy.h"
initial.commit09911bf2008-07-26 23:55:296
[email protected]2f5b1a12009-07-30 19:26:527#include "build/build_config.h"
[email protected]2f5b1a12009-07-30 19:26:528
[email protected]a4888372011-11-19 02:13:339#include "base/bind.h"
[email protected]625332e02010-12-14 07:48:4910#include "base/lazy_instance.h"
[email protected]3b63f8f42011-03-28 01:54:1511#include "base/memory/scoped_handle.h"
[email protected]22c54fdc2008-09-22 22:26:5912#include "base/shared_memory.h"
[email protected]157e5d22009-04-23 18:43:3513#include "build/build_config.h"
[email protected]d3fd748b2011-09-20 17:39:1714#include "content/common/npobject_proxy.h"
15#include "content/common/npobject_util.h"
[email protected]105303e2011-03-14 22:16:1016#include "content/common/plugin_messages.h"
[email protected]3c5c6d82011-03-16 17:23:5817#include "content/plugin/plugin_channel.h"
18#include "content/plugin/plugin_thread.h"
[email protected]5d1fa242011-10-18 23:35:3819#include "content/public/common/content_client.h"
[email protected]a1d29162011-10-14 17:14:0320#include "content/public/common/url_constants.h"
[email protected]91ef7b02011-08-02 15:26:0321#include "skia/ext/platform_canvas.h"
[email protected]c399a8a2008-11-22 19:38:0022#include "skia/ext/platform_device.h"
[email protected]8bd0fe62011-01-17 06:44:3723#include "third_party/WebKit/Source/WebKit/chromium/public/WebBindings.h"
[email protected]08397d52011-02-05 01:53:3824#include "ui/gfx/blit.h"
25#include "ui/gfx/canvas.h"
[email protected]191eb3f72010-12-21 06:27:5026#include "webkit/plugins/npapi/webplugin_delegate_impl.h"
[email protected]22c54fdc2008-09-22 22:26:5927
[email protected]fd85ad62010-12-31 20:39:0228#if defined(OS_MACOSX)
[email protected]0378bf42011-01-01 18:20:1429#include "base/mac/mac_util.h"
[email protected]fd85ad62010-12-31 20:39:0230#include "base/mac/scoped_cftyperef.h"
[email protected]3c5c6d82011-03-16 17:23:5831#include "content/plugin/webplugin_accelerated_surface_proxy_mac.h"
[email protected]fd85ad62010-12-31 20:39:0232#endif
33
[email protected]cb632c32010-08-05 02:54:4234#if defined(USE_X11)
[email protected]9dd7e3d72011-01-20 18:27:0635#include "ui/base/x/x11_util_internal.h"
[email protected]cb632c32010-08-05 02:54:4236#endif
37
[email protected]cd0bd792012-04-14 00:52:1638#if defined(OS_WIN)
[email protected]d30ce6e2012-04-16 15:32:3639#include "content/public/common/sandbox_init.h"
[email protected]cd0bd792012-04-14 00:52:1640#endif
41
[email protected]a3929292009-07-30 00:35:3342using WebKit::WebBindings;
[email protected]191eb3f72010-12-21 06:27:5043
44using webkit::npapi::WebPluginResourceClient;
[email protected]8b4755f2010-10-01 18:04:0645#if defined(OS_MACOSX)
[email protected]191eb3f72010-12-21 06:27:5046using webkit::npapi::WebPluginAcceleratedSurface;
[email protected]8b4755f2010-10-01 18:04:0647#endif
[email protected]a3929292009-07-30 00:35:3348
[email protected]78d172342012-08-15 20:27:3549
50WebPluginProxy::SharedTransportDIB::SharedTransportDIB(TransportDIB* dib)
51 : dib_(dib) {
52}
53
54WebPluginProxy::SharedTransportDIB::~SharedTransportDIB() {
55}
56
initial.commit09911bf2008-07-26 23:55:2957WebPluginProxy::WebPluginProxy(
58 PluginChannel* channel,
59 int route_id,
[email protected]8beff0762009-09-29 02:18:3060 const GURL& page_url,
[email protected]2799c02a2009-11-07 15:39:5561 gfx::NativeViewId containing_window,
62 int host_render_view_routing_id)
initial.commit09911bf2008-07-26 23:55:2963 : channel_(channel),
64 route_id_(route_id),
initial.commit09911bf2008-07-26 23:55:2965 window_npobject_(NULL),
66 plugin_element_(NULL),
[email protected]f103ab72009-09-02 17:10:5967 delegate_(NULL),
[email protected]f1a0eae2008-11-21 18:29:1468 waiting_for_paint_(false),
[email protected]8beff0762009-09-29 02:18:3069 containing_window_(containing_window),
[email protected]ef916272009-07-08 21:40:5570 page_url_(page_url),
[email protected]ab7f2742010-04-14 17:24:5171 transparent_(false),
[email protected]9cf755682011-07-25 22:13:5272 windowless_buffer_index_(0),
[email protected]2799c02a2009-11-07 15:39:5573 host_render_view_routing_id_(host_render_view_routing_id),
[email protected]a4888372011-11-19 02:13:3374 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
[email protected]cb632c32010-08-05 02:54:4275#if defined(USE_X11)
[email protected]9cf755682011-07-25 22:13:5276 windowless_shm_pixmaps_[0] = None;
77 windowless_shm_pixmaps_[1] = None;
78 use_shm_pixmap_ = false;
[email protected]cb632c32010-08-05 02:54:4279
[email protected]9cf755682011-07-25 22:13:5280 // If the X server supports SHM pixmaps
81 // and the color depth and masks match,
82 // then consider using SHM pixmaps for windowless plugin painting.
83 Display* display = ui::GetXDisplay();
84 if (ui::QuerySharedMemorySupport(display) == ui::SHARED_MEMORY_PIXMAP &&
85 ui::BitsPerPixelForPixmapDepth(
[email protected]88a8ffa2011-10-13 01:41:0586 display, DefaultDepth(display, DefaultScreen(display))) == 32) {
87 Visual* vis = DefaultVisual(display, DefaultScreen(display));
[email protected]cb632c32010-08-05 02:54:4288
[email protected]9cf755682011-07-25 22:13:5289 if (vis->red_mask == 0xff0000 &&
90 vis->green_mask == 0xff00 &&
91 vis->blue_mask == 0xff)
92 use_shm_pixmap_ = true;
93 }
[email protected]cb632c32010-08-05 02:54:4294#endif
initial.commit09911bf2008-07-26 23:55:2995}
96
97WebPluginProxy::~WebPluginProxy() {
[email protected]cb632c32010-08-05 02:54:4298#if defined(USE_X11)
[email protected]9cf755682011-07-25 22:13:5299 if (windowless_shm_pixmaps_[0] != None)
100 XFreePixmap(ui::GetXDisplay(), windowless_shm_pixmaps_[0]);
101 if (windowless_shm_pixmaps_[1] != None)
102 XFreePixmap(ui::GetXDisplay(), windowless_shm_pixmaps_[1]);
[email protected]cb632c32010-08-05 02:54:42103#endif
[email protected]8b4755f2010-10-01 18:04:06104
105#if defined(OS_MACOSX)
106 // Destroy the surface early, since it may send messages during cleanup.
107 if (accelerated_surface_.get())
108 accelerated_surface_.reset();
109#endif
[email protected]1eb70a22011-06-23 06:27:30110
111 if (plugin_element_)
112 WebBindings::releaseObject(plugin_element_);
113 if (window_npobject_)
114 WebBindings::releaseObject(window_npobject_);
initial.commit09911bf2008-07-26 23:55:29115}
116
117bool WebPluginProxy::Send(IPC::Message* msg) {
118 return channel_->Send(msg);
119}
120
[email protected]700d3d52009-07-07 17:40:46121void WebPluginProxy::SetWindow(gfx::PluginWindowHandle window) {
122 Send(new PluginHostMsg_SetWindow(route_id_, window));
[email protected]875d4892009-04-21 21:48:36123}
[email protected]096d5cd2009-03-26 19:39:29124
[email protected]78994ab02010-12-08 18:06:44125void WebPluginProxy::SetAcceptsInputEvents(bool accepts) {
126 NOTREACHED();
127}
128
[email protected]140c3032009-06-26 18:22:54129void WebPluginProxy::WillDestroyWindow(gfx::PluginWindowHandle window) {
[email protected]875d4892009-04-21 21:48:36130#if defined(OS_WIN)
131 PluginThread::current()->Send(
132 new PluginProcessHostMsg_PluginWindowDestroyed(
133 window, ::GetParent(window)));
[email protected]753efc42010-03-09 19:52:16134#elif defined(USE_X11)
[email protected]c0478b092009-08-25 20:50:32135 // Nothing to do.
[email protected]140c3032009-06-26 18:22:54136#else
137 NOTIMPLEMENTED();
[email protected]875d4892009-04-21 21:48:36138#endif
initial.commit09911bf2008-07-26 23:55:29139}
140
[email protected]829c2842009-04-01 01:48:52141#if defined(OS_WIN)
142void WebPluginProxy::SetWindowlessPumpEvent(HANDLE pump_messages_event) {
143 HANDLE pump_messages_event_for_renderer = NULL;
[email protected]d30ce6e2012-04-16 15:32:36144 content::BrokerDuplicateHandle(pump_messages_event, channel_->peer_pid(),
[email protected]cd0bd792012-04-14 00:52:16145 &pump_messages_event_for_renderer,
146 SYNCHRONIZE | EVENT_MODIFY_STATE, 0);
[email protected]829c2842009-04-01 01:48:52147 DCHECK(pump_messages_event_for_renderer != NULL);
148 Send(new PluginHostMsg_SetWindowlessPumpEvent(
149 route_id_, pump_messages_event_for_renderer));
150}
[email protected]829c2842009-04-01 01:48:52151#endif
152
[email protected]3d248b22009-12-03 07:11:34153void WebPluginProxy::CancelResource(unsigned long id) {
initial.commit09911bf2008-07-26 23:55:29154 Send(new PluginHostMsg_CancelResource(route_id_, id));
155 resource_clients_.erase(id);
156}
157
158void WebPluginProxy::Invalidate() {
[email protected]b94d3322009-02-12 19:49:04159 gfx::Rect rect(0, 0,
160 delegate_->GetRect().width(),
161 delegate_->GetRect().height());
[email protected]c20b4542008-10-01 00:38:11162 InvalidateRect(rect);
initial.commit09911bf2008-07-26 23:55:29163}
164
165void WebPluginProxy::InvalidateRect(const gfx::Rect& rect) {
[email protected]831058cb2009-08-27 17:42:53166#if defined(OS_MACOSX)
[email protected]23607ccf2010-06-03 23:15:33167 // If this is a Core Animation plugin, all we need to do is inform the
168 // delegate.
[email protected]9cf755682011-07-25 22:13:52169 if (!windowless_context()) {
[email protected]23607ccf2010-06-03 23:15:33170 delegate_->PluginDidInvalidate();
171 return;
172 }
[email protected]51a0bb52010-06-03 21:34:06173
[email protected]831058cb2009-08-27 17:42:53174 // Some plugins will send invalidates larger than their own rect when
175 // offscreen, so constrain invalidates to the plugin rect.
176 gfx::Rect plugin_rect = delegate_->GetRect();
177 plugin_rect.set_origin(gfx::Point(0, 0));
178 const gfx::Rect invalidate_rect(rect.Intersect(plugin_rect));
179#else
180 const gfx::Rect invalidate_rect(rect);
181#endif
182 damaged_rect_ = damaged_rect_.Union(invalidate_rect);
[email protected]20c011b32008-10-09 20:38:57183 // Ignore NPN_InvalidateRect calls with empty rects. Also don't send an
184 // invalidate if it's outside the clipping region, since if we did it won't
185 // lead to a paint and we'll be stuck waiting forever for a DidPaint response.
[email protected]56fcc3f2009-08-07 00:34:55186 //
187 // TODO(piman): There is a race condition here, because this test assumes
188 // that when the paint actually occurs, the clip rect will not have changed.
189 // This is not true because scrolling (or window resize) could occur and be
190 // handled by the renderer before it receives the InvalidateRect message,
191 // changing the clip rect and then not painting.
[email protected]a3edf8442010-04-14 23:57:50192 if (damaged_rect_.IsEmpty() ||
193 !delegate_->GetClipRect().Intersects(damaged_rect_))
[email protected]c20b4542008-10-01 00:38:11194 return;
195
[email protected]c20b4542008-10-01 00:38:11196 // Only send a single InvalidateRect message at a time. From DidPaint we
197 // will dispatch an additional InvalidateRect message if necessary.
198 if (!waiting_for_paint_) {
199 waiting_for_paint_ = true;
[email protected]f1a0eae2008-11-21 18:29:14200 // Invalidates caused by calls to NPN_InvalidateRect/NPN_InvalidateRgn
201 // need to be painted asynchronously as per the NPAPI spec.
202 MessageLoop::current()->PostTask(FROM_HERE,
[email protected]a4888372011-11-19 02:13:33203 base::Bind(&WebPluginProxy::OnPaint, weak_factory_.GetWeakPtr(),
204 damaged_rect_));
[email protected]c20b4542008-10-01 00:38:11205 damaged_rect_ = gfx::Rect();
initial.commit09911bf2008-07-26 23:55:29206 }
207}
208
209NPObject* WebPluginProxy::GetWindowScriptNPObject() {
210 if (window_npobject_)
[email protected]1eb70a22011-06-23 06:27:30211 return window_npobject_;
initial.commit09911bf2008-07-26 23:55:29212
213 int npobject_route_id = channel_->GenerateRouteID();
214 bool success = false;
initial.commit09911bf2008-07-26 23:55:29215 Send(new PluginHostMsg_GetWindowScriptNPObject(
[email protected]ea3d1d82010-01-29 22:35:33216 route_id_, npobject_route_id, &success));
initial.commit09911bf2008-07-26 23:55:29217 if (!success)
218 return NULL;
219
[email protected]ef916272009-07-08 21:40:55220 window_npobject_ = NPObjectProxy::Create(
[email protected]4da8a2e2010-01-20 07:05:23221 channel_, npobject_route_id, containing_window_, page_url_);
initial.commit09911bf2008-07-26 23:55:29222
223 return window_npobject_;
224}
225
226NPObject* WebPluginProxy::GetPluginElement() {
227 if (plugin_element_)
[email protected]1eb70a22011-06-23 06:27:30228 return plugin_element_;
initial.commit09911bf2008-07-26 23:55:29229
230 int npobject_route_id = channel_->GenerateRouteID();
231 bool success = false;
[email protected]df0ca6c82010-10-17 04:09:06232 Send(new PluginHostMsg_GetPluginElement(route_id_, npobject_route_id,
233 &success));
initial.commit09911bf2008-07-26 23:55:29234 if (!success)
235 return NULL;
236
[email protected]ef916272009-07-08 21:40:55237 plugin_element_ = NPObjectProxy::Create(
[email protected]4da8a2e2010-01-20 07:05:23238 channel_, npobject_route_id, containing_window_, page_url_);
initial.commit09911bf2008-07-26 23:55:29239
240 return plugin_element_;
241}
242
[email protected]2dd868f2011-08-29 23:03:57243bool WebPluginProxy::FindProxyForUrl(const GURL& url, std::string* proxy_list) {
244 bool result = false;
245 Send(new PluginHostMsg_ResolveProxy(route_id_, url, &result, proxy_list));
246 return result;
247}
248
initial.commit09911bf2008-07-26 23:55:29249void WebPluginProxy::SetCookie(const GURL& url,
[email protected]79e6a402009-11-18 19:31:40250 const GURL& first_party_for_cookies,
initial.commit09911bf2008-07-26 23:55:29251 const std::string& cookie) {
[email protected]79e6a402009-11-18 19:31:40252 Send(new PluginHostMsg_SetCookie(route_id_, url,
253 first_party_for_cookies, cookie));
initial.commit09911bf2008-07-26 23:55:29254}
255
256std::string WebPluginProxy::GetCookies(const GURL& url,
[email protected]79e6a402009-11-18 19:31:40257 const GURL& first_party_for_cookies) {
initial.commit09911bf2008-07-26 23:55:29258 std::string cookies;
[email protected]79e6a402009-11-18 19:31:40259 Send(new PluginHostMsg_GetCookies(route_id_, url,
260 first_party_for_cookies, &cookies));
initial.commit09911bf2008-07-26 23:55:29261
262 return cookies;
263}
264
initial.commit09911bf2008-07-26 23:55:29265WebPluginResourceClient* WebPluginProxy::GetResourceClient(int id) {
266 ResourceClientMap::iterator iterator = resource_clients_.find(id);
[email protected]e15e9c492009-08-04 07:06:39267 // The IPC messages which deal with streams are now asynchronous. It is
268 // now possible to receive stream messages from the renderer for streams
269 // which may have been cancelled by the plugin.
initial.commit09911bf2008-07-26 23:55:29270 if (iterator == resource_clients_.end()) {
initial.commit09911bf2008-07-26 23:55:29271 return NULL;
272 }
273
274 return iterator->second;
275}
276
[email protected]c84a7852009-09-16 21:36:44277int WebPluginProxy::GetRendererId() {
[email protected]35135512009-07-23 20:36:49278 if (channel_.get())
[email protected]c84a7852009-09-16 21:36:44279 return channel_->renderer_id();
280 return -1;
[email protected]35135512009-07-23 20:36:49281}
282
[email protected]c20b4542008-10-01 00:38:11283void WebPluginProxy::DidPaint() {
284 // If we have an accumulated damaged rect, then check to see if we need to
285 // send out another InvalidateRect message.
286 waiting_for_paint_ = false;
287 if (!damaged_rect_.IsEmpty())
288 InvalidateRect(damaged_rect_);
289}
290
[email protected]ea3d1d82010-01-29 22:35:33291void WebPluginProxy::OnResourceCreated(int resource_id,
292 WebPluginResourceClient* client) {
initial.commit09911bf2008-07-26 23:55:29293 DCHECK(resource_clients_.find(resource_id) == resource_clients_.end());
[email protected]ea3d1d82010-01-29 22:35:33294 resource_clients_[resource_id] = client;
initial.commit09911bf2008-07-26 23:55:29295}
296
[email protected]ea3d1d82010-01-29 22:35:33297void WebPluginProxy::HandleURLRequest(const char* url,
[email protected]d8627c12010-02-27 02:29:05298 const char* method,
[email protected]ea3d1d82010-01-29 22:35:33299 const char* target,
300 const char* buf,
301 unsigned int len,
302 int notify_id,
[email protected]65e82a562010-11-23 00:34:27303 bool popups_allowed,
304 bool notify_redirects) {
[email protected]ea3d1d82010-01-29 22:35:33305 if (!target && (0 == base::strcasecmp(method, "GET"))) {
[email protected]c82a5232009-01-16 01:41:16306 // Please refer to https://bugzilla.mozilla.org/show_bug.cgi?id=366082
307 // for more details on this.
[email protected]b94d3322009-02-12 19:49:04308 if (delegate_->GetQuirks() &
[email protected]191eb3f72010-12-21 06:27:50309 webkit::npapi::WebPluginDelegateImpl::
310 PLUGIN_QUIRK_BLOCK_NONSTANDARD_GETURL_REQUESTS) {
[email protected]c82a5232009-01-16 01:41:16311 GURL request_url(url);
[email protected]abbfaec2011-05-23 23:57:33312 if (!request_url.SchemeIs(chrome::kHttpScheme) &&
313 !request_url.SchemeIs(chrome::kHttpsScheme) &&
314 !request_url.SchemeIs(chrome::kFtpScheme)) {
[email protected]c82a5232009-01-16 01:41:16315 return;
316 }
317 }
318 }
319
initial.commit09911bf2008-07-26 23:55:29320 PluginHostMsg_URLRequest_Params params;
[email protected]ea3d1d82010-01-29 22:35:33321 params.url = url;
initial.commit09911bf2008-07-26 23:55:29322 params.method = method;
initial.commit09911bf2008-07-26 23:55:29323 if (target)
324 params.target = std::string(target);
325
326 if (len) {
327 params.buffer.resize(len);
328 memcpy(&params.buffer.front(), buf, len);
329 }
330
[email protected]ea3d1d82010-01-29 22:35:33331 params.notify_id = notify_id;
initial.commit09911bf2008-07-26 23:55:29332 params.popups_allowed = popups_allowed;
[email protected]65e82a562010-11-23 00:34:27333 params.notify_redirects = notify_redirects;
initial.commit09911bf2008-07-26 23:55:29334
335 Send(new PluginHostMsg_URLRequest(route_id_, params));
336}
license.botbf09a502008-08-24 00:55:55337
[email protected]c20b4542008-10-01 00:38:11338void WebPluginProxy::Paint(const gfx::Rect& rect) {
[email protected]753efc42010-03-09 19:52:16339#if defined(OS_MACOSX)
[email protected]9cf755682011-07-25 22:13:52340 if (!windowless_context())
[email protected]6bf1a812009-07-11 01:57:28341 return;
[email protected]753efc42010-03-09 19:52:16342#else
[email protected]42a36ed2012-02-24 17:49:57343 if (!windowless_canvas() || !windowless_canvas()->getDevice())
[email protected]753efc42010-03-09 19:52:16344 return;
[email protected]6bf1a812009-07-11 01:57:28345#endif
[email protected]22c54fdc2008-09-22 22:26:59346
[email protected]22c54fdc2008-09-22 22:26:59347 // Clear the damaged area so that if the plugin doesn't paint there we won't
348 // end up with the old values.
[email protected]c20b4542008-10-01 00:38:11349 gfx::Rect offset_rect = rect;
[email protected]b94d3322009-02-12 19:49:04350 offset_rect.Offset(delegate_->GetRect().origin());
[email protected]753efc42010-03-09 19:52:16351#if defined(OS_MACOSX)
[email protected]9cf755682011-07-25 22:13:52352 CGContextSaveGState(windowless_context());
353 // It is possible for windowless_contexts_ to change during plugin painting
[email protected]753efc42010-03-09 19:52:16354 // (since the plugin can make a synchronous call during paint event handling),
[email protected]9cf755682011-07-25 22:13:52355 // in which case we don't want to try to restore later. Not an owning ref
[email protected]753efc42010-03-09 19:52:16356 // since owning the ref without owning the shared backing memory doesn't make
357 // sense, so this should only be used for pointer comparisons.
[email protected]9cf755682011-07-25 22:13:52358 CGContextRef saved_context_weak = windowless_context();
359 // We also save the buffer index for the comparison because if we flip buffers
360 // but haven't reallocated them then we do need to restore the context because
361 // it is going to continue to be used.
362 int saved_index = windowless_buffer_index_;
[email protected]753efc42010-03-09 19:52:16363
[email protected]b9ae56902010-04-12 18:34:15364 if (background_context_.get()) {
[email protected]df0ca6c82010-10-17 04:09:06365 base::mac::ScopedCFTypeRef<CGImageRef> image(
[email protected]753efc42010-03-09 19:52:16366 CGBitmapContextCreateImage(background_context_));
367 CGRect source_rect = rect.ToCGRect();
368 // Flip the rect we use to pull from the canvas, since it's upside-down.
369 source_rect.origin.y = CGImageGetHeight(image) - rect.y() - rect.height();
[email protected]df0ca6c82010-10-17 04:09:06370 base::mac::ScopedCFTypeRef<CGImageRef> sub_image(
[email protected]753efc42010-03-09 19:52:16371 CGImageCreateWithImageInRect(image, source_rect));
[email protected]9cf755682011-07-25 22:13:52372 CGContextDrawImage(windowless_context(), rect.ToCGRect(), sub_image);
[email protected]ab7f2742010-04-14 17:24:51373 } else if (transparent_) {
[email protected]9cf755682011-07-25 22:13:52374 CGContextClearRect(windowless_context(), rect.ToCGRect());
[email protected]753efc42010-03-09 19:52:16375 }
[email protected]9cf755682011-07-25 22:13:52376 CGContextClipToRect(windowless_context(), rect.ToCGRect());
[email protected]44f854c2011-05-25 19:02:11377 // TODO(caryclark): This is a temporary workaround to allow the Darwin / Skia
378 // port to share code with the Darwin / CG port. All ports will eventually use
379 // the common code below.
[email protected]9cf755682011-07-25 22:13:52380 delegate_->CGPaint(windowless_context(), rect);
381 if (windowless_contexts_[saved_index].get() == saved_context_weak)
382 CGContextRestoreGState(windowless_contexts_[saved_index]);
[email protected]753efc42010-03-09 19:52:16383#else
[email protected]78d172342012-08-15 20:27:35384 // See above comment about windowless_context_ changing.
385 // http::/crbug.com/139462
386 skia::PlatformCanvas* saved_canvas = windowless_canvas();
387 SkAutoRef local_ref(saved_canvas);
388#if defined(USE_X11)
389 scoped_refptr<SharedTransportDIB> local_dib_ref(
390 windowless_dibs_[windowless_buffer_index_]);
391#endif
392
393 saved_canvas->save();
[email protected]22c54fdc2008-09-22 22:26:59394
[email protected]1d99bfac2009-10-29 19:58:43395 // The given clip rect is relative to the plugin coordinate system.
[email protected]558833a2009-10-23 16:20:01396 SkRect sk_rect = { SkIntToScalar(rect.x()),
397 SkIntToScalar(rect.y()),
398 SkIntToScalar(rect.right()),
399 SkIntToScalar(rect.bottom()) };
[email protected]78d172342012-08-15 20:27:35400 saved_canvas->clipRect(sk_rect);
[email protected]558833a2009-10-23 16:20:01401
402 // Setup the background.
[email protected]42a36ed2012-02-24 17:49:57403 if (background_canvas_.get() && background_canvas_.get()->getDevice()) {
[email protected]1d99bfac2009-10-29 19:58:43404 // When a background canvas is given, we're in transparent mode. This means
405 // the plugin wants to have the image of the page in the canvas it's drawing
[email protected]9cf755682011-07-25 22:13:52406 // into (which is windowless_canvases_) so it can do blending. So we copy
407 // the background bitmap into the windowless canvas.
[email protected]1d99bfac2009-10-29 19:58:43408 const SkBitmap& background_bitmap =
[email protected]62f2e802011-05-26 14:28:35409 skia::GetTopDevice(*background_canvas_)->accessBitmap(false);
[email protected]78d172342012-08-15 20:27:35410 saved_canvas->drawBitmap(background_bitmap, 0, 0);
[email protected]1d99bfac2009-10-29 19:58:43411 } else {
412 // In non-transparent mode, the plugin doesn't care what's underneath, so we
413 // can just give it black.
[email protected]558833a2009-10-23 16:20:01414 SkPaint black_fill_paint;
415 black_fill_paint.setARGB(0xFF, 0x00, 0x00, 0x00);
[email protected]78d172342012-08-15 20:27:35416 saved_canvas->drawPaint(black_fill_paint);
[email protected]558833a2009-10-23 16:20:01417 }
[email protected]24e863242009-03-27 16:21:25418
[email protected]9cf755682011-07-25 22:13:52419 // Bring the windowless canvas into the window coordinate system, which is
[email protected]1d99bfac2009-10-29 19:58:43420 // how the plugin expects to draw (since the windowless API was originally
421 // designed just for scribbling over the web page).
[email protected]78d172342012-08-15 20:27:35422 saved_canvas->translate(SkIntToScalar(-delegate_->GetRect().x()),
423 SkIntToScalar(-delegate_->GetRect().y()));
[email protected]1d99bfac2009-10-29 19:58:43424
[email protected]22c54fdc2008-09-22 22:26:59425 // Before we send the invalidate, paint so that renderer uses the updated
426 // bitmap.
[email protected]78d172342012-08-15 20:27:35427 delegate_->Paint(saved_canvas, offset_rect);
[email protected]24e863242009-03-27 16:21:25428
[email protected]78d172342012-08-15 20:27:35429 saved_canvas->restore();
[email protected]157e5d22009-04-23 18:43:35430#endif
[email protected]22c54fdc2008-09-22 22:26:59431}
432
433void WebPluginProxy::UpdateGeometry(
434 const gfx::Rect& window_rect,
435 const gfx::Rect& clip_rect,
[email protected]9cf755682011-07-25 22:13:52436 const TransportDIB::Handle& windowless_buffer0,
437 const TransportDIB::Handle& windowless_buffer1,
438 int windowless_buffer_index,
[email protected]ab7f2742010-04-14 17:24:51439 const TransportDIB::Handle& background_buffer,
[email protected]9cf755682011-07-25 22:13:52440 bool transparent) {
[email protected]b94d3322009-02-12 19:49:04441 gfx::Rect old = delegate_->GetRect();
442 gfx::Rect old_clip_rect = delegate_->GetClipRect();
[email protected]ab7f2742010-04-14 17:24:51443 transparent_ = transparent;
[email protected]f1a0eae2008-11-21 18:29:14444
[email protected]2b5b8ba2010-03-06 15:32:44445 // Update the buffers before doing anything that could call into plugin code,
446 // so that we don't process buffer changes out of order if plugins make
447 // synchronous calls that lead to nested UpdateGeometry calls.
[email protected]9cf755682011-07-25 22:13:52448 if (TransportDIB::is_valid_handle(windowless_buffer0)) {
449 // The plugin's rect changed, so now we have new buffers to draw into.
450 SetWindowlessBuffers(windowless_buffer0,
451 windowless_buffer1,
452 background_buffer,
453 window_rect);
[email protected]22c54fdc2008-09-22 22:26:59454 }
[email protected]558833a2009-10-23 16:20:01455
[email protected]9cf755682011-07-25 22:13:52456 DCHECK(0 <= windowless_buffer_index && windowless_buffer_index <= 1);
457 windowless_buffer_index_ = windowless_buffer_index;
458#if defined(USE_X11)
459 delegate_->SetWindowlessShmPixmap(windowless_shm_pixmap());
460#endif
461
[email protected]2b5b8ba2010-03-06 15:32:44462#if defined(OS_MACOSX)
[email protected]9cf755682011-07-25 22:13:52463 delegate_->UpdateGeometryAndContext(
464 window_rect, clip_rect, windowless_context());
[email protected]2b5b8ba2010-03-06 15:32:44465#else
466 delegate_->UpdateGeometry(window_rect, clip_rect);
467#endif
468
[email protected]f1a0eae2008-11-21 18:29:14469 // Send over any pending invalidates which occured when the plugin was
470 // off screen.
[email protected]b94d3322009-02-12 19:49:04471 if (delegate_->IsWindowless() && !clip_rect.IsEmpty() &&
[email protected]a3edf8442010-04-14 23:57:50472 !damaged_rect_.IsEmpty()) {
[email protected]f1a0eae2008-11-21 18:29:14473 InvalidateRect(damaged_rect_);
474 }
[email protected]22c54fdc2008-09-22 22:26:59475}
476
[email protected]36808ad2010-10-20 19:18:30477#if defined(OS_WIN)
[email protected]9cf755682011-07-25 22:13:52478
479void WebPluginProxy::CreateCanvasFromHandle(
480 const TransportDIB::Handle& dib_handle,
481 const gfx::Rect& window_rect,
[email protected]78d172342012-08-15 20:27:35482 SkAutoTUnref<skia::PlatformCanvas>* canvas) {
483 canvas->reset(new skia::PlatformCanvas);
484 if (!canvas->get()->initialize(
[email protected]36808ad2010-10-20 19:18:30485 window_rect.width(),
486 window_rect.height(),
487 true,
[email protected]cd0bd792012-04-14 00:52:16488 dib_handle)) {
[email protected]78d172342012-08-15 20:27:35489 canvas->reset(NULL);
[email protected]9cf755682011-07-25 22:13:52490 }
[email protected]1bfecd02011-07-29 00:54:20491 // The canvas does not own the section so we need to close it now.
[email protected]cd0bd792012-04-14 00:52:16492 CloseHandle(dib_handle);
[email protected]9cf755682011-07-25 22:13:52493}
494
495void WebPluginProxy::SetWindowlessBuffers(
496 const TransportDIB::Handle& windowless_buffer0,
497 const TransportDIB::Handle& windowless_buffer1,
498 const TransportDIB::Handle& background_buffer,
499 const gfx::Rect& window_rect) {
500 CreateCanvasFromHandle(windowless_buffer0,
501 window_rect,
502 &windowless_canvases_[0]);
503 if (!windowless_canvases_[0].get()) {
[email protected]78d172342012-08-15 20:27:35504 windowless_canvases_[1].reset(NULL);
505 background_canvas_.reset(NULL);
[email protected]9cf755682011-07-25 22:13:52506 return;
507 }
508 CreateCanvasFromHandle(windowless_buffer1,
509 window_rect,
510 &windowless_canvases_[1]);
511 if (!windowless_canvases_[1].get()) {
[email protected]78d172342012-08-15 20:27:35512 windowless_canvases_[0].reset(NULL);
513 background_canvas_.reset(NULL);
[email protected]36808ad2010-10-20 19:18:30514 return;
515 }
516
517 if (background_buffer) {
[email protected]9cf755682011-07-25 22:13:52518 CreateCanvasFromHandle(background_buffer,
519 window_rect,
520 &background_canvas_);
521 if (!background_canvas_.get()) {
[email protected]78d172342012-08-15 20:27:35522 windowless_canvases_[0].reset(NULL);
523 windowless_canvases_[1].reset(NULL);
[email protected]36808ad2010-10-20 19:18:30524 return;
525 }
526 }
527}
528
529#elif defined(OS_MACOSX)
530
[email protected]9cf755682011-07-25 22:13:52531void WebPluginProxy::CreateDIBAndCGContextFromHandle(
532 const TransportDIB::Handle& dib_handle,
533 const gfx::Rect& window_rect,
534 scoped_ptr<TransportDIB>* dib_out,
535 base::mac::ScopedCFTypeRef<CGContextRef>* cg_context_out) {
[email protected]36808ad2010-10-20 19:18:30536 // Convert the shared memory handle to a handle that works in our process,
537 // and then use that to create a CGContextRef.
[email protected]9cf755682011-07-25 22:13:52538 TransportDIB* dib = TransportDIB::Map(dib_handle);
539 CGContextRef cg_context = NULL;
540 if (dib) {
541 cg_context = CGBitmapContextCreate(
542 dib->memory(),
[email protected]2b5b8ba2010-03-06 15:32:44543 window_rect.width(),
544 window_rect.height(),
[email protected]9cf755682011-07-25 22:13:52545 8,
546 4 * window_rect.width(),
[email protected]0378bf42011-01-01 18:20:14547 base::mac::GetSystemColorSpace(),
[email protected]9cf755682011-07-25 22:13:52548 kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host);
549 CGContextTranslateCTM(cg_context, 0, window_rect.height());
550 CGContextScaleCTM(cg_context, 1, -1);
[email protected]6bf1a812009-07-11 01:57:28551 }
[email protected]9cf755682011-07-25 22:13:52552 dib_out->reset(dib);
553 cg_context_out->reset(cg_context);
554}
555
556void WebPluginProxy::SetWindowlessBuffers(
557 const TransportDIB::Handle& windowless_buffer0,
558 const TransportDIB::Handle& windowless_buffer1,
559 const TransportDIB::Handle& background_buffer,
560 const gfx::Rect& window_rect) {
561 CreateDIBAndCGContextFromHandle(windowless_buffer0,
562 window_rect,
563 &windowless_dibs_[0],
564 &windowless_contexts_[0]);
565 CreateDIBAndCGContextFromHandle(windowless_buffer1,
566 window_rect,
567 &windowless_dibs_[1],
568 &windowless_contexts_[1]);
569 CreateDIBAndCGContextFromHandle(background_buffer,
570 window_rect,
571 &background_dib_,
572 &background_context_);
[email protected]36808ad2010-10-20 19:18:30573}
574
575#elif defined(USE_X11)
576
[email protected]9cf755682011-07-25 22:13:52577void WebPluginProxy::CreateDIBAndCanvasFromHandle(
578 const TransportDIB::Handle& dib_handle,
579 const gfx::Rect& window_rect,
[email protected]78d172342012-08-15 20:27:35580 scoped_refptr<SharedTransportDIB>* dib_out,
581 SkAutoTUnref<skia::PlatformCanvas>* canvas) {
[email protected]9cf755682011-07-25 22:13:52582 TransportDIB* dib = TransportDIB::Map(dib_handle);
[email protected]9cf755682011-07-25 22:13:52583 // dib may be NULL if the renderer has already destroyed the TransportDIB by
584 // the time we receive the handle, e.g. in case of multiple resizes.
585 if (dib) {
[email protected]78d172342012-08-15 20:27:35586 canvas->reset(
587 dib->GetPlatformCanvas(window_rect.width(), window_rect.height()));
588 } else {
589 canvas->reset(NULL);
[email protected]d8683e32010-10-06 11:52:32590 }
[email protected]78d172342012-08-15 20:27:35591 *dib_out = new SharedTransportDIB(dib);
[email protected]9cf755682011-07-25 22:13:52592}
[email protected]cb632c32010-08-05 02:54:42593
[email protected]9cf755682011-07-25 22:13:52594void WebPluginProxy::CreateShmPixmapFromDIB(
595 TransportDIB* dib,
596 const gfx::Rect& window_rect,
597 XID* pixmap_out) {
598 if (dib) {
[email protected]9dd7e3d72011-01-20 18:27:06599 Display* display = ui::GetXDisplay();
600 XID root_window = ui::GetX11RootWindow();
[email protected]cb632c32010-08-05 02:54:42601 XShmSegmentInfo shminfo = {0};
602
[email protected]9cf755682011-07-25 22:13:52603 if (*pixmap_out != None)
604 XFreePixmap(display, *pixmap_out);
[email protected]cb632c32010-08-05 02:54:42605
[email protected]9cf755682011-07-25 22:13:52606 shminfo.shmseg = dib->MapToX(display);
[email protected]cb632c32010-08-05 02:54:42607 // Create a shared memory pixmap based on the image buffer.
[email protected]9cf755682011-07-25 22:13:52608 *pixmap_out = XShmCreatePixmap(display, root_window,
609 NULL, &shminfo,
610 window_rect.width(), window_rect.height(),
[email protected]88a8ffa2011-10-13 01:41:05611 DefaultDepth(display,
612 DefaultScreen(display)));
[email protected]9cf755682011-07-25 22:13:52613 }
614}
[email protected]cb632c32010-08-05 02:54:42615
[email protected]9cf755682011-07-25 22:13:52616void WebPluginProxy::SetWindowlessBuffers(
617 const TransportDIB::Handle& windowless_buffer0,
618 const TransportDIB::Handle& windowless_buffer1,
619 const TransportDIB::Handle& background_buffer,
620 const gfx::Rect& window_rect) {
621 CreateDIBAndCanvasFromHandle(windowless_buffer0,
622 window_rect,
623 &windowless_dibs_[0],
624 &windowless_canvases_[0]);
625 CreateDIBAndCanvasFromHandle(windowless_buffer1,
626 window_rect,
627 &windowless_dibs_[1],
628 &windowless_canvases_[1]);
629 CreateDIBAndCanvasFromHandle(background_buffer,
630 window_rect,
631 &background_dib_,
632 &background_canvas_);
633
634 // If SHM pixmaps support is available, create SHM pixmaps to pass to the
635 // delegate for windowless plugin painting.
636 if (delegate_->IsWindowless() && use_shm_pixmap_) {
[email protected]78d172342012-08-15 20:27:35637 CreateShmPixmapFromDIB(windowless_dibs_[0]->dib(),
[email protected]9cf755682011-07-25 22:13:52638 window_rect,
639 &windowless_shm_pixmaps_[0]);
[email protected]78d172342012-08-15 20:27:35640 CreateShmPixmapFromDIB(windowless_dibs_[1]->dib(),
[email protected]9cf755682011-07-25 22:13:52641 window_rect,
642 &windowless_shm_pixmaps_[1]);
[email protected]cb632c32010-08-05 02:54:42643 }
[email protected]ae849ea2010-10-20 18:00:36644}
[email protected]d8683e32010-10-06 11:52:32645
[email protected]e0825562012-05-10 01:50:47646#elif defined(OS_ANDROID)
647
648void WebPluginProxy::SetWindowlessBuffers(
649 const TransportDIB::Handle& windowless_buffer0,
650 const TransportDIB::Handle& windowless_buffer1,
651 const TransportDIB::Handle& background_buffer,
652 const gfx::Rect& window_rect) {
653 NOTIMPLEMENTED();
654}
655
[email protected]36808ad2010-10-20 19:18:30656#endif
657
[email protected]6f863cd2008-12-05 22:27:39658void WebPluginProxy::CancelDocumentLoad() {
659 Send(new PluginHostMsg_CancelDocumentLoad(route_id_));
660}
661
[email protected]ea3d1d82010-01-29 22:35:33662void WebPluginProxy::InitiateHTTPRangeRequest(
663 const char* url, const char* range_info, int range_request_id) {
664 Send(new PluginHostMsg_InitiateHTTPRangeRequest(
665 route_id_, url, range_info, range_request_id));
[email protected]84f89ca2008-09-19 02:09:49666}
[email protected]f1a0eae2008-11-21 18:29:14667
[email protected]3d248b22009-12-03 07:11:34668void WebPluginProxy::SetDeferResourceLoading(unsigned long resource_id,
669 bool defer) {
[email protected]e15e9c492009-08-04 07:06:39670 Send(new PluginHostMsg_DeferResourceLoading(route_id_, resource_id, defer));
671}
672
[email protected]3d1e89d2010-03-10 20:01:35673#if defined(OS_MACOSX)
[email protected]b7f75862011-01-21 21:15:13674void WebPluginProxy::FocusChanged(bool focused) {
675 IPC::Message* msg = new PluginHostMsg_FocusChanged(route_id_, focused);
676 Send(msg);
677}
678
679void WebPluginProxy::StartIme() {
680 IPC::Message* msg = new PluginHostMsg_StartIme(route_id_);
[email protected]935d63d2010-10-15 23:31:55681 // This message can be sent during event-handling, and needs to be delivered
682 // within that context.
683 msg->set_unblock(true);
684 Send(msg);
685}
686
[email protected]ea04a4e12010-04-15 00:58:03687void WebPluginProxy::BindFakePluginWindowHandle(bool opaque) {
688 Send(new PluginHostMsg_BindFakePluginWindowHandle(route_id_, opaque));
[email protected]3d1e89d2010-03-10 20:01:35689}
690
[email protected]276f89062011-10-13 22:55:50691WebPluginAcceleratedSurface* WebPluginProxy::GetAcceleratedSurface(
692 gfx::GpuPreference gpu_preference) {
[email protected]8b4755f2010-10-01 18:04:06693 if (!accelerated_surface_.get())
[email protected]dc51d1c2011-11-30 04:42:21694 accelerated_surface_.reset(
695 WebPluginAcceleratedSurfaceProxy::Create(this, gpu_preference));
[email protected]8b4755f2010-10-01 18:04:06696 return accelerated_surface_.get();
697}
698
[email protected]3d1e89d2010-03-10 20:01:35699void WebPluginProxy::AcceleratedFrameBuffersDidSwap(
[email protected]7de8fb72012-03-14 04:24:32700 gfx::PluginWindowHandle window, uint64 surface_handle) {
[email protected]f35d6672010-10-28 21:39:14701 Send(new PluginHostMsg_AcceleratedSurfaceBuffersSwapped(
[email protected]7de8fb72012-03-14 04:24:32702 route_id_, window, surface_handle));
[email protected]3d1e89d2010-03-10 20:01:35703}
704
[email protected]8b4755f2010-10-01 18:04:06705void WebPluginProxy::SetAcceleratedSurface(
706 gfx::PluginWindowHandle window,
707 const gfx::Size& size,
[email protected]3d1e89d2010-03-10 20:01:35708 uint64 accelerated_surface_identifier) {
[email protected]44ce0b12010-03-12 16:45:33709 Send(new PluginHostMsg_AcceleratedSurfaceSetIOSurface(
[email protected]8b4755f2010-10-01 18:04:06710 route_id_, window, size.width(), size.height(),
711 accelerated_surface_identifier));
712}
713
714void WebPluginProxy::SetAcceleratedDIB(
715 gfx::PluginWindowHandle window,
716 const gfx::Size& size,
717 const TransportDIB::Handle& dib_handle) {
718 Send(new PluginHostMsg_AcceleratedSurfaceSetTransportDIB(
719 route_id_, window, size.width(), size.height(), dib_handle));
720}
721
722void WebPluginProxy::AllocSurfaceDIB(const size_t size,
723 TransportDIB::Handle* dib_handle) {
724 Send(new PluginHostMsg_AllocTransportDIB(route_id_, size, dib_handle));
725}
726
727void WebPluginProxy::FreeSurfaceDIB(TransportDIB::Id dib_id) {
728 Send(new PluginHostMsg_FreeTransportDIB(route_id_, dib_id));
[email protected]3d1e89d2010-03-10 20:01:35729}
[email protected]dc51d1c2011-11-30 04:42:21730
731void WebPluginProxy::AcceleratedPluginEnabledRendering() {
732 Send(new PluginHostMsg_AcceleratedPluginEnabledRendering(route_id_));
733}
734
735void WebPluginProxy::AcceleratedPluginAllocatedIOSurface(int32 width,
736 int32 height,
737 uint32 surface_id) {
738 Send(new PluginHostMsg_AcceleratedPluginAllocatedIOSurface(
739 route_id_, width, height, surface_id));
740}
741
742void WebPluginProxy::AcceleratedPluginSwappedIOSurface() {
743 Send(new PluginHostMsg_AcceleratedPluginSwappedIOSurface(
744 route_id_));
745}
[email protected]3d1e89d2010-03-10 20:01:35746#endif
747
[email protected]f1a0eae2008-11-21 18:29:14748void WebPluginProxy::OnPaint(const gfx::Rect& damaged_rect) {
[email protected]a82151cc2011-03-15 20:42:39749 content::GetContentClient()->SetActiveURL(page_url_);
[email protected]ef916272009-07-08 21:40:55750
[email protected]f1a0eae2008-11-21 18:29:14751 Paint(damaged_rect);
[email protected]a0b4cb82012-09-11 19:47:18752 Send(new PluginHostMsg_InvalidateRect(route_id_, damaged_rect));
[email protected]f1a0eae2008-11-21 18:29:14753}
[email protected]3c8bd9f2009-03-26 19:40:29754
755bool WebPluginProxy::IsOffTheRecord() {
[email protected]d5e44452011-03-10 18:12:10756 return channel_->incognito();
[email protected]3c8bd9f2009-03-26 19:40:29757}
[email protected]0a703232009-05-23 01:30:33758
759void WebPluginProxy::ResourceClientDeleted(
760 WebPluginResourceClient* resource_client) {
761 ResourceClientMap::iterator index = resource_clients_.begin();
762 while (index != resource_clients_.end()) {
763 WebPluginResourceClient* client = (*index).second;
764
765 if (client == resource_client) {
766 resource_clients_.erase(index++);
767 } else {
768 index++;
769 }
770 }
771}
[email protected]65e82a562010-11-23 00:34:27772
773void WebPluginProxy::URLRedirectResponse(bool allow, int resource_id) {
774 Send(new PluginHostMsg_URLRedirectResponse(route_id_, allow, resource_id));
775}
[email protected]e6ae0f6c2011-10-04 10:39:23776
[email protected]e5b307f2011-10-06 22:55:28777#if defined(OS_WIN) && !defined(USE_AURA)
[email protected]e6ae0f6c2011-10-04 10:39:23778void WebPluginProxy::UpdateIMEStatus() {
779 // Retrieve the IME status from a plug-in and send it to a renderer process
780 // when the plug-in has updated it.
781 int input_type;
782 gfx::Rect caret_rect;
783 if (!delegate_->GetIMEStatus(&input_type, &caret_rect))
784 return;
785
786 Send(new PluginHostMsg_NotifyIMEStatus(route_id_, input_type, caret_rect));
787}
788#endif