1 // Copyright 2014 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 "components/pdf/renderer/pepper_pdf_host.h"
7 #include "components/pdf/common/pdf_messages.h"
8 #include "components/pdf/renderer/pdf_resource_util.h"
9 #include "components/pdf/renderer/ppb_pdf_impl.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 "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/ppb_image_data_shared.h"
22 #include "ppapi/shared_impl/scoped_pp_resource.h"
23 #include "ppapi/thunk/enter.h"
24 #include "ppapi/thunk/ppb_image_data_api.h"
25 #include "skia/ext/platform_canvas.h"
26 #include "third_party/WebKit/public/web/WebDocument.h"
27 #include "third_party/WebKit/public/web/WebElement.h"
28 #include "third_party/WebKit/public/web/WebLocalFrame.h"
29 #include "third_party/WebKit/public/web/WebPluginContainer.h"
30 #include "third_party/WebKit/public/web/WebView.h"
31 #include "third_party/skia/include/core/SkBitmap.h"
32 #include "ui/base/layout.h"
33 #include "ui/gfx/geometry/point.h"
34 #include "ui/gfx/image/image_skia.h"
35 #include "ui/gfx/image/image_skia_rep.h"
39 PepperPDFHost::PepperPDFHost(content::RendererPpapiHost
* host
,
42 : ppapi::host::ResourceHost(host
->GetPpapiHost(), instance
, resource
),
45 PepperPDFHost::~PepperPDFHost() {}
47 int32_t PepperPDFHost::OnResourceMessageReceived(
48 const IPC::Message
& msg
,
49 ppapi::host::HostMessageContext
* context
) {
50 PPAPI_BEGIN_MESSAGE_MAP(PepperPDFHost
, msg
)
51 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_PDF_GetLocalizedString
,
52 OnHostMsgGetLocalizedString
)
53 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_PDF_DidStartLoading
,
54 OnHostMsgDidStartLoading
)
55 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_PDF_DidStopLoading
,
56 OnHostMsgDidStopLoading
)
57 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_PDF_UserMetricsRecordAction
,
58 OnHostMsgUserMetricsRecordAction
)
59 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_PDF_HasUnsupportedFeature
,
60 OnHostMsgHasUnsupportedFeature
)
61 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_PDF_Print
, OnHostMsgPrint
)
62 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_PDF_SaveAs
,
64 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_PDF_GetResourceImage
,
65 OnHostMsgGetResourceImage
)
66 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_PDF_SetSelectedText
,
67 OnHostMsgSetSelectedText
)
68 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_PDF_SetLinkUnderCursor
,
69 OnHostMsgSetLinkUnderCursor
)
70 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_PDF_SetContentRestriction
,
71 OnHostMsgSetContentRestriction
)
72 PPAPI_END_MESSAGE_MAP()
73 return PP_ERROR_FAILED
;
76 int32_t PepperPDFHost::OnHostMsgGetLocalizedString(
77 ppapi::host::HostMessageContext
* context
,
78 PP_ResourceString string_id
) {
79 std::string rv
= GetStringResource(string_id
);
80 context
->reply_msg
= PpapiPluginMsg_PDF_GetLocalizedStringReply(rv
);
84 int32_t PepperPDFHost::OnHostMsgDidStartLoading(
85 ppapi::host::HostMessageContext
* context
) {
86 content::PepperPluginInstance
* instance
=
87 host_
->GetPluginInstance(pp_instance());
89 return PP_ERROR_FAILED
;
90 instance
->GetRenderView()->DidStartLoading();
94 int32_t PepperPDFHost::OnHostMsgDidStopLoading(
95 ppapi::host::HostMessageContext
* context
) {
96 content::PepperPluginInstance
* instance
=
97 host_
->GetPluginInstance(pp_instance());
99 return PP_ERROR_FAILED
;
100 instance
->GetRenderView()->DidStopLoading();
104 int32_t PepperPDFHost::OnHostMsgSetContentRestriction(
105 ppapi::host::HostMessageContext
* context
,
107 content::PepperPluginInstance
* instance
=
108 host_
->GetPluginInstance(pp_instance());
110 return PP_ERROR_FAILED
;
111 instance
->GetRenderView()->Send(new PDFHostMsg_PDFUpdateContentRestrictions(
112 instance
->GetRenderView()->GetRoutingID(), restrictions
));
116 int32_t PepperPDFHost::OnHostMsgUserMetricsRecordAction(
117 ppapi::host::HostMessageContext
* context
,
118 const std::string
& action
) {
120 return PP_ERROR_FAILED
;
121 content::RenderThread::Get()->RecordComputedAction(action
);
125 int32_t PepperPDFHost::OnHostMsgHasUnsupportedFeature(
126 ppapi::host::HostMessageContext
* context
) {
127 content::PepperPluginInstance
* instance
=
128 host_
->GetPluginInstance(pp_instance());
130 return PP_ERROR_FAILED
;
132 blink::WebView
* view
=
133 instance
->GetContainer()->element().document().frame()->view();
134 content::RenderView
* render_view
= content::RenderView::FromWebView(view
);
136 new PDFHostMsg_PDFHasUnsupportedFeature(render_view
->GetRoutingID()));
140 int32_t PepperPDFHost::OnHostMsgPrint(
141 ppapi::host::HostMessageContext
* context
) {
142 return PPB_PDF_Impl::InvokePrintingForInstance(pp_instance()) ? PP_OK
:
146 int32_t PepperPDFHost::OnHostMsgSaveAs(
147 ppapi::host::HostMessageContext
* context
) {
148 content::PepperPluginInstance
* instance
=
149 host_
->GetPluginInstance(pp_instance());
151 return PP_ERROR_FAILED
;
152 GURL url
= instance
->GetPluginURL();
153 content::RenderView
* render_view
= instance
->GetRenderView();
154 blink::WebLocalFrame
* frame
=
155 render_view
->GetWebView()->mainFrame()->toWebLocalFrame();
156 content::Referrer referrer
= content::Referrer::SanitizeForRequest(
157 url
, content::Referrer(frame
->document().url(),
158 frame
->document().referrerPolicy()));
160 new PDFHostMsg_PDFSaveURLAs(render_view
->GetRoutingID(), url
, referrer
));
164 int32_t PepperPDFHost::OnHostMsgGetResourceImage(
165 ppapi::host::HostMessageContext
* context
,
166 PP_ResourceImage image_id
,
168 gfx::ImageSkia
* res_image_skia
= GetImageResource(image_id
);
171 return PP_ERROR_FAILED
;
173 gfx::ImageSkiaRep image_skia_rep
= res_image_skia
->GetRepresentation(scale
);
175 if (image_skia_rep
.is_null() || image_skia_rep
.scale() != scale
)
176 return PP_ERROR_FAILED
;
179 pp_size
.width
= image_skia_rep
.pixel_width();
180 pp_size
.height
= image_skia_rep
.pixel_height();
182 ppapi::HostResource host_resource
;
183 PP_ImageDataDesc image_data_desc
;
184 IPC::PlatformFileForTransit image_handle
;
185 uint32_t byte_count
= 0;
187 CreateImageData(pp_instance(),
188 ppapi::PPB_ImageData_Shared::GetNativeImageDataFormat(),
190 image_skia_rep
.sk_bitmap(),
195 ppapi::ScopedPPResource
image_data_resource(
196 ppapi::ScopedPPResource::PassRef(), host_resource
.host_resource());
198 return PP_ERROR_FAILED
;
200 ppapi::host::ReplyMessageContext reply_context
=
201 context
->MakeReplyMessageContext();
202 ppapi::proxy::SerializedHandle serialized_handle
;
203 serialized_handle
.set_shmem(image_handle
, byte_count
);
204 reply_context
.params
.AppendHandle(serialized_handle
);
207 PpapiPluginMsg_PDF_GetResourceImageReply(host_resource
, image_data_desc
));
209 // Keep a reference to the resource only if the function succeeds.
210 image_data_resource
.Release();
212 return PP_OK_COMPLETIONPENDING
;
215 int32_t PepperPDFHost::OnHostMsgSetSelectedText(
216 ppapi::host::HostMessageContext
* context
,
217 const base::string16
& selected_text
) {
218 content::PepperPluginInstance
* instance
=
219 host_
->GetPluginInstance(pp_instance());
221 return PP_ERROR_FAILED
;
222 instance
->SetSelectedText(selected_text
);
226 int32_t PepperPDFHost::OnHostMsgSetLinkUnderCursor(
227 ppapi::host::HostMessageContext
* context
,
228 const std::string
& url
) {
229 content::PepperPluginInstance
* instance
=
230 host_
->GetPluginInstance(pp_instance());
232 return PP_ERROR_FAILED
;
233 instance
->SetLinkUnderCursor(url
);
237 // TODO(raymes): This function is mainly copied from ppb_image_data_proxy.cc.
238 // It's a mess and needs to be fixed in several ways but this is better done
239 // when we refactor PPB_ImageData. On success, the image handle will be
241 bool PepperPDFHost::CreateImageData(
242 PP_Instance instance
,
243 PP_ImageDataFormat format
,
245 const SkBitmap
& pixels_to_write
,
246 ppapi::HostResource
* result
,
247 PP_ImageDataDesc
* out_image_data_desc
,
248 IPC::PlatformFileForTransit
* out_image_handle
,
249 uint32_t* out_byte_count
) {
250 PP_Resource resource
= ppapi::proxy::PPB_ImageData_Proxy::CreateImageData(
252 ppapi::PPB_ImageData_Shared::SIMPLE
,
255 false /* init_to_zero */,
262 result
->SetHostResource(instance
, resource
);
264 // Write the image to the resource shared memory.
265 ppapi::thunk::EnterResourceNoLock
<ppapi::thunk::PPB_ImageData_API
>
266 enter_resource(resource
, false);
267 if (enter_resource
.failed())
270 ppapi::thunk::PPB_ImageData_API
* image_data
=
271 static_cast<ppapi::thunk::PPB_ImageData_API
*>(enter_resource
.object());
272 SkCanvas
* canvas
= image_data
->GetCanvas();
273 bool needs_unmapping
= false;
275 needs_unmapping
= true;
277 canvas
= image_data
->GetCanvas();
279 return false; // Failure mapping.
282 const SkBitmap
* bitmap
= &skia::GetTopDevice(*canvas
)->accessBitmap(false);
283 pixels_to_write
.copyPixelsTo(
284 bitmap
->getPixels(), bitmap
->getSize(), bitmap
->rowBytes());