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.
5 #include "ppapi/proxy/ppp_printing_proxy.h"
9 #include "base/numerics/safe_conversions.h"
10 #include "ppapi/c/dev/ppp_printing_dev.h"
11 #include "ppapi/proxy/host_dispatcher.h"
12 #include "ppapi/proxy/plugin_dispatcher.h"
13 #include "ppapi/proxy/ppapi_messages.h"
14 #include "ppapi/shared_impl/ppapi_globals.h"
15 #include "ppapi/shared_impl/proxy_lock.h"
16 #include "ppapi/shared_impl/resource_tracker.h"
24 bool HasPrintingPermission(PP_Instance instance
) {
25 Dispatcher
* dispatcher
= HostDispatcher::GetForInstance(instance
);
28 return dispatcher
->permissions().HasPermission(PERMISSION_DEV
);
31 uint32_t QuerySupportedFormats(PP_Instance instance
) {
32 if (!HasPrintingPermission(instance
))
35 HostDispatcher::GetForInstance(instance
)->Send(
36 new PpapiMsg_PPPPrinting_QuerySupportedFormats(API_ID_PPP_PRINTING
,
41 int32_t Begin(PP_Instance instance
,
42 const struct PP_PrintSettings_Dev
* print_settings
) {
43 if (!HasPrintingPermission(instance
))
45 // Settings is just serialized as a string.
46 std::string settings_string
;
47 settings_string
.resize(sizeof(*print_settings
));
48 memcpy(&settings_string
[0], print_settings
, sizeof(*print_settings
));
51 HostDispatcher::GetForInstance(instance
)->Send(
52 new PpapiMsg_PPPPrinting_Begin(API_ID_PPP_PRINTING
, instance
,
53 settings_string
, &result
));
57 PP_Resource
PrintPages(PP_Instance instance
,
58 const PP_PrintPageNumberRange_Dev
* page_ranges
,
59 uint32_t page_range_count
) {
60 if (!HasPrintingPermission(instance
))
62 std::vector
<PP_PrintPageNumberRange_Dev
> pages(
63 page_ranges
, page_ranges
+ page_range_count
);
66 HostDispatcher::GetForInstance(instance
)->Send(
67 new PpapiMsg_PPPPrinting_PrintPages(API_ID_PPP_PRINTING
,
68 instance
, pages
, &result
));
70 // How refcounting works when returning a resource:
72 // The plugin in the plugin process makes a resource that it returns to the
73 // browser. The plugin proxy code returns that ref to us and asynchronously
74 // releases it. Before any release message associated with that operation
75 // comes, we'll get this reply. We need to add one ref since our caller
76 // expects us to add one ref for it to consume.
77 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(
78 result
.host_resource());
79 return result
.host_resource();
82 void End(PP_Instance instance
) {
83 if (!HasPrintingPermission(instance
))
85 HostDispatcher::GetForInstance(instance
)->Send(
86 new PpapiMsg_PPPPrinting_End(API_ID_PPP_PRINTING
, instance
));
89 PP_Bool
IsScalingDisabled(PP_Instance instance
) {
90 if (!HasPrintingPermission(instance
))
93 HostDispatcher::GetForInstance(instance
)->Send(
94 new PpapiMsg_PPPPrinting_IsScalingDisabled(API_ID_PPP_PRINTING
,
96 return PP_FromBool(result
);
99 const PPP_Printing_Dev ppp_printing_interface
= {
100 &QuerySupportedFormats
,
107 // The NaCl plugin doesn't need the host side interface - stub it out.
108 static const PPP_Printing_Dev ppp_printing_interface
= {};
109 #endif // !defined(OS_NACL)
113 PPP_Printing_Proxy::PPP_Printing_Proxy(Dispatcher
* dispatcher
)
114 : InterfaceProxy(dispatcher
),
115 ppp_printing_impl_(NULL
) {
116 if (dispatcher
->IsPlugin()) {
117 ppp_printing_impl_
= static_cast<const PPP_Printing_Dev
*>(
118 dispatcher
->local_get_interface()(PPP_PRINTING_DEV_INTERFACE
));
122 PPP_Printing_Proxy::~PPP_Printing_Proxy() {
126 const PPP_Printing_Dev
* PPP_Printing_Proxy::GetProxyInterface() {
127 return &ppp_printing_interface
;
130 bool PPP_Printing_Proxy::OnMessageReceived(const IPC::Message
& msg
) {
131 if (!dispatcher()->IsPlugin())
135 IPC_BEGIN_MESSAGE_MAP(PPP_Printing_Proxy
, msg
)
136 IPC_MESSAGE_HANDLER(PpapiMsg_PPPPrinting_QuerySupportedFormats
,
137 OnPluginMsgQuerySupportedFormats
)
138 IPC_MESSAGE_HANDLER(PpapiMsg_PPPPrinting_Begin
,
140 IPC_MESSAGE_HANDLER(PpapiMsg_PPPPrinting_PrintPages
,
141 OnPluginMsgPrintPages
)
142 IPC_MESSAGE_HANDLER(PpapiMsg_PPPPrinting_End
,
144 IPC_MESSAGE_HANDLER(PpapiMsg_PPPPrinting_IsScalingDisabled
,
145 OnPluginMsgIsScalingDisabled
)
146 IPC_MESSAGE_UNHANDLED(handled
= false)
147 IPC_END_MESSAGE_MAP()
151 void PPP_Printing_Proxy::OnPluginMsgQuerySupportedFormats(PP_Instance instance
,
153 if (ppp_printing_impl_
) {
154 *result
= CallWhileUnlocked(ppp_printing_impl_
->QuerySupportedFormats
,
161 void PPP_Printing_Proxy::OnPluginMsgBegin(PP_Instance instance
,
162 const std::string
& settings_string
,
166 PP_PrintSettings_Dev settings
;
167 if (settings_string
.size() != sizeof(settings
))
169 memcpy(&settings
, &settings_string
[0], sizeof(settings
));
171 if (ppp_printing_impl_
)
172 *result
= CallWhileUnlocked(ppp_printing_impl_
->Begin
, instance
, &settings
);
175 void PPP_Printing_Proxy::OnPluginMsgPrintPages(
176 PP_Instance instance
,
177 const std::vector
<PP_PrintPageNumberRange_Dev
>& pages
,
178 HostResource
* result
) {
179 if (!ppp_printing_impl_
|| pages
.empty())
182 PP_Resource plugin_resource
= CallWhileUnlocked(
183 ppp_printing_impl_
->PrintPages
,
184 instance
, &pages
[0], base::checked_cast
<uint32_t>(pages
.size()));
185 ResourceTracker
* resource_tracker
= PpapiGlobals::Get()->GetResourceTracker();
186 Resource
* resource_object
= resource_tracker
->GetResource(plugin_resource
);
187 if (!resource_object
)
190 *result
= resource_object
->host_resource();
192 // See PrintPages above for how refcounting works.
193 resource_tracker
->ReleaseResourceSoon(plugin_resource
);
196 void PPP_Printing_Proxy::OnPluginMsgEnd(PP_Instance instance
) {
197 if (ppp_printing_impl_
)
198 CallWhileUnlocked(ppp_printing_impl_
->End
, instance
);
201 void PPP_Printing_Proxy::OnPluginMsgIsScalingDisabled(PP_Instance instance
,
203 if (ppp_printing_impl_
) {
204 *result
= PP_ToBool(CallWhileUnlocked(ppp_printing_impl_
->IsScalingDisabled
,