Upstream version 10.38.222.0
[platform/framework/web/crosswalk.git] / src / chrome / renderer / pepper / pepper_pdf_host.cc
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/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/app/strings/grit/content_strings.h"
11 #include "content/public/common/referrer.h"
12 #include "content/public/renderer/pepper_plugin_instance.h"
13 #include "content/public/renderer/render_thread.h"
14 #include "content/public/renderer/render_view.h"
15 #include "content/public/renderer/renderer_ppapi_host.h"
16 #include "grit/webkit_resources.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"
40
41 namespace {
42
43 struct ResourceImageInfo {
44   PP_ResourceImage pp_id;
45   int res_id;
46 };
47
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}, };
101
102 }  // namespace
103
104 PepperPDFHost::PepperPDFHost(content::RendererPpapiHost* host,
105                              PP_Instance instance,
106                              PP_Resource resource)
107     : ppapi::host::ResourceHost(host->GetPpapiHost(), instance, resource),
108       host_(host) {}
109
110 PepperPDFHost::~PepperPDFHost() {}
111
112 int32_t PepperPDFHost::OnResourceMessageReceived(
113     const IPC::Message& msg,
114     ppapi::host::HostMessageContext* context) {
115   PPAPI_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,
128                                         OnHostMsgSaveAs)
129     PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_PDF_GetResourceImage,
130                                       OnHostMsgGetResourceImage)
131     PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_PDF_SetSelectedText,
132                                       OnHostMsgSetSelectedText)
133     PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_PDF_SetLinkUnderCursor,
134                                       OnHostMsgSetLinkUnderCursor)
135   PPAPI_END_MESSAGE_MAP()
136   return PP_ERROR_FAILED;
137 }
138
139 int32_t PepperPDFHost::OnHostMsgGetLocalizedString(
140     ppapi::host::HostMessageContext* context,
141     PP_ResourceString string_id) {
142   std::string rv;
143   if (string_id == PP_RESOURCESTRING_PDFGETPASSWORD) {
144     rv = base::UTF16ToUTF8(l10n_util::GetStringUTF16(IDS_PDF_NEED_PASSWORD));
145   } else if (string_id == PP_RESOURCESTRING_PDFLOADING) {
146     rv = base::UTF16ToUTF8(l10n_util::GetStringUTF16(IDS_PDF_PAGE_LOADING));
147   } else if (string_id == PP_RESOURCESTRING_PDFLOAD_FAILED) {
148     rv = base::UTF16ToUTF8(l10n_util::GetStringUTF16(IDS_PDF_PAGE_LOAD_FAILED));
149   } else if (string_id == PP_RESOURCESTRING_PDFPROGRESSLOADING) {
150     rv = base::UTF16ToUTF8(l10n_util::GetStringUTF16(IDS_PDF_PROGRESS_LOADING));
151   } else {
152     NOTREACHED();
153     return PP_ERROR_FAILED;
154   }
155
156   context->reply_msg = PpapiPluginMsg_PDF_GetLocalizedStringReply(rv);
157   return PP_OK;
158 }
159
160 int32_t PepperPDFHost::OnHostMsgDidStartLoading(
161     ppapi::host::HostMessageContext* context) {
162   content::PepperPluginInstance* instance =
163       host_->GetPluginInstance(pp_instance());
164   if (!instance)
165     return PP_ERROR_FAILED;
166   instance->GetRenderView()->DidStartLoading();
167   return PP_OK;
168 }
169
170 int32_t PepperPDFHost::OnHostMsgDidStopLoading(
171     ppapi::host::HostMessageContext* context) {
172   content::PepperPluginInstance* instance =
173       host_->GetPluginInstance(pp_instance());
174   if (!instance)
175     return PP_ERROR_FAILED;
176   instance->GetRenderView()->DidStopLoading();
177   return PP_OK;
178 }
179
180 int32_t PepperPDFHost::OnHostMsgSetContentRestriction(
181     ppapi::host::HostMessageContext* context,
182     int restrictions) {
183   content::PepperPluginInstance* instance =
184       host_->GetPluginInstance(pp_instance());
185   if (!instance)
186     return PP_ERROR_FAILED;
187   instance->GetRenderView()->Send(
188       new ChromeViewHostMsg_PDFUpdateContentRestrictions(
189           instance->GetRenderView()->GetRoutingID(), restrictions));
190   return PP_OK;
191 }
192
193 int32_t PepperPDFHost::OnHostMsgUserMetricsRecordAction(
194     ppapi::host::HostMessageContext* context,
195     const std::string& action) {
196   if (action.empty())
197     return PP_ERROR_FAILED;
198   content::RenderThread::Get()->RecordComputedAction(action);
199   return PP_OK;
200 }
201
202 int32_t PepperPDFHost::OnHostMsgHasUnsupportedFeature(
203     ppapi::host::HostMessageContext* context) {
204   content::PepperPluginInstance* instance =
205       host_->GetPluginInstance(pp_instance());
206   if (!instance)
207     return PP_ERROR_FAILED;
208
209   blink::WebView* view =
210       instance->GetContainer()->element().document().frame()->view();
211   content::RenderView* render_view = content::RenderView::FromWebView(view);
212   render_view->Send(new ChromeViewHostMsg_PDFHasUnsupportedFeature(
213       render_view->GetRoutingID()));
214   return PP_OK;
215 }
216
217 int32_t PepperPDFHost::OnHostMsgPrint(
218     ppapi::host::HostMessageContext* context) {
219 #if defined(ENABLE_FULL_PRINTING)
220   content::PepperPluginInstance* instance =
221       host_->GetPluginInstance(pp_instance());
222   if (!instance)
223     return PP_ERROR_FAILED;
224
225   blink::WebElement element = instance->GetContainer()->element();
226   blink::WebView* view = element.document().frame()->view();
227   content::RenderView* render_view = content::RenderView::FromWebView(view);
228
229   using printing::PrintWebViewHelper;
230   PrintWebViewHelper* print_view_helper = PrintWebViewHelper::Get(render_view);
231   if (print_view_helper) {
232     print_view_helper->PrintNode(element);
233     return PP_OK;
234   }
235 #endif
236   return PP_ERROR_FAILED;
237 }
238
239 int32_t PepperPDFHost::OnHostMsgSaveAs(
240     ppapi::host::HostMessageContext* context) {
241   content::PepperPluginInstance* instance =
242       host_->GetPluginInstance(pp_instance());
243   if (!instance)
244     return PP_ERROR_FAILED;
245   GURL url = instance->GetPluginURL();
246   content::RenderView* render_view = instance->GetRenderView();
247   blink::WebLocalFrame* frame =
248       render_view->GetWebView()->mainFrame()->toWebLocalFrame();
249   content::Referrer referrer(frame->document().url(),
250                              frame->document().referrerPolicy());
251   render_view->Send(new ChromeViewHostMsg_PDFSaveURLAs(
252       render_view->GetRoutingID(), url, referrer));
253   return PP_OK;
254 }
255
256 int32_t PepperPDFHost::OnHostMsgGetResourceImage(
257     ppapi::host::HostMessageContext* context,
258     PP_ResourceImage image_id,
259     float scale) {
260   int res_id = 0;
261   for (size_t i = 0; i < arraysize(kResourceImageMap); ++i) {
262     if (kResourceImageMap[i].pp_id == image_id) {
263       res_id = kResourceImageMap[i].res_id;
264       break;
265     }
266   }
267   if (res_id == 0)
268     return PP_ERROR_FAILED;
269
270   gfx::ImageSkia* res_image_skia =
271       ResourceBundle::GetSharedInstance().GetImageSkiaNamed(res_id);
272
273   if (!res_image_skia)
274     return PP_ERROR_FAILED;
275
276   gfx::ImageSkiaRep image_skia_rep = res_image_skia->GetRepresentation(scale);
277
278   if (image_skia_rep.is_null() || image_skia_rep.scale() != scale)
279     return PP_ERROR_FAILED;
280
281   PP_Size pp_size;
282   pp_size.width = image_skia_rep.pixel_width();
283   pp_size.height = image_skia_rep.pixel_height();
284
285   ppapi::HostResource host_resource;
286   PP_ImageDataDesc image_data_desc;
287   IPC::PlatformFileForTransit image_handle;
288   uint32_t byte_count = 0;
289   bool success =
290       CreateImageData(pp_instance(),
291                       ppapi::PPB_ImageData_Shared::GetNativeImageDataFormat(),
292                       pp_size,
293                       image_skia_rep.sk_bitmap(),
294                       &host_resource,
295                       &image_data_desc,
296                       &image_handle,
297                       &byte_count);
298   ppapi::ScopedPPResource image_data_resource(
299       ppapi::ScopedPPResource::PassRef(), host_resource.host_resource());
300   if (!success)
301     return PP_ERROR_FAILED;
302
303   ppapi::host::ReplyMessageContext reply_context =
304       context->MakeReplyMessageContext();
305   ppapi::proxy::SerializedHandle serialized_handle;
306   serialized_handle.set_shmem(image_handle, byte_count);
307   reply_context.params.AppendHandle(serialized_handle);
308   SendReply(
309       reply_context,
310       PpapiPluginMsg_PDF_GetResourceImageReply(host_resource, image_data_desc));
311
312   // Keep a reference to the resource only if the function succeeds.
313   image_data_resource.Release();
314
315   return PP_OK_COMPLETIONPENDING;
316 }
317
318 int32_t PepperPDFHost::OnHostMsgSetSelectedText(
319     ppapi::host::HostMessageContext* context,
320     const base::string16& selected_text) {
321   content::PepperPluginInstance* instance =
322       host_->GetPluginInstance(pp_instance());
323   if (!instance)
324     return PP_ERROR_FAILED;
325   instance->SetSelectedText(selected_text);
326   return PP_OK;
327 }
328
329 int32_t PepperPDFHost::OnHostMsgSetLinkUnderCursor(
330     ppapi::host::HostMessageContext* context,
331     const std::string& url) {
332   content::PepperPluginInstance* instance =
333       host_->GetPluginInstance(pp_instance());
334   if (!instance)
335     return PP_ERROR_FAILED;
336   instance->SetLinkUnderCursor(url);
337   return PP_OK;
338 }
339
340 // TODO(raymes): This function is mainly copied from ppb_image_data_proxy.cc.
341 // It's a mess and needs to be fixed in several ways but this is better done
342 // when we refactor PPB_ImageData. On success, the image handle will be
343 // non-null.
344 bool PepperPDFHost::CreateImageData(
345     PP_Instance instance,
346     PP_ImageDataFormat format,
347     const PP_Size& size,
348     const SkBitmap& pixels_to_write,
349     ppapi::HostResource* result,
350     PP_ImageDataDesc* out_image_data_desc,
351     IPC::PlatformFileForTransit* out_image_handle,
352     uint32_t* out_byte_count) {
353   PP_Resource resource = ppapi::proxy::PPB_ImageData_Proxy::CreateImageData(
354       instance,
355       ppapi::PPB_ImageData_Shared::SIMPLE,
356       format,
357       size,
358       false /* init_to_zero */,
359       out_image_data_desc,
360       out_image_handle,
361       out_byte_count);
362   if (!resource)
363     return false;
364
365   result->SetHostResource(instance, resource);
366
367   // Write the image to the resource shared memory.
368   ppapi::thunk::EnterResourceNoLock<ppapi::thunk::PPB_ImageData_API>
369       enter_resource(resource, false);
370   if (enter_resource.failed())
371     return false;
372
373   ppapi::thunk::PPB_ImageData_API* image_data =
374       static_cast<ppapi::thunk::PPB_ImageData_API*>(enter_resource.object());
375   SkCanvas* canvas = image_data->GetCanvas();
376   bool needs_unmapping = false;
377   if (!canvas) {
378     needs_unmapping = true;
379     image_data->Map();
380     canvas = image_data->GetCanvas();
381     if (!canvas)
382       return false;  // Failure mapping.
383   }
384
385   const SkBitmap* bitmap = &skia::GetTopDevice(*canvas)->accessBitmap(false);
386   pixels_to_write.copyPixelsTo(
387       bitmap->getPixels(), bitmap->getSize(), bitmap->rowBytes());
388
389   if (needs_unmapping)
390     image_data->Unmap();
391
392   return true;
393 }