pdf_resource.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
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 "ppapi/proxy/pdf_resource.h"
6
7#include <stdlib.h>
8#include <string.h>
9
10#include "base/command_line.h"
11#include "base/metrics/histogram.h"
12#include "ppapi/c/pp_errors.h"
13#include "ppapi/c/private/ppb_pdf.h"
14#include "ppapi/proxy/ppapi_messages.h"
15#include "ppapi/proxy/ppb_image_data_proxy.h"
16#include "ppapi/shared_impl/var.h"
17#include "third_party/icu/public/i18n/unicode/usearch.h"
18
19namespace ppapi {
20namespace proxy {
21
22namespace {
23
24// TODO(raymes): This is just copied from render_thread_impl.cc. We should have
25// generic code somewhere to get the locale in the plugin.
26std::string GetLocale() {
27  // The browser process should have passed the locale to the plugin via the
28  // --lang command line flag.
29  const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
30  const std::string& lang = parsed_command_line.GetSwitchValueASCII("lang");
31  DCHECK(!lang.empty());
32  return lang;
33}
34
35}  // namespace
36
37PDFResource::PDFResource(Connection connection, PP_Instance instance)
38    : PluginResource(connection, instance) {
39  SendCreate(RENDERER, PpapiHostMsg_PDF_Create());
40}
41
42PDFResource::~PDFResource() {
43}
44
45thunk::PPB_PDF_API* PDFResource::AsPPB_PDF_API() {
46  return this;
47}
48
49PP_Var PDFResource::GetLocalizedString(PP_ResourceString string_id) {
50  std::string localized_string;
51  int32_t result = SyncCall<PpapiPluginMsg_PDF_GetLocalizedStringReply>(
52      RENDERER, PpapiHostMsg_PDF_GetLocalizedString(string_id),
53      &localized_string);
54  if (result != PP_OK)
55    return PP_MakeUndefined();
56  return ppapi::StringVar::StringToPPVar(localized_string);
57}
58
59void PDFResource::SearchString(const unsigned short* input_string,
60                               const unsigned short* input_term,
61                               bool case_sensitive,
62                               PP_PrivateFindResult** results, int* count) {
63  if (locale_.empty())
64    locale_ = GetLocale();
65  const char16* string = reinterpret_cast<const char16*>(input_string);
66  const char16* term = reinterpret_cast<const char16*>(input_term);
67
68  UErrorCode status = U_ZERO_ERROR;
69  UStringSearch* searcher = usearch_open(term, -1, string, -1, locale_.c_str(),
70                                         0, &status);
71  DCHECK(status == U_ZERO_ERROR || status == U_USING_FALLBACK_WARNING ||
72         status == U_USING_DEFAULT_WARNING);
73  UCollationStrength strength = case_sensitive ? UCOL_TERTIARY : UCOL_PRIMARY;
74
75  UCollator* collator = usearch_getCollator(searcher);
76  if (ucol_getStrength(collator) != strength) {
77    ucol_setStrength(collator, strength);
78    usearch_reset(searcher);
79  }
80
81  status = U_ZERO_ERROR;
82  int match_start = usearch_first(searcher, &status);
83  DCHECK(status == U_ZERO_ERROR);
84
85  std::vector<PP_PrivateFindResult> pp_results;
86  while (match_start != USEARCH_DONE) {
87    size_t matched_length = usearch_getMatchedLength(searcher);
88    PP_PrivateFindResult result;
89    result.start_index = match_start;
90    result.length = matched_length;
91    pp_results.push_back(result);
92    match_start = usearch_next(searcher, &status);
93    DCHECK(status == U_ZERO_ERROR);
94  }
95
96  *count = pp_results.size();
97  if (*count) {
98    *results = reinterpret_cast<PP_PrivateFindResult*>(malloc(
99        *count * sizeof(PP_PrivateFindResult)));
100    memcpy(*results, &pp_results[0], *count * sizeof(PP_PrivateFindResult));
101  } else {
102    *results = NULL;
103  }
104
105  usearch_close(searcher);
106}
107
108void PDFResource::DidStartLoading() {
109  Post(RENDERER, PpapiHostMsg_PDF_DidStartLoading());
110}
111
112void PDFResource::DidStopLoading() {
113  Post(RENDERER, PpapiHostMsg_PDF_DidStopLoading());
114}
115
116void PDFResource::SetContentRestriction(int restrictions) {
117  Post(RENDERER, PpapiHostMsg_PDF_SetContentRestriction(restrictions));
118}
119
120void PDFResource::HistogramPDFPageCount(int count) {
121  UMA_HISTOGRAM_COUNTS_10000("PDF.PageCount", count);
122}
123
124void PDFResource::UserMetricsRecordAction(const PP_Var& action) {
125  scoped_refptr<ppapi::StringVar> action_str(
126      ppapi::StringVar::FromPPVar(action));
127  if (action_str) {
128    Post(RENDERER,
129         PpapiHostMsg_PDF_UserMetricsRecordAction(action_str->value()));
130  }
131}
132
133void PDFResource::HasUnsupportedFeature() {
134  Post(RENDERER, PpapiHostMsg_PDF_HasUnsupportedFeature());
135}
136
137void PDFResource::Print() {
138  Post(RENDERER, PpapiHostMsg_PDF_Print());
139}
140
141void PDFResource::SaveAs() {
142  Post(RENDERER, PpapiHostMsg_PDF_SaveAs());
143}
144
145PP_Bool PDFResource::IsFeatureEnabled(PP_PDFFeature feature) {
146  PP_Bool result = PP_FALSE;
147  switch (feature) {
148    case PP_PDFFEATURE_HIDPI:
149      result = PP_TRUE;
150      break;
151    case PP_PDFFEATURE_PRINTING:
152      // TODO(raymes): Use PrintWebViewHelper::IsPrintingEnabled.
153      result = PP_FALSE;
154      break;
155  }
156  return result;
157}
158
159PP_Resource PDFResource::GetResourceImageForScale(PP_ResourceImage image_id,
160                                                  float scale) {
161  IPC::Message reply;
162  ResourceMessageReplyParams reply_params;
163  int32_t result = GenericSyncCall(
164      RENDERER, PpapiHostMsg_PDF_GetResourceImage(image_id, scale), &reply,
165      &reply_params);
166  if (result != PP_OK)
167    return 0;
168
169  HostResource resource;
170  PP_ImageDataDesc image_desc;
171  int fd;
172  if (!UnpackMessage<PpapiPluginMsg_PDF_GetResourceImageReply>(
173      reply, &resource, &image_desc, &fd)) {
174    return 0;
175  }
176
177  if (resource.is_null())
178    return 0;
179  if (!PPB_ImageData_Shared::IsImageDataDescValid(image_desc))
180    return 0;
181
182#if defined(OS_ANDROID)
183  // This is compiled into android for tests only.
184  return 0;
185#elif defined(TOOLKIT_GTK)
186  return (new ImageData(resource, image_desc, fd))->GetReference();
187#elif defined(OS_LINUX) || defined(OS_WIN) || defined(OS_MACOSX)
188  base::SharedMemoryHandle handle;
189  if (!reply_params.TakeSharedMemoryHandleAtIndex(0, &handle))
190    return 0;
191  return (new ImageData(resource, image_desc, handle))->GetReference();
192#else
193#error Not implemented.
194#endif
195}
196
197PP_Resource PDFResource::GetResourceImage(PP_ResourceImage image_id) {
198  return GetResourceImageForScale(image_id, 1.0f);
199}
200
201}  // namespace proxy
202}  // namespace ppapi
203