Rewrite AndroidSyncSettings to be significantly simpler.
[chromium-blink-merge.git] / components / pdf / renderer / pepper_pdf_host.cc
blob4c9641fa16d631a8810b82fed55416fd38f70286
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"
37 namespace pdf {
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) {}
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,
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_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);
81 return PP_OK;
84 int32_t PepperPDFHost::OnHostMsgDidStartLoading(
85 ppapi::host::HostMessageContext* context) {
86 content::PepperPluginInstance* instance =
87 host_->GetPluginInstance(pp_instance());
88 if (!instance)
89 return PP_ERROR_FAILED;
90 instance->GetRenderView()->DidStartLoading();
91 return PP_OK;
94 int32_t PepperPDFHost::OnHostMsgDidStopLoading(
95 ppapi::host::HostMessageContext* context) {
96 content::PepperPluginInstance* instance =
97 host_->GetPluginInstance(pp_instance());
98 if (!instance)
99 return PP_ERROR_FAILED;
100 instance->GetRenderView()->DidStopLoading();
101 return PP_OK;
104 int32_t PepperPDFHost::OnHostMsgSetContentRestriction(
105 ppapi::host::HostMessageContext* context,
106 int restrictions) {
107 content::PepperPluginInstance* instance =
108 host_->GetPluginInstance(pp_instance());
109 if (!instance)
110 return PP_ERROR_FAILED;
111 instance->GetRenderView()->Send(new PDFHostMsg_PDFUpdateContentRestrictions(
112 instance->GetRenderView()->GetRoutingID(), restrictions));
113 return PP_OK;
116 int32_t PepperPDFHost::OnHostMsgUserMetricsRecordAction(
117 ppapi::host::HostMessageContext* context,
118 const std::string& action) {
119 if (action.empty())
120 return PP_ERROR_FAILED;
121 content::RenderThread::Get()->RecordComputedAction(action);
122 return PP_OK;
125 int32_t PepperPDFHost::OnHostMsgHasUnsupportedFeature(
126 ppapi::host::HostMessageContext* context) {
127 content::PepperPluginInstance* instance =
128 host_->GetPluginInstance(pp_instance());
129 if (!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);
135 render_view->Send(
136 new PDFHostMsg_PDFHasUnsupportedFeature(render_view->GetRoutingID()));
137 return PP_OK;
140 int32_t PepperPDFHost::OnHostMsgPrint(
141 ppapi::host::HostMessageContext* context) {
142 return PPB_PDF_Impl::InvokePrintingForInstance(pp_instance()) ? PP_OK :
143 PP_ERROR_FAILED;
146 int32_t PepperPDFHost::OnHostMsgSaveAs(
147 ppapi::host::HostMessageContext* context) {
148 content::PepperPluginInstance* instance =
149 host_->GetPluginInstance(pp_instance());
150 if (!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()));
159 render_view->Send(
160 new PDFHostMsg_PDFSaveURLAs(render_view->GetRoutingID(), url, referrer));
161 return PP_OK;
164 int32_t PepperPDFHost::OnHostMsgGetResourceImage(
165 ppapi::host::HostMessageContext* context,
166 PP_ResourceImage image_id,
167 float scale) {
168 gfx::ImageSkia* res_image_skia = GetImageResource(image_id);
170 if (!res_image_skia)
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;
178 PP_Size pp_size;
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;
186 bool success =
187 CreateImageData(pp_instance(),
188 ppapi::PPB_ImageData_Shared::GetNativeImageDataFormat(),
189 pp_size,
190 image_skia_rep.sk_bitmap(),
191 &host_resource,
192 &image_data_desc,
193 &image_handle,
194 &byte_count);
195 ppapi::ScopedPPResource image_data_resource(
196 ppapi::ScopedPPResource::PassRef(), host_resource.host_resource());
197 if (!success)
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);
205 SendReply(
206 reply_context,
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());
220 if (!instance)
221 return PP_ERROR_FAILED;
222 instance->SetSelectedText(selected_text);
223 return PP_OK;
226 int32_t PepperPDFHost::OnHostMsgSetLinkUnderCursor(
227 ppapi::host::HostMessageContext* context,
228 const std::string& url) {
229 content::PepperPluginInstance* instance =
230 host_->GetPluginInstance(pp_instance());
231 if (!instance)
232 return PP_ERROR_FAILED;
233 instance->SetLinkUnderCursor(url);
234 return PP_OK;
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
240 // non-null.
241 bool PepperPDFHost::CreateImageData(
242 PP_Instance instance,
243 PP_ImageDataFormat format,
244 const PP_Size& size,
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(
251 instance,
252 ppapi::PPB_ImageData_Shared::SIMPLE,
253 format,
254 size,
255 false /* init_to_zero */,
256 out_image_data_desc,
257 out_image_handle,
258 out_byte_count);
259 if (!resource)
260 return false;
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())
268 return false;
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;
274 if (!canvas) {
275 needs_unmapping = true;
276 image_data->Map();
277 canvas = image_data->GetCanvas();
278 if (!canvas)
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());
286 if (needs_unmapping)
287 image_data->Unmap();
289 return true;
292 } // namespace pdf