// Copyright (c) 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "ppapi/proxy/pdf_resource.h" #include #include #include "base/command_line.h" #include "base/metrics/histogram.h" #include "ppapi/c/pp_errors.h" #include "ppapi/c/private/ppb_pdf.h" #include "ppapi/proxy/ppapi_messages.h" #include "ppapi/proxy/ppb_image_data_proxy.h" #include "ppapi/shared_impl/var.h" #include "third_party/icu/public/i18n/unicode/usearch.h" namespace ppapi { namespace proxy { namespace { // TODO(raymes): This is just copied from render_thread_impl.cc. We should have // generic code somewhere to get the locale in the plugin. std::string GetLocale() { // The browser process should have passed the locale to the plugin via the // --lang command line flag. const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess(); const std::string& lang = parsed_command_line.GetSwitchValueASCII("lang"); DCHECK(!lang.empty()); return lang; } } // namespace PDFResource::PDFResource(Connection connection, PP_Instance instance) : PluginResource(connection, instance) { SendCreate(RENDERER, PpapiHostMsg_PDF_Create()); } PDFResource::~PDFResource() { } thunk::PPB_PDF_API* PDFResource::AsPPB_PDF_API() { return this; } PP_Var PDFResource::GetLocalizedString(PP_ResourceString string_id) { std::string localized_string; int32_t result = SyncCall( RENDERER, PpapiHostMsg_PDF_GetLocalizedString(string_id), &localized_string); if (result != PP_OK) return PP_MakeUndefined(); return ppapi::StringVar::StringToPPVar(localized_string); } void PDFResource::SearchString(const unsigned short* input_string, const unsigned short* input_term, bool case_sensitive, PP_PrivateFindResult** results, int* count) { if (locale_.empty()) locale_ = GetLocale(); const char16* string = reinterpret_cast(input_string); const char16* term = reinterpret_cast(input_term); UErrorCode status = U_ZERO_ERROR; UStringSearch* searcher = usearch_open(term, -1, string, -1, locale_.c_str(), 0, &status); DCHECK(status == U_ZERO_ERROR || status == U_USING_FALLBACK_WARNING || status == U_USING_DEFAULT_WARNING); UCollationStrength strength = case_sensitive ? UCOL_TERTIARY : UCOL_PRIMARY; UCollator* collator = usearch_getCollator(searcher); if (ucol_getStrength(collator) != strength) { ucol_setStrength(collator, strength); usearch_reset(searcher); } status = U_ZERO_ERROR; int match_start = usearch_first(searcher, &status); DCHECK(status == U_ZERO_ERROR); std::vector pp_results; while (match_start != USEARCH_DONE) { size_t matched_length = usearch_getMatchedLength(searcher); PP_PrivateFindResult result; result.start_index = match_start; result.length = matched_length; pp_results.push_back(result); match_start = usearch_next(searcher, &status); DCHECK(status == U_ZERO_ERROR); } *count = pp_results.size(); if (*count) { *results = reinterpret_cast(malloc( *count * sizeof(PP_PrivateFindResult))); memcpy(*results, &pp_results[0], *count * sizeof(PP_PrivateFindResult)); } else { *results = NULL; } usearch_close(searcher); } void PDFResource::DidStartLoading() { Post(RENDERER, PpapiHostMsg_PDF_DidStartLoading()); } void PDFResource::DidStopLoading() { Post(RENDERER, PpapiHostMsg_PDF_DidStopLoading()); } void PDFResource::SetContentRestriction(int restrictions) { Post(RENDERER, PpapiHostMsg_PDF_SetContentRestriction(restrictions)); } void PDFResource::HistogramPDFPageCount(int count) { UMA_HISTOGRAM_COUNTS_10000("PDF.PageCount", count); } void PDFResource::UserMetricsRecordAction(const PP_Var& action) { scoped_refptr action_str( ppapi::StringVar::FromPPVar(action)); if (action_str) { Post(RENDERER, PpapiHostMsg_PDF_UserMetricsRecordAction(action_str->value())); } } void PDFResource::HasUnsupportedFeature() { Post(RENDERER, PpapiHostMsg_PDF_HasUnsupportedFeature()); } void PDFResource::Print() { Post(RENDERER, PpapiHostMsg_PDF_Print()); } void PDFResource::SaveAs() { Post(RENDERER, PpapiHostMsg_PDF_SaveAs()); } PP_Bool PDFResource::IsFeatureEnabled(PP_PDFFeature feature) { PP_Bool result = PP_FALSE; switch (feature) { case PP_PDFFEATURE_HIDPI: result = PP_TRUE; break; } return result; } PP_Resource PDFResource::GetResourceImageForScale(PP_ResourceImage image_id, float scale) { IPC::Message reply; ResourceMessageReplyParams reply_params; int32_t result = GenericSyncCall( RENDERER, PpapiHostMsg_PDF_GetResourceImage(image_id, scale), &reply, &reply_params); if (result != PP_OK) return 0; HostResource resource; std::string image_data_desc; int fd; if (!UnpackMessage( reply, &resource, &image_data_desc, &fd)) { return 0; } if (resource.is_null() || image_data_desc.size() != sizeof(PP_ImageDataDesc)) return 0; // We serialize the PP_ImageDataDesc just by copying to a string. PP_ImageDataDesc desc; memcpy(&desc, image_data_desc.data(), sizeof(PP_ImageDataDesc)); #if defined(OS_ANDROID) // This is compiled into android for tests only. return 0; #elif defined(OS_WIN) || defined(OS_MACOSX) base::SharedMemoryHandle handle; if (!reply_params.TakeSharedMemoryHandleAtIndex(0, &handle)) return 0; return (new ImageData(resource, desc, handle))->GetReference(); #elif defined(OS_LINUX) return (new ImageData(resource, desc, fd))->GetReference(); #else #error Not implemented. #endif } PP_Resource PDFResource::GetResourceImage(PP_ResourceImage image_id) { return GetResourceImageForScale(image_id, 1.0f); } } // namespace proxy } // namespace ppapi