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, instance, &settings);
    172 }
    173 
    174 void PPP_Printing_Proxy::OnPluginMsgPrintPages(
    175     PP_Instance instance,
    176     const std::vector<PP_PrintPageNumberRange_Dev>& pages,
    177     HostResource* result) {
    178   if (!ppp_printing_impl_ || pages.empty())
    179     return;
    180 
    181   PP_Resource plugin_resource = CallWhileUnlocked(
    182       ppp_printing_impl_->PrintPages,
    183       instance, &pages[0], pages.size());
    184   ResourceTracker* resource_tracker = PpapiGlobals::Get()->GetResourceTracker();
    185   Resource* resource_object = resource_tracker->GetResource(plugin_resource);
    186   if (!resource_object)
    187     return;
    188 
    189   *result = resource_object->host_resource();
    190 
    191   // See PrintPages above for how refcounting works.
    192   resource_tracker->ReleaseResourceSoon(plugin_resource);
    193 }
    194 
    195 void PPP_Printing_Proxy::OnPluginMsgEnd(PP_Instance instance) {
    196   if (ppp_printing_impl_)
    197     CallWhileUnlocked(ppp_printing_impl_->End, instance);
    198 }
    199 
    200 void PPP_Printing_Proxy::OnPluginMsgIsScalingDisabled(PP_Instance instance,
    201                                                       bool* result) {
    202   if (ppp_printing_impl_) {
    203     *result = PP_ToBool(CallWhileUnlocked(ppp_printing_impl_->IsScalingDisabled,
    204                                           instance));
    205   } else {
    206     *result = false;
    207   }
    208 }
    209 
    210 }  // namespace proxy
    211 }  // namespace ppapi
    212