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

Side by Side Diff: content/plugin/webplugin_proxy.cc

Issue 1852593004: Remove content/plugin (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@remove_npapi_test_plugin
Patch Set: . Created 4 years, 8 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
« no previous file with comments | « content/plugin/webplugin_proxy.h ('k') | content/public/plugin/BUILD.gn » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/plugin/webplugin_proxy.h"
6
7 #include "build/build_config.h"
8
9 #include "base/bind.h"
10 #include "base/lazy_instance.h"
11 #include "content/child/npapi/webplugin_delegate_impl.h"
12 #include "content/child/plugin_messages.h"
13 #include "content/plugin/plugin_channel.h"
14 #include "content/plugin/plugin_thread.h"
15 #include "content/public/common/content_client.h"
16 #include "skia/ext/platform_canvas.h"
17 #include "ui/gfx/canvas.h"
18 #include "url/url_constants.h"
19
20 #if defined(OS_MACOSX)
21 #include "base/mac/mac_util.h"
22 #include "base/mac/scoped_cftyperef.h"
23 #include "content/plugin/webplugin_accelerated_surface_proxy_mac.h"
24 #endif
25
26 #if defined(OS_WIN)
27 #include "content/common/plugin_process_messages.h"
28 #include "content/public/common/sandbox_init.h"
29 #endif
30
31 namespace content {
32
33 WebPluginProxy::SharedTransportDIB::SharedTransportDIB(TransportDIB* dib)
34 : dib_(dib) {
35 }
36
37 WebPluginProxy::SharedTransportDIB::~SharedTransportDIB() {
38 }
39
40 WebPluginProxy::WebPluginProxy(
41 PluginChannel* channel,
42 int route_id,
43 const GURL& page_url,
44 int host_render_view_routing_id)
45 : channel_(channel),
46 route_id_(route_id),
47 delegate_(NULL),
48 waiting_for_paint_(false),
49 page_url_(page_url),
50 windowless_buffer_index_(0),
51 host_render_view_routing_id_(host_render_view_routing_id),
52 weak_factory_(this) {
53 }
54
55 WebPluginProxy::~WebPluginProxy() {
56 #if defined(OS_MACOSX)
57 // Destroy the surface early, since it may send messages during cleanup.
58 if (accelerated_surface_)
59 accelerated_surface_.reset();
60 #endif
61 }
62
63 bool WebPluginProxy::Send(IPC::Message* msg) {
64 return channel_->Send(msg);
65 }
66
67 void WebPluginProxy::Invalidate() {
68 gfx::Rect rect(0, 0,
69 delegate_->GetRect().width(),
70 delegate_->GetRect().height());
71 InvalidateRect(rect);
72 }
73
74 void WebPluginProxy::InvalidateRect(const gfx::Rect& rect) {
75 #if defined(OS_MACOSX)
76 // If this is a Core Animation plugin, all we need to do is inform the
77 // delegate.
78 if (!windowless_context()) {
79 delegate_->PluginDidInvalidate();
80 return;
81 }
82
83 // Some plugins will send invalidates larger than their own rect when
84 // offscreen, so constrain invalidates to the plugin rect.
85 gfx::Rect plugin_rect = delegate_->GetRect();
86 plugin_rect.set_origin(gfx::Point(0, 0));
87 plugin_rect.Intersect(rect);
88 const gfx::Rect invalidate_rect(plugin_rect);
89 #else
90 const gfx::Rect invalidate_rect(rect);
91 #endif
92 damaged_rect_.Union(invalidate_rect);
93 // Ignore NPN_InvalidateRect calls with empty rects. Also don't send an
94 // invalidate if it's outside the clipping region, since if we did it won't
95 // lead to a paint and we'll be stuck waiting forever for a DidPaint response.
96 //
97 // TODO(piman): There is a race condition here, because this test assumes
98 // that when the paint actually occurs, the clip rect will not have changed.
99 // This is not true because scrolling (or window resize) could occur and be
100 // handled by the renderer before it receives the InvalidateRect message,
101 // changing the clip rect and then not painting.
102 if (damaged_rect_.IsEmpty() ||
103 !delegate_->GetClipRect().Intersects(damaged_rect_))
104 return;
105
106 // Only send a single InvalidateRect message at a time. From DidPaint we
107 // will dispatch an additional InvalidateRect message if necessary.
108 if (!waiting_for_paint_) {
109 waiting_for_paint_ = true;
110 // Invalidates caused by calls to NPN_InvalidateRect/NPN_InvalidateRgn
111 // need to be painted asynchronously as per the NPAPI spec.
112 base::MessageLoop::current()->PostTask(
113 FROM_HERE,
114 base::Bind(&WebPluginProxy::OnPaint,
115 weak_factory_.GetWeakPtr(),
116 damaged_rect_));
117 damaged_rect_ = gfx::Rect();
118 }
119 }
120
121 bool WebPluginProxy::FindProxyForUrl(const GURL& url, std::string* proxy_list) {
122 bool result = false;
123 Send(new PluginHostMsg_ResolveProxy(route_id_, url, &result, proxy_list));
124 return result;
125 }
126
127 void WebPluginProxy::SetCookie(const GURL& url,
128 const GURL& first_party_for_cookies,
129 const std::string& cookie) {
130 Send(new PluginHostMsg_SetCookie(route_id_, url,
131 first_party_for_cookies, cookie));
132 }
133
134 std::string WebPluginProxy::GetCookies(const GURL& url,
135 const GURL& first_party_for_cookies) {
136 std::string cookies;
137 Send(new PluginHostMsg_GetCookies(route_id_, url,
138 first_party_for_cookies, &cookies));
139
140 return cookies;
141 }
142
143 int WebPluginProxy::GetRendererId() {
144 if (channel_.get())
145 return channel_->renderer_id();
146 return -1;
147 }
148
149 void WebPluginProxy::DidPaint() {
150 // If we have an accumulated damaged rect, then check to see if we need to
151 // send out another InvalidateRect message.
152 waiting_for_paint_ = false;
153 if (!damaged_rect_.IsEmpty())
154 InvalidateRect(damaged_rect_);
155 }
156
157 void WebPluginProxy::Paint(const gfx::Rect& rect) {
158 #if defined(OS_MACOSX)
159 if (!windowless_context())
160 return;
161 #else
162 if (!windowless_canvas() || !windowless_canvas()->getDevice())
163 return;
164 #endif
165
166 // Clear the damaged area so that if the plugin doesn't paint there we won't
167 // end up with the old values.
168 gfx::Rect offset_rect = rect;
169 offset_rect.Offset(delegate_->GetRect().OffsetFromOrigin());
170 #if defined(OS_MACOSX)
171 CGContextSaveGState(windowless_context());
172 // It is possible for windowless_contexts_ to change during plugin painting
173 // (since the plugin can make a synchronous call during paint event handling),
174 // in which case we don't want to try to restore later. Not an owning ref
175 // since owning the ref without owning the shared backing memory doesn't make
176 // sense, so this should only be used for pointer comparisons.
177 CGContextRef saved_context_weak = windowless_context();
178 // We also save the buffer index for the comparison because if we flip buffers
179 // but haven't reallocated them then we do need to restore the context because
180 // it is going to continue to be used.
181 int saved_index = windowless_buffer_index_;
182
183 CGContextClipToRect(windowless_context(), rect.ToCGRect());
184 // TODO(caryclark): This is a temporary workaround to allow the Darwin / Skia
185 // port to share code with the Darwin / CG port. All ports will eventually use
186 // the common code below.
187 delegate_->CGPaint(windowless_context(), rect);
188 if (windowless_contexts_[saved_index].get() == saved_context_weak)
189 CGContextRestoreGState(windowless_contexts_[saved_index]);
190 #else
191 // See above comment about windowless_context_ changing.
192 // http::/crbug.com/139462
193 skia::RefPtr<SkCanvas> saved_canvas = windowless_canvas();
194
195 saved_canvas->save();
196
197 // The given clip rect is relative to the plugin coordinate system.
198 SkRect sk_rect = { SkIntToScalar(rect.x()),
199 SkIntToScalar(rect.y()),
200 SkIntToScalar(rect.right()),
201 SkIntToScalar(rect.bottom()) };
202 saved_canvas->clipRect(sk_rect);
203
204 // Fill a transparent value so that if the plugin supports transparency that
205 // will work.
206 saved_canvas->drawColor(SkColorSetARGB(0, 0, 0, 0), SkXfermode::kSrc_Mode);
207
208 // Bring the windowless canvas into the window coordinate system, which is
209 // how the plugin expects to draw (since the windowless API was originally
210 // designed just for scribbling over the web page).
211 saved_canvas->translate(SkIntToScalar(-delegate_->GetRect().x()),
212 SkIntToScalar(-delegate_->GetRect().y()));
213
214 // Before we send the invalidate, paint so that renderer uses the updated
215 // bitmap.
216 delegate_->Paint(saved_canvas.get(), offset_rect);
217
218 saved_canvas->restore();
219 #endif
220 }
221
222 void WebPluginProxy::UpdateGeometry(
223 const gfx::Rect& window_rect,
224 const gfx::Rect& clip_rect,
225 const TransportDIB::Handle& windowless_buffer0,
226 const TransportDIB::Handle& windowless_buffer1,
227 int windowless_buffer_index) {
228 gfx::Rect old = delegate_->GetRect();
229 gfx::Rect old_clip_rect = delegate_->GetClipRect();
230
231 // Update the buffers before doing anything that could call into plugin code,
232 // so that we don't process buffer changes out of order if plugins make
233 // synchronous calls that lead to nested UpdateGeometry calls.
234 if (TransportDIB::is_valid_handle(windowless_buffer0)) {
235 // The plugin's rect changed, so now we have new buffers to draw into.
236 SetWindowlessBuffers(windowless_buffer0,
237 windowless_buffer1,
238 window_rect);
239 }
240
241 DCHECK(0 <= windowless_buffer_index && windowless_buffer_index <= 1);
242 windowless_buffer_index_ = windowless_buffer_index;
243
244 #if defined(OS_MACOSX)
245 delegate_->UpdateGeometryAndContext(
246 window_rect, clip_rect, windowless_context());
247 #else
248 delegate_->UpdateGeometry(window_rect, clip_rect);
249 #endif
250
251 // Send over any pending invalidates which occured when the plugin was
252 // off screen.
253 if (!clip_rect.IsEmpty() && !damaged_rect_.IsEmpty()) {
254 InvalidateRect(damaged_rect_);
255 }
256 }
257
258 #if defined(OS_WIN)
259
260 void WebPluginProxy::CreateCanvasFromHandle(
261 const TransportDIB::Handle& dib_handle,
262 const gfx::Rect& window_rect,
263 skia::RefPtr<SkCanvas>* canvas) {
264 *canvas = skia::AdoptRef(skia::CreatePlatformCanvas(
265 window_rect.width(), window_rect.height(), true, dib_handle.GetHandle(),
266 skia::RETURN_NULL_ON_FAILURE));
267 // The canvas does not own the section so we need to close it now.
268 dib_handle.Close();
269 }
270
271 void WebPluginProxy::SetWindowlessBuffers(
272 const TransportDIB::Handle& windowless_buffer0,
273 const TransportDIB::Handle& windowless_buffer1,
274 const gfx::Rect& window_rect) {
275 CreateCanvasFromHandle(windowless_buffer0,
276 window_rect,
277 &windowless_canvases_[0]);
278 if (!windowless_canvases_[0]) {
279 windowless_canvases_[1].clear();
280 return;
281 }
282 CreateCanvasFromHandle(windowless_buffer1,
283 window_rect,
284 &windowless_canvases_[1]);
285 if (!windowless_canvases_[1]) {
286 windowless_canvases_[0].clear();
287 return;
288 }
289 }
290
291 #elif defined(OS_MACOSX)
292
293 void WebPluginProxy::CreateDIBAndCGContextFromHandle(
294 const TransportDIB::Handle& dib_handle,
295 const gfx::Rect& window_rect,
296 scoped_ptr<TransportDIB>* dib_out,
297 base::ScopedCFTypeRef<CGContextRef>* cg_context_out) {
298 // Convert the shared memory handle to a handle that works in our process,
299 // and then use that to create a CGContextRef.
300 TransportDIB* dib = TransportDIB::Map(dib_handle);
301 CGContextRef cg_context = NULL;
302 if (dib) {
303 cg_context = CGBitmapContextCreate(
304 dib->memory(),
305 window_rect.width(),
306 window_rect.height(),
307 8,
308 4 * window_rect.width(),
309 base::mac::GetSystemColorSpace(),
310 kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host);
311 CGContextTranslateCTM(cg_context, 0, window_rect.height());
312 CGContextScaleCTM(cg_context, 1, -1);
313 }
314 dib_out->reset(dib);
315 cg_context_out->reset(cg_context);
316 }
317
318 void WebPluginProxy::SetWindowlessBuffers(
319 const TransportDIB::Handle& windowless_buffer0,
320 const TransportDIB::Handle& windowless_buffer1,
321 const gfx::Rect& window_rect) {
322 CreateDIBAndCGContextFromHandle(windowless_buffer0,
323 window_rect,
324 &windowless_dibs_[0],
325 &windowless_contexts_[0]);
326 CreateDIBAndCGContextFromHandle(windowless_buffer1,
327 window_rect,
328 &windowless_dibs_[1],
329 &windowless_contexts_[1]);
330 }
331
332 #else
333
334 void WebPluginProxy::SetWindowlessBuffers(
335 const TransportDIB::Handle& windowless_buffer0,
336 const TransportDIB::Handle& windowless_buffer1,
337 const gfx::Rect& window_rect) {
338 NOTIMPLEMENTED();
339 }
340
341 #endif
342
343 void WebPluginProxy::CancelDocumentLoad() {
344 Send(new PluginHostMsg_CancelDocumentLoad(route_id_));
345 }
346
347 void WebPluginProxy::DidStartLoading() {
348 Send(new PluginHostMsg_DidStartLoading(route_id_));
349 }
350
351 void WebPluginProxy::DidStopLoading() {
352 Send(new PluginHostMsg_DidStopLoading(route_id_));
353 }
354
355 #if defined(OS_MACOSX)
356 void WebPluginProxy::FocusChanged(bool focused) {
357 IPC::Message* msg = new PluginHostMsg_FocusChanged(route_id_, focused);
358 Send(msg);
359 }
360
361 void WebPluginProxy::StartIme() {
362 IPC::Message* msg = new PluginHostMsg_StartIme(route_id_);
363 // This message can be sent during event-handling, and needs to be delivered
364 // within that context.
365 msg->set_unblock(true);
366 Send(msg);
367 }
368
369 WebPluginAcceleratedSurface* WebPluginProxy::GetAcceleratedSurface(
370 gfx::GpuPreference gpu_preference) {
371 if (!accelerated_surface_)
372 accelerated_surface_.reset(
373 WebPluginAcceleratedSurfaceProxy::Create(this, gpu_preference));
374 return accelerated_surface_.get();
375 }
376
377 void WebPluginProxy::AcceleratedPluginEnabledRendering() {
378 Send(new PluginHostMsg_AcceleratedPluginEnabledRendering(route_id_));
379 }
380
381 void WebPluginProxy::AcceleratedPluginAllocatedIOSurface(int32_t width,
382 int32_t height,
383 uint32_t surface_id) {
384 Send(new PluginHostMsg_AcceleratedPluginAllocatedIOSurface(
385 route_id_, width, height, surface_id));
386 }
387
388 void WebPluginProxy::AcceleratedPluginSwappedIOSurface() {
389 Send(new PluginHostMsg_AcceleratedPluginSwappedIOSurface(
390 route_id_));
391 }
392 #endif
393
394 void WebPluginProxy::OnPaint(const gfx::Rect& damaged_rect) {
395 GetContentClient()->SetActiveURL(page_url_);
396
397 Paint(damaged_rect);
398 Send(new PluginHostMsg_InvalidateRect(route_id_, damaged_rect));
399 }
400
401 bool WebPluginProxy::IsOffTheRecord() {
402 return channel_->incognito();
403 }
404
405 } // namespace content
OLDNEW
« no previous file with comments | « content/plugin/webplugin_proxy.h ('k') | content/public/plugin/BUILD.gn » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698