Elim cr-checkbox
[chromium-blink-merge.git] / ppapi / proxy / ppp_printing_proxy.cc
blob81710efcc5f66d75410a1d77ad4d4eba55ac5138
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"
7 #include <string.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/plugin_resource_tracker.h"
14 #include "ppapi/proxy/ppapi_messages.h"
15 #include "ppapi/shared_impl/ppapi_globals.h"
16 #include "ppapi/shared_impl/proxy_lock.h"
17 #include "ppapi/shared_impl/resource_tracker.h"
19 namespace ppapi {
20 namespace proxy {
22 namespace {
24 #if !defined(OS_NACL)
25 bool HasPrintingPermission(PP_Instance instance) {
26 Dispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
27 if (!dispatcher)
28 return false;
29 return dispatcher->permissions().HasPermission(PERMISSION_DEV);
32 uint32_t QuerySupportedFormats(PP_Instance instance) {
33 if (!HasPrintingPermission(instance))
34 return 0;
35 uint32_t result = 0;
36 HostDispatcher::GetForInstance(instance)->Send(
37 new PpapiMsg_PPPPrinting_QuerySupportedFormats(API_ID_PPP_PRINTING,
38 instance, &result));
39 return result;
42 int32_t Begin(PP_Instance instance,
43 const struct PP_PrintSettings_Dev* print_settings) {
44 if (!HasPrintingPermission(instance))
45 return 0;
46 // Settings is just serialized as a string.
47 std::string settings_string;
48 settings_string.resize(sizeof(*print_settings));
49 memcpy(&settings_string[0], print_settings, sizeof(*print_settings));
51 int32_t result = 0;
52 HostDispatcher::GetForInstance(instance)->Send(
53 new PpapiMsg_PPPPrinting_Begin(API_ID_PPP_PRINTING, instance,
54 settings_string, &result));
55 return result;
58 PP_Resource PrintPages(PP_Instance instance,
59 const PP_PrintPageNumberRange_Dev* page_ranges,
60 uint32_t page_range_count) {
61 if (!HasPrintingPermission(instance))
62 return 0;
63 std::vector<PP_PrintPageNumberRange_Dev> pages(
64 page_ranges, page_ranges + page_range_count);
66 HostResource result;
67 HostDispatcher::GetForInstance(instance)->Send(
68 new PpapiMsg_PPPPrinting_PrintPages(API_ID_PPP_PRINTING,
69 instance, pages, &result));
71 // Explicilty don't add a reference to the received resource here. The plugin
72 // adds a ref during creation of the resource and it will "abandon" the
73 // resource to release it, which ensures that the initial ref won't be
74 // decremented. See the comment below in OnPluginMsgPrintPages.
76 return result.host_resource();
79 void End(PP_Instance instance) {
80 if (!HasPrintingPermission(instance))
81 return;
82 HostDispatcher::GetForInstance(instance)->Send(
83 new PpapiMsg_PPPPrinting_End(API_ID_PPP_PRINTING, instance));
86 PP_Bool IsScalingDisabled(PP_Instance instance) {
87 if (!HasPrintingPermission(instance))
88 return PP_FALSE;
89 bool result = false;
90 HostDispatcher::GetForInstance(instance)->Send(
91 new PpapiMsg_PPPPrinting_IsScalingDisabled(API_ID_PPP_PRINTING,
92 instance, &result));
93 return PP_FromBool(result);
96 const PPP_Printing_Dev ppp_printing_interface = {
97 &QuerySupportedFormats,
98 &Begin,
99 &PrintPages,
100 &End,
101 &IsScalingDisabled
103 #else
104 // The NaCl plugin doesn't need the host side interface - stub it out.
105 static const PPP_Printing_Dev ppp_printing_interface = {};
106 #endif // !defined(OS_NACL)
108 } // namespace
110 PPP_Printing_Proxy::PPP_Printing_Proxy(Dispatcher* dispatcher)
111 : InterfaceProxy(dispatcher),
112 ppp_printing_impl_(NULL) {
113 if (dispatcher->IsPlugin()) {
114 ppp_printing_impl_ = static_cast<const PPP_Printing_Dev*>(
115 dispatcher->local_get_interface()(PPP_PRINTING_DEV_INTERFACE));
119 PPP_Printing_Proxy::~PPP_Printing_Proxy() {
122 // static
123 const PPP_Printing_Dev* PPP_Printing_Proxy::GetProxyInterface() {
124 return &ppp_printing_interface;
127 bool PPP_Printing_Proxy::OnMessageReceived(const IPC::Message& msg) {
128 if (!dispatcher()->IsPlugin())
129 return false;
131 bool handled = true;
132 IPC_BEGIN_MESSAGE_MAP(PPP_Printing_Proxy, msg)
133 IPC_MESSAGE_HANDLER(PpapiMsg_PPPPrinting_QuerySupportedFormats,
134 OnPluginMsgQuerySupportedFormats)
135 IPC_MESSAGE_HANDLER(PpapiMsg_PPPPrinting_Begin,
136 OnPluginMsgBegin)
137 IPC_MESSAGE_HANDLER(PpapiMsg_PPPPrinting_PrintPages,
138 OnPluginMsgPrintPages)
139 IPC_MESSAGE_HANDLER(PpapiMsg_PPPPrinting_End,
140 OnPluginMsgEnd)
141 IPC_MESSAGE_HANDLER(PpapiMsg_PPPPrinting_IsScalingDisabled,
142 OnPluginMsgIsScalingDisabled)
143 IPC_MESSAGE_UNHANDLED(handled = false)
144 IPC_END_MESSAGE_MAP()
145 return handled;
148 void PPP_Printing_Proxy::OnPluginMsgQuerySupportedFormats(PP_Instance instance,
149 uint32_t* result) {
150 if (ppp_printing_impl_) {
151 *result = CallWhileUnlocked(ppp_printing_impl_->QuerySupportedFormats,
152 instance);
153 } else {
154 *result = 0;
158 void PPP_Printing_Proxy::OnPluginMsgBegin(PP_Instance instance,
159 const std::string& settings_string,
160 int32_t* result) {
161 *result = 0;
163 PP_PrintSettings_Dev settings;
164 if (settings_string.size() != sizeof(settings))
165 return;
166 memcpy(&settings, &settings_string[0], sizeof(settings));
168 if (ppp_printing_impl_)
169 *result = CallWhileUnlocked(ppp_printing_impl_->Begin, instance, &settings);
172 void PPP_Printing_Proxy::OnPluginMsgPrintPages(
173 PP_Instance instance,
174 const std::vector<PP_PrintPageNumberRange_Dev>& pages,
175 HostResource* result) {
176 if (!ppp_printing_impl_ || pages.empty())
177 return;
179 PP_Resource plugin_resource = CallWhileUnlocked(
180 ppp_printing_impl_->PrintPages,
181 instance, &pages[0], base::checked_cast<uint32_t>(pages.size()));
182 ResourceTracker* resource_tracker = PpapiGlobals::Get()->GetResourceTracker();
183 Resource* resource_object = resource_tracker->GetResource(plugin_resource);
184 if (!resource_object)
185 return;
187 *result = resource_object->host_resource();
189 // Abandon the resource on the plugin side. This releases a reference to the
190 // resource and allows the plugin side of the resource (the proxy resource) to
191 // be destroyed without sending a message to the renderer notifing it that the
192 // plugin has released the resource. This used to call
193 // ResourceTracker::ReleaseResource directly which would trigger an IPC to be
194 // sent to the renderer to remove a ref to the resource. However due to
195 // arbitrary ordering of received sync/async IPCs in the renderer, this
196 // sometimes resulted in the resource being destroyed in the renderer before
197 // the renderer had a chance to add a reference to it. See crbug.com/490611.
198 static_cast<PluginResourceTracker*>(resource_tracker)
199 ->AbandonResource(plugin_resource);
202 void PPP_Printing_Proxy::OnPluginMsgEnd(PP_Instance instance) {
203 if (ppp_printing_impl_)
204 CallWhileUnlocked(ppp_printing_impl_->End, instance);
207 void PPP_Printing_Proxy::OnPluginMsgIsScalingDisabled(PP_Instance instance,
208 bool* result) {
209 if (ppp_printing_impl_) {
210 *result = PP_ToBool(CallWhileUnlocked(ppp_printing_impl_->IsScalingDisabled,
211 instance));
212 } else {
213 *result = false;
217 } // namespace proxy
218 } // namespace ppapi