blob: f02257870ffd51ee8360901708005de20f635963 [file] [log] [blame]
[email protected]ce6f5912012-05-16 23:07:301// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]8e553f492010-10-25 20:05:442// 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_helper.h"
6
[email protected]eb08bbe52012-09-07 09:32:017#include <cups/ppd.h>
avi126e93c2015-12-21 21:48:168#include <stddef.h>
[email protected]eb08bbe52012-09-07 09:32:019
thestigd24bc532016-05-17 21:07:0610#include <string>
11#include <vector>
12
[email protected]6bdc52272014-05-27 00:12:3313#include "base/base_paths.h"
thestig22dfc4012014-09-05 08:29:4414#include "base/files/file_util.h"
[email protected]8e553f492010-10-25 20:05:4415#include "base/logging.h"
[email protected]6bdc52272014-05-27 00:12:3316#include "base/path_service.h"
[email protected]896d161f2013-06-11 22:52:2417#include "base/strings/string_number_conversions.h"
[email protected]d778e0422013-03-06 18:10:2218#include "base/strings/string_split.h"
[email protected]79fe2272013-07-13 20:01:4019#include "base/strings/string_util.h"
[email protected]8b6098e2012-09-07 04:21:2120#include "base/values.h"
[email protected]8b6098e2012-09-07 04:21:2121#include "printing/backend/print_backend.h"
22#include "printing/backend/print_backend_consts.h"
[email protected]117eb82d2014-06-13 22:00:5723#include "printing/units.h"
[email protected]79fe2272013-07-13 20:01:4024#include "url/gurl.h"
[email protected]8b6098e2012-09-07 04:21:2125
thestig91d04b62017-03-23 19:39:1326using base::EqualsCaseInsensitiveASCII;
27
[email protected]675a1ae2013-10-14 20:24:3728namespace printing {
29
[email protected]8b6098e2012-09-07 04:21:2130// This section contains helper code for PPD parsing for semantic capabilities.
31namespace {
32
33const char kColorDevice[] = "ColorDevice";
34const char kColorModel[] = "ColorModel";
35const char kColorMode[] = "ColorMode";
36const char kProcessColorModel[] = "ProcessColorModel";
37const char kPrintoutMode[] = "PrintoutMode";
38const char kDraftGray[] = "Draft.Gray";
39const char kHighGray[] = "High.Gray";
40
thestig1847e482017-03-11 02:58:3141constexpr char kDuplex[] = "Duplex";
42constexpr char kDuplexNone[] = "None";
43constexpr char kDuplexTumble[] = "DuplexTumble";
44constexpr char kPageSize[] = "PageSize";
45
46// Brother printer specific options.
47constexpr char kBrotherDuplex[] = "BRDuplex";
48constexpr char kBrotherMonoColor[] = "BRMonoColor";
49constexpr char kBrotherPrintQuality[] = "BRPrintQuality";
[email protected]117eb82d2014-06-13 22:00:5750
thestig91d04b62017-03-23 19:39:1351// Samsung printer specific options.
52constexpr char kSamsungColorTrue[] = "True";
53constexpr char kSamsungColorFalse[] = "False";
54
[email protected]79f63882013-02-10 05:15:4555void ParseLpOptions(const base::FilePath& filepath,
thestigd24bc532016-05-17 21:07:0656 base::StringPiece printer_name,
57 int* num_options,
58 cups_option_t** options) {
[email protected]8b6098e2012-09-07 04:21:2159 std::string content;
[email protected]82f84b92013-08-30 18:23:5060 if (!base::ReadFileToString(filepath, &content))
[email protected]8b6098e2012-09-07 04:21:2161 return;
62
63 const char kDest[] = "dest";
64 const char kDefault[] = "default";
65 const size_t kDestLen = sizeof(kDest) - 1;
66 const size_t kDefaultLen = sizeof(kDefault) - 1;
[email protected]8b6098e2012-09-07 04:21:2167
brettw8a800902015-07-10 18:28:3368 for (base::StringPiece line :
69 base::SplitStringPiece(content, "\n", base::KEEP_WHITESPACE,
70 base::SPLIT_WANT_NONEMPTY)) {
71 if (base::StartsWith(line, base::StringPiece(kDefault, kDefaultLen),
72 base::CompareCase::INSENSITIVE_ASCII) &&
[email protected]8b6098e2012-09-07 04:21:2173 isspace(line[kDefaultLen])) {
74 line = line.substr(kDefaultLen);
brettw8a800902015-07-10 18:28:3375 } else if (base::StartsWith(line, base::StringPiece(kDest, kDestLen),
76 base::CompareCase::INSENSITIVE_ASCII) &&
[email protected]8b6098e2012-09-07 04:21:2177 isspace(line[kDestLen])) {
78 line = line.substr(kDestLen);
79 } else {
80 continue;
81 }
82
brettw8a800902015-07-10 18:28:3383 line = base::TrimWhitespaceASCII(line, base::TRIM_ALL);
[email protected]8b6098e2012-09-07 04:21:2184 if (line.empty())
85 continue;
86
87 size_t space_found = line.find(' ');
brettw8a800902015-07-10 18:28:3388 if (space_found == base::StringPiece::npos)
[email protected]8b6098e2012-09-07 04:21:2189 continue;
90
brettw8a800902015-07-10 18:28:3391 base::StringPiece name = line.substr(0, space_found);
[email protected]8b6098e2012-09-07 04:21:2192 if (name.empty())
93 continue;
94
thestig91d04b62017-03-23 19:39:1395 if (!EqualsCaseInsensitiveASCII(printer_name, name))
[email protected]8b6098e2012-09-07 04:21:2196 continue; // This is not the required printer.
[email protected]8b6098e2012-09-07 04:21:2197
98 line = line.substr(space_found + 1);
[email protected]8af69c6c2014-03-03 19:05:3199 // Remove extra spaces.
brettw8a800902015-07-10 18:28:33100 line = base::TrimWhitespaceASCII(line, base::TRIM_ALL);
[email protected]8b6098e2012-09-07 04:21:21101 if (line.empty())
102 continue;
thestigd24bc532016-05-17 21:07:06103
brettw8a800902015-07-10 18:28:33104 // Parse the selected printer custom options. Need to pass a
105 // null-terminated string.
106 *num_options = cupsParseOptions(line.as_string().c_str(), 0, options);
[email protected]8b6098e2012-09-07 04:21:21107 }
108}
109
thestigd24bc532016-05-17 21:07:06110void MarkLpOptions(base::StringPiece printer_name, ppd_file_t** ppd) {
111 cups_option_t* options = nullptr;
[email protected]8b6098e2012-09-07 04:21:21112 int num_options = 0;
[email protected]8b6098e2012-09-07 04:21:21113
114 const char kSystemLpOptionPath[] = "/etc/cups/lpoptions";
115 const char kUserLpOptionPath[] = ".cups/lpoptions";
116
[email protected]79f63882013-02-10 05:15:45117 std::vector<base::FilePath> file_locations;
118 file_locations.push_back(base::FilePath(kSystemLpOptionPath));
[email protected]6bdc52272014-05-27 00:12:33119 base::FilePath homedir;
Avi Drissmanea15ea02018-05-07 18:55:12120 base::PathService::Get(base::DIR_HOME, &homedir);
[email protected]6bdc52272014-05-27 00:12:33121 file_locations.push_back(base::FilePath(homedir.Append(kUserLpOptionPath)));
[email protected]8b6098e2012-09-07 04:21:21122
thestigd24bc532016-05-17 21:07:06123 for (const base::FilePath& location : file_locations) {
[email protected]8b6098e2012-09-07 04:21:21124 num_options = 0;
thestigd24bc532016-05-17 21:07:06125 options = nullptr;
126 ParseLpOptions(location, printer_name, &num_options, &options);
[email protected]8b6098e2012-09-07 04:21:21127 if (num_options > 0 && options) {
128 cupsMarkOptions(*ppd, num_options, options);
129 cupsFreeOptions(num_options, options);
130 }
131 }
132}
[email protected]8b6098e2012-09-07 04:21:21133
thestig1847e482017-03-11 02:58:31134void GetDuplexSettings(ppd_file_t* ppd,
135 bool* duplex_capable,
136 DuplexMode* duplex_default) {
137 ppd_choice_t* duplex_choice = ppdFindMarkedChoice(ppd, kDuplex);
138 if (!duplex_choice) {
139 ppd_option_t* option = ppdFindOption(ppd, kDuplex);
140 if (!option)
141 option = ppdFindOption(ppd, kBrotherDuplex);
142 if (!option)
143 return;
144
145 duplex_choice = ppdFindChoice(option, option->defchoice);
146 }
147
148 if (!duplex_choice)
149 return;
150
151 *duplex_capable = true;
152 const char* choice = duplex_choice->choice;
thestig91d04b62017-03-23 19:39:13153 if (EqualsCaseInsensitiveASCII(choice, kDuplexNone)) {
thestig1847e482017-03-11 02:58:31154 *duplex_default = SIMPLEX;
thestig91d04b62017-03-23 19:39:13155 } else if (EqualsCaseInsensitiveASCII(choice, kDuplexTumble)) {
thestig1847e482017-03-11 02:58:31156 *duplex_default = SHORT_EDGE;
157 } else {
158 *duplex_default = LONG_EDGE;
159 }
160}
161
[email protected]8b6098e2012-09-07 04:21:21162bool GetBasicColorModelSettings(ppd_file_t* ppd,
[email protected]675a1ae2013-10-14 20:24:37163 ColorModel* color_model_for_black,
164 ColorModel* color_model_for_color,
[email protected]8b6098e2012-09-07 04:21:21165 bool* color_is_default) {
166 ppd_option_t* color_model = ppdFindOption(ppd, kColorModel);
167 if (!color_model)
168 return false;
169
thestigd24bc532016-05-17 21:07:06170 if (ppdFindChoice(color_model, kBlack))
171 *color_model_for_black = BLACK;
172 else if (ppdFindChoice(color_model, kGray))
173 *color_model_for_black = GRAY;
174 else if (ppdFindChoice(color_model, kGrayscale))
175 *color_model_for_black = GRAYSCALE;
[email protected]8b6098e2012-09-07 04:21:21176
thestigd24bc532016-05-17 21:07:06177 if (ppdFindChoice(color_model, kColor))
178 *color_model_for_color = COLOR;
179 else if (ppdFindChoice(color_model, kCMYK))
180 *color_model_for_color = CMYK;
181 else if (ppdFindChoice(color_model, kRGB))
182 *color_model_for_color = RGB;
183 else if (ppdFindChoice(color_model, kRGBA))
184 *color_model_for_color = RGBA;
185 else if (ppdFindChoice(color_model, kRGB16))
186 *color_model_for_color = RGB16;
187 else if (ppdFindChoice(color_model, kCMY))
188 *color_model_for_color = CMY;
189 else if (ppdFindChoice(color_model, kKCMY))
190 *color_model_for_color = KCMY;
191 else if (ppdFindChoice(color_model, kCMY_K))
192 *color_model_for_color = CMY_K;
[email protected]8b6098e2012-09-07 04:21:21193
194 ppd_choice_t* marked_choice = ppdFindMarkedChoice(ppd, kColorModel);
195 if (!marked_choice)
196 marked_choice = ppdFindChoice(color_model, color_model->defchoice);
197
198 if (marked_choice) {
199 *color_is_default =
thestig91d04b62017-03-23 19:39:13200 !EqualsCaseInsensitiveASCII(marked_choice->choice, kBlack) &&
201 !EqualsCaseInsensitiveASCII(marked_choice->choice, kGray) &&
202 !EqualsCaseInsensitiveASCII(marked_choice->choice, kGrayscale);
[email protected]8b6098e2012-09-07 04:21:21203 }
204 return true;
205}
206
207bool GetPrintOutModeColorSettings(ppd_file_t* ppd,
[email protected]675a1ae2013-10-14 20:24:37208 ColorModel* color_model_for_black,
209 ColorModel* color_model_for_color,
[email protected]8b6098e2012-09-07 04:21:21210 bool* color_is_default) {
211 ppd_option_t* printout_mode = ppdFindOption(ppd, kPrintoutMode);
212 if (!printout_mode)
213 return false;
214
thestigd24bc532016-05-17 21:07:06215 *color_model_for_color = PRINTOUTMODE_NORMAL;
216 *color_model_for_black = PRINTOUTMODE_NORMAL;
[email protected]8b6098e2012-09-07 04:21:21217
218 // Check to see if NORMAL_GRAY value is supported by PrintoutMode.
219 // If NORMAL_GRAY is not supported, NORMAL value is used to
220 // represent grayscale. If NORMAL_GRAY is supported, NORMAL is used to
221 // represent color.
thestigd24bc532016-05-17 21:07:06222 if (ppdFindChoice(printout_mode, kNormalGray))
223 *color_model_for_black = PRINTOUTMODE_NORMAL_GRAY;
[email protected]8b6098e2012-09-07 04:21:21224
225 // Get the default marked choice to identify the default color setting
226 // value.
227 ppd_choice_t* printout_mode_choice = ppdFindMarkedChoice(ppd, kPrintoutMode);
228 if (!printout_mode_choice) {
229 printout_mode_choice = ppdFindChoice(printout_mode,
230 printout_mode->defchoice);
231 }
232 if (printout_mode_choice) {
thestig91d04b62017-03-23 19:39:13233 if (EqualsCaseInsensitiveASCII(printout_mode_choice->choice, kNormalGray) ||
234 EqualsCaseInsensitiveASCII(printout_mode_choice->choice, kHighGray) ||
235 EqualsCaseInsensitiveASCII(printout_mode_choice->choice, kDraftGray)) {
thestigd24bc532016-05-17 21:07:06236 *color_model_for_black = PRINTOUTMODE_NORMAL_GRAY;
[email protected]8b6098e2012-09-07 04:21:21237 *color_is_default = false;
238 }
239 }
240 return true;
241}
242
243bool GetColorModeSettings(ppd_file_t* ppd,
[email protected]675a1ae2013-10-14 20:24:37244 ColorModel* color_model_for_black,
245 ColorModel* color_model_for_color,
[email protected]8b6098e2012-09-07 04:21:21246 bool* color_is_default) {
thestig1847e482017-03-11 02:58:31247 // Samsung printers use "ColorMode" attribute in their PPDs.
[email protected]8b6098e2012-09-07 04:21:21248 ppd_option_t* color_mode_option = ppdFindOption(ppd, kColorMode);
249 if (!color_mode_option)
250 return false;
251
thestig91d04b62017-03-23 19:39:13252 if (ppdFindChoice(color_mode_option, kColor) ||
253 ppdFindChoice(color_mode_option, kSamsungColorTrue)) {
thestigd24bc532016-05-17 21:07:06254 *color_model_for_color = COLORMODE_COLOR;
thestig91d04b62017-03-23 19:39:13255 }
[email protected]8b6098e2012-09-07 04:21:21256
thestig91d04b62017-03-23 19:39:13257 if (ppdFindChoice(color_mode_option, kMonochrome) ||
258 ppdFindChoice(color_mode_option, kSamsungColorFalse)) {
thestigd24bc532016-05-17 21:07:06259 *color_model_for_black = COLORMODE_MONOCHROME;
thestig91d04b62017-03-23 19:39:13260 }
[email protected]8b6098e2012-09-07 04:21:21261
262 ppd_choice_t* mode_choice = ppdFindMarkedChoice(ppd, kColorMode);
263 if (!mode_choice) {
264 mode_choice = ppdFindChoice(color_mode_option,
265 color_mode_option->defchoice);
266 }
267
268 if (mode_choice) {
thestigd24bc532016-05-17 21:07:06269 *color_is_default =
thestig91d04b62017-03-23 19:39:13270 EqualsCaseInsensitiveASCII(mode_choice->choice, kColor) ||
271 EqualsCaseInsensitiveASCII(mode_choice->choice, kSamsungColorTrue);
[email protected]8b6098e2012-09-07 04:21:21272 }
273 return true;
274}
275
thestig1847e482017-03-11 02:58:31276bool GetBrotherColorSettings(ppd_file_t* ppd,
277 ColorModel* color_model_for_black,
278 ColorModel* color_model_for_color,
279 bool* color_is_default) {
280 // Some Brother printers use "BRMonoColor" attribute in their PPDs.
281 // Some Brother printers use "BRPrintQuality" attribute in their PPDs.
282 ppd_option_t* color_mode_option = ppdFindOption(ppd, kBrotherMonoColor);
283 if (!color_mode_option)
284 color_mode_option = ppdFindOption(ppd, kBrotherPrintQuality);
285 if (!color_mode_option)
286 return false;
287
thestigca4af0b2017-03-15 18:28:48288 if (ppdFindChoice(color_mode_option, kFullColor))
289 *color_model_for_color = BROTHER_CUPS_COLOR;
290 else if (ppdFindChoice(color_mode_option, kColor))
291 *color_model_for_color = BROTHER_BRSCRIPT3_COLOR;
292
293 if (ppdFindChoice(color_mode_option, kMono))
294 *color_model_for_black = BROTHER_CUPS_MONO;
295 else if (ppdFindChoice(color_mode_option, kBlack))
296 *color_model_for_black = BROTHER_BRSCRIPT3_BLACK;
thestig1847e482017-03-11 02:58:31297
298 ppd_choice_t* marked_choice = ppdFindMarkedChoice(ppd, kColorMode);
299 if (!marked_choice) {
300 marked_choice =
301 ppdFindChoice(color_mode_option, color_mode_option->defchoice);
302 }
303 if (marked_choice) {
304 *color_is_default =
thestig91d04b62017-03-23 19:39:13305 !EqualsCaseInsensitiveASCII(marked_choice->choice, kBlack) &&
306 !EqualsCaseInsensitiveASCII(marked_choice->choice, kMono);
thestig1847e482017-03-11 02:58:31307 }
308 return true;
309}
310
[email protected]8b6098e2012-09-07 04:21:21311bool GetHPColorSettings(ppd_file_t* ppd,
[email protected]675a1ae2013-10-14 20:24:37312 ColorModel* color_model_for_black,
313 ColorModel* color_model_for_color,
[email protected]8b6098e2012-09-07 04:21:21314 bool* color_is_default) {
thestig1847e482017-03-11 02:58:31315 // HP printers use "Color/Color Model" attribute in their PPDs.
thestigd24bc532016-05-17 21:07:06316 ppd_option_t* color_mode_option = ppdFindOption(ppd, kColor);
[email protected]8b6098e2012-09-07 04:21:21317 if (!color_mode_option)
318 return false;
319
thestigd24bc532016-05-17 21:07:06320 if (ppdFindChoice(color_mode_option, kColor))
321 *color_model_for_color = HP_COLOR_COLOR;
322 if (ppdFindChoice(color_mode_option, kBlack))
323 *color_model_for_black = HP_COLOR_BLACK;
[email protected]8b6098e2012-09-07 04:21:21324
325 ppd_choice_t* mode_choice = ppdFindMarkedChoice(ppd, kColorMode);
326 if (!mode_choice) {
327 mode_choice = ppdFindChoice(color_mode_option,
328 color_mode_option->defchoice);
329 }
330 if (mode_choice) {
thestig91d04b62017-03-23 19:39:13331 *color_is_default = EqualsCaseInsensitiveASCII(mode_choice->choice, kColor);
[email protected]8b6098e2012-09-07 04:21:21332 }
333 return true;
334}
335
336bool GetProcessColorModelSettings(ppd_file_t* ppd,
[email protected]675a1ae2013-10-14 20:24:37337 ColorModel* color_model_for_black,
338 ColorModel* color_model_for_color,
[email protected]8b6098e2012-09-07 04:21:21339 bool* color_is_default) {
thestig1847e482017-03-11 02:58:31340 // Canon printers use "ProcessColorModel" attribute in their PPDs.
[email protected]8b6098e2012-09-07 04:21:21341 ppd_option_t* color_mode_option = ppdFindOption(ppd, kProcessColorModel);
342 if (!color_mode_option)
343 return false;
344
thestigd24bc532016-05-17 21:07:06345 if (ppdFindChoice(color_mode_option, kRGB))
346 *color_model_for_color = PROCESSCOLORMODEL_RGB;
347 else if (ppdFindChoice(color_mode_option, kCMYK))
348 *color_model_for_color = PROCESSCOLORMODEL_CMYK;
[email protected]8b6098e2012-09-07 04:21:21349
thestigd24bc532016-05-17 21:07:06350 if (ppdFindChoice(color_mode_option, kGreyscale))
351 *color_model_for_black = PROCESSCOLORMODEL_GREYSCALE;
[email protected]8b6098e2012-09-07 04:21:21352
353 ppd_choice_t* mode_choice = ppdFindMarkedChoice(ppd, kProcessColorModel);
354 if (!mode_choice) {
355 mode_choice = ppdFindChoice(color_mode_option,
356 color_mode_option->defchoice);
357 }
358
359 if (mode_choice) {
thestigd24bc532016-05-17 21:07:06360 *color_is_default =
thestig91d04b62017-03-23 19:39:13361 !EqualsCaseInsensitiveASCII(mode_choice->choice, kGreyscale);
[email protected]8b6098e2012-09-07 04:21:21362 }
363 return true;
364}
365
366bool GetColorModelSettings(ppd_file_t* ppd,
[email protected]675a1ae2013-10-14 20:24:37367 ColorModel* cm_black,
368 ColorModel* cm_color,
[email protected]8b6098e2012-09-07 04:21:21369 bool* is_color) {
370 bool is_color_device = false;
thestigd24bc532016-05-17 21:07:06371 ppd_attr_t* attr = ppdFindAttr(ppd, kColorDevice, nullptr);
[email protected]8b6098e2012-09-07 04:21:21372 if (attr && attr->value)
373 is_color_device = ppd->color_device;
374
375 *is_color = is_color_device;
376 return (is_color_device &&
377 GetBasicColorModelSettings(ppd, cm_black, cm_color, is_color)) ||
thestig1847e482017-03-11 02:58:31378 GetPrintOutModeColorSettings(ppd, cm_black, cm_color, is_color) ||
379 GetColorModeSettings(ppd, cm_black, cm_color, is_color) ||
380 GetHPColorSettings(ppd, cm_black, cm_color, is_color) ||
381 GetBrotherColorSettings(ppd, cm_black, cm_color, is_color) ||
382 GetProcessColorModelSettings(ppd, cm_black, cm_color, is_color);
[email protected]8b6098e2012-09-07 04:21:21383}
384
[email protected]8e553f492010-10-25 20:05:44385// Default port for IPP print servers.
[email protected]675a1ae2013-10-14 20:24:37386const int kDefaultIPPServerPort = 631;
387
388} // namespace
[email protected]8e553f492010-10-25 20:05:44389
390// Helper wrapper around http_t structure, with connection and cleanup
391// functionality.
[email protected]ce6f5912012-05-16 23:07:30392HttpConnectionCUPS::HttpConnectionCUPS(const GURL& print_server_url,
393 http_encryption_t encryption)
thestigd24bc532016-05-17 21:07:06394 : http_(nullptr) {
[email protected]8e553f492010-10-25 20:05:44395 // If we have an empty url, use default print server.
396 if (print_server_url.is_empty())
397 return;
398
399 int port = print_server_url.IntPort();
[email protected]04307e02014-05-01 18:01:49400 if (port == url::PORT_UNSPECIFIED)
[email protected]8e553f492010-10-25 20:05:44401 port = kDefaultIPPServerPort;
402
[email protected]675a1ae2013-10-14 20:24:37403 http_ = httpConnectEncrypt(print_server_url.host().c_str(), port, encryption);
thestigd24bc532016-05-17 21:07:06404 if (!http_) {
[email protected]675a1ae2013-10-14 20:24:37405 LOG(ERROR) << "CP_CUPS: Failed connecting to print server: "
406 << print_server_url;
[email protected]8e553f492010-10-25 20:05:44407 }
408}
409
410HttpConnectionCUPS::~HttpConnectionCUPS() {
thestigd24bc532016-05-17 21:07:06411 if (http_)
[email protected]8e553f492010-10-25 20:05:44412 httpClose(http_);
413}
414
[email protected]5a49cdca02010-12-06 18:17:39415void HttpConnectionCUPS::SetBlocking(bool blocking) {
416 httpBlocking(http_, blocking ? 1 : 0);
417}
418
[email protected]8e553f492010-10-25 20:05:44419http_t* HttpConnectionCUPS::http() {
420 return http_;
421}
422
thestigd24bc532016-05-17 21:07:06423bool ParsePpdCapabilities(base::StringPiece printer_name,
424 base::StringPiece printer_capabilities,
425 PrinterSemanticCapsAndDefaults* printer_info) {
[email protected]79f63882013-02-10 05:15:45426 base::FilePath ppd_file_path;
[email protected]03d9afc02013-12-03 17:55:52427 if (!base::CreateTemporaryFile(&ppd_file_path))
[email protected]8b6098e2012-09-07 04:21:21428 return false;
429
430 int data_size = printer_capabilities.length();
[email protected]e5c2a22e2014-03-06 20:42:30431 if (data_size != base::WriteFile(
[email protected]8b6098e2012-09-07 04:21:21432 ppd_file_path,
433 printer_capabilities.data(),
434 data_size)) {
[email protected]dd3aa792013-07-16 19:10:23435 base::DeleteFile(ppd_file_path, false);
[email protected]8b6098e2012-09-07 04:21:21436 return false;
437 }
438
439 ppd_file_t* ppd = ppdOpenFile(ppd_file_path.value().c_str());
[email protected]117eb82d2014-06-13 22:00:57440 if (!ppd) {
441 int line = 0;
442 ppd_status_t ppd_status = ppdLastError(&line);
443 LOG(ERROR) << "Failed to open PDD file: error " << ppd_status << " at line "
444 << line << ", " << ppdErrorString(ppd_status);
[email protected]8b6098e2012-09-07 04:21:21445 return false;
[email protected]117eb82d2014-06-13 22:00:57446 }
alekseys87e02202014-09-17 21:24:56447 ppdMarkDefaults(ppd);
448 MarkLpOptions(printer_name, &ppd);
[email protected]8b6098e2012-09-07 04:21:21449
thestigd24bc532016-05-17 21:07:06450 PrinterSemanticCapsAndDefaults caps;
[email protected]dfb4a9d2014-06-05 21:44:45451 caps.collate_capable = true;
452 caps.collate_default = true;
453 caps.copies_capable = true;
454
thestig1847e482017-03-11 02:58:31455 GetDuplexSettings(ppd, &caps.duplex_capable, &caps.duplex_default);
[email protected]8b6098e2012-09-07 04:21:21456
457 bool is_color = false;
[email protected]675a1ae2013-10-14 20:24:37458 ColorModel cm_color = UNKNOWN_COLOR_MODEL, cm_black = UNKNOWN_COLOR_MODEL;
[email protected]8b6098e2012-09-07 04:21:21459 if (!GetColorModelSettings(ppd, &cm_black, &cm_color, &is_color)) {
460 VLOG(1) << "Unknown printer color model";
461 }
462
[email protected]675a1ae2013-10-14 20:24:37463 caps.color_changeable = ((cm_color != UNKNOWN_COLOR_MODEL) &&
464 (cm_black != UNKNOWN_COLOR_MODEL) &&
465 (cm_color != cm_black));
[email protected]8b6098e2012-09-07 04:21:21466 caps.color_default = is_color;
[email protected]4e7ee5a2013-10-18 03:13:35467 caps.color_model = cm_color;
468 caps.bw_model = cm_black;
[email protected]8b6098e2012-09-07 04:21:21469
[email protected]117eb82d2014-06-13 22:00:57470 if (ppd->num_sizes > 0 && ppd->sizes) {
471 VLOG(1) << "Paper list size - " << ppd->num_sizes;
472 ppd_option_t* paper_option = ppdFindOption(ppd, kPageSize);
473 for (int i = 0; i < ppd->num_sizes; ++i) {
474 gfx::Size paper_size_microns(
Lei Zhangd11ab162018-06-26 04:28:50475 ConvertUnit(ppd->sizes[i].width, kPointsPerInch, kMicronsPerInch),
476 ConvertUnit(ppd->sizes[i].length, kPointsPerInch, kMicronsPerInch));
[email protected]117eb82d2014-06-13 22:00:57477 if (paper_size_microns.width() > 0 && paper_size_microns.height() > 0) {
478 PrinterSemanticCapsAndDefaults::Paper paper;
479 paper.size_um = paper_size_microns;
480 paper.vendor_id = ppd->sizes[i].name;
481 if (paper_option) {
482 ppd_choice_t* paper_choice =
483 ppdFindChoice(paper_option, ppd->sizes[i].name);
484 // Human readable paper name should be UTF-8 encoded, but some PPDs
485 // do not follow this standard.
486 if (paper_choice && base::IsStringUTF8(paper_choice->text)) {
487 paper.display_name = paper_choice->text;
488 }
489 }
490 caps.papers.push_back(paper);
491 if (i == 0 || ppd->sizes[i].marked) {
492 caps.default_paper = paper;
493 }
494 }
495 }
496 }
497
[email protected]8b6098e2012-09-07 04:21:21498 ppdClose(ppd);
[email protected]dd3aa792013-07-16 19:10:23499 base::DeleteFile(ppd_file_path, false);
[email protected]8b6098e2012-09-07 04:21:21500
501 *printer_info = caps;
502 return true;
503}
504
[email protected]8e553f492010-10-25 20:05:44505} // namespace printing