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/source/i18n/unicode/usearch.h" 18 19 namespace ppapi { 20 namespace proxy { 21 22 namespace { 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. 26 std::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 37 PDFResource::PDFResource(Connection connection, PP_Instance instance) 38 : PluginResource(connection, instance) { 39 SendCreate(RENDERER, PpapiHostMsg_PDF_Create()); 40 } 41 42 PDFResource::~PDFResource() { 43 } 44 45 thunk::PPB_PDF_API* PDFResource::AsPPB_PDF_API() { 46 return this; 47 } 48 49 PP_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 59 void 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 108 void PDFResource::DidStartLoading() { 109 Post(RENDERER, PpapiHostMsg_PDF_DidStartLoading()); 110 } 111 112 void PDFResource::DidStopLoading() { 113 Post(RENDERER, PpapiHostMsg_PDF_DidStopLoading()); 114 } 115 116 void PDFResource::SetContentRestriction(int restrictions) { 117 Post(RENDERER, PpapiHostMsg_PDF_SetContentRestriction(restrictions)); 118 } 119 120 void PDFResource::HistogramPDFPageCount(int count) { 121 UMA_HISTOGRAM_COUNTS_10000("PDF.PageCount", count); 122 } 123 124 void PDFResource::UserMetricsRecordAction(const PP_Var& action) { 125 scoped_refptr<ppapi::StringVar> action_str( 126 ppapi::StringVar::FromPPVar(action)); 127 if (action_str.get()) { 128 Post(RENDERER, 129 PpapiHostMsg_PDF_UserMetricsRecordAction(action_str->value())); 130 } 131 } 132 133 void PDFResource::HasUnsupportedFeature() { 134 Post(RENDERER, PpapiHostMsg_PDF_HasUnsupportedFeature()); 135 } 136 137 void PDFResource::Print() { 138 Post(RENDERER, PpapiHostMsg_PDF_Print()); 139 } 140 141 void PDFResource::SaveAs() { 142 Post(RENDERER, PpapiHostMsg_PDF_SaveAs()); 143 } 144 145 PP_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 159 PP_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 if (!UnpackMessage<PpapiPluginMsg_PDF_GetResourceImageReply>( 172 reply, &resource, &image_desc)) { 173 return 0; 174 } 175 176 if (resource.is_null()) 177 return 0; 178 if (!PPB_ImageData_Shared::IsImageDataDescValid(image_desc)) 179 return 0; 180 181 base::SharedMemoryHandle handle; 182 if (!reply_params.TakeSharedMemoryHandleAtIndex(0, &handle)) 183 return 0; 184 return (new SimpleImageData(resource, image_desc, handle))->GetReference(); 185 } 186 187 PP_Resource PDFResource::GetResourceImage(PP_ResourceImage image_id) { 188 return GetResourceImageForScale(image_id, 1.0f); 189 } 190 191 PP_Bool PDFResource::IsOutOfProcess() { 192 return PP_TRUE; 193 } 194 195 } // namespace proxy 196 } // namespace ppapi 197