Home | History | Annotate | Download | only in proxy
      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.
      4 
      5 #include "ppapi/proxy/ppp_printing_proxy.h"
      6 
      7 #include <string.h>
      8 
      9 #include "ppapi/c/dev/ppp_printing_dev.h"
     10 #include "ppapi/proxy/host_dispatcher.h"
     11 #include "ppapi/proxy/plugin_dispatcher.h"
     12 #include "ppapi/proxy/ppapi_messages.h"
     13 #include "ppapi/shared_impl/ppapi_globals.h"
     14 #include "ppapi/shared_impl/proxy_lock.h"
     15 #include "ppapi/shared_impl/resource_tracker.h"
     16 
     17 namespace ppapi {
     18 namespace proxy {
     19 
     20 namespace {
     21 
     22 #if !defined(OS_NACL)
     23 bool HasPrintingPermission(PP_Instance instance) {
     24   Dispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
     25   if (!dispatcher)
     26     return false;
     27   return dispatcher->permissions().HasPermission(PERMISSION_DEV);
     28 }
     29 
     30 uint32_t QuerySupportedFormats(PP_Instance instance) {
     31   if (!HasPrintingPermission(instance))
     32     return 0;
     33   uint32_t result = 0;
     34   HostDispatcher::GetForInstance(instance)->Send(
     35       new PpapiMsg_PPPPrinting_QuerySupportedFormats(API_ID_PPP_PRINTING,
     36                                                      instance, &result));
     37   return result;
     38 }
     39 
     40 int32_t Begin(PP_Instance instance,
     41               const struct PP_PrintSettings_Dev* print_settings) {
     42   if (!HasPrintingPermission(instance))
     43     return 0;
     44   // Settings is just serialized as a string.
     45   std::string settings_string;
     46   settings_string.resize(sizeof(*print_settings));
     47   memcpy(&settings_string[0], print_settings, sizeof(*print_settings));
     48 
     49   int32_t result = 0;
     50   HostDispatcher::GetForInstance(instance)->Send(
     51       new PpapiMsg_PPPPrinting_Begin(API_ID_PPP_PRINTING, instance,
     52                                      settings_string, &result));
     53   return result;
     54 }
     55 
     56 PP_Resource PrintPages(PP_Instance instance,
     57                        const PP_PrintPageNumberRange_Dev* page_ranges,
     58                        uint32_t page_range_count) {
     59   if (!HasPrintingPermission(instance))
     60     return 0;
     61   std::vector<PP_PrintPageNumberRange_Dev> pages(
     62       page_ranges, page_ranges + page_range_count);
     63 
     64   HostResource result;
     65   HostDispatcher::GetForInstance(instance)->Send(
     66       new PpapiMsg_PPPPrinting_PrintPages(API_ID_PPP_PRINTING,
     67                                           instance, pages, &result));
     68 
     69   // How refcounting works when returning a resource:
     70   //
     71   // The plugin in the plugin process makes a resource that it returns to the
     72   // browser. The plugin proxy code returns that ref to us and asynchronously
     73   // releases it. Before any release message associated with that operation
     74   // comes, we'll get this reply. We need to add one ref since our caller
     75   // expects us to add one ref for it to consume.
     76   PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(
     77       result.host_resource());
     78   return result.host_resource();
     79 }
     80 
     81 void End(PP_Instance instance) {
     82   if (!HasPrintingPermission(instance))
     83     return;
     84   HostDispatcher::GetForInstance(instance)->Send(
     85       new PpapiMsg_PPPPrinting_End(API_ID_PPP_PRINTING, instance));
     86 }
     87 
     88 PP_Bool IsScalingDisabled(PP_Instance instance) {
     89   if (!HasPrintingPermission(instance))
     90     return PP_FALSE;
     91   bool result = false;
     92   HostDispatcher::GetForInstance(instance)->Send(
     93       new PpapiMsg_PPPPrinting_IsScalingDisabled(API_ID_PPP_PRINTING,
     94                                                  instance, &result));
     95   return PP_FromBool(result);
     96 }
     97 
     98 const PPP_Printing_Dev ppp_printing_interface = {
     99   &QuerySupportedFormats,
    100   &Begin,
    101   &PrintPages,
    102   &End,
    103   &IsScalingDisabled
    104 };
    105 #else
    106 // The NaCl plugin doesn't need the host side interface - stub it out.
    107 static const PPP_Printing_Dev ppp_printing_interface = {};
    108 #endif  // !defined(OS_NACL)
    109 
    110 }  // namespace
    111 
    112 PPP_Printing_Proxy::PPP_Printing_Proxy(Dispatcher* dispatcher)
    113     : InterfaceProxy(dispatcher),
    114       ppp_printing_impl_(NULL) {
    115   if (dispatcher->IsPlugin()) {
    116     ppp_printing_impl_ = static_cast<const PPP_Printing_Dev*>(
    117         dispatcher->local_get_interface()(PPP_PRINTING_DEV_INTERFACE));
    118   }
    119 }
    120 
    121 PPP_Printing_Proxy::~PPP_Printing_Proxy() {
    122 }
    123 
    124 // static
    125 const PPP_Printing_Dev* PPP_Printing_Proxy::GetProxyInterface() {
    126   return &ppp_printing_interface;
    127 }
    128 
    129 bool PPP_Printing_Proxy::OnMessageReceived(const IPC::Message& msg) {
    130   if (!dispatcher()->IsPlugin())
    131     return false;
    132 
    133   bool handled = true;
    134   IPC_BEGIN_MESSAGE_MAP(PPP_Printing_Proxy, msg)
    135     IPC_MESSAGE_HANDLER(PpapiMsg_PPPPrinting_QuerySupportedFormats,
    136                         OnPluginMsgQuerySupportedFormats)
    137     IPC_MESSAGE_HANDLER(PpapiMsg_PPPPrinting_Begin,
    138                         OnPluginMsgBegin)
    139     IPC_MESSAGE_HANDLER(PpapiMsg_PPPPrinting_PrintPages,
    140                         OnPluginMsgPrintPages)
    141     IPC_MESSAGE_HANDLER(PpapiMsg_PPPPrinting_End,
    142                         OnPluginMsgEnd)
    143     IPC_MESSAGE_HANDLER(PpapiMsg_PPPPrinting_IsScalingDisabled,
    144                         OnPluginMsgIsScalingDisabled)
    145     IPC_MESSAGE_UNHANDLED(handled = false)
    146   IPC_END_MESSAGE_MAP()
    147   return handled;
    148 }
    149 
    150 void PPP_Printing_Proxy::OnPluginMsgQuerySupportedFormats(PP_Instance instance,
    151                                                           uint32_t* result) {
    152   if (ppp_printing_impl_) {
    153     *result = CallWhileUnlocked(ppp_printing_impl_->QuerySupportedFormats,
    154                                 instance);
    155   } else {
    156     *result = 0;
    157   }
    158 }
    159 
    160 void PPP_Printing_Proxy::OnPluginMsgBegin(PP_Instance instance,
    161                                           const std::string& settings_string,
    162                                           int32_t* result) {
    163   *result = 0;
    164 
    165   PP_PrintSettings_Dev settings;
    166   if (settings_string.size() != sizeof(settings))
    167     return;
    168   memcpy(&settings, &settings_string[0], sizeof(settings));
    169 
    170   if (ppp_printing_impl_) {
    171     *result = CallWhileUnlocked(ppp_printing_impl_->Begin,
    172         instance,
    173         const_cast<const PP_PrintSettings_Dev*>(&settings));
    174   }
    175 }
    176 
    177 void PPP_Printing_Proxy::OnPluginMsgPrintPages(
    178     PP_Instance instance,
    179     const std::vector<PP_PrintPageNumberRange_Dev>& pages,
    180     HostResource* result) {
    181   if (!ppp_printing_impl_ || pages.empty())
    182     return;
    183 
    184   PP_Resource plugin_resource = CallWhileUnlocked(
    185       ppp_printing_impl_->PrintPages,
    186       instance, &pages[0], static_cast<uint32_t>(pages.size()));
    187   ResourceTracker* resource_tracker = PpapiGlobals::Get()->GetResourceTracker();
    188   Resource* resource_object = resource_tracker->GetResource(plugin_resource);
    189   if (!resource_object)
    190     return;
    191 
    192   *result = resource_object->host_resource();
    193 
    194   // See PrintPages above for how refcounting works.
    195   resource_tracker->ReleaseResourceSoon(plugin_resource);
    196 }
    197 
    198 void PPP_Printing_Proxy::OnPluginMsgEnd(PP_Instance instance) {
    199   if (ppp_printing_impl_)
    200     CallWhileUnlocked(ppp_printing_impl_->End, instance);
    201 }
    202 
    203 void PPP_Printing_Proxy::OnPluginMsgIsScalingDisabled(PP_Instance instance,
    204                                                       bool* result) {
    205   if (ppp_printing_impl_) {
    206     *result = PP_ToBool(CallWhileUnlocked(ppp_printing_impl_->IsScalingDisabled,
    207                                           instance));
    208   } else {
    209     *result = false;
    210   }
    211 }
    212 
    213 }  // namespace proxy
    214 }  // namespace ppapi
    215