Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(11)

Side by Side Diff: printing/backend/cups_printer.cc

Issue 2105463002: Create a new print backend for the updated CUPS APIs (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix printing gyp file. Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 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 "printing/backend/cups_printer.h"
6
7 #include <cups/cups.h>
8
9 #include <string>
10
11 #include "base/files/file.h"
12 #include "base/files/file_path.h"
13 #include "base/files/file_util.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "printing/backend/cups_connection.h"
16 #include "printing/backend/print_backend.h"
17
18 namespace {
19
20 const char kDriverInfoTagName[] = "system_driverinfo";
21
22 const char kCUPSPrinterInfoOpt[] = "printer-info";
23 const char kCUPSPrinterStateOpt[] = "printer-state";
24 const char kCUPSPrinterMakeModelOpt[] = "printer-make-and-model";
25
26 } // namespace
27
28 namespace printing {
29
30 void DestinationDeleter::operator()(cups_dest_t* dest) const {
31 cupsFreeDests(1, dest);
32 }
33
34 void DestInfoDeleter::operator()(cups_dinfo_t* info) const {
35 cupsFreeDestInfo(info);
36 }
37
38 CupsPrinter::CupsPrinter(base::WeakPtr<http_t> http,
39 cups_dest_t* dest,
40 cups_dinfo_t* info)
41 : cups_http_(http), destination_(dest), dest_info_(info) {}
42
43 CupsPrinter::CupsPrinter(CupsPrinter&& printer)
44 : cups_http_(std::move(printer.cups_http_)),
45 destination_(std::move(printer.destination_)),
46 dest_info_(std::move(printer.dest_info_)) {}
47
48 CupsPrinter::~CupsPrinter() {}
49
50 bool CupsPrinter::is_default() const {
51 return destination_->is_default;
52 }
53
54 ipp_attribute_t* CupsPrinter::GetSupportedOptionValues(
55 base::StringPiece option_name) const {
56 if (!InitializeDestInfo())
57 return NULL;
Lei Zhang 2016/07/13 01:08:42 More NULLs
skau 2016/07/14 20:43:05 Done.
58
59 return cupsFindDestSupported(cups_http_.get(), destination_.get(),
60 dest_info_.get(),
61 option_name.as_string().c_str());
62 }
63
64 std::vector<base::StringPiece> CupsPrinter::GetSupportedOptionValueStrings(
65 base::StringPiece option_name) const {
66 ipp_attribute_t* attr = GetSupportedOptionValues(option_name);
67 std::vector<base::StringPiece> values;
68 if (attr == nullptr) {
Lei Zhang 2016/07/13 01:08:42 More equality checks again nullptr.
skau 2016/07/14 20:43:06 Done.
69 return values;
70 }
71
72 base::StringPiece value;
73 int num_options = ippGetCount(attr);
74 for (int i = 0; i < num_options; ++i) {
75 value.set(ippGetString(attr, i, NULL));
76 values.push_back(value);
77 }
78
79 return values;
80 }
81
82 ipp_attribute_t* CupsPrinter::GetDefaultOptionValue(
83 base::StringPiece option_name) const {
84 if (!InitializeDestInfo())
85 return NULL;
86
87 return cupsFindDestDefault(cups_http_.get(), destination_.get(),
88 dest_info_.get(), option_name.as_string().c_str());
89 }
90
91 bool CupsPrinter::CheckOptionSupported(base::StringPiece name,
92 base::StringPiece value) const {
93 int supported = cupsCheckDestSupported(
94 cups_http_.get(), destination_.get(), dest_info_.get(),
95 name.as_string().c_str(), value.as_string().c_str());
96 return supported == 1;
97 }
98
99 bool CupsPrinter::ToPrinterInfo(PrinterBasicInfo* printer_info) const {
100 const cups_dest_t* printer = destination_.get();
101
102 printer_info->printer_name = printer->name;
103 printer_info->is_default = printer->is_default;
104
105 const char* info = cupsGetOption(kCUPSPrinterInfoOpt, printer->num_options,
106 printer->options);
107 if (info)
108 printer_info->printer_description = info;
109
110 const char* state = cupsGetOption(kCUPSPrinterStateOpt, printer->num_options,
111 printer->options);
112 if (state)
113 base::StringToInt(state, &printer_info->printer_status);
114
115 const char* drv_info = cupsGetOption(kCUPSPrinterMakeModelOpt,
116 printer->num_options, printer->options);
117 if (drv_info)
118 printer_info->options[kDriverInfoTagName] = *drv_info;
119
120 // Store printer options.
121 for (int opt_index = 0; opt_index < printer->num_options; ++opt_index) {
122 printer_info->options[printer->options[opt_index].name] =
123 printer->options[opt_index].value;
124 }
125
126 return true;
127 }
128
129 base::FilePath CupsPrinter::GetPPD() const {
130 base::StringPiece printer_name = destination_->name;
131 const char* ppd_path =
132 cupsGetPPD2(cups_http_.get(), printer_name.as_string().c_str());
133 base::FilePath path(ppd_path);
134
135 if (ppd_path) {
136 // There is no reliable way right now to detect full and complete PPD
137 // get downloaded. If we reach http timeout, it may simply return
138 // downloaded part as a full response. It might be good enough to check
139 // http->data_remaining or http->_data_remaining, unfortunately http_t
140 // is an internal structure and fields are not exposed in CUPS headers.
141 // httpGetLength or httpGetLength2 returning the full content size.
142 // Comparing file size against that content length might be unreliable
143 // since some http reponses are encoded and content_length > file size.
144 // Let's just check for the obvious CUPS and http errors here.
145 ipp_status_t error_code = cupsLastError();
146 int http_error = httpError(cups_http_.get());
147 if (error_code > IPP_OK_EVENTS_COMPLETE || http_error != 0) {
148 LOG(ERROR) << "Error downloading PPD file, name: " << destination_->name
149 << ", CUPS error: " << static_cast<int>(error_code)
150 << ", HTTP error: " << http_error;
151 base::DeleteFile(path, false);
152 path.clear();
153 }
154 }
155
156 return path;
157 }
158
159 const std::string CupsPrinter::GetName() const {
160 return std::string(destination_->name);
161 }
162
163 const std::string CupsPrinter::GetMakeAndModel() const {
164 const char* make_and_model =
165 cupsGetOption(kCUPSPrinterMakeModelOpt, destination_->num_options,
166 destination_->options);
167 if (!make_and_model) {
Lei Zhang 2016/07/13 01:08:42 return make_and_model ? std::string(make_and_model
skau 2016/07/14 20:43:06 Done.
168 return std::string();
169 }
170
171 return std::string(make_and_model);
172 }
173
174 bool CupsPrinter::IsAvailable() const {
175 return cups_http_ && destination_ && InitializeDestInfo();
176 }
177
178 bool CupsPrinter::InitializeDestInfo() const {
179 if (dest_info_)
180 return true;
181
182 cups_dinfo_t* info = cupsCopyDestInfo(cups_http_.get(), destination_.get());
183
184 if (info == nullptr)
185 return false;
186
187 dest_info_.reset(info);
188 return true;
189 }
190
191 ipp_status_t CupsPrinter::CreateJob(int* job_id,
192 base::StringPiece title,
193 const std::vector<cups_option_t>& options) {
194 cups_option_t* data = const_cast<cups_option_t*>(
195 options.data()); // createDestJob will not modify the data
196 ipp_status_t create_status = cupsCreateDestJob(
197 cups_http_.get(), destination_.get(), dest_info_.get(), job_id,
198 title.as_string().c_str(), options.size(), data);
199
200 return create_status;
201 }
202
203 bool CupsPrinter::StartDocument(int job_id,
204 base::StringPiece document_name,
205 bool last_document,
206 const std::vector<cups_option_t>& options) {
207 cups_option_t* data = const_cast<cups_option_t*>(
208 options.data()); // createStartDestDocument will not modify the data
209 http_status_t start_doc_status = cupsStartDestDocument(
210 cups_http_.get(), destination_.get(), dest_info_.get(), job_id,
211 document_name.as_string().c_str(), CUPS_FORMAT_PDF, options.size(), data,
212 last_document ? 0 : 1);
213
214 return start_doc_status == HTTP_CONTINUE;
215 }
216
217 bool CupsPrinter::StreamData(char* buffer, int len) {
218 http_status_t status = cupsWriteRequestData(cups_http_.get(), buffer, len);
219 return status == HTTP_STATUS_CONTINUE;
220 }
221
222 bool CupsPrinter::FinishDocument() {
223 DCHECK(cups_http_);
224 DCHECK(destination_);
225 DCHECK(dest_info_);
226
227 ipp_status_t status = cupsFinishDestDocument(
228 cups_http_.get(), destination_.get(), dest_info_.get());
229
230 return status == IPP_STATUS_OK;
231 }
232
233 ipp_status_t CupsPrinter::CloseJob(int job_id) {
234 return cupsCloseDestJob(cups_http_.get(), destination_.get(),
235 dest_info_.get(), job_id);
236 }
237
238 } // namespace printing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698