GuestViews should be able to specify task manager entries
[chromium-blink-merge.git] / chrome / renderer / pepper / ppb_pdf_impl.cc
blob516178c9ff899a31e6386d39725b7ec55f3ee18c
1 // Copyright (c) 2012 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 "chrome/renderer/pepper/ppb_pdf_impl.h"
7 #include "base/files/scoped_file.h"
8 #include "base/metrics/histogram.h"
9 #include "base/numerics/safe_conversions.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "build/build_config.h"
12 #include "chrome/common/render_messages.h"
13 #include "chrome/renderer/printing/print_web_view_helper.h"
14 #include "content/app/resources/grit/content_resources.h"
15 #include "content/app/strings/grit/content_strings.h"
16 #include "content/public/common/child_process_sandbox_support_linux.h"
17 #include "content/public/common/referrer.h"
18 #include "content/public/renderer/pepper_plugin_instance.h"
19 #include "content/public/renderer/render_thread.h"
20 #include "content/public/renderer/render_view.h"
21 #include "ppapi/c/pp_resource.h"
22 #include "ppapi/c/private/ppb_pdf.h"
23 #include "ppapi/c/trusted/ppb_browser_font_trusted.h"
24 #include "ppapi/shared_impl/ppapi_globals.h"
25 #include "ppapi/shared_impl/resource.h"
26 #include "ppapi/shared_impl/resource_tracker.h"
27 #include "ppapi/shared_impl/var.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/icu/source/i18n/unicode/usearch.h"
34 #include "third_party/skia/include/core/SkBitmap.h"
35 #include "ui/base/l10n/l10n_util.h"
36 #include "ui/base/resource/resource_bundle.h"
38 namespace {
40 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
41 class PrivateFontFile : public ppapi::Resource {
42 public:
43 PrivateFontFile(PP_Instance instance, int fd)
44 : Resource(ppapi::OBJECT_IS_IMPL, instance), fd_(fd) {}
46 bool GetFontTable(uint32_t table, void* output, uint32_t* output_length) {
47 size_t temp_size = static_cast<size_t>(*output_length);
48 bool rv = content::GetFontTable(
49 fd_.get(), table, 0 /* offset */, static_cast<uint8_t*>(output),
50 &temp_size);
51 *output_length = base::checked_cast<uint32_t>(temp_size);
52 return rv;
55 protected:
56 virtual ~PrivateFontFile() {}
58 private:
59 base::ScopedFD fd_;
61 #endif
63 struct ResourceImageInfo {
64 PP_ResourceImage pp_id;
65 int res_id;
68 static const ResourceImageInfo kResourceImageMap[] = {
69 {PP_RESOURCEIMAGE_PDF_BUTTON_FTP, IDR_PDF_BUTTON_FTP},
70 {PP_RESOURCEIMAGE_PDF_BUTTON_FTP_HOVER, IDR_PDF_BUTTON_FTP_HOVER},
71 {PP_RESOURCEIMAGE_PDF_BUTTON_FTP_PRESSED, IDR_PDF_BUTTON_FTP_PRESSED},
72 {PP_RESOURCEIMAGE_PDF_BUTTON_FTW, IDR_PDF_BUTTON_FTW},
73 {PP_RESOURCEIMAGE_PDF_BUTTON_FTW_HOVER, IDR_PDF_BUTTON_FTW_HOVER},
74 {PP_RESOURCEIMAGE_PDF_BUTTON_FTW_PRESSED, IDR_PDF_BUTTON_FTW_PRESSED},
75 {PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMIN_END, IDR_PDF_BUTTON_ZOOMIN_END},
76 {PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMIN_END_HOVER,
77 IDR_PDF_BUTTON_ZOOMIN_END_HOVER},
78 {PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMIN_END_PRESSED,
79 IDR_PDF_BUTTON_ZOOMIN_END_PRESSED},
80 {PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMIN, IDR_PDF_BUTTON_ZOOMIN},
81 {PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMIN_HOVER, IDR_PDF_BUTTON_ZOOMIN_HOVER},
82 {PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMIN_PRESSED, IDR_PDF_BUTTON_ZOOMIN_PRESSED},
83 {PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMOUT, IDR_PDF_BUTTON_ZOOMOUT},
84 {PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMOUT_HOVER, IDR_PDF_BUTTON_ZOOMOUT_HOVER},
85 {PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMOUT_PRESSED,
86 IDR_PDF_BUTTON_ZOOMOUT_PRESSED},
87 {PP_RESOURCEIMAGE_PDF_BUTTON_SAVE, IDR_PDF_BUTTON_SAVE},
88 {PP_RESOURCEIMAGE_PDF_BUTTON_SAVE_HOVER, IDR_PDF_BUTTON_SAVE_HOVER},
89 {PP_RESOURCEIMAGE_PDF_BUTTON_SAVE_PRESSED, IDR_PDF_BUTTON_SAVE_PRESSED},
90 {PP_RESOURCEIMAGE_PDF_BUTTON_PRINT, IDR_PDF_BUTTON_PRINT},
91 {PP_RESOURCEIMAGE_PDF_BUTTON_PRINT_HOVER, IDR_PDF_BUTTON_PRINT_HOVER},
92 {PP_RESOURCEIMAGE_PDF_BUTTON_PRINT_PRESSED, IDR_PDF_BUTTON_PRINT_PRESSED},
93 {PP_RESOURCEIMAGE_PDF_BUTTON_PRINT_DISABLED, IDR_PDF_BUTTON_PRINT_DISABLED},
94 {PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_0, IDR_PDF_THUMBNAIL_0},
95 {PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_1, IDR_PDF_THUMBNAIL_1},
96 {PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_2, IDR_PDF_THUMBNAIL_2},
97 {PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_3, IDR_PDF_THUMBNAIL_3},
98 {PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_4, IDR_PDF_THUMBNAIL_4},
99 {PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_5, IDR_PDF_THUMBNAIL_5},
100 {PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_6, IDR_PDF_THUMBNAIL_6},
101 {PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_7, IDR_PDF_THUMBNAIL_7},
102 {PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_8, IDR_PDF_THUMBNAIL_8},
103 {PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_9, IDR_PDF_THUMBNAIL_9},
104 {PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_NUM_BACKGROUND,
105 IDR_PDF_THUMBNAIL_NUM_BACKGROUND},
106 {PP_RESOURCEIMAGE_PDF_PROGRESS_BAR_0, IDR_PDF_PROGRESS_BAR_0},
107 {PP_RESOURCEIMAGE_PDF_PROGRESS_BAR_1, IDR_PDF_PROGRESS_BAR_1},
108 {PP_RESOURCEIMAGE_PDF_PROGRESS_BAR_2, IDR_PDF_PROGRESS_BAR_2},
109 {PP_RESOURCEIMAGE_PDF_PROGRESS_BAR_3, IDR_PDF_PROGRESS_BAR_3},
110 {PP_RESOURCEIMAGE_PDF_PROGRESS_BAR_4, IDR_PDF_PROGRESS_BAR_4},
111 {PP_RESOURCEIMAGE_PDF_PROGRESS_BAR_5, IDR_PDF_PROGRESS_BAR_5},
112 {PP_RESOURCEIMAGE_PDF_PROGRESS_BAR_6, IDR_PDF_PROGRESS_BAR_6},
113 {PP_RESOURCEIMAGE_PDF_PROGRESS_BAR_7, IDR_PDF_PROGRESS_BAR_7},
114 {PP_RESOURCEIMAGE_PDF_PROGRESS_BAR_8, IDR_PDF_PROGRESS_BAR_8},
115 {PP_RESOURCEIMAGE_PDF_PROGRESS_BAR_BACKGROUND,
116 IDR_PDF_PROGRESS_BAR_BACKGROUND},
117 {PP_RESOURCEIMAGE_PDF_PAGE_INDICATOR_BACKGROUND,
118 IDR_PDF_PAGE_INDICATOR_BACKGROUND},
119 {PP_RESOURCEIMAGE_PDF_PAGE_DROPSHADOW, IDR_PDF_PAGE_DROPSHADOW},
120 {PP_RESOURCEIMAGE_PDF_PAN_SCROLL_ICON, IDR_PAN_SCROLL_ICON}, };
122 #if defined(ENABLE_FULL_PRINTING)
124 blink::WebElement GetWebElement(PP_Instance instance_id) {
125 content::PepperPluginInstance* instance =
126 content::PepperPluginInstance::Get(instance_id);
127 if (!instance)
128 return blink::WebElement();
129 return instance->GetContainer()->element();
132 printing::PrintWebViewHelper* GetPrintWebViewHelper(
133 const blink::WebElement& element) {
134 if (element.isNull())
135 return NULL;
136 blink::WebView* view = element.document().frame()->view();
137 content::RenderView* render_view = content::RenderView::FromWebView(view);
138 return printing::PrintWebViewHelper::Get(render_view);
141 bool IsPrintingEnabled(PP_Instance instance_id) {
142 blink::WebElement element = GetWebElement(instance_id);
143 printing::PrintWebViewHelper* helper = GetPrintWebViewHelper(element);
144 return helper && helper->IsPrintingEnabled();
147 #else // ENABLE_FULL_PRINTING
149 bool IsPrintingEnabled(PP_Instance instance_id) { return false; }
151 #endif // ENABLE_FULL_PRINTING
153 PP_Var GetLocalizedString(PP_Instance instance_id,
154 PP_ResourceString string_id) {
155 content::PepperPluginInstance* instance =
156 content::PepperPluginInstance::Get(instance_id);
157 if (!instance)
158 return PP_MakeUndefined();
160 std::string rv;
161 if (string_id == PP_RESOURCESTRING_PDFGETPASSWORD) {
162 rv = base::UTF16ToUTF8(l10n_util::GetStringUTF16(IDS_PDF_NEED_PASSWORD));
163 } else if (string_id == PP_RESOURCESTRING_PDFLOADING) {
164 rv = base::UTF16ToUTF8(l10n_util::GetStringUTF16(IDS_PDF_PAGE_LOADING));
165 } else if (string_id == PP_RESOURCESTRING_PDFLOAD_FAILED) {
166 rv = base::UTF16ToUTF8(l10n_util::GetStringUTF16(IDS_PDF_PAGE_LOAD_FAILED));
167 } else if (string_id == PP_RESOURCESTRING_PDFPROGRESSLOADING) {
168 rv = base::UTF16ToUTF8(l10n_util::GetStringUTF16(IDS_PDF_PROGRESS_LOADING));
169 } else {
170 NOTREACHED();
173 return ppapi::StringVar::StringToPPVar(rv);
176 PP_Resource GetFontFileWithFallback(
177 PP_Instance instance_id,
178 const PP_BrowserFont_Trusted_Description* description,
179 PP_PrivateFontCharset charset) {
180 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
181 // Validate the instance before using it below.
182 if (!content::PepperPluginInstance::Get(instance_id))
183 return 0;
185 scoped_refptr<ppapi::StringVar> face_name(
186 ppapi::StringVar::FromPPVar(description->face));
187 if (!face_name)
188 return 0;
190 int fd = content::MatchFontWithFallback(
191 face_name->value().c_str(),
192 description->weight >= PP_BROWSERFONT_TRUSTED_WEIGHT_BOLD,
193 description->italic,
194 charset,
195 description->family);
196 if (fd == -1)
197 return 0;
199 scoped_refptr<PrivateFontFile> font(new PrivateFontFile(instance_id, fd));
201 return font->GetReference();
202 #else
203 // For trusted PPAPI plugins, this is only needed in Linux since font loading
204 // on Windows and Mac works through the renderer sandbox.
205 return 0;
206 #endif
209 bool GetFontTableForPrivateFontFile(PP_Resource font_file,
210 uint32_t table,
211 void* output,
212 uint32_t* output_length) {
213 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
214 ppapi::Resource* resource =
215 ppapi::PpapiGlobals::Get()->GetResourceTracker()->GetResource(font_file);
216 if (!resource)
217 return false;
219 PrivateFontFile* font = static_cast<PrivateFontFile*>(resource);
220 return font->GetFontTable(table, output, output_length);
221 #else
222 return false;
223 #endif
226 void SearchString(PP_Instance instance,
227 const unsigned short* input_string,
228 const unsigned short* input_term,
229 bool case_sensitive,
230 PP_PrivateFindResult** results,
231 int* count) {
232 const base::char16* string =
233 reinterpret_cast<const base::char16*>(input_string);
234 const base::char16* term = reinterpret_cast<const base::char16*>(input_term);
236 UErrorCode status = U_ZERO_ERROR;
237 UStringSearch* searcher =
238 usearch_open(term,
240 string,
242 content::RenderThread::Get()->GetLocale().c_str(),
244 &status);
245 DCHECK(status == U_ZERO_ERROR || status == U_USING_FALLBACK_WARNING ||
246 status == U_USING_DEFAULT_WARNING);
247 UCollationStrength strength = case_sensitive ? UCOL_TERTIARY : UCOL_PRIMARY;
249 UCollator* collator = usearch_getCollator(searcher);
250 if (ucol_getStrength(collator) != strength) {
251 ucol_setStrength(collator, strength);
252 usearch_reset(searcher);
255 status = U_ZERO_ERROR;
256 int match_start = usearch_first(searcher, &status);
257 DCHECK(status == U_ZERO_ERROR);
259 std::vector<PP_PrivateFindResult> pp_results;
260 while (match_start != USEARCH_DONE) {
261 size_t matched_length = usearch_getMatchedLength(searcher);
262 PP_PrivateFindResult result;
263 result.start_index = match_start;
264 result.length = matched_length;
265 pp_results.push_back(result);
266 match_start = usearch_next(searcher, &status);
267 DCHECK(status == U_ZERO_ERROR);
270 *count = pp_results.size();
271 if (*count) {
272 *results = reinterpret_cast<PP_PrivateFindResult*>(
273 malloc(*count * sizeof(PP_PrivateFindResult)));
274 memcpy(*results, &pp_results[0], *count * sizeof(PP_PrivateFindResult));
275 } else {
276 *results = NULL;
279 usearch_close(searcher);
282 void DidStartLoading(PP_Instance instance_id) {
283 content::PepperPluginInstance* instance =
284 content::PepperPluginInstance::Get(instance_id);
285 if (!instance)
286 return;
287 instance->GetRenderView()->DidStartLoading();
290 void DidStopLoading(PP_Instance instance_id) {
291 content::PepperPluginInstance* instance =
292 content::PepperPluginInstance::Get(instance_id);
293 if (!instance)
294 return;
295 instance->GetRenderView()->DidStopLoading();
298 void SetContentRestriction(PP_Instance instance_id, int restrictions) {
299 content::PepperPluginInstance* instance =
300 content::PepperPluginInstance::Get(instance_id);
301 if (!instance)
302 return;
303 instance->GetRenderView()->Send(
304 new ChromeViewHostMsg_PDFUpdateContentRestrictions(
305 instance->GetRenderView()->GetRoutingID(), restrictions));
308 void HistogramPDFPageCount(PP_Instance instance, int count) {
309 UMA_HISTOGRAM_COUNTS_10000("PDF.PageCount", count);
312 void UserMetricsRecordAction(PP_Instance instance, PP_Var action) {
313 scoped_refptr<ppapi::StringVar> action_str(
314 ppapi::StringVar::FromPPVar(action));
315 if (action_str)
316 content::RenderThread::Get()->RecordComputedAction(action_str->value());
319 void HasUnsupportedFeature(PP_Instance instance_id) {
320 content::PepperPluginInstance* instance =
321 content::PepperPluginInstance::Get(instance_id);
322 if (!instance)
323 return;
325 // Only want to show an info bar if the pdf is the whole tab.
326 if (!instance->IsFullPagePlugin())
327 return;
329 blink::WebView* view =
330 instance->GetContainer()->element().document().frame()->view();
331 content::RenderView* render_view = content::RenderView::FromWebView(view);
332 render_view->Send(new ChromeViewHostMsg_PDFHasUnsupportedFeature(
333 render_view->GetRoutingID()));
336 void SaveAs(PP_Instance instance_id) {
337 content::PepperPluginInstance* instance =
338 content::PepperPluginInstance::Get(instance_id);
339 if (!instance)
340 return;
341 GURL url = instance->GetPluginURL();
343 content::RenderView* render_view = instance->GetRenderView();
344 blink::WebLocalFrame* frame =
345 render_view->GetWebView()->mainFrame()->toWebLocalFrame();
346 content::Referrer referrer(frame->document().url(),
347 frame->document().referrerPolicy());
348 render_view->Send(new ChromeViewHostMsg_PDFSaveURLAs(
349 render_view->GetRoutingID(), url, referrer));
352 PP_Bool IsFeatureEnabled(PP_Instance instance, PP_PDFFeature feature) {
353 switch (feature) {
354 case PP_PDFFEATURE_HIDPI:
355 return PP_TRUE;
356 case PP_PDFFEATURE_PRINTING:
357 return IsPrintingEnabled(instance) ? PP_TRUE : PP_FALSE;
359 return PP_FALSE;
362 PP_Resource GetResourceImageForScale(PP_Instance instance_id,
363 PP_ResourceImage image_id,
364 float scale) {
365 int res_id = 0;
366 for (size_t i = 0; i < arraysize(kResourceImageMap); ++i) {
367 if (kResourceImageMap[i].pp_id == image_id) {
368 res_id = kResourceImageMap[i].res_id;
369 break;
372 if (res_id == 0)
373 return 0;
375 // Validate the instance.
376 content::PepperPluginInstance* instance =
377 content::PepperPluginInstance::Get(instance_id);
378 if (!instance)
379 return 0;
381 gfx::ImageSkia* res_image_skia =
382 ResourceBundle::GetSharedInstance().GetImageSkiaNamed(res_id);
384 if (!res_image_skia)
385 return 0;
387 return instance->CreateImage(res_image_skia, scale);
390 PP_Resource GetResourceImage(PP_Instance instance_id,
391 PP_ResourceImage image_id) {
392 return GetResourceImageForScale(instance_id, image_id, 1.0f);
395 PP_Var ModalPromptForPassword(PP_Instance instance_id, PP_Var message) {
396 content::PepperPluginInstance* instance =
397 content::PepperPluginInstance::Get(instance_id);
398 if (!instance)
399 return PP_MakeUndefined();
401 std::string actual_value;
402 scoped_refptr<ppapi::StringVar> message_string(
403 ppapi::StringVar::FromPPVar(message));
405 IPC::SyncMessage* msg = new ChromeViewHostMsg_PDFModalPromptForPassword(
406 instance->GetRenderView()->GetRoutingID(),
407 message_string->value(),
408 &actual_value);
409 msg->EnableMessagePumping();
410 instance->GetRenderView()->Send(msg);
412 return ppapi::StringVar::StringToPPVar(actual_value);
415 PP_Bool IsOutOfProcess(PP_Instance instance_id) { return PP_FALSE; }
417 void SetSelectedText(PP_Instance instance_id, const char* selected_text) {
418 // This function is intended for out of process PDF plugin.
421 void SetLinkUnderCursor(PP_Instance instance_id, const char* url) {
422 content::PepperPluginInstance* instance =
423 content::PepperPluginInstance::Get(instance_id);
424 if (!instance)
425 return;
426 instance->SetLinkUnderCursor(url);
429 const PPB_PDF ppb_pdf = { //
430 &GetLocalizedString, //
431 &GetResourceImage, //
432 &GetFontFileWithFallback, //
433 &GetFontTableForPrivateFontFile, //
434 &SearchString, //
435 &DidStartLoading, //
436 &DidStopLoading, //
437 &SetContentRestriction, //
438 &HistogramPDFPageCount, //
439 &UserMetricsRecordAction, //
440 &HasUnsupportedFeature, //
441 &SaveAs, //
442 &PPB_PDF_Impl::InvokePrintingForInstance, //
443 &IsFeatureEnabled, //
444 &GetResourceImageForScale, //
445 &ModalPromptForPassword, //
446 &IsOutOfProcess, //
447 &SetSelectedText, //
448 &SetLinkUnderCursor, //
451 } // namespace
453 // static
454 const PPB_PDF* PPB_PDF_Impl::GetInterface() { return &ppb_pdf; }
456 // static
457 void PPB_PDF_Impl::InvokePrintingForInstance(PP_Instance instance_id) {
458 #if defined(ENABLE_FULL_PRINTING)
459 blink::WebElement element = GetWebElement(instance_id);
460 printing::PrintWebViewHelper* helper = GetPrintWebViewHelper(element);
461 if (helper)
462 helper->PrintNode(element);
463 #endif // ENABLE_FULL_PRINTING