• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "components/pdf/renderer/pepper_pdf_host.h"
6 
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"
36 
37 namespace pdf {
38 
PepperPDFHost(content::RendererPpapiHost * host,PP_Instance instance,PP_Resource resource)39 PepperPDFHost::PepperPDFHost(content::RendererPpapiHost* host,
40                              PP_Instance instance,
41                              PP_Resource resource)
42     : ppapi::host::ResourceHost(host->GetPpapiHost(), instance, resource),
43       host_(host) {}
44 
~PepperPDFHost()45 PepperPDFHost::~PepperPDFHost() {}
46 
OnResourceMessageReceived(const IPC::Message & msg,ppapi::host::HostMessageContext * context)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,
63                                         OnHostMsgSaveAs)
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_END_MESSAGE_MAP()
71   return PP_ERROR_FAILED;
72 }
73 
OnHostMsgGetLocalizedString(ppapi::host::HostMessageContext * context,PP_ResourceString string_id)74 int32_t PepperPDFHost::OnHostMsgGetLocalizedString(
75     ppapi::host::HostMessageContext* context,
76     PP_ResourceString string_id) {
77   std::string rv = GetStringResource(string_id);
78   context->reply_msg = PpapiPluginMsg_PDF_GetLocalizedStringReply(rv);
79   return PP_OK;
80 }
81 
OnHostMsgDidStartLoading(ppapi::host::HostMessageContext * context)82 int32_t PepperPDFHost::OnHostMsgDidStartLoading(
83     ppapi::host::HostMessageContext* context) {
84   content::PepperPluginInstance* instance =
85       host_->GetPluginInstance(pp_instance());
86   if (!instance)
87     return PP_ERROR_FAILED;
88   instance->GetRenderView()->DidStartLoading();
89   return PP_OK;
90 }
91 
OnHostMsgDidStopLoading(ppapi::host::HostMessageContext * context)92 int32_t PepperPDFHost::OnHostMsgDidStopLoading(
93     ppapi::host::HostMessageContext* context) {
94   content::PepperPluginInstance* instance =
95       host_->GetPluginInstance(pp_instance());
96   if (!instance)
97     return PP_ERROR_FAILED;
98   instance->GetRenderView()->DidStopLoading();
99   return PP_OK;
100 }
101 
OnHostMsgSetContentRestriction(ppapi::host::HostMessageContext * context,int restrictions)102 int32_t PepperPDFHost::OnHostMsgSetContentRestriction(
103     ppapi::host::HostMessageContext* context,
104     int restrictions) {
105   content::PepperPluginInstance* instance =
106       host_->GetPluginInstance(pp_instance());
107   if (!instance)
108     return PP_ERROR_FAILED;
109   instance->GetRenderView()->Send(new PDFHostMsg_PDFUpdateContentRestrictions(
110       instance->GetRenderView()->GetRoutingID(), restrictions));
111   return PP_OK;
112 }
113 
OnHostMsgUserMetricsRecordAction(ppapi::host::HostMessageContext * context,const std::string & action)114 int32_t PepperPDFHost::OnHostMsgUserMetricsRecordAction(
115     ppapi::host::HostMessageContext* context,
116     const std::string& action) {
117   if (action.empty())
118     return PP_ERROR_FAILED;
119   content::RenderThread::Get()->RecordComputedAction(action);
120   return PP_OK;
121 }
122 
OnHostMsgHasUnsupportedFeature(ppapi::host::HostMessageContext * context)123 int32_t PepperPDFHost::OnHostMsgHasUnsupportedFeature(
124     ppapi::host::HostMessageContext* context) {
125   content::PepperPluginInstance* instance =
126       host_->GetPluginInstance(pp_instance());
127   if (!instance)
128     return PP_ERROR_FAILED;
129 
130   blink::WebView* view =
131       instance->GetContainer()->element().document().frame()->view();
132   content::RenderView* render_view = content::RenderView::FromWebView(view);
133   render_view->Send(
134       new PDFHostMsg_PDFHasUnsupportedFeature(render_view->GetRoutingID()));
135   return PP_OK;
136 }
137 
OnHostMsgPrint(ppapi::host::HostMessageContext * context)138 int32_t PepperPDFHost::OnHostMsgPrint(
139     ppapi::host::HostMessageContext* context) {
140   return PPB_PDF_Impl::InvokePrintingForInstance(pp_instance()) ? PP_OK :
141       PP_ERROR_FAILED;
142 }
143 
OnHostMsgSaveAs(ppapi::host::HostMessageContext * context)144 int32_t PepperPDFHost::OnHostMsgSaveAs(
145     ppapi::host::HostMessageContext* context) {
146   content::PepperPluginInstance* instance =
147       host_->GetPluginInstance(pp_instance());
148   if (!instance)
149     return PP_ERROR_FAILED;
150   GURL url = instance->GetPluginURL();
151   content::RenderView* render_view = instance->GetRenderView();
152   blink::WebLocalFrame* frame =
153       render_view->GetWebView()->mainFrame()->toWebLocalFrame();
154   content::Referrer referrer(frame->document().url(),
155                              frame->document().referrerPolicy());
156   render_view->Send(
157       new PDFHostMsg_PDFSaveURLAs(render_view->GetRoutingID(), url, referrer));
158   return PP_OK;
159 }
160 
OnHostMsgGetResourceImage(ppapi::host::HostMessageContext * context,PP_ResourceImage image_id,float scale)161 int32_t PepperPDFHost::OnHostMsgGetResourceImage(
162     ppapi::host::HostMessageContext* context,
163     PP_ResourceImage image_id,
164     float scale) {
165   gfx::ImageSkia* res_image_skia = GetImageResource(image_id);
166 
167   if (!res_image_skia)
168     return PP_ERROR_FAILED;
169 
170   gfx::ImageSkiaRep image_skia_rep = res_image_skia->GetRepresentation(scale);
171 
172   if (image_skia_rep.is_null() || image_skia_rep.scale() != scale)
173     return PP_ERROR_FAILED;
174 
175   PP_Size pp_size;
176   pp_size.width = image_skia_rep.pixel_width();
177   pp_size.height = image_skia_rep.pixel_height();
178 
179   ppapi::HostResource host_resource;
180   PP_ImageDataDesc image_data_desc;
181   IPC::PlatformFileForTransit image_handle;
182   uint32_t byte_count = 0;
183   bool success =
184       CreateImageData(pp_instance(),
185                       ppapi::PPB_ImageData_Shared::GetNativeImageDataFormat(),
186                       pp_size,
187                       image_skia_rep.sk_bitmap(),
188                       &host_resource,
189                       &image_data_desc,
190                       &image_handle,
191                       &byte_count);
192   ppapi::ScopedPPResource image_data_resource(
193       ppapi::ScopedPPResource::PassRef(), host_resource.host_resource());
194   if (!success)
195     return PP_ERROR_FAILED;
196 
197   ppapi::host::ReplyMessageContext reply_context =
198       context->MakeReplyMessageContext();
199   ppapi::proxy::SerializedHandle serialized_handle;
200   serialized_handle.set_shmem(image_handle, byte_count);
201   reply_context.params.AppendHandle(serialized_handle);
202   SendReply(
203       reply_context,
204       PpapiPluginMsg_PDF_GetResourceImageReply(host_resource, image_data_desc));
205 
206   // Keep a reference to the resource only if the function succeeds.
207   image_data_resource.Release();
208 
209   return PP_OK_COMPLETIONPENDING;
210 }
211 
OnHostMsgSetSelectedText(ppapi::host::HostMessageContext * context,const base::string16 & selected_text)212 int32_t PepperPDFHost::OnHostMsgSetSelectedText(
213     ppapi::host::HostMessageContext* context,
214     const base::string16& selected_text) {
215   content::PepperPluginInstance* instance =
216       host_->GetPluginInstance(pp_instance());
217   if (!instance)
218     return PP_ERROR_FAILED;
219   instance->SetSelectedText(selected_text);
220   return PP_OK;
221 }
222 
OnHostMsgSetLinkUnderCursor(ppapi::host::HostMessageContext * context,const std::string & url)223 int32_t PepperPDFHost::OnHostMsgSetLinkUnderCursor(
224     ppapi::host::HostMessageContext* context,
225     const std::string& url) {
226   content::PepperPluginInstance* instance =
227       host_->GetPluginInstance(pp_instance());
228   if (!instance)
229     return PP_ERROR_FAILED;
230   instance->SetLinkUnderCursor(url);
231   return PP_OK;
232 }
233 
234 // TODO(raymes): This function is mainly copied from ppb_image_data_proxy.cc.
235 // It's a mess and needs to be fixed in several ways but this is better done
236 // when we refactor PPB_ImageData. On success, the image handle will be
237 // non-null.
CreateImageData(PP_Instance instance,PP_ImageDataFormat format,const PP_Size & size,const SkBitmap & pixels_to_write,ppapi::HostResource * result,PP_ImageDataDesc * out_image_data_desc,IPC::PlatformFileForTransit * out_image_handle,uint32_t * out_byte_count)238 bool PepperPDFHost::CreateImageData(
239     PP_Instance instance,
240     PP_ImageDataFormat format,
241     const PP_Size& size,
242     const SkBitmap& pixels_to_write,
243     ppapi::HostResource* result,
244     PP_ImageDataDesc* out_image_data_desc,
245     IPC::PlatformFileForTransit* out_image_handle,
246     uint32_t* out_byte_count) {
247   PP_Resource resource = ppapi::proxy::PPB_ImageData_Proxy::CreateImageData(
248       instance,
249       ppapi::PPB_ImageData_Shared::SIMPLE,
250       format,
251       size,
252       false /* init_to_zero */,
253       out_image_data_desc,
254       out_image_handle,
255       out_byte_count);
256   if (!resource)
257     return false;
258 
259   result->SetHostResource(instance, resource);
260 
261   // Write the image to the resource shared memory.
262   ppapi::thunk::EnterResourceNoLock<ppapi::thunk::PPB_ImageData_API>
263       enter_resource(resource, false);
264   if (enter_resource.failed())
265     return false;
266 
267   ppapi::thunk::PPB_ImageData_API* image_data =
268       static_cast<ppapi::thunk::PPB_ImageData_API*>(enter_resource.object());
269   SkCanvas* canvas = image_data->GetCanvas();
270   bool needs_unmapping = false;
271   if (!canvas) {
272     needs_unmapping = true;
273     image_data->Map();
274     canvas = image_data->GetCanvas();
275     if (!canvas)
276       return false;  // Failure mapping.
277   }
278 
279   const SkBitmap* bitmap = &skia::GetTopDevice(*canvas)->accessBitmap(false);
280   pixels_to_write.copyPixelsTo(
281       bitmap->getPixels(), bitmap->getSize(), bitmap->rowBytes());
282 
283   if (needs_unmapping)
284     image_data->Unmap();
285 
286   return true;
287 }
288 
289 }  // namespace pdf
290