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)
HasPrintingPermission(PP_Instance instance)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
QuerySupportedFormats(PP_Instance instance)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
Begin(PP_Instance instance,const struct PP_PrintSettings_Dev * print_settings)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
PrintPages(PP_Instance instance,const PP_PrintPageNumberRange_Dev * page_ranges,uint32_t page_range_count)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
End(PP_Instance instance)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
IsScalingDisabled(PP_Instance instance)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
PPP_Printing_Proxy(Dispatcher * dispatcher)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
~PPP_Printing_Proxy()121 PPP_Printing_Proxy::~PPP_Printing_Proxy() {
122 }
123
124 // static
GetProxyInterface()125 const PPP_Printing_Dev* PPP_Printing_Proxy::GetProxyInterface() {
126 return &ppp_printing_interface;
127 }
128
OnMessageReceived(const IPC::Message & msg)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
OnPluginMsgQuerySupportedFormats(PP_Instance instance,uint32_t * result)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
OnPluginMsgBegin(PP_Instance instance,const std::string & settings_string,int32_t * result)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
OnPluginMsgPrintPages(PP_Instance instance,const std::vector<PP_PrintPageNumberRange_Dev> & pages,HostResource * result)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
OnPluginMsgEnd(PP_Instance instance)198 void PPP_Printing_Proxy::OnPluginMsgEnd(PP_Instance instance) {
199 if (ppp_printing_impl_)
200 CallWhileUnlocked(ppp_printing_impl_->End, instance);
201 }
202
OnPluginMsgIsScalingDisabled(PP_Instance instance,bool * result)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