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

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 typos. 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
« no previous file with comments | « printing/backend/cups_printer.h ('k') | printing/backend/print_backend_chromeos.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 #include <utility>
11
12 #include "base/files/file.h"
13 #include "base/files/file_path.h"
14 #include "base/files/file_util.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "printing/backend/cups_connection.h"
17 #include "printing/backend/print_backend.h"
18
19 namespace {
20
21 const char kDriverInfoTagName[] = "system_driverinfo";
22
23 const char kCUPSPrinterInfoOpt[] = "printer-info";
24 const char kCUPSPrinterStateOpt[] = "printer-state";
25 const char kCUPSPrinterMakeModelOpt[] = "printer-make-and-model";
26
27 } // namespace
28
29 namespace printing {
30
31 CupsPrinter::CupsPrinter(http_t* http,
32 std::unique_ptr<cups_dest_t, DestinationDeleter> dest,
33 std::unique_ptr<cups_dinfo_t, DestInfoDeleter> info)
34 : cups_http_(http),
35 destination_(std::move(dest)),
36 dest_info_(std::move(info)) {
37 DCHECK(cups_http_);
38 DCHECK(destination_);
39 }
40
41 CupsPrinter::CupsPrinter(CupsPrinter&& printer)
42 : cups_http_(printer.cups_http_),
43 destination_(std::move(printer.destination_)),
44 dest_info_(std::move(printer.dest_info_)) {
45 DCHECK(cups_http_);
46 DCHECK(destination_);
47 }
48
49 CupsPrinter::~CupsPrinter() {}
50
51 bool CupsPrinter::is_default() const {
52 return destination_->is_default;
53 }
54
55 ipp_attribute_t* CupsPrinter::GetSupportedOptionValues(
56 base::StringPiece option_name) const {
57 if (!InitializeDestInfo())
58 return nullptr;
59
60 return cupsFindDestSupported(cups_http_, destination_.get(), 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) {
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, nullptr));
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 nullptr;
86
87 return cupsFindDestDefault(cups_http_, destination_.get(), dest_info_.get(),
88 option_name.as_string().c_str());
89 }
90
91 bool CupsPrinter::CheckOptionSupported(base::StringPiece name,
92 base::StringPiece value) const {
93 if (!InitializeDestInfo())
94 return false;
95
96 int supported = cupsCheckDestSupported(
97 cups_http_, destination_.get(), dest_info_.get(),
98 name.as_string().c_str(), value.as_string().c_str());
99 return supported == 1;
100 }
101
102 bool CupsPrinter::ToPrinterInfo(PrinterBasicInfo* printer_info) const {
103 const cups_dest_t* printer = destination_.get();
104
105 printer_info->printer_name = printer->name;
106 printer_info->is_default = printer->is_default;
107
108 const char* info = cupsGetOption(kCUPSPrinterInfoOpt, printer->num_options,
109 printer->options);
110 if (info)
111 printer_info->printer_description = info;
112
113 const char* state = cupsGetOption(kCUPSPrinterStateOpt, printer->num_options,
114 printer->options);
115 if (state)
116 base::StringToInt(state, &printer_info->printer_status);
117
118 const char* drv_info = cupsGetOption(kCUPSPrinterMakeModelOpt,
119 printer->num_options, printer->options);
120 if (drv_info)
121 printer_info->options[kDriverInfoTagName] = *drv_info;
122
123 // Store printer options.
124 for (int opt_index = 0; opt_index < printer->num_options; ++opt_index) {
125 printer_info->options[printer->options[opt_index].name] =
126 printer->options[opt_index].value;
127 }
128
129 return true;
130 }
131
132 base::FilePath CupsPrinter::GetPPD() const {
133 base::StringPiece printer_name = destination_->name;
134 const char* ppd_path =
135 cupsGetPPD2(cups_http_, printer_name.as_string().c_str());
136 base::FilePath path(ppd_path);
137
138 if (ppd_path) {
139 // There is no reliable way right now to detect full and complete PPD
140 // get downloaded. If we reach http timeout, it may simply return
141 // downloaded part as a full response. It might be good enough to check
142 // http->data_remaining or http->_data_remaining, unfortunately http_t
143 // is an internal structure and fields are not exposed in CUPS headers.
144 // httpGetLength or httpGetLength2 returning the full content size.
145 // Comparing file size against that content length might be unreliable
146 // since some http reponses are encoded and content_length > file size.
147 // Let's just check for the obvious CUPS and http errors here.
148 ipp_status_t error_code = cupsLastError();
149 int http_error = httpError(cups_http_);
150 if (error_code > IPP_OK_EVENTS_COMPLETE || http_error != 0) {
151 LOG(ERROR) << "Error downloading PPD file, name: " << destination_->name
152 << ", CUPS error: " << static_cast<int>(error_code)
153 << ", HTTP error: " << http_error;
154 base::DeleteFile(path, false);
155 path.clear();
156 }
157 }
158
159 return path;
160 }
161
162 std::string CupsPrinter::GetName() const {
163 return std::string(destination_->name);
164 }
165
166 std::string CupsPrinter::GetMakeAndModel() const {
167 const char* make_and_model =
168 cupsGetOption(kCUPSPrinterMakeModelOpt, destination_->num_options,
169 destination_->options);
170
171 return make_and_model ? std::string(make_and_model) : std::string();
172 }
173
174 bool CupsPrinter::IsAvailable() const {
175 return InitializeDestInfo();
176 }
177
178 bool CupsPrinter::InitializeDestInfo() const {
179 if (dest_info_)
180 return true;
181
182 dest_info_.reset(cupsCopyDestInfo(cups_http_, destination_.get()));
183 return !!dest_info_;
184 }
185
186 ipp_status_t CupsPrinter::CreateJob(int* job_id,
187 base::StringPiece title,
188 const std::vector<cups_option_t>& options) {
189 DCHECK(dest_info_) << "Verify availability before starting a print job";
190
191 cups_option_t* data = const_cast<cups_option_t*>(
192 options.data()); // createDestJob will not modify the data
193 ipp_status_t create_status = cupsCreateDestJob(
194 cups_http_, destination_.get(), dest_info_.get(), job_id,
195 title.as_string().c_str(), options.size(), data);
196
197 return create_status;
198 }
199
200 bool CupsPrinter::StartDocument(int job_id,
201 base::StringPiece document_name,
202 bool last_document,
203 const std::vector<cups_option_t>& options) {
204 DCHECK(dest_info_);
205 DCHECK(job_id);
206
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_, 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(const std::vector<char>& buffer) {
218 http_status_t status =
219 cupsWriteRequestData(cups_http_, buffer.data(), buffer.size());
220 return status == HTTP_STATUS_CONTINUE;
221 }
222
223 bool CupsPrinter::FinishDocument() {
224 DCHECK(dest_info_);
225
226 ipp_status_t status =
227 cupsFinishDestDocument(cups_http_, destination_.get(), dest_info_.get());
228
229 return status == IPP_STATUS_OK;
230 }
231
232 ipp_status_t CupsPrinter::CloseJob(int job_id) {
233 DCHECK(dest_info_);
234 DCHECK(job_id);
235
236 return cupsCloseDestJob(cups_http_, destination_.get(), dest_info_.get(),
237 job_id);
238 }
239
240 } // namespace printing
OLDNEW
« no previous file with comments | « printing/backend/cups_printer.h ('k') | printing/backend/print_backend_chromeos.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698