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

Side by Side Diff: webkit/glue/plugins/pepper_plugin_instance.cc

Issue 5828003: Move the Pepper implementation from webkit/glue/plugins/pepper_* to... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2010 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 "webkit/glue/plugins/pepper_plugin_instance.h"
6
7 #include "base/logging.h"
8 #include "base/metrics/histogram.h"
9 #if defined(OS_MACOSX)
10 #include "base/mac_util.h"
11 #include "base/mac/scoped_cftyperef.h"
12 #endif
13 #include "base/scoped_ptr.h"
14 #include "base/utf_string_conversions.h"
15 #include "gfx/rect.h"
16 #if defined(OS_WIN)
17 #include "gfx/codec/jpeg_codec.h"
18 #include "gfx/gdi_util.h"
19 #endif
20 #include "gfx/skia_util.h"
21 #include "ppapi/c/dev/ppb_find_dev.h"
22 #include "ppapi/c/dev/ppb_fullscreen_dev.h"
23 #include "ppapi/c/dev/ppb_zoom_dev.h"
24 #include "ppapi/c/dev/ppp_find_dev.h"
25 #include "ppapi/c/dev/ppp_selection_dev.h"
26 #include "ppapi/c/dev/ppp_zoom_dev.h"
27 #include "ppapi/c/pp_input_event.h"
28 #include "ppapi/c/pp_instance.h"
29 #include "ppapi/c/pp_rect.h"
30 #include "ppapi/c/pp_resource.h"
31 #include "ppapi/c/pp_var.h"
32 #include "ppapi/c/ppb_core.h"
33 #include "ppapi/c/ppb_instance.h"
34 #include "ppapi/c/ppp_instance.h"
35 #include "printing/native_metafile.h"
36 #include "printing/units.h"
37 #include "skia/ext/vector_platform_device.h"
38 #include "skia/ext/platform_canvas.h"
39 #include "third_party/WebKit/WebKit/chromium/public/WebBindings.h"
40 #include "third_party/WebKit/WebKit/chromium/public/WebCursorInfo.h"
41 #include "third_party/WebKit/WebKit/chromium/public/WebDocument.h"
42 #include "third_party/WebKit/WebKit/chromium/public/WebElement.h"
43 #include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
44 #include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h"
45 #include "third_party/WebKit/WebKit/chromium/public/WebPluginContainer.h"
46 #include "third_party/WebKit/WebKit/chromium/public/WebRect.h"
47 #include "third_party/WebKit/WebKit/chromium/public/WebString.h"
48 #include "third_party/WebKit/WebKit/chromium/public/WebURLRequest.h"
49 #include "third_party/WebKit/WebKit/chromium/public/WebView.h"
50 #include "webkit/glue/plugins/pepper_buffer.h"
51 #include "webkit/glue/plugins/pepper_common.h"
52 #include "webkit/glue/plugins/pepper_graphics_2d.h"
53 #include "webkit/glue/plugins/pepper_graphics_3d.h"
54 #include "webkit/glue/plugins/pepper_event_conversion.h"
55 #include "webkit/glue/plugins/pepper_fullscreen_container.h"
56 #include "webkit/glue/plugins/pepper_image_data.h"
57 #include "webkit/glue/plugins/pepper_plugin_delegate.h"
58 #include "webkit/glue/plugins/pepper_plugin_module.h"
59 #include "webkit/glue/plugins/pepper_string.h"
60 #include "webkit/glue/plugins/pepper_url_loader.h"
61 #include "webkit/glue/plugins/pepper_var.h"
62 #include "webkit/glue/plugins/ppp_private.h"
63
64 using WebKit::WebBindings;
65 using WebKit::WebCanvas;
66 using WebKit::WebCursorInfo;
67 using WebKit::WebDocument;
68 using WebKit::WebFrame;
69 using WebKit::WebInputEvent;
70 using WebKit::WebPluginContainer;
71 using WebKit::WebString;
72 using WebKit::WebURLRequest;
73 using WebKit::WebView;
74
75 namespace pepper {
76
77 #if defined(OS_WIN)
78 // Exported by pdf.dll
79 typedef bool (*RenderPDFPageToDCProc)(
80 const unsigned char* pdf_buffer, int buffer_size, int page_number, HDC dc,
81 int dpi_x, int dpi_y, int bounds_origin_x, int bounds_origin_y,
82 int bounds_width, int bounds_height, bool fit_to_bounds,
83 bool stretch_to_bounds, bool keep_aspect_ratio, bool center_in_bounds);
84 #endif // defined(OS_WIN)
85
86 namespace {
87
88 #define COMPILE_ASSERT_MATCHING_ENUM(webkit_name, np_name) \
89 COMPILE_ASSERT(int(WebCursorInfo::webkit_name) == int(np_name), \
90 mismatching_enums)
91
92 COMPILE_ASSERT_MATCHING_ENUM(TypePointer, PP_CURSORTYPE_POINTER);
93 COMPILE_ASSERT_MATCHING_ENUM(TypeCross, PP_CURSORTYPE_CROSS);
94 COMPILE_ASSERT_MATCHING_ENUM(TypeHand, PP_CURSORTYPE_HAND);
95 COMPILE_ASSERT_MATCHING_ENUM(TypeIBeam, PP_CURSORTYPE_IBEAM);
96 COMPILE_ASSERT_MATCHING_ENUM(TypeWait, PP_CURSORTYPE_WAIT);
97 COMPILE_ASSERT_MATCHING_ENUM(TypeHelp, PP_CURSORTYPE_HELP);
98 COMPILE_ASSERT_MATCHING_ENUM(TypeEastResize, PP_CURSORTYPE_EASTRESIZE);
99 COMPILE_ASSERT_MATCHING_ENUM(TypeNorthResize, PP_CURSORTYPE_NORTHRESIZE);
100 COMPILE_ASSERT_MATCHING_ENUM(TypeNorthEastResize,
101 PP_CURSORTYPE_NORTHEASTRESIZE);
102 COMPILE_ASSERT_MATCHING_ENUM(TypeNorthWestResize,
103 PP_CURSORTYPE_NORTHWESTRESIZE);
104 COMPILE_ASSERT_MATCHING_ENUM(TypeSouthResize, PP_CURSORTYPE_SOUTHRESIZE);
105 COMPILE_ASSERT_MATCHING_ENUM(TypeSouthEastResize,
106 PP_CURSORTYPE_SOUTHEASTRESIZE);
107 COMPILE_ASSERT_MATCHING_ENUM(TypeSouthWestResize,
108 PP_CURSORTYPE_SOUTHWESTRESIZE);
109 COMPILE_ASSERT_MATCHING_ENUM(TypeWestResize, PP_CURSORTYPE_WESTRESIZE);
110 COMPILE_ASSERT_MATCHING_ENUM(TypeNorthSouthResize,
111 PP_CURSORTYPE_NORTHSOUTHRESIZE);
112 COMPILE_ASSERT_MATCHING_ENUM(TypeEastWestResize, PP_CURSORTYPE_EASTWESTRESIZE);
113 COMPILE_ASSERT_MATCHING_ENUM(TypeNorthEastSouthWestResize,
114 PP_CURSORTYPE_NORTHEASTSOUTHWESTRESIZE);
115 COMPILE_ASSERT_MATCHING_ENUM(TypeNorthWestSouthEastResize,
116 PP_CURSORTYPE_NORTHWESTSOUTHEASTRESIZE);
117 COMPILE_ASSERT_MATCHING_ENUM(TypeColumnResize, PP_CURSORTYPE_COLUMNRESIZE);
118 COMPILE_ASSERT_MATCHING_ENUM(TypeRowResize, PP_CURSORTYPE_ROWRESIZE);
119 COMPILE_ASSERT_MATCHING_ENUM(TypeMiddlePanning, PP_CURSORTYPE_MIDDLEPANNING);
120 COMPILE_ASSERT_MATCHING_ENUM(TypeEastPanning, PP_CURSORTYPE_EASTPANNING);
121 COMPILE_ASSERT_MATCHING_ENUM(TypeNorthPanning, PP_CURSORTYPE_NORTHPANNING);
122 COMPILE_ASSERT_MATCHING_ENUM(TypeNorthEastPanning,
123 PP_CURSORTYPE_NORTHEASTPANNING);
124 COMPILE_ASSERT_MATCHING_ENUM(TypeNorthWestPanning,
125 PP_CURSORTYPE_NORTHWESTPANNING);
126 COMPILE_ASSERT_MATCHING_ENUM(TypeSouthPanning, PP_CURSORTYPE_SOUTHPANNING);
127 COMPILE_ASSERT_MATCHING_ENUM(TypeSouthEastPanning,
128 PP_CURSORTYPE_SOUTHEASTPANNING);
129 COMPILE_ASSERT_MATCHING_ENUM(TypeSouthWestPanning,
130 PP_CURSORTYPE_SOUTHWESTPANNING);
131 COMPILE_ASSERT_MATCHING_ENUM(TypeWestPanning, PP_CURSORTYPE_WESTPANNING);
132 COMPILE_ASSERT_MATCHING_ENUM(TypeMove, PP_CURSORTYPE_MOVE);
133 COMPILE_ASSERT_MATCHING_ENUM(TypeVerticalText, PP_CURSORTYPE_VERTICALTEXT);
134 COMPILE_ASSERT_MATCHING_ENUM(TypeCell, PP_CURSORTYPE_CELL);
135 COMPILE_ASSERT_MATCHING_ENUM(TypeContextMenu, PP_CURSORTYPE_CONTEXTMENU);
136 COMPILE_ASSERT_MATCHING_ENUM(TypeAlias, PP_CURSORTYPE_ALIAS);
137 COMPILE_ASSERT_MATCHING_ENUM(TypeProgress, PP_CURSORTYPE_PROGRESS);
138 COMPILE_ASSERT_MATCHING_ENUM(TypeNoDrop, PP_CURSORTYPE_NODROP);
139 COMPILE_ASSERT_MATCHING_ENUM(TypeCopy, PP_CURSORTYPE_COPY);
140 COMPILE_ASSERT_MATCHING_ENUM(TypeNone, PP_CURSORTYPE_NONE);
141 COMPILE_ASSERT_MATCHING_ENUM(TypeNotAllowed, PP_CURSORTYPE_NOTALLOWED);
142 COMPILE_ASSERT_MATCHING_ENUM(TypeZoomIn, PP_CURSORTYPE_ZOOMIN);
143 COMPILE_ASSERT_MATCHING_ENUM(TypeZoomOut, PP_CURSORTYPE_ZOOMOUT);
144 COMPILE_ASSERT_MATCHING_ENUM(TypeCustom, PP_CURSORTYPE_CUSTOM);
145
146 void RectToPPRect(const gfx::Rect& input, PP_Rect* output) {
147 *output = PP_MakeRectFromXYWH(input.x(), input.y(),
148 input.width(), input.height());
149 }
150
151 PP_Var GetWindowObject(PP_Instance instance_id) {
152 PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
153 if (!instance)
154 return PP_MakeUndefined();
155 return instance->GetWindowObject();
156 }
157
158 PP_Var GetOwnerElementObject(PP_Instance instance_id) {
159 PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
160 if (!instance)
161 return PP_MakeUndefined();
162 return instance->GetOwnerElementObject();
163 }
164
165 PP_Bool BindGraphics(PP_Instance instance_id, PP_Resource graphics_id) {
166 PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
167 if (!instance)
168 return PP_FALSE;
169 return BoolToPPBool(instance->BindGraphics(graphics_id));
170 }
171
172 PP_Bool IsFullFrame(PP_Instance instance_id) {
173 PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
174 if (!instance)
175 return PP_FALSE;
176 return BoolToPPBool(instance->full_frame());
177 }
178
179 PP_Var ExecuteScript(PP_Instance instance_id,
180 PP_Var script,
181 PP_Var* exception) {
182 PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
183 if (!instance)
184 return PP_MakeUndefined();
185 return instance->ExecuteScript(script, exception);
186 }
187
188 const PPB_Instance ppb_instance = {
189 &GetWindowObject,
190 &GetOwnerElementObject,
191 &BindGraphics,
192 &IsFullFrame,
193 &ExecuteScript,
194 };
195
196 void NumberOfFindResultsChanged(PP_Instance instance_id,
197 int32_t total,
198 PP_Bool final_result) {
199 PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
200 if (!instance)
201 return;
202
203 DCHECK_NE(instance->find_identifier(), -1);
204 instance->delegate()->NumberOfFindResultsChanged(
205 instance->find_identifier(), total, PPBoolToBool(final_result));
206 }
207
208 void SelectedFindResultChanged(PP_Instance instance_id,
209 int32_t index) {
210 PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
211 if (!instance)
212 return;
213
214 DCHECK_NE(instance->find_identifier(), -1);
215 instance->delegate()->SelectedFindResultChanged(
216 instance->find_identifier(), index);
217 }
218
219 const PPB_Find_Dev ppb_find = {
220 &NumberOfFindResultsChanged,
221 &SelectedFindResultChanged,
222 };
223
224 PP_Bool IsFullscreen(PP_Instance instance_id) {
225 PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
226 if (!instance)
227 return PP_FALSE;
228 return BoolToPPBool(instance->IsFullscreen());
229 }
230
231 PP_Bool SetFullscreen(PP_Instance instance_id, PP_Bool fullscreen) {
232 PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
233 if (!instance)
234 return PP_FALSE;
235 return BoolToPPBool(instance->SetFullscreen(PPBoolToBool(fullscreen)));
236 }
237
238 const PPB_Fullscreen_Dev ppb_fullscreen = {
239 &IsFullscreen,
240 &SetFullscreen,
241 };
242
243 void ZoomChanged(PP_Instance instance_id, double factor) {
244 PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
245 if (!instance)
246 return;
247
248 // We only want to tell the page to change its zoom if the whole page is the
249 // PDF. If we're in an iframe, then don't do anything.
250 WebFrame* frame = instance->container()->element().document().frame();
251 if (!frame->view()->mainFrame()->document().isPluginDocument())
252 return;
253
254 double zoom_level = WebView::zoomFactorToZoomLevel(factor);
255 // The conversino from zoom level to factor, and back, can introduce rounding
256 // errors. i.e. WebKit originally tells us 3.0, but by the time we tell the
257 // plugin and it tells us back, the level becomes 3.000000000004. Need to
258 // round or else otherwise if the user zooms out, it will go to 3.0 instead of
259 // 2.0.
260 int rounded =
261 static_cast<int>(zoom_level + (zoom_level > 0 ? 0.001 : -0.001));
262 if (abs(rounded - zoom_level) < 0.001)
263 zoom_level = rounded;
264 instance->container()->zoomLevelChanged(zoom_level);
265 }
266
267 void ZoomLimitsChanged(PP_Instance instance_id,
268 double minimum_factor,
269 double maximium_factor) {
270 if (minimum_factor > maximium_factor) {
271 NOTREACHED();
272 return;
273 }
274
275 PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
276 if (!instance)
277 return;
278 instance->delegate()->ZoomLimitsChanged(minimum_factor, maximium_factor);
279 }
280
281 const PPB_Zoom_Dev ppb_zoom = {
282 &ZoomChanged,
283 &ZoomLimitsChanged
284 };
285
286 } // namespace
287
288 PluginInstance::PluginInstance(PluginDelegate* delegate,
289 PluginModule* module,
290 const PPP_Instance* instance_interface)
291 : delegate_(delegate),
292 module_(module),
293 instance_interface_(instance_interface),
294 pp_instance_(0),
295 container_(NULL),
296 full_frame_(false),
297 has_webkit_focus_(false),
298 has_content_area_focus_(false),
299 find_identifier_(-1),
300 plugin_find_interface_(NULL),
301 plugin_private_interface_(NULL),
302 plugin_selection_interface_(NULL),
303 plugin_zoom_interface_(NULL),
304 #if defined (OS_LINUX)
305 num_pages_(0),
306 pdf_output_done_(false),
307 #endif // defined (OS_LINUX)
308 plugin_print_interface_(NULL),
309 plugin_graphics_3d_interface_(NULL),
310 always_on_top_(false),
311 fullscreen_container_(NULL) {
312 pp_instance_ = ResourceTracker::Get()->AddInstance(this);
313
314 memset(&current_print_settings_, 0, sizeof(current_print_settings_));
315 DCHECK(delegate);
316 module_->InstanceCreated(this);
317 delegate_->InstanceCreated(this);
318 }
319
320 PluginInstance::~PluginInstance() {
321 FOR_EACH_OBSERVER(Observer, observers_, InstanceDestroyed(this));
322
323 delegate_->InstanceDeleted(this);
324 module_->InstanceDeleted(this);
325
326 ResourceTracker::Get()->InstanceDeleted(pp_instance_);
327 }
328
329 // static
330 const PPB_Instance* PluginInstance::GetInterface() {
331 return &ppb_instance;
332 }
333
334 // static
335 const PPB_Find_Dev* PluginInstance::GetFindInterface() {
336 return &ppb_find;
337 }
338
339 // static
340 const PPB_Fullscreen_Dev* PluginInstance::GetFullscreenInterface() {
341 return &ppb_fullscreen;
342 }
343
344 // static
345 const PPB_Zoom_Dev* PluginInstance::GetZoomInterface() {
346 return &ppb_zoom;
347 }
348
349 void PluginInstance::AddObserver(Observer* observer) {
350 observers_.AddObserver(observer);
351 }
352
353 void PluginInstance::RemoveObserver(Observer* observer) {
354 observers_.RemoveObserver(observer);
355 }
356
357 void PluginInstance::Paint(WebCanvas* canvas,
358 const gfx::Rect& plugin_rect,
359 const gfx::Rect& paint_rect) {
360 if (bound_graphics_2d())
361 bound_graphics_2d()->Paint(canvas, plugin_rect, paint_rect);
362 }
363
364 void PluginInstance::InvalidateRect(const gfx::Rect& rect) {
365 if (fullscreen_container_) {
366 if (rect.IsEmpty())
367 fullscreen_container_->Invalidate();
368 else
369 fullscreen_container_->InvalidateRect(rect);
370 } else {
371 if (!container_ || position_.IsEmpty())
372 return; // Nothing to do.
373 if (rect.IsEmpty())
374 container_->invalidate();
375 else
376 container_->invalidateRect(rect);
377 }
378 }
379
380 void PluginInstance::ScrollRect(int dx, int dy, const gfx::Rect& rect) {
381 if (fullscreen_container_) {
382 fullscreen_container_->ScrollRect(dx, dy, rect);
383 } else {
384 if (full_frame_) {
385 container_->scrollRect(dx, dy, rect);
386 } else {
387 // Can't do optimized scrolling since there could be other elements on top
388 // of us.
389 InvalidateRect(rect);
390 }
391 }
392 }
393
394 unsigned PluginInstance::GetBackingTextureId() {
395 if (!bound_graphics_3d())
396 return 0;
397
398 return bound_graphics_3d()->GetBackingTextureId();
399 }
400
401 void PluginInstance::CommitBackingTexture() {
402 container_->commitBackingTexture();
403 }
404
405 PP_Var PluginInstance::GetWindowObject() {
406 if (!container_)
407 return PP_MakeUndefined();
408
409 WebFrame* frame = container_->element().document().frame();
410 if (!frame)
411 return PP_MakeUndefined();
412
413 return ObjectVar::NPObjectToPPVar(module(), frame->windowObject());
414 }
415
416 PP_Var PluginInstance::GetOwnerElementObject() {
417 if (!container_)
418 return PP_MakeUndefined();
419 return ObjectVar::NPObjectToPPVar(module(),
420 container_->scriptableObjectForElement());
421 }
422
423 bool PluginInstance::BindGraphics(PP_Resource graphics_id) {
424 if (!graphics_id) {
425 // Special-case clearing the current device.
426 if (bound_graphics_.get()) {
427 if (bound_graphics_2d()) {
428 bound_graphics_2d()->BindToInstance(NULL);
429 } else if (bound_graphics_.get()) {
430 bound_graphics_3d()->SetSwapBuffersCallback(NULL);
431 bound_graphics_3d()->BindToInstance(NULL);
432 }
433 InvalidateRect(gfx::Rect());
434 }
435 bound_graphics_ = NULL;
436 return true;
437 }
438
439 scoped_refptr<Graphics2D> graphics_2d =
440 Resource::GetAs<Graphics2D>(graphics_id);
441 scoped_refptr<Graphics3D> graphics_3d =
442 Resource::GetAs<Graphics3D>(graphics_id);
443
444 if (graphics_2d) {
445 if (!graphics_2d->BindToInstance(this))
446 return false; // Can't bind to more than one instance.
447
448 // See http://crbug.com/49403: this can be further optimized by keeping the
449 // old device around and painting from it.
450 if (bound_graphics_2d()) {
451 // Start the new image with the content of the old image until the plugin
452 // repaints.
453 const SkBitmap* old_backing_bitmap =
454 bound_graphics_2d()->image_data()->GetMappedBitmap();
455 SkRect old_size = SkRect::MakeWH(
456 SkScalar(static_cast<float>(old_backing_bitmap->width())),
457 SkScalar(static_cast<float>(old_backing_bitmap->height())));
458
459 SkCanvas canvas(*graphics_2d->image_data()->GetMappedBitmap());
460 canvas.drawBitmap(*old_backing_bitmap, 0, 0);
461
462 // Fill in any extra space with white.
463 canvas.clipRect(old_size, SkRegion::kDifference_Op);
464 canvas.drawARGB(255, 255, 255, 255);
465 }
466
467 bound_graphics_ = graphics_2d;
468 // BindToInstance will have invalidated the plugin if necessary.
469 } else if (graphics_3d) {
470 if (!graphics_3d->BindToInstance(this))
471 return false;
472
473 bound_graphics_ = graphics_3d;
474 bound_graphics_3d()->SetSwapBuffersCallback(
475 NewCallback(this, &PluginInstance::CommitBackingTexture));
476 }
477
478 return true;
479 }
480
481 bool PluginInstance::SetCursor(PP_CursorType_Dev type) {
482 cursor_.reset(new WebCursorInfo(static_cast<WebCursorInfo::Type>(type)));
483 return true;
484 }
485
486 PP_Var PluginInstance::ExecuteScript(PP_Var script, PP_Var* exception) {
487 TryCatch try_catch(module(), exception);
488 if (try_catch.has_exception())
489 return PP_MakeUndefined();
490
491 // Convert the script into an inconvenient NPString object.
492 scoped_refptr<StringVar> script_string(StringVar::FromPPVar(script));
493 if (!script_string) {
494 try_catch.SetException("Script param to ExecuteScript must be a string.");
495 return PP_MakeUndefined();
496 }
497 NPString np_script;
498 np_script.UTF8Characters = script_string->value().c_str();
499 np_script.UTF8Length = script_string->value().length();
500
501 // Get the current frame to pass to the evaluate function.
502 WebFrame* frame = container_->element().document().frame();
503 if (!frame) {
504 try_catch.SetException("No frame to execute script in.");
505 return PP_MakeUndefined();
506 }
507
508 NPVariant result;
509 bool ok = WebBindings::evaluate(NULL, frame->windowObject(), &np_script,
510 &result);
511 if (!ok) {
512 // TODO(brettw) bug 54011: The TryCatch isn't working properly and
513 // doesn't actually catch this exception.
514 try_catch.SetException("Exception caught");
515 WebBindings::releaseVariantValue(&result);
516 return PP_MakeUndefined();
517 }
518
519 PP_Var ret = Var::NPVariantToPPVar(module_, &result);
520 WebBindings::releaseVariantValue(&result);
521 return ret;
522 }
523
524 void PluginInstance::Delete() {
525 instance_interface_->DidDestroy(pp_instance());
526
527 if (fullscreen_container_) {
528 fullscreen_container_->Destroy();
529 fullscreen_container_ = NULL;
530 }
531 container_ = NULL;
532 }
533
534 bool PluginInstance::Initialize(WebPluginContainer* container,
535 const std::vector<std::string>& arg_names,
536 const std::vector<std::string>& arg_values,
537 bool full_frame) {
538 container_ = container;
539 full_frame_ = full_frame;
540
541 size_t argc = 0;
542 scoped_array<const char*> argn(new const char*[arg_names.size()]);
543 scoped_array<const char*> argv(new const char*[arg_names.size()]);
544 for (size_t i = 0; i < arg_names.size(); ++i) {
545 argn[argc] = arg_names[i].c_str();
546 argv[argc] = arg_values[i].c_str();
547 argc++;
548 }
549
550 return PPBoolToBool(instance_interface_->DidCreate(pp_instance(),
551 argc,
552 argn.get(),
553 argv.get()));
554 }
555
556 bool PluginInstance::HandleDocumentLoad(URLLoader* loader) {
557 Resource::ScopedResourceId resource(loader);
558 return PPBoolToBool(instance_interface_->HandleDocumentLoad(pp_instance(),
559 resource.id));
560 }
561
562 bool PluginInstance::HandleInputEvent(const WebKit::WebInputEvent& event,
563 WebCursorInfo* cursor_info) {
564 std::vector<PP_InputEvent> pp_events;
565 CreatePPEvent(event, &pp_events);
566
567 // Each input event may generate more than one PP_InputEvent.
568 bool rv = false;
569 for (size_t i = 0; i < pp_events.size(); i++) {
570 rv |= PPBoolToBool(instance_interface_->HandleInputEvent(pp_instance(),
571 &pp_events[i]));
572 }
573
574 if (cursor_.get())
575 *cursor_info = *cursor_;
576 return rv;
577 }
578
579 PP_Var PluginInstance::GetInstanceObject() {
580 return instance_interface_->GetInstanceObject(pp_instance());
581 }
582
583 void PluginInstance::ViewChanged(const gfx::Rect& position,
584 const gfx::Rect& clip) {
585 if (position.size() != position_.size() && bound_graphics_3d()) {
586 // TODO(apatrick): This is a hack to force the back buffer to resize.
587 // It is obviously wrong to call SwapBuffers when a partial frame has
588 // potentially been rendered. Plan is to embed resize commands in the
589 // command buffer just before ViewChanged is called.
590 bound_graphics_3d()->ResizeBackingTexture(position.size());
591 bound_graphics_3d()->SwapBuffers();
592 }
593
594 position_ = position;
595
596 if (clip.IsEmpty()) {
597 // WebKit can give weird (x,y) positions for empty clip rects (since the
598 // position technically doesn't matter). But we want to make these
599 // consistent since this is given to the plugin, so force everything to 0
600 // in the "everything is clipped" case.
601 clip_ = gfx::Rect();
602 } else {
603 clip_ = clip;
604 }
605
606 PP_Rect pp_position, pp_clip;
607 RectToPPRect(position_, &pp_position);
608 RectToPPRect(clip_, &pp_clip);
609 instance_interface_->DidChangeView(pp_instance(), &pp_position, &pp_clip);
610 }
611
612 void PluginInstance::SetWebKitFocus(bool has_focus) {
613 if (has_webkit_focus_ == has_focus)
614 return;
615
616 bool old_plugin_focus = PluginHasFocus();
617 has_webkit_focus_ = has_focus;
618 if (PluginHasFocus() != old_plugin_focus) {
619 instance_interface_->DidChangeFocus(pp_instance(),
620 BoolToPPBool(PluginHasFocus()));
621 }
622 }
623
624 void PluginInstance::SetContentAreaFocus(bool has_focus) {
625 if (has_content_area_focus_ == has_focus)
626 return;
627
628 bool old_plugin_focus = PluginHasFocus();
629 has_content_area_focus_ = has_focus;
630 if (PluginHasFocus() != old_plugin_focus) {
631 instance_interface_->DidChangeFocus(pp_instance(),
632 BoolToPPBool(PluginHasFocus()));
633 }
634 }
635
636 void PluginInstance::ViewInitiatedPaint() {
637 if (bound_graphics_2d())
638 bound_graphics_2d()->ViewInitiatedPaint();
639 }
640
641 void PluginInstance::ViewFlushedPaint() {
642 if (bound_graphics_2d())
643 bound_graphics_2d()->ViewFlushedPaint();
644 }
645
646 bool PluginInstance::GetBitmapForOptimizedPluginPaint(
647 const gfx::Rect& paint_bounds,
648 TransportDIB** dib,
649 gfx::Rect* location,
650 gfx::Rect* clip) {
651 if (!always_on_top_)
652 return false;
653 if (!bound_graphics_2d() || !bound_graphics_2d()->is_always_opaque())
654 return false;
655
656 // We specifically want to compare against the area covered by the backing
657 // store when seeing if we cover the given paint bounds, since the backing
658 // store could be smaller than the declared plugin area.
659 ImageData* image_data = bound_graphics_2d()->image_data();
660 gfx::Rect plugin_backing_store_rect(position_.origin(),
661 gfx::Size(image_data->width(),
662 image_data->height()));
663 gfx::Rect clip_page(clip_);
664 clip_page.Offset(position_.origin());
665 gfx::Rect plugin_paint_rect = plugin_backing_store_rect.Intersect(clip_page);
666 if (!plugin_paint_rect.Contains(paint_bounds))
667 return false;
668
669 *dib = image_data->platform_image()->GetTransportDIB();
670 *location = plugin_backing_store_rect;
671 *clip = clip_page;
672 return true;
673 }
674
675 string16 PluginInstance::GetSelectedText(bool html) {
676 if (!LoadSelectionInterface())
677 return string16();
678
679 PP_Var rv = plugin_selection_interface_->GetSelectedText(pp_instance(),
680 BoolToPPBool(html));
681 scoped_refptr<StringVar> string(StringVar::FromPPVar(rv));
682 Var::PluginReleasePPVar(rv); // Release the ref the plugin transfered to us.
683 if (!string)
684 return string16();
685 return UTF8ToUTF16(string->value());
686 }
687
688 string16 PluginInstance::GetLinkAtPosition(const gfx::Point& point) {
689 if (!LoadPrivateInterface())
690 return string16();
691
692 PP_Point p;
693 p.x = point.x();
694 p.y = point.y();
695 PP_Var rv = plugin_private_interface_->GetLinkAtPosition(pp_instance(), p);
696 scoped_refptr<StringVar> string(StringVar::FromPPVar(rv));
697 Var::PluginReleasePPVar(rv); // Release the ref the plugin transfered to us.
698 if (!string)
699 return string16();
700 return UTF8ToUTF16(string->value());
701 }
702
703 void PluginInstance::Zoom(double factor, bool text_only) {
704 if (!LoadZoomInterface())
705 return;
706 plugin_zoom_interface_->Zoom(pp_instance(), factor, BoolToPPBool(text_only));
707 }
708
709 bool PluginInstance::StartFind(const string16& search_text,
710 bool case_sensitive,
711 int identifier) {
712 if (!LoadFindInterface())
713 return false;
714 find_identifier_ = identifier;
715 return PPBoolToBool(
716 plugin_find_interface_->StartFind(
717 pp_instance(),
718 UTF16ToUTF8(search_text.c_str()).c_str(),
719 BoolToPPBool(case_sensitive)));
720 }
721
722 void PluginInstance::SelectFindResult(bool forward) {
723 if (LoadFindInterface())
724 plugin_find_interface_->SelectFindResult(pp_instance(),
725 BoolToPPBool(forward));
726 }
727
728 void PluginInstance::StopFind() {
729 if (!LoadFindInterface())
730 return;
731 find_identifier_ = -1;
732 plugin_find_interface_->StopFind(pp_instance());
733 }
734
735 bool PluginInstance::LoadFindInterface() {
736 if (!plugin_find_interface_) {
737 plugin_find_interface_ =
738 reinterpret_cast<const PPP_Find_Dev*>(module_->GetPluginInterface(
739 PPP_FIND_DEV_INTERFACE));
740 }
741
742 return !!plugin_find_interface_;
743 }
744
745 bool PluginInstance::LoadPrivateInterface() {
746 if (!plugin_private_interface_) {
747 plugin_private_interface_ =
748 reinterpret_cast<const PPP_Private*>(module_->GetPluginInterface(
749 PPP_PRIVATE_INTERFACE));
750 }
751
752 return !!plugin_private_interface_;
753 }
754
755 bool PluginInstance::LoadSelectionInterface() {
756 if (!plugin_selection_interface_) {
757 plugin_selection_interface_ =
758 reinterpret_cast<const PPP_Selection_Dev*>(module_->GetPluginInterface(
759 PPP_SELECTION_DEV_INTERFACE));
760 }
761
762 return !!plugin_selection_interface_;
763 }
764
765 bool PluginInstance::LoadZoomInterface() {
766 if (!plugin_zoom_interface_) {
767 plugin_zoom_interface_ =
768 reinterpret_cast<const PPP_Zoom_Dev*>(module_->GetPluginInterface(
769 PPP_ZOOM_DEV_INTERFACE));
770 }
771
772 return !!plugin_zoom_interface_;
773 }
774
775 bool PluginInstance::PluginHasFocus() const {
776 return has_webkit_focus_ && has_content_area_focus_;
777 }
778
779 bool PluginInstance::GetPreferredPrintOutputFormat(
780 PP_PrintOutputFormat_Dev* format) {
781 if (!plugin_print_interface_) {
782 plugin_print_interface_ =
783 reinterpret_cast<const PPP_Printing_Dev*>(module_->GetPluginInterface(
784 PPP_PRINTING_DEV_INTERFACE));
785 }
786 if (!plugin_print_interface_)
787 return false;
788 uint32_t format_count = 0;
789 PP_PrintOutputFormat_Dev* supported_formats =
790 plugin_print_interface_->QuerySupportedFormats(pp_instance(),
791 &format_count);
792 if (!supported_formats)
793 return false;
794
795 bool found_supported_format = false;
796 for (uint32_t index = 0; index < format_count; index++) {
797 if (supported_formats[index] == PP_PRINTOUTPUTFORMAT_PDF) {
798 // If we found PDF, we are done.
799 found_supported_format = true;
800 *format = PP_PRINTOUTPUTFORMAT_PDF;
801 break;
802 } else if (supported_formats[index] == PP_PRINTOUTPUTFORMAT_RASTER) {
803 // We found raster. Keep looking.
804 found_supported_format = true;
805 *format = PP_PRINTOUTPUTFORMAT_RASTER;
806 }
807 }
808 PluginModule::GetCore()->MemFree(supported_formats);
809 return found_supported_format;
810 }
811
812 bool PluginInstance::SupportsPrintInterface() {
813 PP_PrintOutputFormat_Dev format;
814 return GetPreferredPrintOutputFormat(&format);
815 }
816
817 int PluginInstance::PrintBegin(const gfx::Rect& printable_area,
818 int printer_dpi) {
819 PP_PrintOutputFormat_Dev format;
820 if (!GetPreferredPrintOutputFormat(&format)) {
821 // PrintBegin should not have been called since SupportsPrintInterface
822 // would have returned false;
823 NOTREACHED();
824 return 0;
825 }
826
827 PP_PrintSettings_Dev print_settings;
828 RectToPPRect(printable_area, &print_settings.printable_area);
829 print_settings.dpi = printer_dpi;
830 print_settings.orientation = PP_PRINTORIENTATION_NORMAL;
831 print_settings.grayscale = PP_FALSE;
832 print_settings.format = format;
833 int num_pages = plugin_print_interface_->Begin(pp_instance(),
834 &print_settings);
835 if (!num_pages)
836 return 0;
837 current_print_settings_ = print_settings;
838 #if defined (OS_LINUX)
839 num_pages_ = num_pages;
840 pdf_output_done_ = false;
841 #endif // (OS_LINUX)
842 return num_pages;
843 }
844
845 bool PluginInstance::PrintPage(int page_number, WebKit::WebCanvas* canvas) {
846 DCHECK(plugin_print_interface_);
847 PP_PrintPageNumberRange_Dev page_range;
848 #if defined(OS_LINUX)
849 if (current_print_settings_.format == PP_PRINTOUTPUTFORMAT_PDF) {
850 // On Linux we will try and output all pages as PDF in the first call to
851 // PrintPage. This is a temporary hack.
852 // TODO(sanjeevr): Remove this hack and fix this by changing the print
853 // interfaces for WebFrame and WebPlugin.
854 if (page_number != 0)
855 return pdf_output_done_;
856 page_range.first_page_number = 0;
857 page_range.last_page_number = num_pages_ - 1;
858 }
859 #else // defined(OS_LINUX)
860 page_range.first_page_number = page_range.last_page_number = page_number;
861 #endif // defined(OS_LINUX)
862
863 PP_Resource print_output =
864 plugin_print_interface_->PrintPages(pp_instance(), &page_range, 1);
865
866 if (!print_output)
867 return false;
868
869 bool ret = false;
870
871 if (current_print_settings_.format == PP_PRINTOUTPUTFORMAT_PDF)
872 ret = PrintPDFOutput(print_output, canvas);
873 else if (current_print_settings_.format == PP_PRINTOUTPUTFORMAT_RASTER)
874 ret = PrintRasterOutput(print_output, canvas);
875
876 // Now we need to release the print output resource.
877 PluginModule::GetCore()->ReleaseResource(print_output);
878
879 return ret;
880 }
881
882 void PluginInstance::PrintEnd() {
883 DCHECK(plugin_print_interface_);
884 if (plugin_print_interface_)
885 plugin_print_interface_->End(pp_instance());
886 memset(&current_print_settings_, 0, sizeof(current_print_settings_));
887 #if defined(OS_MACOSX)
888 last_printed_page_ = NULL;
889 #elif defined(OS_LINUX)
890 num_pages_ = 0;
891 pdf_output_done_ = false;
892 #endif // defined(OS_LINUX)
893 }
894
895 bool PluginInstance::IsFullscreen() {
896 return fullscreen_container_ != NULL;
897 }
898
899 bool PluginInstance::SetFullscreen(bool fullscreen) {
900 bool is_fullscreen = (fullscreen_container_ != NULL);
901 if (fullscreen == is_fullscreen)
902 return true;
903 VLOG(1) << "Setting fullscreen to " << (fullscreen ? "on" : "off");
904 if (fullscreen) {
905 fullscreen_container_ = delegate_->CreateFullscreenContainer(this);
906 } else {
907 fullscreen_container_->Destroy();
908 fullscreen_container_ = NULL;
909 // TODO(piman): currently the fullscreen container resizes the plugin to the
910 // fullscreen size so we need to reset the size here. Eventually it will
911 // transparently scale and this won't be necessary.
912 if (container_) {
913 container_->reportGeometry();
914 container_->invalidate();
915 }
916 }
917 return true;
918 }
919
920 bool PluginInstance::NavigateToURL(const char* url, const char* target) {
921 if (!url || !target || !container_)
922 return false;
923
924 WebDocument document = container_->element().document();
925 GURL complete_url = document.completeURL(WebString::fromUTF8(url));
926 // Don't try to deal with the security issues of javascript.
927 if (complete_url.SchemeIs("javascript"))
928 return false;
929
930 WebURLRequest request(complete_url);
931 document.frame()->setReferrerForRequest(request, GURL());
932 request.setHTTPMethod(WebString::fromUTF8("GET"));
933 request.setFirstPartyForCookies(document.firstPartyForCookies());
934
935 WebString target_str = WebString::fromUTF8(target);
936 container_->loadFrameRequest(request, target_str, false, NULL);
937 return true;
938 }
939
940 bool PluginInstance::PrintPDFOutput(PP_Resource print_output,
941 WebKit::WebCanvas* canvas) {
942 scoped_refptr<Buffer> buffer(Resource::GetAs<Buffer>(print_output));
943 if (!buffer.get() || !buffer->is_mapped() || !buffer->size()) {
944 NOTREACHED();
945 return false;
946 }
947 #if defined(OS_WIN)
948 // For Windows, we need the PDF DLL to render the output PDF to a DC.
949 HMODULE pdf_module = GetModuleHandle(L"pdf.dll");
950 if (!pdf_module)
951 return false;
952 RenderPDFPageToDCProc render_proc =
953 reinterpret_cast<RenderPDFPageToDCProc>(
954 GetProcAddress(pdf_module, "RenderPDFPageToDC"));
955 if (!render_proc)
956 return false;
957 #endif // defined(OS_WIN)
958
959 bool ret = false;
960 #if defined(OS_LINUX)
961 // On Linux we need to get the backing PdfPsMetafile and write the bits
962 // directly.
963 cairo_t* context = canvas->beginPlatformPaint();
964 printing::NativeMetafile* metafile =
965 printing::NativeMetafile::FromCairoContext(context);
966 DCHECK(metafile);
967 if (metafile) {
968 ret = metafile->SetRawData(buffer->mapped_buffer(), buffer->size());
969 if (ret)
970 pdf_output_done_ = true;
971 }
972 canvas->endPlatformPaint();
973 #elif defined(OS_MACOSX)
974 printing::NativeMetafile metafile;
975 // Create a PDF metafile and render from there into the passed in context.
976 if (metafile.Init(buffer->mapped_buffer(), buffer->size())) {
977 // Flip the transform.
978 CGContextSaveGState(canvas);
979 CGContextTranslateCTM(canvas, 0,
980 current_print_settings_.printable_area.size.height);
981 CGContextScaleCTM(canvas, 1.0, -1.0);
982 CGRect page_rect;
983 page_rect.origin.x = current_print_settings_.printable_area.point.x;
984 page_rect.origin.y = current_print_settings_.printable_area.point.y;
985 page_rect.size.width = current_print_settings_.printable_area.size.width;
986 page_rect.size.height = current_print_settings_.printable_area.size.height;
987
988 ret = metafile.RenderPage(1, canvas, page_rect, true, false, true, true);
989 CGContextRestoreGState(canvas);
990 }
991 #elif defined(OS_WIN)
992 // On Windows, we now need to render the PDF to the DC that backs the
993 // supplied canvas.
994 skia::VectorPlatformDevice& device =
995 static_cast<skia::VectorPlatformDevice&>(
996 canvas->getTopPlatformDevice());
997 HDC dc = device.getBitmapDC();
998 gfx::Size size_in_pixels;
999 size_in_pixels.set_width(
1000 printing::ConvertUnit(current_print_settings_.printable_area.size.width,
1001 static_cast<int>(printing::kPointsPerInch),
1002 current_print_settings_.dpi));
1003 size_in_pixels.set_height(
1004 printing::ConvertUnit(current_print_settings_.printable_area.size.height,
1005 static_cast<int>(printing::kPointsPerInch),
1006 current_print_settings_.dpi));
1007 // We need to render using the actual printer DPI (rendering to a smaller
1008 // set of pixels leads to a blurry output). However, we need to counter the
1009 // scaling up that will happen in the browser.
1010 XFORM xform = {0};
1011 xform.eM11 = xform.eM22 = static_cast<float>(printing::kPointsPerInch) /
1012 static_cast<float>(current_print_settings_.dpi);
1013 ModifyWorldTransform(dc, &xform, MWT_LEFTMULTIPLY);
1014
1015 ret = render_proc(buffer->mapped_buffer(), buffer->size(), 0, dc,
1016 current_print_settings_.dpi, current_print_settings_.dpi,
1017 0, 0, size_in_pixels.width(),
1018 size_in_pixels.height(), true, false, true, true);
1019 #endif // defined(OS_WIN)
1020
1021 return ret;
1022 }
1023
1024 bool PluginInstance::PrintRasterOutput(PP_Resource print_output,
1025 WebKit::WebCanvas* canvas) {
1026 scoped_refptr<ImageData> image(Resource::GetAs<ImageData>(print_output));
1027 if (!image.get() || !image->is_mapped())
1028 return false;
1029
1030 const SkBitmap* bitmap = image->GetMappedBitmap();
1031 if (!bitmap)
1032 return false;
1033
1034 // Draw the printed image into the supplied canvas.
1035 SkIRect src_rect;
1036 src_rect.set(0, 0, bitmap->width(), bitmap->height());
1037 SkRect dest_rect;
1038 dest_rect.set(
1039 SkIntToScalar(current_print_settings_.printable_area.point.x),
1040 SkIntToScalar(current_print_settings_.printable_area.point.y),
1041 SkIntToScalar(current_print_settings_.printable_area.point.x +
1042 current_print_settings_.printable_area.size.width),
1043 SkIntToScalar(current_print_settings_.printable_area.point.y +
1044 current_print_settings_.printable_area.size.height));
1045 bool draw_to_canvas = true;
1046 gfx::Rect dest_rect_gfx;
1047 dest_rect_gfx.set_x(current_print_settings_.printable_area.point.x);
1048 dest_rect_gfx.set_y(current_print_settings_.printable_area.point.y);
1049 dest_rect_gfx.set_width(current_print_settings_.printable_area.size.width);
1050 dest_rect_gfx.set_height(current_print_settings_.printable_area.size.height);
1051
1052 #if defined(OS_WIN)
1053 // Since this is a raster output, the size of the bitmap can be
1054 // huge (especially at high printer DPIs). On Windows, this can
1055 // result in a HUGE EMF (on Mac and Linux the output goes to PDF
1056 // which appears to Flate compress the bitmap). So, if this bitmap
1057 // is larger than 20 MB, we save the bitmap as a JPEG into the EMF
1058 // DC. Note: We chose JPEG over PNG because JPEG compression seems
1059 // way faster (about 4 times faster).
1060 static const int kCompressionThreshold = 20 * 1024 * 1024;
1061 if (bitmap->getSize() > kCompressionThreshold) {
1062 DrawJPEGToPlatformDC(*bitmap, dest_rect_gfx, canvas);
1063 draw_to_canvas = false;
1064 }
1065 #endif // defined(OS_WIN)
1066 #if defined(OS_MACOSX)
1067 draw_to_canvas = false;
1068 DrawSkBitmapToCanvas(*bitmap, canvas, dest_rect_gfx,
1069 current_print_settings_.printable_area.size.height);
1070 // See comments in the header file.
1071 last_printed_page_ = image;
1072 #else // defined(OS_MACOSX)
1073 if (draw_to_canvas)
1074 canvas->drawBitmapRect(*bitmap, &src_rect, dest_rect);
1075 #endif // defined(OS_MACOSX)
1076 return true;
1077 }
1078
1079 #if defined(OS_WIN)
1080 bool PluginInstance::DrawJPEGToPlatformDC(
1081 const SkBitmap& bitmap,
1082 const gfx::Rect& printable_area,
1083 WebKit::WebCanvas* canvas) {
1084 skia::VectorPlatformDevice& device =
1085 static_cast<skia::VectorPlatformDevice&>(
1086 canvas->getTopPlatformDevice());
1087 HDC dc = device.getBitmapDC();
1088 // TODO(sanjeevr): This is a temporary hack. If we output a JPEG
1089 // to the EMF, the EnumEnhMetaFile call fails in the browser
1090 // process. The failure also happens if we output nothing here.
1091 // We need to investigate the reason for this failure and fix it.
1092 // In the meantime this temporary hack of drawing an empty
1093 // rectangle in the DC gets us by.
1094 Rectangle(dc, 0, 0, 0, 0);
1095
1096 // Ideally we should add JPEG compression to the VectorPlatformDevice class
1097 // However, Skia currently has no JPEG compression code and we cannot
1098 // depend on gfx/jpeg_codec.h in Skia. So we do the compression here.
1099 SkAutoLockPixels lock(bitmap);
1100 DCHECK(bitmap.getConfig() == SkBitmap::kARGB_8888_Config);
1101 const uint32_t* pixels =
1102 static_cast<const uint32_t*>(bitmap.getPixels());
1103 std::vector<unsigned char> compressed_image;
1104 base::TimeTicks start_time = base::TimeTicks::Now();
1105 bool encoded = gfx::JPEGCodec::Encode(
1106 reinterpret_cast<const unsigned char*>(pixels),
1107 gfx::JPEGCodec::FORMAT_BGRA, bitmap.width(), bitmap.height(),
1108 static_cast<int>(bitmap.rowBytes()), 100, &compressed_image);
1109 UMA_HISTOGRAM_TIMES("PepperPluginPrint.RasterBitmapCompressTime",
1110 base::TimeTicks::Now() - start_time);
1111 if (!encoded) {
1112 NOTREACHED();
1113 return false;
1114 }
1115 BITMAPINFOHEADER bmi = {0};
1116 gfx::CreateBitmapHeader(bitmap.width(), bitmap.height(), &bmi);
1117 bmi.biCompression = BI_JPEG;
1118 bmi.biSizeImage = compressed_image.size();
1119 bmi.biHeight = -bmi.biHeight;
1120 StretchDIBits(dc, printable_area.x(), printable_area.y(),
1121 printable_area.width(), printable_area.height(),
1122 0, 0, bitmap.width(), bitmap.height(),
1123 &compressed_image.front(),
1124 reinterpret_cast<const BITMAPINFO*>(&bmi),
1125 DIB_RGB_COLORS, SRCCOPY);
1126 return true;
1127 }
1128 #endif // OS_WIN
1129
1130 #if defined(OS_MACOSX)
1131 void PluginInstance::DrawSkBitmapToCanvas(
1132 const SkBitmap& bitmap, WebKit::WebCanvas* canvas,
1133 const gfx::Rect& dest_rect,
1134 int canvas_height) {
1135 SkAutoLockPixels lock(bitmap);
1136 DCHECK(bitmap.getConfig() == SkBitmap::kARGB_8888_Config);
1137 base::mac::ScopedCFTypeRef<CGDataProviderRef> data_provider(
1138 CGDataProviderCreateWithData(
1139 NULL, bitmap.getAddr32(0, 0),
1140 bitmap.rowBytes() * bitmap.height(), NULL));
1141 base::mac::ScopedCFTypeRef<CGImageRef> image(
1142 CGImageCreate(
1143 bitmap.width(), bitmap.height(),
1144 8, 32, bitmap.rowBytes(),
1145 mac_util::GetSystemColorSpace(),
1146 kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
1147 data_provider, NULL, false, kCGRenderingIntentDefault));
1148
1149 // Flip the transform
1150 CGContextSaveGState(canvas);
1151 CGContextTranslateCTM(canvas, 0, canvas_height);
1152 CGContextScaleCTM(canvas, 1.0, -1.0);
1153
1154 CGRect bounds;
1155 bounds.origin.x = dest_rect.x();
1156 bounds.origin.y = canvas_height - dest_rect.y() - dest_rect.height();
1157 bounds.size.width = dest_rect.width();
1158 bounds.size.height = dest_rect.height();
1159
1160 CGContextDrawImage(canvas, bounds, image);
1161 CGContextRestoreGState(canvas);
1162 }
1163 #endif // defined(OS_MACOSX)
1164
1165 Graphics2D* PluginInstance::bound_graphics_2d() const {
1166 if (bound_graphics_.get() == NULL)
1167 return NULL;
1168
1169 return bound_graphics_->Cast<Graphics2D>();
1170 }
1171
1172 Graphics3D* PluginInstance::bound_graphics_3d() const {
1173 if (bound_graphics_.get() == NULL)
1174 return NULL;
1175
1176 return bound_graphics_->Cast<Graphics3D>();
1177 }
1178
1179 } // namespace pepper
OLDNEW
« no previous file with comments | « webkit/glue/plugins/pepper_plugin_instance.h ('k') | webkit/glue/plugins/pepper_plugin_module.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698