ppp_printing_proxy.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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
17namespace ppapi {
18namespace proxy {
19
20namespace {
21
22uint32_t QuerySupportedFormats(PP_Instance instance) {
23  uint32_t result = 0;
24  HostDispatcher::GetForInstance(instance)->Send(
25      new PpapiMsg_PPPPrinting_QuerySupportedFormats(API_ID_PPP_PRINTING,
26                                                     instance, &result));
27  return result;
28}
29
30int32_t Begin(PP_Instance instance,
31              const struct PP_PrintSettings_Dev* print_settings) {
32  // Settings is just serialized as a string.
33  std::string settings_string;
34  settings_string.resize(sizeof(*print_settings));
35  memcpy(&settings_string[0], print_settings, sizeof(*print_settings));
36
37  int32_t result = 0;
38  HostDispatcher::GetForInstance(instance)->Send(
39      new PpapiMsg_PPPPrinting_Begin(API_ID_PPP_PRINTING, instance,
40                                     settings_string, &result));
41  return result;
42}
43
44PP_Resource PrintPages(PP_Instance instance,
45                       const PP_PrintPageNumberRange_Dev* page_ranges,
46                       uint32_t page_range_count) {
47  std::vector<PP_PrintPageNumberRange_Dev> pages(
48      page_ranges, page_ranges + page_range_count);
49
50  HostResource result;
51  HostDispatcher::GetForInstance(instance)->Send(
52      new PpapiMsg_PPPPrinting_PrintPages(API_ID_PPP_PRINTING,
53                                          instance, pages, &result));
54
55  // How refcounting works when returning a resource:
56  //
57  // The plugin in the plugin process makes a resource that it returns to the
58  // browser. The plugin proxy code returns that ref to us and asynchronously
59  // releases it. Before any release message associated with that operation
60  // comes, we'll get this reply. We need to add one ref since our caller
61  // expects us to add one ref for it to consume.
62  PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(
63      result.host_resource());
64  return result.host_resource();
65}
66
67void End(PP_Instance instance) {
68  HostDispatcher::GetForInstance(instance)->Send(
69      new PpapiMsg_PPPPrinting_End(API_ID_PPP_PRINTING, instance));
70}
71
72PP_Bool IsScalingDisabled(PP_Instance instance) {
73  bool result = false;
74  HostDispatcher::GetForInstance(instance)->Send(
75      new PpapiMsg_PPPPrinting_IsScalingDisabled(API_ID_PPP_PRINTING,
76                                                 instance, &result));
77  return PP_FromBool(result);
78}
79
80const PPP_Printing_Dev ppp_printing_interface = {
81  &QuerySupportedFormats,
82  &Begin,
83  &PrintPages,
84  &End,
85  &IsScalingDisabled
86};
87
88}  // namespace
89
90PPP_Printing_Proxy::PPP_Printing_Proxy(Dispatcher* dispatcher)
91    : InterfaceProxy(dispatcher),
92      ppp_printing_impl_(NULL) {
93  if (dispatcher->IsPlugin()) {
94    ppp_printing_impl_ = static_cast<const PPP_Printing_Dev*>(
95        dispatcher->local_get_interface()(PPP_PRINTING_DEV_INTERFACE));
96  }
97}
98
99PPP_Printing_Proxy::~PPP_Printing_Proxy() {
100}
101
102// static
103const PPP_Printing_Dev* PPP_Printing_Proxy::GetProxyInterface() {
104  return &ppp_printing_interface;
105}
106
107bool PPP_Printing_Proxy::OnMessageReceived(const IPC::Message& msg) {
108  bool handled = true;
109  IPC_BEGIN_MESSAGE_MAP(PPP_Printing_Proxy, msg)
110    IPC_MESSAGE_HANDLER(PpapiMsg_PPPPrinting_QuerySupportedFormats,
111                        OnPluginMsgQuerySupportedFormats)
112    IPC_MESSAGE_HANDLER(PpapiMsg_PPPPrinting_Begin,
113                        OnPluginMsgBegin)
114    IPC_MESSAGE_HANDLER(PpapiMsg_PPPPrinting_PrintPages,
115                        OnPluginMsgPrintPages)
116    IPC_MESSAGE_HANDLER(PpapiMsg_PPPPrinting_End,
117                        OnPluginMsgEnd)
118    IPC_MESSAGE_HANDLER(PpapiMsg_PPPPrinting_IsScalingDisabled,
119                        OnPluginMsgIsScalingDisabled)
120    IPC_MESSAGE_UNHANDLED(handled = false)
121  IPC_END_MESSAGE_MAP()
122  return handled;
123}
124
125void PPP_Printing_Proxy::OnPluginMsgQuerySupportedFormats(PP_Instance instance,
126                                                          uint32_t* result) {
127  if (ppp_printing_impl_)
128    *result = ppp_printing_impl_->QuerySupportedFormats(instance);
129  else
130    *result = 0;
131}
132
133void PPP_Printing_Proxy::OnPluginMsgBegin(PP_Instance instance,
134                                          const std::string& settings_string,
135                                          int32_t* result) {
136  *result = 0;
137
138  PP_PrintSettings_Dev settings;
139  if (settings_string.size() != sizeof(settings))
140    return;
141  memcpy(&settings, &settings_string[0], sizeof(settings));
142
143  if (ppp_printing_impl_)
144    *result = ppp_printing_impl_->Begin(instance, &settings);
145}
146
147void PPP_Printing_Proxy::OnPluginMsgPrintPages(
148    PP_Instance instance,
149    const std::vector<PP_PrintPageNumberRange_Dev>& pages,
150    HostResource* result) {
151  if (!ppp_printing_impl_ || pages.empty())
152    return;
153
154  PP_Resource plugin_resource = ppp_printing_impl_->PrintPages(
155      instance, &pages[0], static_cast<uint32_t>(pages.size()));
156  ResourceTracker* resource_tracker = PpapiGlobals::Get()->GetResourceTracker();
157  Resource* resource_object = resource_tracker->GetResource(plugin_resource);
158  if (!resource_object)
159    return;
160
161  *result = resource_object->host_resource();
162
163  // See PrintPages above for how refcounting works.
164  resource_tracker->ReleaseResourceSoon(plugin_resource);
165}
166
167void PPP_Printing_Proxy::OnPluginMsgEnd(PP_Instance instance) {
168  if (ppp_printing_impl_)
169    ppp_printing_impl_->End(instance);
170}
171
172void PPP_Printing_Proxy::OnPluginMsgIsScalingDisabled(PP_Instance instance,
173                                                      bool* result) {
174  if (ppp_printing_impl_)
175    *result = PP_ToBool(ppp_printing_impl_->IsScalingDisabled(instance));
176  else
177    *result = false;
178}
179
180}  // namespace proxy
181}  // namespace ppapi
182