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.
5 #include "chrome/renderer/pepper/pepper_pdf_host.h"
7 #include "base/strings/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/common/referrer.h"
11 #include "content/public/renderer/pepper_plugin_instance.h"
12 #include "content/public/renderer/render_thread.h"
13 #include "content/public/renderer/render_view.h"
14 #include "content/public/renderer/renderer_ppapi_host.h"
15 #include "grit/webkit_resources.h"
16 #include "grit/webkit_strings.h"
17 #include "ppapi/host/dispatch_host_message.h"
18 #include "ppapi/host/host_message_context.h"
19 #include "ppapi/host/ppapi_host.h"
20 #include "ppapi/proxy/host_dispatcher.h"
21 #include "ppapi/proxy/ppapi_messages.h"
22 #include "ppapi/proxy/ppb_image_data_proxy.h"
23 #include "ppapi/shared_impl/ppb_image_data_shared.h"
24 #include "ppapi/shared_impl/scoped_pp_resource.h"
25 #include "ppapi/thunk/enter.h"
26 #include "ppapi/thunk/ppb_image_data_api.h"
27 #include "skia/ext/platform_canvas.h"
28 #include "third_party/WebKit/public/web/WebDocument.h"
29 #include "third_party/WebKit/public/web/WebElement.h"
30 #include "third_party/WebKit/public/web/WebLocalFrame.h"
31 #include "third_party/WebKit/public/web/WebPluginContainer.h"
32 #include "third_party/WebKit/public/web/WebView.h"
33 #include "third_party/skia/include/core/SkBitmap.h"
34 #include "ui/base/l10n/l10n_util.h"
35 #include "ui/base/layout.h"
36 #include "ui/base/resource/resource_bundle.h"
37 #include "ui/gfx/image/image_skia.h"
38 #include "ui/gfx/image/image_skia_rep.h"
39 #include "ui/gfx/point.h"
43 struct ResourceImageInfo
{
44 PP_ResourceImage pp_id
;
48 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_PRINT_DISABLED
, IDR_PDF_BUTTON_PRINT_DISABLED
},
74 {PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_0
, IDR_PDF_THUMBNAIL_0
},
75 {PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_1
, IDR_PDF_THUMBNAIL_1
},
76 {PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_2
, IDR_PDF_THUMBNAIL_2
},
77 {PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_3
, IDR_PDF_THUMBNAIL_3
},
78 {PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_4
, IDR_PDF_THUMBNAIL_4
},
79 {PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_5
, IDR_PDF_THUMBNAIL_5
},
80 {PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_6
, IDR_PDF_THUMBNAIL_6
},
81 {PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_7
, IDR_PDF_THUMBNAIL_7
},
82 {PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_8
, IDR_PDF_THUMBNAIL_8
},
83 {PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_9
, IDR_PDF_THUMBNAIL_9
},
84 {PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_NUM_BACKGROUND
,
85 IDR_PDF_THUMBNAIL_NUM_BACKGROUND
},
86 {PP_RESOURCEIMAGE_PDF_PROGRESS_BAR_0
, IDR_PDF_PROGRESS_BAR_0
},
87 {PP_RESOURCEIMAGE_PDF_PROGRESS_BAR_1
, IDR_PDF_PROGRESS_BAR_1
},
88 {PP_RESOURCEIMAGE_PDF_PROGRESS_BAR_2
, IDR_PDF_PROGRESS_BAR_2
},
89 {PP_RESOURCEIMAGE_PDF_PROGRESS_BAR_3
, IDR_PDF_PROGRESS_BAR_3
},
90 {PP_RESOURCEIMAGE_PDF_PROGRESS_BAR_4
, IDR_PDF_PROGRESS_BAR_4
},
91 {PP_RESOURCEIMAGE_PDF_PROGRESS_BAR_5
, IDR_PDF_PROGRESS_BAR_5
},
92 {PP_RESOURCEIMAGE_PDF_PROGRESS_BAR_6
, IDR_PDF_PROGRESS_BAR_6
},
93 {PP_RESOURCEIMAGE_PDF_PROGRESS_BAR_7
, IDR_PDF_PROGRESS_BAR_7
},
94 {PP_RESOURCEIMAGE_PDF_PROGRESS_BAR_8
, IDR_PDF_PROGRESS_BAR_8
},
95 {PP_RESOURCEIMAGE_PDF_PROGRESS_BAR_BACKGROUND
,
96 IDR_PDF_PROGRESS_BAR_BACKGROUND
},
97 {PP_RESOURCEIMAGE_PDF_PAGE_INDICATOR_BACKGROUND
,
98 IDR_PDF_PAGE_INDICATOR_BACKGROUND
},
99 {PP_RESOURCEIMAGE_PDF_PAGE_DROPSHADOW
, IDR_PDF_PAGE_DROPSHADOW
},
100 {PP_RESOURCEIMAGE_PDF_PAN_SCROLL_ICON
, IDR_PAN_SCROLL_ICON
}, };
104 PepperPDFHost::PepperPDFHost(content::RendererPpapiHost
* host
,
105 PP_Instance instance
,
106 PP_Resource resource
)
107 : ppapi::host::ResourceHost(host
->GetPpapiHost(), instance
, resource
),
110 PepperPDFHost::~PepperPDFHost() {}
112 int32_t PepperPDFHost::OnResourceMessageReceived(
113 const IPC::Message
& msg
,
114 ppapi::host::HostMessageContext
* context
) {
115 IPC_BEGIN_MESSAGE_MAP(PepperPDFHost
, msg
)
116 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_PDF_GetLocalizedString
,
117 OnHostMsgGetLocalizedString
)
118 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_PDF_DidStartLoading
,
119 OnHostMsgDidStartLoading
)
120 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_PDF_DidStopLoading
,
121 OnHostMsgDidStopLoading
)
122 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_PDF_UserMetricsRecordAction
,
123 OnHostMsgUserMetricsRecordAction
)
124 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_PDF_HasUnsupportedFeature
,
125 OnHostMsgHasUnsupportedFeature
)
126 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_PDF_Print
, OnHostMsgPrint
)
127 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_PDF_SaveAs
, OnHostMsgSaveAs
)
128 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_PDF_GetResourceImage
,
129 OnHostMsgGetResourceImage
)
130 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_PDF_SetSelectedText
,
131 OnHostMsgSetSelectedText
)
132 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_PDF_SetLinkUnderCursor
,
133 OnHostMsgSetLinkUnderCursor
)
134 IPC_END_MESSAGE_MAP()
135 return PP_ERROR_FAILED
;
138 int32_t PepperPDFHost::OnHostMsgGetLocalizedString(
139 ppapi::host::HostMessageContext
* context
,
140 PP_ResourceString string_id
) {
142 if (string_id
== PP_RESOURCESTRING_PDFGETPASSWORD
) {
143 rv
= base::UTF16ToUTF8(l10n_util::GetStringUTF16(IDS_PDF_NEED_PASSWORD
));
144 } else if (string_id
== PP_RESOURCESTRING_PDFLOADING
) {
145 rv
= base::UTF16ToUTF8(l10n_util::GetStringUTF16(IDS_PDF_PAGE_LOADING
));
146 } else if (string_id
== PP_RESOURCESTRING_PDFLOAD_FAILED
) {
147 rv
= base::UTF16ToUTF8(l10n_util::GetStringUTF16(IDS_PDF_PAGE_LOAD_FAILED
));
148 } else if (string_id
== PP_RESOURCESTRING_PDFPROGRESSLOADING
) {
149 rv
= base::UTF16ToUTF8(l10n_util::GetStringUTF16(IDS_PDF_PROGRESS_LOADING
));
152 return PP_ERROR_FAILED
;
155 context
->reply_msg
= PpapiPluginMsg_PDF_GetLocalizedStringReply(rv
);
159 int32_t PepperPDFHost::OnHostMsgDidStartLoading(
160 ppapi::host::HostMessageContext
* context
) {
161 content::PepperPluginInstance
* instance
=
162 host_
->GetPluginInstance(pp_instance());
164 return PP_ERROR_FAILED
;
165 instance
->GetRenderView()->DidStartLoading();
169 int32_t PepperPDFHost::OnHostMsgDidStopLoading(
170 ppapi::host::HostMessageContext
* context
) {
171 content::PepperPluginInstance
* instance
=
172 host_
->GetPluginInstance(pp_instance());
174 return PP_ERROR_FAILED
;
175 instance
->GetRenderView()->DidStopLoading();
179 int32_t PepperPDFHost::OnHostMsgSetContentRestriction(
180 ppapi::host::HostMessageContext
* context
,
182 content::PepperPluginInstance
* instance
=
183 host_
->GetPluginInstance(pp_instance());
185 return PP_ERROR_FAILED
;
186 instance
->GetRenderView()->Send(
187 new ChromeViewHostMsg_PDFUpdateContentRestrictions(
188 instance
->GetRenderView()->GetRoutingID(), restrictions
));
192 int32_t PepperPDFHost::OnHostMsgUserMetricsRecordAction(
193 ppapi::host::HostMessageContext
* context
,
194 const std::string
& action
) {
196 return PP_ERROR_FAILED
;
197 content::RenderThread::Get()->RecordComputedAction(action
);
201 int32_t PepperPDFHost::OnHostMsgHasUnsupportedFeature(
202 ppapi::host::HostMessageContext
* context
) {
203 content::PepperPluginInstance
* instance
=
204 host_
->GetPluginInstance(pp_instance());
206 return PP_ERROR_FAILED
;
208 // Only want to show an info bar if the pdf is the whole tab.
209 if (!instance
->IsFullPagePlugin())
212 blink::WebView
* view
=
213 instance
->GetContainer()->element().document().frame()->view();
214 content::RenderView
* render_view
= content::RenderView::FromWebView(view
);
215 render_view
->Send(new ChromeViewHostMsg_PDFHasUnsupportedFeature(
216 render_view
->GetRoutingID()));
220 int32_t PepperPDFHost::OnHostMsgPrint(
221 ppapi::host::HostMessageContext
* context
) {
222 #if defined(ENABLE_FULL_PRINTING)
223 content::PepperPluginInstance
* instance
=
224 host_
->GetPluginInstance(pp_instance());
226 return PP_ERROR_FAILED
;
228 blink::WebElement element
= instance
->GetContainer()->element();
229 blink::WebView
* view
= element
.document().frame()->view();
230 content::RenderView
* render_view
= content::RenderView::FromWebView(view
);
232 using printing::PrintWebViewHelper
;
233 PrintWebViewHelper
* print_view_helper
= PrintWebViewHelper::Get(render_view
);
234 if (print_view_helper
) {
235 print_view_helper
->PrintNode(element
);
239 return PP_ERROR_FAILED
;
242 int32_t PepperPDFHost::OnHostMsgSaveAs(
243 ppapi::host::HostMessageContext
* context
) {
244 content::PepperPluginInstance
* instance
=
245 host_
->GetPluginInstance(pp_instance());
247 return PP_ERROR_FAILED
;
248 GURL url
= instance
->GetPluginURL();
249 content::RenderView
* render_view
= instance
->GetRenderView();
250 blink::WebLocalFrame
* frame
=
251 render_view
->GetWebView()->mainFrame()->toWebLocalFrame();
252 content::Referrer
referrer(frame
->document().url(),
253 frame
->document().referrerPolicy());
254 render_view
->Send(new ChromeViewHostMsg_PDFSaveURLAs(
255 render_view
->GetRoutingID(), url
, referrer
));
259 int32_t PepperPDFHost::OnHostMsgGetResourceImage(
260 ppapi::host::HostMessageContext
* context
,
261 PP_ResourceImage image_id
,
264 for (size_t i
= 0; i
< arraysize(kResourceImageMap
); ++i
) {
265 if (kResourceImageMap
[i
].pp_id
== image_id
) {
266 res_id
= kResourceImageMap
[i
].res_id
;
271 return PP_ERROR_FAILED
;
273 gfx::ImageSkia
* res_image_skia
=
274 ResourceBundle::GetSharedInstance().GetImageSkiaNamed(res_id
);
277 return PP_ERROR_FAILED
;
279 gfx::ImageSkiaRep image_skia_rep
= res_image_skia
->GetRepresentation(scale
);
281 if (image_skia_rep
.is_null() || image_skia_rep
.scale() != scale
)
282 return PP_ERROR_FAILED
;
285 pp_size
.width
= image_skia_rep
.pixel_width();
286 pp_size
.height
= image_skia_rep
.pixel_height();
288 ppapi::HostResource host_resource
;
289 PP_ImageDataDesc image_data_desc
;
290 IPC::PlatformFileForTransit image_handle
;
291 uint32_t byte_count
= 0;
293 CreateImageData(pp_instance(),
294 ppapi::PPB_ImageData_Shared::GetNativeImageDataFormat(),
296 image_skia_rep
.sk_bitmap(),
301 ppapi::ScopedPPResource
image_data_resource(
302 ppapi::ScopedPPResource::PassRef(), host_resource
.host_resource());
304 return PP_ERROR_FAILED
;
306 ppapi::host::ReplyMessageContext reply_context
=
307 context
->MakeReplyMessageContext();
308 ppapi::proxy::SerializedHandle serialized_handle
;
309 serialized_handle
.set_shmem(image_handle
, byte_count
);
310 reply_context
.params
.AppendHandle(serialized_handle
);
313 PpapiPluginMsg_PDF_GetResourceImageReply(host_resource
, image_data_desc
));
315 // Keep a reference to the resource only if the function succeeds.
316 image_data_resource
.Release();
318 return PP_OK_COMPLETIONPENDING
;
321 int32_t PepperPDFHost::OnHostMsgSetSelectedText(
322 ppapi::host::HostMessageContext
* context
,
323 const base::string16
& selected_text
) {
324 content::PepperPluginInstance
* instance
=
325 host_
->GetPluginInstance(pp_instance());
327 return PP_ERROR_FAILED
;
328 instance
->SetSelectedText(selected_text
);
332 int32_t PepperPDFHost::OnHostMsgSetLinkUnderCursor(
333 ppapi::host::HostMessageContext
* context
,
334 const std::string
& url
) {
335 content::PepperPluginInstance
* instance
=
336 host_
->GetPluginInstance(pp_instance());
338 return PP_ERROR_FAILED
;
339 instance
->SetLinkUnderCursor(url
);
343 // TODO(raymes): This function is mainly copied from ppb_image_data_proxy.cc.
344 // It's a mess and needs to be fixed in several ways but this is better done
345 // when we refactor PPB_ImageData. On success, the image handle will be
347 bool PepperPDFHost::CreateImageData(
348 PP_Instance instance
,
349 PP_ImageDataFormat format
,
351 const SkBitmap
& pixels_to_write
,
352 ppapi::HostResource
* result
,
353 PP_ImageDataDesc
* out_image_data_desc
,
354 IPC::PlatformFileForTransit
* out_image_handle
,
355 uint32_t* out_byte_count
) {
356 PP_Resource resource
= ppapi::proxy::PPB_ImageData_Proxy::CreateImageData(
358 ppapi::PPB_ImageData_Shared::SIMPLE
,
361 false /* init_to_zero */,
368 result
->SetHostResource(instance
, resource
);
370 // Write the image to the resource shared memory.
371 ppapi::thunk::EnterResourceNoLock
<ppapi::thunk::PPB_ImageData_API
>
372 enter_resource(resource
, false);
373 if (enter_resource
.failed())
376 ppapi::thunk::PPB_ImageData_API
* image_data
=
377 static_cast<ppapi::thunk::PPB_ImageData_API
*>(enter_resource
.object());
378 SkCanvas
* canvas
= image_data
->GetCanvas();
379 bool needs_unmapping
= false;
381 needs_unmapping
= true;
383 canvas
= image_data
->GetCanvas();
385 return false; // Failure mapping.
388 const SkBitmap
* bitmap
= &skia::GetTopDevice(*canvas
)->accessBitmap(false);
389 pixels_to_write
.copyPixelsTo(
390 bitmap
->getPixels(), bitmap
->getSize(), bitmap
->rowBytes());