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