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

Side by Side Diff: chrome/renderer/webplugin_delegate_pepper.cc

Issue 6646025: Deleted WebPluginDelegatePepper. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/renderer/webplugin_delegate_pepper.h ('k') | gpu/demos/demos.gyp » ('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) 2011 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 #define PEPPER_APIS_ENABLED 1
6
7 #include "chrome/renderer/webplugin_delegate_pepper.h"
8
9 #include <string>
10 #include <vector>
11
12 #if defined(OS_LINUX)
13 #include <unistd.h>
14 #endif
15
16 #include "base/file_path.h"
17 #include "base/file_util.h"
18 #include "base/md5.h"
19 #include "base/message_loop.h"
20 #include "base/metrics/histogram.h"
21 #include "base/metrics/stats_counters.h"
22 #include "base/path_service.h"
23 #include "base/process_util.h"
24 #include "base/scoped_ptr.h"
25 #include "base/string_number_conversions.h"
26 #include "base/string_util.h"
27 #include "base/task.h"
28 #include "base/time.h"
29 #include "base/utf_string_conversions.h"
30 #include "chrome/common/chrome_paths.h"
31 #include "chrome/common/render_messages.h"
32 #include "chrome/common/render_messages_params.h"
33 #include "chrome/renderer/pepper_widget.h"
34 #include "chrome/renderer/render_thread.h"
35 #include "chrome/renderer/render_view.h"
36 #include "chrome/renderer/webplugin_delegate_proxy.h"
37 #include "ui/gfx/blit.h"
38 #include "printing/native_metafile_factory.h"
39 #include "printing/native_metafile.h"
40 #include "third_party/npapi/bindings/npapi_extensions.h"
41 #include "third_party/npapi/bindings/npapi_extensions_private.h"
42 #include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h"
43 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
44 #include "webkit/glue/webcursor.h"
45 #include "webkit/glue/webkit_glue.h"
46 #include "webkit/plugins/npapi/plugin_constants_win.h"
47 #include "webkit/plugins/npapi/plugin_instance.h"
48 #include "webkit/plugins/npapi/plugin_lib.h"
49 #include "webkit/plugins/npapi/plugin_list.h"
50 #include "webkit/plugins/npapi/plugin_host.h"
51 #include "webkit/plugins/npapi/plugin_stream_url.h"
52
53 #if defined(OS_MACOSX)
54 #include "base/mac/mac_util.h"
55 #include "base/mac/scoped_cftyperef.h"
56 #elif defined(OS_LINUX)
57 #include "chrome/renderer/renderer_sandbox_support_linux.h"
58 #include "printing/pdf_ps_metafile_cairo.h"
59 #elif defined(OS_WIN)
60 #include "printing/units.h"
61 #include "skia/ext/vector_platform_device.h"
62 #include "ui/gfx/codec/jpeg_codec.h"
63 #include "ui/gfx/gdi_util.h"
64 #endif
65
66 using webkit::npapi::WebPlugin;
67 using webkit::npapi::WebPluginDelegate;
68 using webkit::npapi::WebPluginResourceClient;
69 using WebKit::WebCursorInfo;
70 using WebKit::WebKeyboardEvent;
71 using WebKit::WebInputEvent;
72 using WebKit::WebMouseEvent;
73 using WebKit::WebMouseWheelEvent;
74
75 namespace {
76
77 // Implementation artifacts for a context
78 struct Device2DImpl {
79 TransportDIB* dib;
80 };
81
82 } // namespace
83
84 static const float kPointsPerInch = 72.0;
85
86 #if defined(OS_WIN)
87 // Exported by pdf.dll
88 typedef bool (*RenderPDFPageToDCProc)(
89 const unsigned char* pdf_buffer, int buffer_size, int page_number, HDC dc,
90 int dpi_x, int dpi_y, int bounds_origin_x, int bounds_origin_y,
91 int bounds_width, int bounds_height, bool fit_to_bounds,
92 bool stretch_to_bounds, bool keep_aspect_ratio, bool center_in_bounds);
93 #endif // defined(OS_WIN)
94
95 WebPluginDelegatePepper* WebPluginDelegatePepper::Create(
96 const FilePath& filename,
97 const std::string& mime_type,
98 const base::WeakPtr<RenderView>& render_view) {
99 scoped_refptr<webkit::npapi::PluginLib> plugin_lib(
100 webkit::npapi::PluginLib::CreatePluginLib(filename));
101 if (plugin_lib.get() == NULL)
102 return NULL;
103
104 NPError err = plugin_lib->NP_Initialize();
105 if (err != NPERR_NO_ERROR)
106 return NULL;
107
108 scoped_refptr<webkit::npapi::PluginInstance> instance(
109 plugin_lib->CreateInstance(mime_type));
110 return new WebPluginDelegatePepper(render_view,
111 instance.get());
112 }
113
114 void WebPluginDelegatePepper::didChooseFile(
115 const WebKit::WebVector<WebKit::WebString>& file_names) {
116 if (file_names.isEmpty()) {
117 current_choose_file_callback_(NULL, 0, current_choose_file_user_data_);
118 } else {
119 // Construct a bunch of 8-bit strings for the callback.
120 std::vector<std::string> file_strings;
121 file_strings.resize(file_names.size());
122 for (size_t i = 0; i < file_names.size(); i++)
123 file_strings[i] = file_names[0].utf8();
124
125 // Construct an array of pointers to each of the strings.
126 std::vector<const char*> pointers_to_strings;
127 pointers_to_strings.resize(file_strings.size());
128 for (size_t i = 0; i < file_strings.size(); i++)
129 pointers_to_strings[i] = file_strings[i].c_str();
130
131 current_choose_file_callback_(
132 &pointers_to_strings[0],
133 static_cast<int>(pointers_to_strings.size()),
134 current_choose_file_user_data_);
135 }
136 }
137
138 bool WebPluginDelegatePepper::Initialize(
139 const GURL& url,
140 const std::vector<std::string>& arg_names,
141 const std::vector<std::string>& arg_values,
142 WebPlugin* plugin,
143 bool load_manually) {
144 plugin_ = plugin;
145
146 instance_->set_web_plugin(plugin_);
147 int argc = 0;
148 scoped_array<char*> argn(new char*[arg_names.size()]);
149 scoped_array<char*> argv(new char*[arg_names.size()]);
150 for (size_t i = 0; i < arg_names.size(); ++i) {
151 argn[argc] = const_cast<char*>(arg_names[i].c_str());
152 argv[argc] = const_cast<char*>(arg_values[i].c_str());
153 argc++;
154 }
155
156 bool start_result = instance_->Start(
157 url, argn.get(), argv.get(), argc, load_manually);
158 if (!start_result)
159 return false;
160
161 plugin_url_ = url.spec();
162
163 return true;
164 }
165
166 void WebPluginDelegatePepper::DestroyInstance() {
167 if (instance_ && (instance_->npp()->ndata != NULL)) {
168 // Shutdown all streams before destroying so that
169 // no streams are left "in progress". Need to do
170 // this before calling set_web_plugin(NULL) because the
171 // instance uses the helper to do the download.
172 instance_->CloseStreams();
173
174 window_.window = NULL;
175 instance_->NPP_SetWindow(&window_);
176
177 instance_->NPP_Destroy();
178
179 instance_->set_web_plugin(NULL);
180
181 instance_ = 0;
182 }
183 }
184
185 void WebPluginDelegatePepper::UpdateGeometry(
186 const gfx::Rect& window_rect,
187 const gfx::Rect& clip_rect) {
188 // Only resend to the instance if the geometry has changed.
189 if (window_rect == window_rect_ && clip_rect == clip_rect_)
190 return;
191
192 clip_rect_ = clip_rect;
193 cutout_rects_.clear();
194
195 if (window_rect_ == window_rect)
196 return;
197 window_rect_ = window_rect;
198
199 // TODO(brettw) figure out how to tell the plugin that the size changed and it
200 // needs to repaint?
201 SkBitmap new_committed;
202 new_committed.setConfig(SkBitmap::kARGB_8888_Config,
203 window_rect_.width(), window_rect_.height());
204 new_committed.allocPixels();
205 committed_bitmap_ = new_committed;
206
207 if (!instance())
208 return;
209
210 ForwardSetWindow();
211 }
212
213 NPObject* WebPluginDelegatePepper::GetPluginScriptableObject() {
214 return instance_->GetPluginScriptableObject();
215 }
216
217 void WebPluginDelegatePepper::DidFinishLoadWithReason(
218 const GURL& url, NPReason reason, int notify_id) {
219 instance()->DidFinishLoadWithReason(url, reason, notify_id);
220 }
221
222 int WebPluginDelegatePepper::GetProcessId() {
223 // We are in process, so the plugin pid is this current process pid.
224 return base::GetCurrentProcId();
225 }
226
227 void WebPluginDelegatePepper::SendJavaScriptStream(
228 const GURL& url,
229 const std::string& result,
230 bool success,
231 int notify_id) {
232 instance()->SendJavaScriptStream(url, result, success, notify_id);
233 }
234
235 void WebPluginDelegatePepper::DidReceiveManualResponse(
236 const GURL& url, const std::string& mime_type,
237 const std::string& headers, uint32 expected_length, uint32 last_modified) {
238 instance()->DidReceiveManualResponse(url, mime_type, headers,
239 expected_length, last_modified);
240 }
241
242 void WebPluginDelegatePepper::DidReceiveManualData(const char* buffer,
243 int length) {
244 instance()->DidReceiveManualData(buffer, length);
245 }
246
247 void WebPluginDelegatePepper::DidFinishManualLoading() {
248 instance()->DidFinishManualLoading();
249 }
250
251 void WebPluginDelegatePepper::DidManualLoadFail() {
252 instance()->DidManualLoadFail();
253 }
254
255 FilePath WebPluginDelegatePepper::GetPluginPath() {
256 return instance()->plugin_lib()->plugin_info().path;
257 }
258
259 void WebPluginDelegatePepper::RenderViewInitiatedPaint() {
260 // Broadcast event to all 2D contexts.
261 Graphics2DMap::iterator iter2d(&graphic2d_contexts_);
262 while (!iter2d.IsAtEnd()) {
263 iter2d.GetCurrentValue()->RenderViewInitiatedPaint();
264 iter2d.Advance();
265 }
266 }
267
268 void WebPluginDelegatePepper::RenderViewFlushedPaint() {
269 // Broadcast event to all 2D contexts.
270 Graphics2DMap::iterator iter2d(&graphic2d_contexts_);
271 while (!iter2d.IsAtEnd()) {
272 iter2d.GetCurrentValue()->RenderViewFlushedPaint();
273 iter2d.Advance();
274 }
275 }
276
277 WebPluginResourceClient* WebPluginDelegatePepper::CreateResourceClient(
278 unsigned long resource_id, const GURL& url, int notify_id) {
279 return instance()->CreateStream(resource_id, url, std::string(), notify_id);
280 }
281
282 WebPluginResourceClient* WebPluginDelegatePepper::CreateSeekableResourceClient(
283 unsigned long resource_id, int range_request_id) {
284 return instance()->GetRangeRequest(range_request_id);
285 }
286
287 bool WebPluginDelegatePepper::StartFind(const string16& search_text,
288 bool case_sensitive,
289 int identifier) {
290 if (!GetFindExtensions())
291 return false;
292 find_identifier_ = identifier;
293 GetFindExtensions()->startFind(
294 instance()->npp(), UTF16ToUTF8(search_text).c_str(), case_sensitive);
295 return true;
296 }
297
298 void WebPluginDelegatePepper::SelectFindResult(bool forward) {
299 GetFindExtensions()->selectFindResult(instance()->npp(), forward);
300 }
301
302 void WebPluginDelegatePepper::StopFind() {
303 find_identifier_ = -1;
304 GetFindExtensions()->stopFind(instance()->npp());
305 }
306
307 void WebPluginDelegatePepper::NumberOfFindResultsChanged(int total,
308 bool final_result) {
309 DCHECK(find_identifier_ != -1);
310
311 render_view_->reportFindInPageMatchCount(
312 find_identifier_, total, final_result);
313 }
314
315 void WebPluginDelegatePepper::SelectedFindResultChanged(int index) {
316 render_view_->reportFindInPageSelection(
317 find_identifier_, index + 1, WebKit::WebRect());
318 }
319
320 bool WebPluginDelegatePepper::ChooseFile(const char* mime_types,
321 int mode,
322 NPChooseFileCallback callback,
323 void* user_data) {
324 if (!render_view_ || !callback)
325 return false;
326
327 if (current_choose_file_callback_)
328 return false; // Reentrant call to browse, only one can be outstanding
329 // per plugin.
330
331 // TODO(brettw) do something with the mime types!
332 current_choose_file_callback_ = callback;
333 current_choose_file_user_data_ = user_data;
334
335 ViewHostMsg_RunFileChooser_Params ipc_params;
336 switch (mode) {
337 case NPChooseFile_Open:
338 ipc_params.mode = ViewHostMsg_RunFileChooser_Params::Open;
339 break;
340 case NPChooseFile_OpenMultiple:
341 ipc_params.mode = ViewHostMsg_RunFileChooser_Params::OpenMultiple;
342 break;
343 case NPChooseFile_Save:
344 ipc_params.mode = ViewHostMsg_RunFileChooser_Params::Save;
345 break;
346 default:
347 return false;
348 }
349 return render_view_->ScheduleFileChooser(ipc_params, this);
350 }
351
352 NPWidgetExtensions* WebPluginDelegatePepper::GetWidgetExtensions() {
353 return PepperWidget::GetWidgetExtensions();
354 }
355
356 #define COMPILE_ASSERT_MATCHING_ENUM(webkit_name, np_name) \
357 COMPILE_ASSERT(int(WebCursorInfo::webkit_name) == int(np_name), \
358 mismatching_enums)
359
360 COMPILE_ASSERT_MATCHING_ENUM(TypePointer, NPCursorTypePointer);
361 COMPILE_ASSERT_MATCHING_ENUM(TypeCross, NPCursorTypeCross);
362 COMPILE_ASSERT_MATCHING_ENUM(TypeHand, NPCursorTypeHand);
363 COMPILE_ASSERT_MATCHING_ENUM(TypeIBeam, NPCursorTypeIBeam);
364 COMPILE_ASSERT_MATCHING_ENUM(TypeWait, NPCursorTypeWait);
365 COMPILE_ASSERT_MATCHING_ENUM(TypeHelp, NPCursorTypeHelp);
366 COMPILE_ASSERT_MATCHING_ENUM(TypeEastResize, NPCursorTypeEastResize);
367 COMPILE_ASSERT_MATCHING_ENUM(TypeNorthResize, NPCursorTypeNorthResize);
368 COMPILE_ASSERT_MATCHING_ENUM(TypeNorthEastResize, NPCursorTypeNorthEastResize);
369 COMPILE_ASSERT_MATCHING_ENUM(TypeNorthWestResize, NPCursorTypeNorthWestResize);
370 COMPILE_ASSERT_MATCHING_ENUM(TypeSouthResize, NPCursorTypeSouthResize);
371 COMPILE_ASSERT_MATCHING_ENUM(TypeSouthEastResize, NPCursorTypeSouthEastResize);
372 COMPILE_ASSERT_MATCHING_ENUM(TypeSouthWestResize, NPCursorTypeSouthWestResize);
373 COMPILE_ASSERT_MATCHING_ENUM(TypeWestResize, NPCursorTypeWestResize);
374 COMPILE_ASSERT_MATCHING_ENUM(TypeNorthSouthResize,
375 NPCursorTypeNorthSouthResize);
376 COMPILE_ASSERT_MATCHING_ENUM(TypeEastWestResize, NPCursorTypeEastWestResize);
377 COMPILE_ASSERT_MATCHING_ENUM(TypeNorthEastSouthWestResize,
378 NPCursorTypeNorthEastSouthWestResize);
379 COMPILE_ASSERT_MATCHING_ENUM(TypeNorthWestSouthEastResize,
380 NPCursorTypeNorthWestSouthEastResize);
381 COMPILE_ASSERT_MATCHING_ENUM(TypeColumnResize, NPCursorTypeColumnResize);
382 COMPILE_ASSERT_MATCHING_ENUM(TypeRowResize, NPCursorTypeRowResize);
383 COMPILE_ASSERT_MATCHING_ENUM(TypeMiddlePanning, NPCursorTypeMiddlePanning);
384 COMPILE_ASSERT_MATCHING_ENUM(TypeEastPanning, NPCursorTypeEastPanning);
385 COMPILE_ASSERT_MATCHING_ENUM(TypeNorthPanning, NPCursorTypeNorthPanning);
386 COMPILE_ASSERT_MATCHING_ENUM(TypeNorthEastPanning,
387 NPCursorTypeNorthEastPanning);
388 COMPILE_ASSERT_MATCHING_ENUM(TypeNorthWestPanning,
389 NPCursorTypeNorthWestPanning);
390 COMPILE_ASSERT_MATCHING_ENUM(TypeSouthPanning, NPCursorTypeSouthPanning);
391 COMPILE_ASSERT_MATCHING_ENUM(TypeSouthEastPanning,
392 NPCursorTypeSouthEastPanning);
393 COMPILE_ASSERT_MATCHING_ENUM(TypeSouthWestPanning,
394 NPCursorTypeSouthWestPanning);
395 COMPILE_ASSERT_MATCHING_ENUM(TypeWestPanning, NPCursorTypeWestPanning);
396 COMPILE_ASSERT_MATCHING_ENUM(TypeMove, NPCursorTypeMove);
397 COMPILE_ASSERT_MATCHING_ENUM(TypeVerticalText, NPCursorTypeVerticalText);
398 COMPILE_ASSERT_MATCHING_ENUM(TypeCell, NPCursorTypeCell);
399 COMPILE_ASSERT_MATCHING_ENUM(TypeContextMenu, NPCursorTypeContextMenu);
400 COMPILE_ASSERT_MATCHING_ENUM(TypeAlias, NPCursorTypeAlias);
401 COMPILE_ASSERT_MATCHING_ENUM(TypeProgress, NPCursorTypeProgress);
402 COMPILE_ASSERT_MATCHING_ENUM(TypeNoDrop, NPCursorTypeNoDrop);
403 COMPILE_ASSERT_MATCHING_ENUM(TypeCopy, NPCursorTypeCopy);
404 COMPILE_ASSERT_MATCHING_ENUM(TypeNone, NPCursorTypeNone);
405 COMPILE_ASSERT_MATCHING_ENUM(TypeNotAllowed, NPCursorTypeNotAllowed);
406 COMPILE_ASSERT_MATCHING_ENUM(TypeZoomIn, NPCursorTypeZoomIn);
407 COMPILE_ASSERT_MATCHING_ENUM(TypeZoomOut, NPCursorTypeZoomOut);
408
409 bool WebPluginDelegatePepper::SetCursor(NPCursorType type) {
410 cursor_.reset(new WebCursorInfo(static_cast<WebCursorInfo::Type>(type)));
411 return true;
412 }
413
414 NPError NPMatchFontWithFallback(NPP instance,
415 const NPFontDescription* description,
416 NPFontID* id) {
417 #if defined(OS_LINUX)
418 int fd = renderer_sandbox_support::MatchFontWithFallback(
419 description->face, description->weight >= 700, description->italic,
420 description->charset);
421 if (fd == -1)
422 return NPERR_GENERIC_ERROR;
423 *id = fd;
424 return NPERR_NO_ERROR;
425 #else
426 NOTIMPLEMENTED();
427 return NPERR_GENERIC_ERROR;
428 #endif
429 }
430
431 NPError GetFontTable(NPP instance,
432 NPFontID id,
433 uint32_t table,
434 void* output,
435 size_t* output_length) {
436 #if defined(OS_LINUX)
437 bool rv = renderer_sandbox_support::GetFontTable(
438 id, table, static_cast<uint8_t*>(output), output_length);
439 return rv ? NPERR_NO_ERROR : NPERR_GENERIC_ERROR;
440 #else
441 NOTIMPLEMENTED();
442 return NPERR_GENERIC_ERROR;
443 #endif
444 }
445
446 NPError NPDestroyFont(NPP instance, NPFontID id) {
447 #if defined(OS_LINUX)
448 close(id);
449 return NPERR_NO_ERROR;
450 #else
451 NOTIMPLEMENTED();
452 return NPERR_GENERIC_ERROR;
453 #endif
454 }
455
456 NPFontExtensions g_font_extensions = {
457 NPMatchFontWithFallback,
458 GetFontTable,
459 NPDestroyFont
460 };
461
462 NPFontExtensions* WebPluginDelegatePepper::GetFontExtensions() {
463 return &g_font_extensions;
464 }
465
466 void WebPluginDelegatePepper::SetZoomFactor(float scale, bool text_only) {
467 NPPExtensions* extensions = NULL;
468 instance()->NPP_GetValue(NPPVPepperExtensions, &extensions);
469 if (extensions && extensions->zoom)
470 extensions->zoom(instance()->npp(), scale, text_only);
471 }
472
473 bool WebPluginDelegatePepper::HasSelection() const {
474 return !GetSelectedText(false).empty();
475 }
476
477 string16 WebPluginDelegatePepper::GetSelectionAsText() const {
478 return GetSelectedText(false);
479 }
480
481 string16 WebPluginDelegatePepper::GetSelectionAsMarkup() const {
482 return GetSelectedText(true);
483 }
484
485 string16 WebPluginDelegatePepper::GetSelectedText(bool html) const {
486 NPPExtensions* extensions = NULL;
487 instance_->NPP_GetValue(NPPVPepperExtensions, &extensions);
488 if (!extensions || !extensions->getSelection)
489 return string16();
490
491 void* text;
492 NPSelectionType type = html ? NPSelectionTypeHTML : NPSelectionTypePlainText;
493 NPP npp = instance_->npp();
494 if (extensions->getSelection(npp, &type, &text) != NPERR_NO_ERROR)
495 return string16();
496
497 string16 rv = UTF8ToUTF16(static_cast<char*>(text));
498 webkit::npapi::PluginHost::Singleton()->host_functions()->memfree(text);
499 return rv;
500 }
501
502 NPError WebPluginDelegatePepper::Device2DQueryCapability(int32 capability,
503 int32* value) {
504 return NPERR_GENERIC_ERROR;
505 }
506
507 NPError WebPluginDelegatePepper::Device2DQueryConfig(
508 const NPDeviceContext2DConfig* request,
509 NPDeviceContext2DConfig* obtain) {
510 return NPERR_GENERIC_ERROR;
511 }
512
513 NPError WebPluginDelegatePepper::Device2DInitializeContext(
514 const NPDeviceContext2DConfig* config,
515 NPDeviceContext2D* context) {
516
517 if (!render_view_) {
518 return NPERR_GENERIC_ERROR;
519 }
520
521 // This is a windowless plugin, so set it to have no handle. Defer this
522 // until we know the plugin will use the 2D device.
523 plugin_->SetWindow(gfx::kNullPluginWindow);
524
525 scoped_ptr<Graphics2DDeviceContext> g2d(new Graphics2DDeviceContext(this));
526 NPError status = g2d->Initialize(window_rect_, config, context);
527 if (NPERR_NO_ERROR == status) {
528 context->reserved = reinterpret_cast<void *>(
529 graphic2d_contexts_.Add(g2d.release()));
530 }
531 return status;
532 }
533
534 NPError WebPluginDelegatePepper::Device2DSetStateContext(
535 NPDeviceContext2D* context,
536 int32 state,
537 intptr_t value) {
538 return NPERR_GENERIC_ERROR;
539 }
540
541 NPError WebPluginDelegatePepper::Device2DGetStateContext(
542 NPDeviceContext2D* context,
543 int32 state,
544 intptr_t* value) {
545 if (state == NPExtensionsReservedStateSharedMemory) {
546 if (!context)
547 return NPERR_INVALID_PARAM;
548 Graphics2DDeviceContext* ctx = GetGraphicsContext(context);
549 if (!ctx)
550 return NPERR_INVALID_PARAM;
551 *value = reinterpret_cast<intptr_t>(ctx->transport_dib());
552 return NPERR_NO_ERROR;
553 } else if (state == NPExtensionsReservedStateSharedMemoryChecksum) {
554 if (!context)
555 return NPERR_INVALID_PARAM;
556 // Bytes per pixel.
557 static const int kBytesPixel = 4;
558 int32 row_count = context->dirty.bottom - context->dirty.top;
559 int32 stride = context->dirty.right - context->dirty.left;
560 size_t length = row_count * stride * kBytesPixel;
561 MD5Digest md5_result; // 128-bit digest
562 MD5Sum(context->region, length, &md5_result);
563 std::string hex_md5 = MD5DigestToBase16(md5_result);
564 // Return the least significant 8 characters (i.e. 4 bytes)
565 // of the 32 character hexadecimal result as an int.
566 int int_val;
567 DCHECK_EQ(hex_md5.length(), 32u);
568 base::HexStringToInt(hex_md5.begin() + 24, hex_md5.end(), &int_val);
569 *value = int_val;
570 return NPERR_NO_ERROR;
571 }
572 return NPERR_GENERIC_ERROR;
573 }
574
575 NPError WebPluginDelegatePepper::Device2DFlushContext(
576 NPP id,
577 NPDeviceContext2D* context,
578 NPDeviceFlushContextCallbackPtr callback,
579 void* user_data) {
580 if (!context)
581 return NPERR_INVALID_PARAM;
582
583 Graphics2DDeviceContext* ctx = graphic2d_contexts_.Lookup(
584 reinterpret_cast<intptr_t>(context->reserved));
585 if (!ctx)
586 return NPERR_INVALID_PARAM; // TODO(brettw) call callback.
587
588 return ctx->Flush(&committed_bitmap_, context, callback, id, user_data);
589 }
590
591 NPError WebPluginDelegatePepper::Device2DDestroyContext(
592 NPDeviceContext2D* context) {
593
594 if (!context || !graphic2d_contexts_.Lookup(
595 reinterpret_cast<intptr_t>(context->reserved))) {
596 return NPERR_INVALID_PARAM;
597 }
598 graphic2d_contexts_.Remove(reinterpret_cast<intptr_t>(context->reserved));
599 memset(context, 0, sizeof(NPDeviceContext2D));
600 return NPERR_NO_ERROR;
601 }
602
603 Graphics2DDeviceContext* WebPluginDelegatePepper::GetGraphicsContext(
604 NPDeviceContext2D* context) {
605 return graphic2d_contexts_.Lookup(
606 reinterpret_cast<intptr_t>(context->reserved));
607 }
608
609 NPError WebPluginDelegatePepper::Device3DQueryCapability(int32 capability,
610 int32* value) {
611 return NPERR_GENERIC_ERROR;
612 }
613
614 NPError WebPluginDelegatePepper::Device3DQueryConfig(
615 const NPDeviceContext3DConfig* request,
616 NPDeviceContext3DConfig* obtain) {
617 return NPERR_GENERIC_ERROR;
618 }
619
620 NPError WebPluginDelegatePepper::Device3DInitializeContext(
621 const NPDeviceContext3DConfig* config,
622 NPDeviceContext3D* context) {
623 return NPERR_GENERIC_ERROR;
624 }
625
626 NPError WebPluginDelegatePepper::Device3DSetStateContext(
627 NPDeviceContext3D* context,
628 int32 state,
629 intptr_t value) {
630 return NPERR_GENERIC_ERROR;
631 }
632
633 NPError WebPluginDelegatePepper::Device3DGetStateContext(
634 NPDeviceContext3D* context,
635 int32 state,
636 intptr_t* value) {
637 return NPERR_GENERIC_ERROR;
638 }
639
640 NPError WebPluginDelegatePepper::Device3DFlushContext(
641 NPP id,
642 NPDeviceContext3D* context,
643 NPDeviceFlushContextCallbackPtr callback,
644 void* user_data) {
645 return NPERR_GENERIC_ERROR;
646 }
647
648 NPError WebPluginDelegatePepper::Device3DDestroyContext(
649 NPDeviceContext3D* context) {
650 return NPERR_GENERIC_ERROR;
651 }
652
653 NPError WebPluginDelegatePepper::Device3DCreateBuffer(
654 NPDeviceContext3D* context,
655 size_t size,
656 int32* id) {
657 return NPERR_GENERIC_ERROR;
658 }
659
660 NPError WebPluginDelegatePepper::Device3DDestroyBuffer(
661 NPDeviceContext3D* context,
662 int32 id) {
663 return NPERR_GENERIC_ERROR;
664 }
665
666 NPError WebPluginDelegatePepper::Device3DMapBuffer(
667 NPDeviceContext3D* context,
668 int32 id,
669 NPDeviceBuffer* np_buffer) {
670 return NPERR_GENERIC_ERROR;
671 }
672
673 NPError WebPluginDelegatePepper::Device3DGetNumConfigs(int32* num_configs) {
674 return NPERR_GENERIC_ERROR;
675 }
676
677 NPError WebPluginDelegatePepper::Device3DGetConfigAttribs(
678 int32 config,
679 int32* attrib_list) {
680 return NPERR_GENERIC_ERROR;
681 }
682
683 NPError WebPluginDelegatePepper::Device3DCreateContext(
684 int32 config,
685 const int32* attrib_list,
686 NPDeviceContext3D** context) {
687 return NPERR_GENERIC_ERROR;
688 }
689
690 NPError WebPluginDelegatePepper::Device3DRegisterCallback(
691 NPP id,
692 NPDeviceContext3D* context,
693 int32 callback_type,
694 NPDeviceGenericCallbackPtr callback,
695 void* callback_data) {
696 return NPERR_GENERIC_ERROR;
697 }
698
699 NPError WebPluginDelegatePepper::Device3DSynchronizeContext(
700 NPP id,
701 NPDeviceContext3D* context,
702 NPDeviceSynchronizationMode mode,
703 const int32* input_attrib_list,
704 int32* output_attrib_list,
705 NPDeviceSynchronizeContextCallbackPtr callback,
706 void* callback_data) {
707 return NPERR_GENERIC_ERROR;
708 }
709
710 NPError WebPluginDelegatePepper::DeviceAudioQueryCapability(int32 capability,
711 int32* value) {
712 // TODO(neb,cpu) implement QueryCapability
713 return NPERR_GENERIC_ERROR;
714 }
715
716 NPError WebPluginDelegatePepper::DeviceAudioQueryConfig(
717 const NPDeviceContextAudioConfig* request,
718 NPDeviceContextAudioConfig* obtain) {
719 // TODO(neb,cpu) implement QueryConfig
720 return NPERR_GENERIC_ERROR;
721 }
722
723 NPError WebPluginDelegatePepper::DeviceAudioInitializeContext(
724 const NPDeviceContextAudioConfig* config,
725 NPDeviceContextAudio* context) {
726
727 if (!render_view_) {
728 return NPERR_GENERIC_ERROR;
729 }
730
731 scoped_ptr<AudioDeviceContext> audio(new AudioDeviceContext());
732 NPError status = audio->Initialize(render_view_->audio_message_filter(),
733 config, context);
734 if (NPERR_NO_ERROR == status) {
735 context->reserved =
736 reinterpret_cast<void *>(audio_contexts_.Add(audio.release()));
737 }
738 return status;
739 }
740
741 NPError WebPluginDelegatePepper::DeviceAudioSetStateContext(
742 NPDeviceContextAudio* context,
743 int32 state,
744 intptr_t value) {
745 // TODO(neb,cpu) implement SetStateContext
746 return NPERR_GENERIC_ERROR;
747 }
748
749 NPError WebPluginDelegatePepper::DeviceAudioGetStateContext(
750 NPDeviceContextAudio* context,
751 int32 state,
752 intptr_t* value) {
753 if (state == NPExtensionsReservedStateSharedMemory) {
754 if (!context)
755 return NPERR_INVALID_PARAM;
756 AudioDeviceContext* ctx = audio_contexts_.Lookup(
757 reinterpret_cast<intptr_t>(context->reserved));
758 if (!ctx)
759 return NPERR_INVALID_PARAM;
760 *value = reinterpret_cast<intptr_t>(ctx->shared_memory());
761 return NPERR_NO_ERROR;
762 } else if (state == NPExtensionsReservedStateSharedMemorySize) {
763 if (!context)
764 return NPERR_INVALID_PARAM;
765 AudioDeviceContext* ctx = audio_contexts_.Lookup(
766 reinterpret_cast<intptr_t>(context->reserved));
767 if (!ctx)
768 return NPERR_INVALID_PARAM;
769 *value = static_cast<intptr_t>(ctx->shared_memory_size());
770 return NPERR_NO_ERROR;
771 } else if (state == NPExtensionsReservedStateSyncChannel) {
772 if (!context)
773 return NPERR_INVALID_PARAM;
774 AudioDeviceContext* ctx = audio_contexts_.Lookup(
775 reinterpret_cast<intptr_t>(context->reserved));
776 if (!ctx)
777 return NPERR_INVALID_PARAM;
778 *value = reinterpret_cast<intptr_t>(ctx->socket());
779 return NPERR_NO_ERROR;
780 }
781 return NPERR_GENERIC_ERROR;
782 }
783
784 NPError WebPluginDelegatePepper::DeviceAudioFlushContext(
785 NPP id,
786 NPDeviceContextAudio* context,
787 NPDeviceFlushContextCallbackPtr callback,
788 void* user_data) {
789 // TODO(neb,cpu) implement FlushContext
790 return NPERR_GENERIC_ERROR;
791 }
792
793 NPError WebPluginDelegatePepper::DeviceAudioDestroyContext(
794 NPDeviceContextAudio* context) {
795 if (!context || !audio_contexts_.Lookup(
796 reinterpret_cast<intptr_t>(context->reserved))) {
797 return NPERR_INVALID_PARAM;
798 }
799 audio_contexts_.Remove(reinterpret_cast<intptr_t>(context->reserved));
800 memset(context, 0, sizeof(NPDeviceContextAudio));
801 return NPERR_NO_ERROR;
802 }
803
804 bool WebPluginDelegatePepper::PrintSupportsPrintExtension() {
805 return GetPrintExtensions() != NULL;
806 }
807
808 int WebPluginDelegatePepper::PrintBegin(const gfx::Rect& printable_area,
809 int printer_dpi) {
810 int32 num_pages = 0;
811 NPPPrintExtensions* print_extensions = GetPrintExtensions();
812 if (print_extensions) {
813 NPRect np_printable_area = {0};
814 np_printable_area.left = printable_area.x();
815 np_printable_area.top = printable_area.y();
816 np_printable_area.right = np_printable_area.left + printable_area.width();
817 np_printable_area.bottom = np_printable_area.top + printable_area.height();
818 if (NPERR_NO_ERROR == print_extensions->printBegin(instance()->npp(),
819 &np_printable_area,
820 printer_dpi,
821 &num_pages)) {
822 current_printable_area_ = printable_area;
823 current_printer_dpi_ = printer_dpi;
824 }
825 }
826 #if defined (OS_LINUX)
827 num_pages_ = num_pages;
828 pdf_output_done_ = false;
829 #endif // (OS_LINUX)
830 return num_pages;
831 }
832
833 bool WebPluginDelegatePepper::VectorPrintPage(int page_number,
834 WebKit::WebCanvas* canvas) {
835 NPPPrintExtensions* print_extensions = GetPrintExtensions();
836 if (!print_extensions)
837 return false;
838 #if defined(OS_WIN)
839 // For Windows, we need the PDF DLL to render the output PDF to a DC.
840 FilePath pdf_path;
841 PathService::Get(chrome::FILE_PDF_PLUGIN, &pdf_path);
842 HMODULE pdf_module = GetModuleHandle(pdf_path.value().c_str());
843 if (!pdf_module)
844 return false;
845 RenderPDFPageToDCProc render_proc =
846 reinterpret_cast<RenderPDFPageToDCProc>(
847 GetProcAddress(pdf_module, "RenderPDFPageToDC"));
848 if (!render_proc)
849 return false;
850 #endif // defined(OS_WIN)
851
852 unsigned char* pdf_output = NULL;
853 int32 output_size = 0;
854 NPPrintPageNumberRange page_range;
855 #if defined(OS_LINUX)
856 // On Linux we will try and output all pages as PDF in the first call to
857 // PrintPage. This is a temporary hack.
858 // TODO(sanjeevr): Remove this hack and fix this by changing the print
859 // interfaces for WebFrame and WebPlugin.
860 if (page_number != 0)
861 return pdf_output_done_;
862 page_range.firstPageNumber = 0;
863 page_range.lastPageNumber = num_pages_ - 1;
864 #else // defined(OS_LINUX)
865 page_range.firstPageNumber = page_range.lastPageNumber = page_number;
866 #endif // defined(OS_LINUX)
867 NPError err = print_extensions->printPagesAsPDF(instance()->npp(),
868 &page_range, 1,
869 &pdf_output, &output_size);
870 if (err != NPERR_NO_ERROR)
871 return false;
872
873 bool ret = false;
874 #if defined(OS_LINUX)
875 // On Linux we need to get the backing PdfPsMetafile and write the bits
876 // directly.
877 cairo_t* context = canvas->beginPlatformPaint();
878 printing::NativeMetafile* metafile =
879 printing::PdfPsMetafile::FromCairoContext(context);
880 DCHECK(metafile);
881 if (metafile) {
882 ret = metafile->SetRawData(pdf_output, output_size);
883 if (ret)
884 pdf_output_done_ = true;
885 }
886 canvas->endPlatformPaint();
887 #elif defined(OS_MACOSX)
888 scoped_ptr<printing::NativeMetafile> metafile(
889 printing::NativeMetafileFactory::CreateMetafile());
890 // Create a PDF metafile and render from there into the passed in context.
891 if (metafile->Init(pdf_output, output_size)) {
892 // Flip the transform.
893 CGContextSaveGState(canvas);
894 CGContextTranslateCTM(canvas, 0, current_printable_area_.height());
895 CGContextScaleCTM(canvas, 1.0, -1.0);
896 ret = metafile->RenderPage(1, canvas, current_printable_area_.ToCGRect(),
897 true, false, true, true);
898 CGContextRestoreGState(canvas);
899 }
900 #elif defined(OS_WIN)
901 // On Windows, we now need to render the PDF to the DC that backs the
902 // supplied canvas.
903 skia::VectorPlatformDevice& device =
904 static_cast<skia::VectorPlatformDevice&>(
905 canvas->getTopPlatformDevice());
906 HDC dc = device.getBitmapDC();
907 gfx::Size size_in_pixels;
908 size_in_pixels.set_width(
909 printing::ConvertUnit(current_printable_area_.width(),
910 static_cast<int>(kPointsPerInch),
911 current_printer_dpi_));
912 size_in_pixels.set_height(
913 printing::ConvertUnit(current_printable_area_.height(),
914 static_cast<int>(kPointsPerInch),
915 current_printer_dpi_));
916 // We need to render using the actual printer DPI (rendering to a smaller
917 // set of pixels leads to a blurry output). However, we need to counter the
918 // scaling up that will happen in the browser.
919 XFORM xform = {0};
920 xform.eM11 = xform.eM22 = kPointsPerInch / current_printer_dpi_;
921 ModifyWorldTransform(dc, &xform, MWT_LEFTMULTIPLY);
922
923 ret = render_proc(pdf_output, output_size, 0, dc, current_printer_dpi_,
924 current_printer_dpi_, 0, 0, size_in_pixels.width(),
925 size_in_pixels.height(), true, false, true, true);
926 #endif // defined(OS_WIN)
927
928 webkit::npapi::PluginHost::Singleton()->host_functions()->memfree(
929 pdf_output);
930 return ret;
931 }
932
933 bool WebPluginDelegatePepper::PrintPage(int page_number,
934 WebKit::WebCanvas* canvas) {
935 NPPPrintExtensions* print_extensions = GetPrintExtensions();
936 if (!print_extensions)
937 return false;
938
939 // First try and use vector print.
940 if (VectorPrintPage(page_number, canvas))
941 return true;
942
943 DCHECK(!current_printable_area_.IsEmpty());
944
945 // Calculate the width and height needed for the raster image.
946 NPRect np_printable_area = {0};
947 np_printable_area.left = current_printable_area_.x();
948 np_printable_area.top = current_printable_area_.y();
949 np_printable_area.right =
950 current_printable_area_.x() + current_printable_area_.width();
951 np_printable_area.bottom =
952 current_printable_area_.y() + current_printable_area_.height();
953 gfx::Size size_in_pixels;
954 if (!CalculatePrintedPageDimensions(page_number, print_extensions,
955 &size_in_pixels)) {
956 return false;
957 }
958
959 // Now print the page onto a 2d device context.
960 scoped_ptr<Graphics2DDeviceContext> g2d(new Graphics2DDeviceContext(this));
961 NPDeviceContext2DConfig config;
962 NPDeviceContext2D context;
963 gfx::Rect surface_rect(size_in_pixels);
964 NPError err = g2d->Initialize(surface_rect, &config, &context);
965 if (err != NPERR_NO_ERROR) {
966 NOTREACHED();
967 return false;
968 }
969 err = print_extensions->printPageRaster(instance()->npp(), page_number,
970 &context);
971 if (err != NPERR_NO_ERROR)
972 return false;
973
974 SkBitmap committed;
975 committed.setConfig(SkBitmap::kARGB_8888_Config, size_in_pixels.width(),
976 size_in_pixels.height());
977 committed.allocPixels();
978 err = g2d->Flush(&committed, &context, NULL, instance()->npp(), NULL);
979 if (err != NPERR_NO_ERROR) {
980 NOTREACHED();
981 return false;
982 }
983 // Draw the printed image into the supplied canvas.
984 SkIRect src_rect;
985 src_rect.set(0, 0, size_in_pixels.width(), size_in_pixels.height());
986 SkRect dest_rect;
987 dest_rect.set(SkIntToScalar(current_printable_area_.x()),
988 SkIntToScalar(current_printable_area_.y()),
989 SkIntToScalar(current_printable_area_.x() +
990 current_printable_area_.width()),
991 SkIntToScalar(current_printable_area_.y() +
992 current_printable_area_.height()));
993 bool draw_to_canvas = true;
994 #if defined(OS_WIN)
995 // Since this is a raster output, the size of the bitmap can be
996 // huge (especially at high printer DPIs). On Windows, this can
997 // result in a HUGE EMF (on Mac and Linux the output goes to PDF
998 // which appears to Flate compress the bitmap). So, if this bitmap
999 // is larger than 20 MB, we save the bitmap as a JPEG into the EMF
1000 // DC. Note: We chose JPEG over PNG because JPEG compression seems
1001 // way faster (about 4 times faster).
1002 static const int kCompressionThreshold = 20 * 1024 * 1024;
1003 if (committed.getSize() > kCompressionThreshold) {
1004 DrawJPEGToPlatformDC(committed, current_printable_area_, canvas);
1005 draw_to_canvas = false;
1006 }
1007 #endif // defined(OS_WIN)
1008 #if defined(OS_MACOSX)
1009 draw_to_canvas = false;
1010 DrawSkBitmapToCanvas(committed, canvas, current_printable_area_,
1011 current_printable_area_.height());
1012 // See comments in the header file.
1013 last_printed_page_ = committed;
1014 #else // defined(OS_MACOSX)
1015 if (draw_to_canvas)
1016 canvas->drawBitmapRect(committed, &src_rect, dest_rect);
1017 #endif // defined(OS_MACOSX)
1018 return true;
1019 }
1020
1021 void WebPluginDelegatePepper::PrintEnd() {
1022 NPPPrintExtensions* print_extensions = GetPrintExtensions();
1023 if (print_extensions)
1024 print_extensions->printEnd(instance()->npp());
1025 current_printable_area_ = gfx::Rect();
1026 current_printer_dpi_ = -1;
1027 #if defined(OS_MACOSX)
1028 last_printed_page_ = SkBitmap();
1029 #elif defined(OS_LINUX)
1030 num_pages_ = 0;
1031 pdf_output_done_ = false;
1032 #endif // defined(OS_LINUX)
1033 }
1034
1035 WebPluginDelegatePepper::WebPluginDelegatePepper(
1036 const base::WeakPtr<RenderView>& render_view,
1037 webkit::npapi::PluginInstance *instance)
1038 : render_view_(render_view),
1039 plugin_(NULL),
1040 instance_(instance),
1041 current_printer_dpi_(-1),
1042 #if defined (OS_LINUX)
1043 num_pages_(0),
1044 pdf_output_done_(false),
1045 #endif // (OS_LINUX)
1046 find_identifier_(-1),
1047 current_choose_file_callback_(NULL),
1048 current_choose_file_user_data_(NULL) {
1049 // For now we keep a window struct, although it isn't used.
1050 memset(&window_, 0, sizeof(window_));
1051 // All Pepper plugins are windowless and transparent.
1052 // TODO(sehr): disable resetting these NPPVs by plugins.
1053 instance->set_windowless(true);
1054 instance->set_transparent(true);
1055 }
1056
1057 WebPluginDelegatePepper::~WebPluginDelegatePepper() {
1058 DestroyInstance();
1059
1060 if (render_view_)
1061 render_view_->OnPepperPluginDestroy(this);
1062 }
1063
1064 void WebPluginDelegatePepper::ForwardSetWindow() {
1065 window_.clipRect.top = clip_rect_.y();
1066 window_.clipRect.left = clip_rect_.x();
1067 window_.clipRect.bottom = clip_rect_.y() + clip_rect_.height();
1068 window_.clipRect.right = clip_rect_.x() + clip_rect_.width();
1069 window_.height = window_rect_.height();
1070 window_.width = window_rect_.width();
1071 window_.x = window_rect_.x();
1072 window_.y = window_rect_.y();
1073 window_.type = NPWindowTypeDrawable;
1074 instance()->NPP_SetWindow(&window_);
1075 }
1076
1077 void WebPluginDelegatePepper::PluginDestroyed() {
1078 delete this;
1079 }
1080
1081 void WebPluginDelegatePepper::Paint(WebKit::WebCanvas* canvas,
1082 const gfx::Rect& rect) {
1083 // Blit from background_context to context.
1084 if (!committed_bitmap_.isNull()) {
1085 #if defined(OS_MACOSX)
1086 DrawSkBitmapToCanvas(committed_bitmap_, canvas, window_rect_,
1087 static_cast<int>(CGBitmapContextGetHeight(canvas)));
1088 #else
1089 canvas->drawBitmap(committed_bitmap_,
1090 SkIntToScalar(window_rect_.origin().x()),
1091 SkIntToScalar(window_rect_.origin().y()));
1092 #endif
1093 }
1094 }
1095
1096 void WebPluginDelegatePepper::Print(gfx::NativeDrawingContext context) {
1097 NOTIMPLEMENTED();
1098 }
1099
1100 void WebPluginDelegatePepper::InstallMissingPlugin() {
1101 NOTIMPLEMENTED();
1102 }
1103
1104 void WebPluginDelegatePepper::SetFocus(bool focused) {
1105 if (!focused)
1106 return;
1107
1108 NPPepperEvent npevent;
1109
1110 npevent.type = NPEventType_Focus;
1111 npevent.size = sizeof(npevent);
1112 // TODO(sehr): what timestamp should this have?
1113 npevent.timeStampSeconds = 0.0;
1114 // Currently this API only supports gaining focus.
1115 npevent.u.focus.value = 1;
1116 instance()->NPP_HandleEvent(&npevent);
1117 }
1118
1119 // Anonymous namespace for functions converting WebInputEvents to NPAPI types.
1120 namespace {
1121 NPEventTypes ConvertEventTypes(WebInputEvent::Type wetype) {
1122 switch (wetype) {
1123 case WebInputEvent::MouseDown:
1124 return NPEventType_MouseDown;
1125 case WebInputEvent::MouseUp:
1126 return NPEventType_MouseUp;
1127 case WebInputEvent::MouseMove:
1128 return NPEventType_MouseMove;
1129 case WebInputEvent::MouseEnter:
1130 return NPEventType_MouseEnter;
1131 case WebInputEvent::MouseLeave:
1132 return NPEventType_MouseLeave;
1133 case WebInputEvent::MouseWheel:
1134 return NPEventType_MouseWheel;
1135 case WebInputEvent::RawKeyDown:
1136 return NPEventType_RawKeyDown;
1137 case WebInputEvent::KeyDown:
1138 return NPEventType_KeyDown;
1139 case WebInputEvent::KeyUp:
1140 return NPEventType_KeyUp;
1141 case WebInputEvent::Char:
1142 return NPEventType_Char;
1143 case WebInputEvent::Undefined:
1144 default:
1145 return NPEventType_Undefined;
1146 }
1147 }
1148
1149 void BuildKeyEvent(const WebInputEvent* event, NPPepperEvent* npevent) {
1150 const WebKeyboardEvent* key_event =
1151 reinterpret_cast<const WebKeyboardEvent*>(event);
1152 npevent->u.key.modifier = key_event->modifiers;
1153 npevent->u.key.normalizedKeyCode = key_event->windowsKeyCode;
1154 }
1155
1156 void BuildCharEvent(const WebInputEvent* event, NPPepperEvent* npevent) {
1157 const WebKeyboardEvent* key_event =
1158 reinterpret_cast<const WebKeyboardEvent*>(event);
1159 npevent->u.character.modifier = key_event->modifiers;
1160 // For consistency, check that the sizes of the texts agree.
1161 DCHECK(sizeof(npevent->u.character.text) == sizeof(key_event->text));
1162 DCHECK(sizeof(npevent->u.character.unmodifiedText) ==
1163 sizeof(key_event->unmodifiedText));
1164 for (size_t i = 0; i < WebKeyboardEvent::textLengthCap; ++i) {
1165 npevent->u.character.text[i] = key_event->text[i];
1166 npevent->u.character.unmodifiedText[i] = key_event->unmodifiedText[i];
1167 }
1168 }
1169
1170 void BuildMouseEvent(const WebInputEvent* event, NPPepperEvent* npevent) {
1171 const WebMouseEvent* mouse_event =
1172 reinterpret_cast<const WebMouseEvent*>(event);
1173 npevent->u.mouse.modifier = mouse_event->modifiers;
1174 npevent->u.mouse.button = mouse_event->button;
1175 npevent->u.mouse.x = mouse_event->x;
1176 npevent->u.mouse.y = mouse_event->y;
1177 npevent->u.mouse.clickCount = mouse_event->clickCount;
1178 }
1179
1180 void BuildMouseWheelEvent(const WebInputEvent* event, NPPepperEvent* npevent) {
1181 const WebMouseWheelEvent* mouse_wheel_event =
1182 reinterpret_cast<const WebMouseWheelEvent*>(event);
1183 npevent->u.wheel.modifier = mouse_wheel_event->modifiers;
1184 npevent->u.wheel.deltaX = mouse_wheel_event->deltaX;
1185 npevent->u.wheel.deltaY = mouse_wheel_event->deltaY;
1186 npevent->u.wheel.wheelTicksX = mouse_wheel_event->wheelTicksX;
1187 npevent->u.wheel.wheelTicksY = mouse_wheel_event->wheelTicksY;
1188 npevent->u.wheel.scrollByPage = mouse_wheel_event->scrollByPage;
1189 }
1190 } // namespace
1191
1192 bool WebPluginDelegatePepper::HandleInputEvent(const WebInputEvent& event,
1193 WebCursorInfo* cursor_info) {
1194 NPPepperEvent npevent;
1195
1196 npevent.type = ConvertEventTypes(event.type);
1197 npevent.size = sizeof(npevent);
1198 npevent.timeStampSeconds = event.timeStampSeconds;
1199 switch (npevent.type) {
1200 case NPEventType_Undefined:
1201 return false;
1202 case NPEventType_MouseDown:
1203 case NPEventType_MouseUp:
1204 case NPEventType_MouseMove:
1205 case NPEventType_MouseEnter:
1206 case NPEventType_MouseLeave:
1207 BuildMouseEvent(&event, &npevent);
1208 break;
1209 case NPEventType_MouseWheel:
1210 BuildMouseWheelEvent(&event, &npevent);
1211 break;
1212 case NPEventType_RawKeyDown:
1213 case NPEventType_KeyDown:
1214 case NPEventType_KeyUp:
1215 BuildKeyEvent(&event, &npevent);
1216 break;
1217 case NPEventType_Char:
1218 BuildCharEvent(&event, &npevent);
1219 break;
1220 case NPEventType_Minimize:
1221 case NPEventType_Focus:
1222 case NPEventType_Device:
1223 // NOTIMPLEMENTED();
1224 break;
1225 }
1226 bool rv = instance()->NPP_HandleEvent(&npevent) != 0;
1227 if (cursor_.get())
1228 *cursor_info = *cursor_;
1229 return rv;
1230 }
1231
1232 bool WebPluginDelegatePepper::CalculatePrintedPageDimensions(
1233 int page_number,
1234 NPPPrintExtensions* print_extensions,
1235 gfx::Size* page_dimensions) {
1236 int32 width_in_pixels = 0;
1237 int32 height_in_pixels = 0;
1238 NPError err = print_extensions->getRasterDimensions(
1239 instance()->npp(), page_number, &width_in_pixels, &height_in_pixels);
1240 if (err != NPERR_NO_ERROR)
1241 return false;
1242
1243 DCHECK(width_in_pixels && height_in_pixels);
1244 page_dimensions->SetSize(width_in_pixels, height_in_pixels);
1245 return true;
1246 }
1247
1248 NPPPrintExtensions* WebPluginDelegatePepper::GetPrintExtensions() {
1249 NPPPrintExtensions* ret = NULL;
1250 NPPExtensions* extensions = NULL;
1251 instance()->NPP_GetValue(NPPVPepperExtensions, &extensions);
1252 if (extensions && extensions->getPrintExtensions)
1253 ret = extensions->getPrintExtensions(instance()->npp());
1254 return ret;
1255 }
1256
1257 NPPFindExtensions* WebPluginDelegatePepper::GetFindExtensions() {
1258 NPPFindExtensions* ret = NULL;
1259 NPPExtensions* extensions = NULL;
1260 instance()->NPP_GetValue(NPPVPepperExtensions, &extensions);
1261 if (extensions && extensions->getFindExtensions)
1262 ret = extensions->getFindExtensions(instance()->npp());
1263 return ret;
1264 }
1265
1266 #if defined(OS_WIN)
1267 bool WebPluginDelegatePepper::DrawJPEGToPlatformDC(
1268 const SkBitmap& bitmap,
1269 const gfx::Rect& printable_area,
1270 WebKit::WebCanvas* canvas) {
1271 skia::VectorPlatformDevice& device =
1272 static_cast<skia::VectorPlatformDevice&>(
1273 canvas->getTopPlatformDevice());
1274 HDC dc = device.getBitmapDC();
1275 // TODO(sanjeevr): This is a temporary hack. If we output a JPEG
1276 // to the EMF, the EnumEnhMetaFile call fails in the browser
1277 // process. The failure also happens if we output nothing here.
1278 // We need to investigate the reason for this failure and fix it.
1279 // In the meantime this temporary hack of drawing an empty
1280 // rectangle in the DC gets us by.
1281 Rectangle(dc, 0, 0, 0, 0);
1282
1283 // Ideally we should add JPEG compression to the VectorPlatformDevice class
1284 // However, Skia currently has no JPEG compression code and we cannot
1285 // depend on gfx/jpeg_codec.h in Skia. So we do the compression here.
1286 SkAutoLockPixels lock(bitmap);
1287 DCHECK(bitmap.getConfig() == SkBitmap::kARGB_8888_Config);
1288 const uint32_t* pixels =
1289 static_cast<const uint32_t*>(bitmap.getPixels());
1290 std::vector<unsigned char> compressed_image;
1291 base::TimeTicks start_time = base::TimeTicks::Now();
1292 bool encoded = gfx::JPEGCodec::Encode(
1293 reinterpret_cast<const unsigned char*>(pixels),
1294 gfx::JPEGCodec::FORMAT_BGRA, bitmap.width(), bitmap.height(),
1295 static_cast<int>(bitmap.rowBytes()), 100, &compressed_image);
1296 UMA_HISTOGRAM_TIMES("PepperPluginPrint.RasterBitmapCompressTime",
1297 base::TimeTicks::Now() - start_time);
1298 if (!encoded) {
1299 NOTREACHED();
1300 return false;
1301 }
1302 BITMAPINFOHEADER bmi = {0};
1303 gfx::CreateBitmapHeader(bitmap.width(), bitmap.height(), &bmi);
1304 bmi.biCompression = BI_JPEG;
1305 bmi.biSizeImage = compressed_image.size();
1306 bmi.biHeight = -bmi.biHeight;
1307 StretchDIBits(dc, printable_area.x(), printable_area.y(),
1308 printable_area.width(), printable_area.height(),
1309 0, 0, bitmap.width(), bitmap.height(),
1310 &compressed_image.front(),
1311 reinterpret_cast<const BITMAPINFO*>(&bmi),
1312 DIB_RGB_COLORS, SRCCOPY);
1313 return true;
1314 }
1315 #endif // OS_WIN
1316
1317 #if defined(OS_MACOSX)
1318 void WebPluginDelegatePepper::DrawSkBitmapToCanvas(
1319 const SkBitmap& bitmap, WebKit::WebCanvas* canvas,
1320 const gfx::Rect& dest_rect,
1321 int canvas_height) {
1322 SkAutoLockPixels lock(bitmap);
1323 DCHECK(bitmap.getConfig() == SkBitmap::kARGB_8888_Config);
1324 base::mac::ScopedCFTypeRef<CGDataProviderRef> data_provider(
1325 CGDataProviderCreateWithData(
1326 NULL, bitmap.getAddr32(0, 0),
1327 bitmap.rowBytes() * bitmap.height(), NULL));
1328 base::mac::ScopedCFTypeRef<CGImageRef> image(
1329 CGImageCreate(
1330 bitmap.width(), bitmap.height(),
1331 8, 32, bitmap.rowBytes(),
1332 base::mac::GetSystemColorSpace(),
1333 kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
1334 data_provider, NULL, false, kCGRenderingIntentDefault));
1335
1336 // Flip the transform
1337 CGContextSaveGState(canvas);
1338 CGContextTranslateCTM(canvas, 0, canvas_height);
1339 CGContextScaleCTM(canvas, 1.0, -1.0);
1340
1341 CGRect bounds;
1342 bounds.origin.x = dest_rect.x();
1343 bounds.origin.y = canvas_height - dest_rect.y() - dest_rect.height();
1344 bounds.size.width = dest_rect.width();
1345 bounds.size.height = dest_rect.height();
1346
1347 CGContextDrawImage(canvas, bounds, image);
1348 CGContextRestoreGState(canvas);
1349 }
1350 #endif // defined(OS_MACOSX)
OLDNEW
« no previous file with comments | « chrome/renderer/webplugin_delegate_pepper.h ('k') | gpu/demos/demos.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698