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

Side by Side Diff: chrome/renderer/pepper/pepper_pdf_host.cc

Issue 13004012: Implement the host side of the PPB_PDF proxy. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/renderer/pepper/pepper_pdf_host.h"
6
7 #include "base/utf_string_conversions.h"
8 #include "chrome/common/render_messages.h"
9 #include "chrome/renderer/printing/print_web_view_helper.h"
10 #include "content/public/renderer/render_thread.h"
11 #include "content/public/renderer/render_view.h"
12 #include "content/public/renderer/renderer_ppapi_host.h"
13 #include "grit/webkit_resources.h"
14 #include "grit/webkit_strings.h"
15 #include "ppapi/host/dispatch_host_message.h"
16 #include "ppapi/host/host_message_context.h"
17 #include "ppapi/host/ppapi_host.h"
18 #include "ppapi/proxy/host_dispatcher.h"
19 #include "ppapi/proxy/ppapi_messages.h"
20 #include "ppapi/proxy/ppb_image_data_proxy.h"
21 #include "ppapi/shared_impl/scoped_pp_resource.h"
22 #include "ppapi/thunk/enter.h"
23 #include "skia/ext/platform_canvas.h"
24 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
25 #include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h"
26 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
27 #include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginContainer.h"
28 #include "ui/base/l10n/l10n_util.h"
29 #include "ui/base/layout.h"
30 #include "ui/base/resource/resource_bundle.h"
31 #include "ui/gfx/image/image_skia.h"
32 #include "ui/gfx/image/image_skia_rep.h"
33 #include "ui/gfx/point.h"
34 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
35 #include "webkit/plugins/ppapi/ppb_image_data_impl.h"
36
37 using webkit::ppapi::PluginInstance;
38
39 namespace chrome {
40
41 namespace {
42
43 struct ResourceImageInfo {
44 PP_ResourceImage pp_id;
45 int res_id;
46 };
47
48 static const ResourceImageInfo kResourceImageMap[] = {
49 { PP_RESOURCEIMAGE_PDF_BUTTON_FTP, IDR_PDF_BUTTON_FTP },
50 { PP_RESOURCEIMAGE_PDF_BUTTON_FTP_HOVER, IDR_PDF_BUTTON_FTP_HOVER },
51 { PP_RESOURCEIMAGE_PDF_BUTTON_FTP_PRESSED, IDR_PDF_BUTTON_FTP_PRESSED },
52 { PP_RESOURCEIMAGE_PDF_BUTTON_FTW, IDR_PDF_BUTTON_FTW },
53 { PP_RESOURCEIMAGE_PDF_BUTTON_FTW_HOVER, IDR_PDF_BUTTON_FTW_HOVER },
54 { PP_RESOURCEIMAGE_PDF_BUTTON_FTW_PRESSED, IDR_PDF_BUTTON_FTW_PRESSED },
55 { PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMIN_END, IDR_PDF_BUTTON_ZOOMIN_END },
56 { PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMIN_END_HOVER,
57 IDR_PDF_BUTTON_ZOOMIN_END_HOVER },
58 { PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMIN_END_PRESSED,
59 IDR_PDF_BUTTON_ZOOMIN_END_PRESSED },
60 { PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMIN, IDR_PDF_BUTTON_ZOOMIN },
61 { PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMIN_HOVER, IDR_PDF_BUTTON_ZOOMIN_HOVER },
62 { PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMIN_PRESSED, IDR_PDF_BUTTON_ZOOMIN_PRESSED },
63 { PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMOUT, IDR_PDF_BUTTON_ZOOMOUT },
64 { PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMOUT_HOVER, IDR_PDF_BUTTON_ZOOMOUT_HOVER },
65 { PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMOUT_PRESSED,
66 IDR_PDF_BUTTON_ZOOMOUT_PRESSED },
67 { PP_RESOURCEIMAGE_PDF_BUTTON_SAVE, IDR_PDF_BUTTON_SAVE },
68 { PP_RESOURCEIMAGE_PDF_BUTTON_SAVE_HOVER, IDR_PDF_BUTTON_SAVE_HOVER },
69 { PP_RESOURCEIMAGE_PDF_BUTTON_SAVE_PRESSED, IDR_PDF_BUTTON_SAVE_PRESSED },
70 { PP_RESOURCEIMAGE_PDF_BUTTON_PRINT, IDR_PDF_BUTTON_PRINT },
71 { PP_RESOURCEIMAGE_PDF_BUTTON_PRINT_HOVER, IDR_PDF_BUTTON_PRINT_HOVER },
72 { PP_RESOURCEIMAGE_PDF_BUTTON_PRINT_PRESSED, IDR_PDF_BUTTON_PRINT_PRESSED },
73 { PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_0, IDR_PDF_THUMBNAIL_0 },
74 { PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_1, IDR_PDF_THUMBNAIL_1 },
75 { PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_2, IDR_PDF_THUMBNAIL_2 },
76 { PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_3, IDR_PDF_THUMBNAIL_3 },
77 { PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_4, IDR_PDF_THUMBNAIL_4 },
78 { PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_5, IDR_PDF_THUMBNAIL_5 },
79 { PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_6, IDR_PDF_THUMBNAIL_6 },
80 { PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_7, IDR_PDF_THUMBNAIL_7 },
81 { PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_8, IDR_PDF_THUMBNAIL_8 },
82 { PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_9, IDR_PDF_THUMBNAIL_9 },
83 { PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_NUM_BACKGROUND,
84 IDR_PDF_THUMBNAIL_NUM_BACKGROUND },
85 { PP_RESOURCEIMAGE_PDF_PROGRESS_BAR_0, IDR_PDF_PROGRESS_BAR_0 },
86 { PP_RESOURCEIMAGE_PDF_PROGRESS_BAR_1, IDR_PDF_PROGRESS_BAR_1 },
87 { PP_RESOURCEIMAGE_PDF_PROGRESS_BAR_2, IDR_PDF_PROGRESS_BAR_2 },
88 { PP_RESOURCEIMAGE_PDF_PROGRESS_BAR_3, IDR_PDF_PROGRESS_BAR_3 },
89 { PP_RESOURCEIMAGE_PDF_PROGRESS_BAR_4, IDR_PDF_PROGRESS_BAR_4 },
90 { PP_RESOURCEIMAGE_PDF_PROGRESS_BAR_5, IDR_PDF_PROGRESS_BAR_5 },
91 { PP_RESOURCEIMAGE_PDF_PROGRESS_BAR_6, IDR_PDF_PROGRESS_BAR_6 },
92 { PP_RESOURCEIMAGE_PDF_PROGRESS_BAR_7, IDR_PDF_PROGRESS_BAR_7 },
93 { PP_RESOURCEIMAGE_PDF_PROGRESS_BAR_8, IDR_PDF_PROGRESS_BAR_8 },
94 { PP_RESOURCEIMAGE_PDF_PROGRESS_BAR_BACKGROUND,
95 IDR_PDF_PROGRESS_BAR_BACKGROUND },
96 { PP_RESOURCEIMAGE_PDF_PAGE_INDICATOR_BACKGROUND,
97 IDR_PDF_PAGE_INDICATOR_BACKGROUND },
98 { PP_RESOURCEIMAGE_PDF_PAGE_DROPSHADOW, IDR_PDF_PAGE_DROPSHADOW },
99 { PP_RESOURCEIMAGE_PDF_PAN_SCROLL_ICON, IDR_PAN_SCROLL_ICON },
100 };
101
102 // Valid strings for user metrics actions.
103 static const char* kValidUserMetricsActions[] = {
104 "PDF.PrintPage",
105 "PDF.ZoomFromBrowser",
106 "PDF.FitToPageButton",
107 "PDF.FitToWidthButton",
108 "PDF.ZoomOutButton",
109 "PDF.ZoomInButton",
110 "PDF.SaveButton",
111 "PDF.PrintButton",
112 "PDF.LoadSuccess",
113 "PDF.LoadFailure",
114 "PDF.PreviewDocumentLoadFailure",
115 };
116
117 } // namespace
118
119 PepperPDFHost::PepperPDFHost(
120 content::RendererPpapiHost* host,
121 PP_Instance instance,
122 PP_Resource resource)
123 : ppapi::host::ResourceHost(host->GetPpapiHost(), instance, resource),
124 host_(host) {
125 }
126
127 PepperPDFHost::~PepperPDFHost() {
128 }
129
130 int32_t PepperPDFHost::OnResourceMessageReceived(
131 const IPC::Message& msg,
132 ppapi::host::HostMessageContext* context) {
133 IPC_BEGIN_MESSAGE_MAP(PepperPDFHost, msg)
134 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_PDF_GetLocalizedString,
135 OnHostMsgGetLocalizedString)
136 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_PDF_DidStartLoading,
137 OnHostMsgDidStartLoading)
138 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_PDF_DidStopLoading,
139 OnHostMsgDidStopLoading)
140 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_PDF_UserMetricsRecordAction,
141 OnHostMsgUserMetricsRecordAction)
142 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_PDF_HasUnsupportedFeature,
143 OnHostMsgHasUnsupportedFeature)
144 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_PDF_Print,
145 OnHostMsgPrint)
146 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_PDF_SaveAs,
147 OnHostMsgSaveAs)
148 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_PDF_GetResourceImage,
149 OnHostMsgGetResourceImage)
150 IPC_END_MESSAGE_MAP()
151 return PP_ERROR_FAILED;
152 }
153
154 int32_t PepperPDFHost::OnHostMsgGetLocalizedString(
155 ppapi::host::HostMessageContext* context,
156 int string_id) {
157 PP_ResourceString resource_string_id =
158 static_cast<PP_ResourceString>(string_id);
yzshen1 2013/04/03 18:32:39 If we pass |string_id| as int to be 'safe', then w
raymes 2013/04/03 23:18:21 I just changed it to send the enum value.
yzshen1 2013/04/04 01:30:07 There was a discussion about passing enum values o
159 std::string rv;
160 if (resource_string_id == PP_RESOURCESTRING_PDFGETPASSWORD) {
161 rv = UTF16ToUTF8(l10n_util::GetStringUTF16(IDS_PDF_NEED_PASSWORD));
162 } else if (resource_string_id == PP_RESOURCESTRING_PDFLOADING) {
163 rv = UTF16ToUTF8(l10n_util::GetStringUTF16(IDS_PDF_PAGE_LOADING));
164 } else if (resource_string_id == PP_RESOURCESTRING_PDFLOAD_FAILED) {
165 rv = UTF16ToUTF8(l10n_util::GetStringUTF16(IDS_PDF_PAGE_LOAD_FAILED));
166 } else if (resource_string_id == PP_RESOURCESTRING_PDFPROGRESSLOADING) {
167 rv = UTF16ToUTF8(l10n_util::GetStringUTF16(IDS_PDF_PROGRESS_LOADING));
168 } else {
169 NOTREACHED();
170 return PP_ERROR_FAILED;
171 }
172
173 context->reply_msg = PpapiPluginMsg_PDF_GetLocalizedStringReply(rv);
174 return PP_OK;
175 }
176
177 int32_t PepperPDFHost::OnHostMsgDidStartLoading(
178 ppapi::host::HostMessageContext* context) {
179 PluginInstance* instance = host_->GetPluginInstance(pp_instance());
180 if (!instance)
181 return PP_ERROR_FAILED;
182 instance->delegate()->DidStartLoading();
183 return PP_OK;
184 }
185
186 int32_t PepperPDFHost::OnHostMsgDidStopLoading(
187 ppapi::host::HostMessageContext* context) {
188 PluginInstance* instance = host_->GetPluginInstance(pp_instance());
189 if (!instance)
190 return PP_ERROR_FAILED;
191 instance->delegate()->DidStopLoading();
192 return PP_OK;
193 }
194
195 int32_t PepperPDFHost::OnHostMsgSetContentRestriction(
196 ppapi::host::HostMessageContext* context, int restrictions) {
197 PluginInstance* instance = host_->GetPluginInstance(pp_instance());
198 if (!instance)
199 return PP_ERROR_FAILED;
200 instance->delegate()->SetContentRestriction(restrictions);
201 return PP_OK;
202 }
203
204 int32_t PepperPDFHost::OnHostMsgUserMetricsRecordAction(
205 ppapi::host::HostMessageContext* context,
206 std::string action) {
207 bool valid = false;
208 for (size_t i = 0; i < arraysize(kResourceImageMap); ++i) {
209 if (action == kValidUserMetricsActions[i]) {
210 valid = true;
211 break;
212 }
213 }
214 if (!valid) {
215 NOTREACHED();
216 return PP_ERROR_FAILED;
217 }
218 content::RenderThread::Get()->RecordUserMetrics(action);
219 return PP_OK;
220 }
221
222 int32_t PepperPDFHost::OnHostMsgHasUnsupportedFeature(
223 ppapi::host::HostMessageContext* context) {
224 PluginInstance* instance = host_->GetPluginInstance(pp_instance());
225 if (!instance)
226 return PP_ERROR_FAILED;
227
228 // Only want to show an info bar if the pdf is the whole tab.
229 if (!instance->IsFullPagePlugin())
230 return PP_OK;
231
232 WebKit::WebView* view =
233 instance->container()->element().document().frame()->view();
234 content::RenderView* render_view = content::RenderView::FromWebView(view);
235 render_view->Send(new ChromeViewHostMsg_PDFHasUnsupportedFeature(
236 render_view->GetRoutingID()));
237 return PP_OK;
238 }
239
240 int32_t PepperPDFHost::OnHostMsgPrint(
241 ppapi::host::HostMessageContext* context) {
242 #if defined(ENABLE_PRINTING)
243 PluginInstance* instance = host_->GetPluginInstance(pp_instance());
244 if (!instance)
245 return PP_ERROR_FAILED;
246
247 WebKit::WebElement element = instance->container()->element();
248 WebKit::WebView* view = element.document().frame()->view();
249 content::RenderView* render_view = content::RenderView::FromWebView(view);
250
251 using printing::PrintWebViewHelper;
252 PrintWebViewHelper* print_view_helper = PrintWebViewHelper::Get(render_view);
253 if (print_view_helper) {
254 print_view_helper->PrintNode(element);
255 return PP_OK;
256 }
257 #endif
258 return PP_ERROR_FAILED;
259 }
260
261 int32_t PepperPDFHost::OnHostMsgSaveAs(
262 ppapi::host::HostMessageContext* context) {
263 PluginInstance* instance = host_->GetPluginInstance(pp_instance());
264 if (!instance)
265 return PP_ERROR_FAILED;
266 instance->delegate()->SaveURLAs(instance->plugin_url());
267 return PP_OK;
268 }
269
270 int32_t PepperPDFHost::OnHostMsgGetResourceImage(
271 ppapi::host::HostMessageContext* context,
272 int image_id,
273 float scale) {
274 int res_id = 0;
275 for (size_t i = 0; i < arraysize(kResourceImageMap); ++i) {
276 if (kResourceImageMap[i].pp_id ==
277 static_cast<PP_ResourceImage>(image_id)) {
278 res_id = kResourceImageMap[i].res_id;
279 break;
280 }
281 }
282 if (res_id == 0)
283 return PP_ERROR_FAILED;
284
285 ui::ScaleFactor scale_factor = ui::GetScaleFactorFromScale(scale);
286
287 gfx::ImageSkia* res_image_skia =
288 ResourceBundle::GetSharedInstance().GetImageSkiaNamed(res_id);
289
290 if (!res_image_skia)
291 return PP_ERROR_FAILED;
292
293 gfx::ImageSkiaRep image_skia_rep = res_image_skia->GetRepresentation(
294 scale_factor);
295
296 if (image_skia_rep.is_null() || image_skia_rep.scale_factor() != scale_factor)
297 return PP_ERROR_FAILED;
298
299 PP_Size pp_size;
300 pp_size.width = image_skia_rep.pixel_width();
301 pp_size.height = image_skia_rep.pixel_height();
302
303 ppapi::HostResource host_resource;
304 std::string image_data_desc;
305 ppapi::proxy::ImageHandle image_handle;
306 uint32_t byte_count = 0;
307 bool success = CreateImageData(
308 pp_instance(),
309 webkit::ppapi::PPB_ImageData_Impl::GetNativeImageDataFormat(),
310 pp_size,
311 image_skia_rep.sk_bitmap(),
312 &host_resource,
313 &image_data_desc,
314 &image_handle,
315 &byte_count);
316 ppapi::ScopedPPResource image_data_resource(
317 ppapi::ScopedPPResource::PassRef(), host_resource.host_resource());
318 if (!success)
319 return PP_ERROR_FAILED;
320
321 ppapi::host::ReplyMessageContext reply_context =
322 context->MakeReplyMessageContext();
323 // This mess of #defines is needed to translate between ImageHandles and
324 // SerializedHandles. This is something that should be addressed with a
325 // refactoring of PPB_ImageData.
326 #if defined(OS_WIN)
327 ppapi::proxy::SerializedHandle serialized_handle;
328 PpapiPluginMsg_PDF_GetResourceImageReply reply_msg(host_resource,
329 image_data_desc,
330 0);
331 ppapi::proxy::HostDispatcher* dispatcher =
332 ppapi::proxy::HostDispatcher::GetForInstance(pp_instance());
333 if (!dispatcher)
334 return PP_ERROR_FAILED;
335 serialized_handle.set_shmem(
336 dispatcher->ShareHandleWithRemote(image_handle, false), byte_count);
337 reply_context.params.AppendHandle(serialized_handle);
338 #elif defined(OS_MACOSX)
339 ppapi::proxy::SerializedHandle serialized_handle;
340 PpapiPluginMsg_PDF_GetResourceImageReply reply_msg(host_resource,
341 image_data_desc,
342 0);
343 serialized_handle.set_shmem(image_handle, byte_count);
344 reply_context.params.AppendHandle(serialized_handle);
345 #elif defined(OS_LINUX)
346 // For linux, we pass the SysV shared memory key in the message.
347 PpapiPluginMsg_PDF_GetResourceImageReply reply_msg(host_resource,
348 image_data_desc,
349 image_handle);
350 #else
351 #error Not implemented.
352 #endif
353
354 SendReply(reply_context, reply_msg);
355
356 // Keep a reference to the resource only if the function succeeds.
357 image_data_resource.Release();
358
359 return PP_OK_COMPLETIONPENDING;
360 }
361
362 // TODO(raymes): This function is mainly copied from ppb_image_data_proxy.cc.
363 // It's a mess and needs to be fixed in several ways but this is better done
364 // when we refactor PPB_ImageData. On success, the serialized handle will be
365 // non-null.
366 bool PepperPDFHost::CreateImageData(
367 PP_Instance instance,
368 int32_t format,
yzshen1 2013/04/03 18:32:39 Why not making it PP_ImageDataFormat directly?
raymes 2013/04/03 23:18:21 Done.
369 const PP_Size& size,
370 const SkBitmap& pixels_to_write,
371 ppapi::HostResource* result,
372 std::string* out_image_data_desc,
373 ppapi::proxy::ImageHandle* out_image_handle,
374 uint32_t* out_byte_count) {
375 // Create the resource.
376 ppapi::thunk::EnterResourceCreation enter(instance);
377 if (enter.failed())
378 return false;
379
380 PP_Resource resource = enter.functions()->CreateImageData(
381 instance, static_cast<PP_ImageDataFormat>(format), size, PP_FALSE);
382 if (!resource)
383 return false;
384 result->SetHostResource(instance, resource);
385
386 // Write the image to the resource shared memory.
387 ppapi::thunk::EnterResourceNoLock<ppapi::thunk::PPB_ImageData_API>
388 enter_resource(resource, false);
389 if (enter_resource.failed())
390 return false;
391
392 webkit::ppapi::PPB_ImageData_Impl* image_data =
393 static_cast<webkit::ppapi::PPB_ImageData_Impl*>(enter_resource.object());
394 webkit::ppapi::ImageDataAutoMapper mapper(image_data);
395 if (!mapper.is_valid())
396 return false;
397
398 skia::PlatformCanvas* canvas = image_data->GetPlatformCanvas();
399 // Note: Do not skBitmap::copyTo the canvas bitmap directly because it will
400 // ignore the allocated pixels in shared memory and re-allocate a new buffer.
401 canvas->writePixels(pixels_to_write, 0, 0);
402
403 // Get the image description, it's just serialized as a string.
404 PP_ImageDataDesc desc;
405 if (enter_resource.object()->Describe(&desc) == PP_TRUE) {
406 out_image_data_desc->resize(sizeof(PP_ImageDataDesc));
407 memcpy(&(*out_image_data_desc)[0], &desc, sizeof(PP_ImageDataDesc));
408 } else {
409 return false;
410 }
411
412 // Get the shared memory handle.
413 int32_t handle = 0;
414 if (enter_resource.object()->GetSharedMemory(
415 &handle, out_byte_count) != PP_OK) {
416 return false;
417 }
418
419 *out_image_handle = ppapi::proxy::ImageData::HandleFromInt(handle);
420 return true;
421 }
422
423 } // namespace chrome
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698