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

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
« no previous file with comments | « chrome/renderer/pepper/pepper_pdf_host.h ('k') | chrome/test/ppapi/ppapi_browsertest.cc » ('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) 2013 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 PP_ResourceString string_id) {
157 std::string rv;
158 if (string_id == PP_RESOURCESTRING_PDFGETPASSWORD) {
159 rv = UTF16ToUTF8(l10n_util::GetStringUTF16(IDS_PDF_NEED_PASSWORD));
160 } else if (string_id == PP_RESOURCESTRING_PDFLOADING) {
161 rv = UTF16ToUTF8(l10n_util::GetStringUTF16(IDS_PDF_PAGE_LOADING));
162 } else if (string_id == PP_RESOURCESTRING_PDFLOAD_FAILED) {
163 rv = UTF16ToUTF8(l10n_util::GetStringUTF16(IDS_PDF_PAGE_LOAD_FAILED));
164 } else if (string_id == PP_RESOURCESTRING_PDFPROGRESSLOADING) {
165 rv = UTF16ToUTF8(l10n_util::GetStringUTF16(IDS_PDF_PROGRESS_LOADING));
166 } else {
167 NOTREACHED();
168 return PP_ERROR_FAILED;
169 }
170
171 context->reply_msg = PpapiPluginMsg_PDF_GetLocalizedStringReply(rv);
172 return PP_OK;
173 }
174
175 int32_t PepperPDFHost::OnHostMsgDidStartLoading(
176 ppapi::host::HostMessageContext* context) {
177 PluginInstance* instance = host_->GetPluginInstance(pp_instance());
178 if (!instance)
179 return PP_ERROR_FAILED;
180 instance->delegate()->DidStartLoading();
181 return PP_OK;
182 }
183
184 int32_t PepperPDFHost::OnHostMsgDidStopLoading(
185 ppapi::host::HostMessageContext* context) {
186 PluginInstance* instance = host_->GetPluginInstance(pp_instance());
187 if (!instance)
188 return PP_ERROR_FAILED;
189 instance->delegate()->DidStopLoading();
190 return PP_OK;
191 }
192
193 int32_t PepperPDFHost::OnHostMsgSetContentRestriction(
194 ppapi::host::HostMessageContext* context, int restrictions) {
195 PluginInstance* instance = host_->GetPluginInstance(pp_instance());
196 if (!instance)
197 return PP_ERROR_FAILED;
198 instance->delegate()->SetContentRestriction(restrictions);
199 return PP_OK;
200 }
201
202 int32_t PepperPDFHost::OnHostMsgUserMetricsRecordAction(
203 ppapi::host::HostMessageContext* context,
204 const std::string& action) {
205 bool valid = false;
206 for (size_t i = 0; i < arraysize(kResourceImageMap); ++i) {
207 if (action == kValidUserMetricsActions[i]) {
208 valid = true;
209 break;
210 }
211 }
212 if (!valid) {
213 NOTREACHED();
214 return PP_ERROR_FAILED;
215 }
216 content::RenderThread::Get()->RecordUserMetrics(action);
217 return PP_OK;
218 }
219
220 int32_t PepperPDFHost::OnHostMsgHasUnsupportedFeature(
221 ppapi::host::HostMessageContext* context) {
222 PluginInstance* instance = host_->GetPluginInstance(pp_instance());
223 if (!instance)
224 return PP_ERROR_FAILED;
225
226 // Only want to show an info bar if the pdf is the whole tab.
227 if (!instance->IsFullPagePlugin())
228 return PP_OK;
229
230 WebKit::WebView* view =
231 instance->container()->element().document().frame()->view();
232 content::RenderView* render_view = content::RenderView::FromWebView(view);
233 render_view->Send(new ChromeViewHostMsg_PDFHasUnsupportedFeature(
234 render_view->GetRoutingID()));
235 return PP_OK;
236 }
237
238 int32_t PepperPDFHost::OnHostMsgPrint(
239 ppapi::host::HostMessageContext* context) {
240 #if defined(ENABLE_PRINTING)
241 PluginInstance* instance = host_->GetPluginInstance(pp_instance());
242 if (!instance)
243 return PP_ERROR_FAILED;
244
245 WebKit::WebElement element = instance->container()->element();
246 WebKit::WebView* view = element.document().frame()->view();
247 content::RenderView* render_view = content::RenderView::FromWebView(view);
248
249 using printing::PrintWebViewHelper;
250 PrintWebViewHelper* print_view_helper = PrintWebViewHelper::Get(render_view);
251 if (print_view_helper) {
252 print_view_helper->PrintNode(element);
253 return PP_OK;
254 }
255 #endif
256 return PP_ERROR_FAILED;
257 }
258
259 int32_t PepperPDFHost::OnHostMsgSaveAs(
260 ppapi::host::HostMessageContext* context) {
261 PluginInstance* instance = host_->GetPluginInstance(pp_instance());
262 if (!instance)
263 return PP_ERROR_FAILED;
264 instance->delegate()->SaveURLAs(instance->plugin_url());
265 return PP_OK;
266 }
267
268 int32_t PepperPDFHost::OnHostMsgGetResourceImage(
269 ppapi::host::HostMessageContext* context,
270 PP_ResourceImage image_id,
271 float scale) {
272 int res_id = 0;
273 for (size_t i = 0; i < arraysize(kResourceImageMap); ++i) {
274 if (kResourceImageMap[i].pp_id == image_id) {
275 res_id = kResourceImageMap[i].res_id;
276 break;
277 }
278 }
279 if (res_id == 0)
280 return PP_ERROR_FAILED;
281
282 ui::ScaleFactor scale_factor = ui::GetScaleFactorFromScale(scale);
283
284 gfx::ImageSkia* res_image_skia =
285 ResourceBundle::GetSharedInstance().GetImageSkiaNamed(res_id);
286
287 if (!res_image_skia)
288 return PP_ERROR_FAILED;
289
290 gfx::ImageSkiaRep image_skia_rep = res_image_skia->GetRepresentation(
291 scale_factor);
292
293 if (image_skia_rep.is_null() || image_skia_rep.scale_factor() != scale_factor)
294 return PP_ERROR_FAILED;
295
296 PP_Size pp_size;
297 pp_size.width = image_skia_rep.pixel_width();
298 pp_size.height = image_skia_rep.pixel_height();
299
300 ppapi::HostResource host_resource;
301 std::string image_data_desc;
302 ppapi::proxy::ImageHandle image_handle;
303 uint32_t byte_count = 0;
304 bool success = CreateImageData(
305 pp_instance(),
306 webkit::ppapi::PPB_ImageData_Impl::GetNativeImageDataFormat(),
307 pp_size,
308 image_skia_rep.sk_bitmap(),
309 &host_resource,
310 &image_data_desc,
311 &image_handle,
312 &byte_count);
313 ppapi::ScopedPPResource image_data_resource(
314 ppapi::ScopedPPResource::PassRef(), host_resource.host_resource());
315 if (!success)
316 return PP_ERROR_FAILED;
317
318 ppapi::host::ReplyMessageContext reply_context =
319 context->MakeReplyMessageContext();
320 // This mess of #defines is needed to translate between ImageHandles and
321 // SerializedHandles. This is something that should be addressed with a
322 // refactoring of PPB_ImageData.
323 #if defined(OS_WIN)
324 ppapi::proxy::SerializedHandle serialized_handle;
325 PpapiPluginMsg_PDF_GetResourceImageReply reply_msg(host_resource,
326 image_data_desc,
327 0);
328 ppapi::proxy::HostDispatcher* dispatcher =
329 ppapi::proxy::HostDispatcher::GetForInstance(pp_instance());
330 if (!dispatcher)
331 return PP_ERROR_FAILED;
332 serialized_handle.set_shmem(
333 dispatcher->ShareHandleWithRemote(image_handle, false), byte_count);
334 reply_context.params.AppendHandle(serialized_handle);
335 #elif defined(OS_MACOSX)
336 ppapi::proxy::SerializedHandle serialized_handle;
337 PpapiPluginMsg_PDF_GetResourceImageReply reply_msg(host_resource,
338 image_data_desc,
339 0);
340 serialized_handle.set_shmem(image_handle, byte_count);
341 reply_context.params.AppendHandle(serialized_handle);
342 #elif defined(OS_LINUX)
343 // For linux, we pass the SysV shared memory key in the message.
344 PpapiPluginMsg_PDF_GetResourceImageReply reply_msg(host_resource,
345 image_data_desc,
346 image_handle);
347 #else
348 #error Not implemented.
349 #endif
350
351 SendReply(reply_context, reply_msg);
352
353 // Keep a reference to the resource only if the function succeeds.
354 image_data_resource.Release();
355
356 return PP_OK_COMPLETIONPENDING;
357 }
358
359 // TODO(raymes): This function is mainly copied from ppb_image_data_proxy.cc.
360 // It's a mess and needs to be fixed in several ways but this is better done
361 // when we refactor PPB_ImageData. On success, the serialized handle will be
362 // non-null.
363 bool PepperPDFHost::CreateImageData(
364 PP_Instance instance,
365 PP_ImageDataFormat format,
366 const PP_Size& size,
367 const SkBitmap& pixels_to_write,
368 ppapi::HostResource* result,
369 std::string* out_image_data_desc,
370 ppapi::proxy::ImageHandle* out_image_handle,
371 uint32_t* out_byte_count) {
372 // Create the resource.
373 ppapi::thunk::EnterResourceCreation enter(instance);
374 if (enter.failed())
375 return false;
376
377 PP_Resource resource = enter.functions()->CreateImageData(instance, format,
378 size, PP_FALSE);
379 if (!resource)
380 return false;
381 result->SetHostResource(instance, resource);
382
383 // Write the image to the resource shared memory.
384 ppapi::thunk::EnterResourceNoLock<ppapi::thunk::PPB_ImageData_API>
385 enter_resource(resource, false);
386 if (enter_resource.failed())
387 return false;
388
389 webkit::ppapi::PPB_ImageData_Impl* image_data =
390 static_cast<webkit::ppapi::PPB_ImageData_Impl*>(enter_resource.object());
391 webkit::ppapi::ImageDataAutoMapper mapper(image_data);
392 if (!mapper.is_valid())
393 return false;
394
395 skia::PlatformCanvas* canvas = image_data->GetPlatformCanvas();
396 // Note: Do not skBitmap::copyTo the canvas bitmap directly because it will
397 // ignore the allocated pixels in shared memory and re-allocate a new buffer.
398 canvas->writePixels(pixels_to_write, 0, 0);
399
400 // Get the image description, it's just serialized as a string.
401 PP_ImageDataDesc desc;
402 if (enter_resource.object()->Describe(&desc) == PP_TRUE) {
403 out_image_data_desc->resize(sizeof(PP_ImageDataDesc));
404 memcpy(&(*out_image_data_desc)[0], &desc, sizeof(PP_ImageDataDesc));
405 } else {
406 return false;
407 }
408
409 // Get the shared memory handle.
410 int32_t handle = 0;
411 if (enter_resource.object()->GetSharedMemory(
412 &handle, out_byte_count) != PP_OK) {
413 return false;
414 }
415
416 *out_image_handle = ppapi::proxy::ImageData::HandleFromInt(handle);
417 return true;
418 }
419
420 } // namespace chrome
OLDNEW
« no previous file with comments | « chrome/renderer/pepper/pepper_pdf_host.h ('k') | chrome/test/ppapi/ppapi_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698