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/image/image_skia.h"
34 #include "ui/gfx/image/image_skia_rep.h"
35 #include "ui/gfx/point.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(frame
->document().url(),
157 frame
->document().referrerPolicy());
159 new PDFHostMsg_PDFSaveURLAs(render_view
->GetRoutingID(), url
, referrer
));
163 int32_t PepperPDFHost::OnHostMsgGetResourceImage(
164 ppapi::host::HostMessageContext
* context
,
165 PP_ResourceImage image_id
,
167 gfx::ImageSkia
* res_image_skia
= GetImageResource(image_id
);
170 return PP_ERROR_FAILED
;
172 gfx::ImageSkiaRep image_skia_rep
= res_image_skia
->GetRepresentation(scale
);
174 if (image_skia_rep
.is_null() || image_skia_rep
.scale() != scale
)
175 return PP_ERROR_FAILED
;
178 pp_size
.width
= image_skia_rep
.pixel_width();
179 pp_size
.height
= image_skia_rep
.pixel_height();
181 ppapi::HostResource host_resource
;
182 PP_ImageDataDesc image_data_desc
;
183 IPC::PlatformFileForTransit image_handle
;
184 uint32_t byte_count
= 0;
186 CreateImageData(pp_instance(),
187 ppapi::PPB_ImageData_Shared::GetNativeImageDataFormat(),
189 image_skia_rep
.sk_bitmap(),
194 ppapi::ScopedPPResource
image_data_resource(
195 ppapi::ScopedPPResource::PassRef(), host_resource
.host_resource());
197 return PP_ERROR_FAILED
;
199 ppapi::host::ReplyMessageContext reply_context
=
200 context
->MakeReplyMessageContext();
201 ppapi::proxy::SerializedHandle serialized_handle
;
202 serialized_handle
.set_shmem(image_handle
, byte_count
);
203 reply_context
.params
.AppendHandle(serialized_handle
);
206 PpapiPluginMsg_PDF_GetResourceImageReply(host_resource
, image_data_desc
));
208 // Keep a reference to the resource only if the function succeeds.
209 image_data_resource
.Release();
211 return PP_OK_COMPLETIONPENDING
;
214 int32_t PepperPDFHost::OnHostMsgSetSelectedText(
215 ppapi::host::HostMessageContext
* context
,
216 const base::string16
& selected_text
) {
217 content::PepperPluginInstance
* instance
=
218 host_
->GetPluginInstance(pp_instance());
220 return PP_ERROR_FAILED
;
221 instance
->SetSelectedText(selected_text
);
225 int32_t PepperPDFHost::OnHostMsgSetLinkUnderCursor(
226 ppapi::host::HostMessageContext
* context
,
227 const std::string
& url
) {
228 content::PepperPluginInstance
* instance
=
229 host_
->GetPluginInstance(pp_instance());
231 return PP_ERROR_FAILED
;
232 instance
->SetLinkUnderCursor(url
);
236 // TODO(raymes): This function is mainly copied from ppb_image_data_proxy.cc.
237 // It's a mess and needs to be fixed in several ways but this is better done
238 // when we refactor PPB_ImageData. On success, the image handle will be
240 bool PepperPDFHost::CreateImageData(
241 PP_Instance instance
,
242 PP_ImageDataFormat format
,
244 const SkBitmap
& pixels_to_write
,
245 ppapi::HostResource
* result
,
246 PP_ImageDataDesc
* out_image_data_desc
,
247 IPC::PlatformFileForTransit
* out_image_handle
,
248 uint32_t* out_byte_count
) {
249 PP_Resource resource
= ppapi::proxy::PPB_ImageData_Proxy::CreateImageData(
251 ppapi::PPB_ImageData_Shared::SIMPLE
,
254 false /* init_to_zero */,
261 result
->SetHostResource(instance
, resource
);
263 // Write the image to the resource shared memory.
264 ppapi::thunk::EnterResourceNoLock
<ppapi::thunk::PPB_ImageData_API
>
265 enter_resource(resource
, false);
266 if (enter_resource
.failed())
269 ppapi::thunk::PPB_ImageData_API
* image_data
=
270 static_cast<ppapi::thunk::PPB_ImageData_API
*>(enter_resource
.object());
271 SkCanvas
* canvas
= image_data
->GetCanvas();
272 bool needs_unmapping
= false;
274 needs_unmapping
= true;
276 canvas
= image_data
->GetCanvas();
278 return false; // Failure mapping.
281 const SkBitmap
* bitmap
= &skia::GetTopDevice(*canvas
)->accessBitmap(false);
282 pixels_to_write
.copyPixelsTo(
283 bitmap
->getPixels(), bitmap
->getSize(), bitmap
->rowBytes());