cups_helper.cc revision 58537e28ecd584eab876aee8be7156509866d23a
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "printing/backend/cups_helper.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cups/ppd.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string_number_conversions.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_split.h"
137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/strings/string_util.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "printing/backend/print_backend.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "printing/backend/print_backend_consts.h"
177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This section contains helper code for PPD parsing for semantic capabilities.
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kColorDevice[] = "ColorDevice";
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kColorModel[] = "ColorModel";
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kColorMode[] = "ColorMode";
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kProcessColorModel[] = "ProcessColorModel";
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kPrintoutMode[] = "PrintoutMode";
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kDraftGray[] = "Draft.Gray";
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kHighGray[] = "High.Gray";
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kDuplex[] = "Duplex";
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kDuplexNone[] = "None";
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_MACOSX)
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ParseLpOptions(const base::FilePath& filepath,
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    const std::string& printer_name,
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    int* num_options, cups_option_t** options) {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string content;
3858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (!base::ReadFileToString(filepath, &content))
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char kDest[] = "dest";
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char kDefault[] = "default";
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t kDestLen = sizeof(kDest) - 1;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t kDefaultLen = sizeof(kDefault) - 1;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> lines;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::SplitString(content, '\n', &lines);
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < lines.size(); ++i) {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string line = lines[i];
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (line.empty())
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (base::strncasecmp (line.c_str(), kDefault, kDefaultLen) == 0 &&
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        isspace(line[kDefaultLen])) {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      line = line.substr(kDefaultLen);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (base::strncasecmp (line.c_str(), kDest, kDestLen) == 0 &&
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               isspace(line[kDestLen])) {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      line = line.substr(kDestLen);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TrimWhitespaceASCII(line, TRIM_ALL, &line);
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (line.empty())
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t space_found = line.find(' ');
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (space_found == std::string::npos)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string name = line.substr(0, space_found);
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (name.empty())
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (base::strncasecmp(printer_name.c_str(), name.c_str(),
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          name.length()) != 0) {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;  // This is not the required printer.
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    line = line.substr(space_found + 1);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TrimWhitespaceASCII(line, TRIM_ALL, &line);  // Remove extra spaces.
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (line.empty())
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Parse the selected printer custom options.
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *num_options = cupsParseOptions(line.c_str(), 0, options);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MarkLpOptions(const std::string& printer_name, ppd_file_t** ppd) {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cups_option_t* options = NULL;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int num_options = 0;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ppdMarkDefaults(*ppd);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char kSystemLpOptionPath[] = "/etc/cups/lpoptions";
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char kUserLpOptionPath[] = ".cups/lpoptions";
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<base::FilePath> file_locations;
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  file_locations.push_back(base::FilePath(kSystemLpOptionPath));
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  file_locations.push_back(base::FilePath(
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      file_util::GetHomeDir().Append(kUserLpOptionPath)));
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (std::vector<base::FilePath>::const_iterator it = file_locations.begin();
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != file_locations.end(); ++it) {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    num_options = 0;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    options = NULL;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ParseLpOptions(*it, printer_name, &num_options, &options);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (num_options > 0 && options) {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cupsMarkOptions(*ppd, num_options, options);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cupsFreeOptions(num_options, options);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // !defined(OS_MACOSX)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetBasicColorModelSettings(ppd_file_t* ppd,
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                int* color_model_for_black,
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                int* color_model_for_color,
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                bool* color_is_default) {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ppd_option_t* color_model = ppdFindOption(ppd, kColorModel);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!color_model)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ppdFindChoice(color_model, printing::kBlack))
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *color_model_for_black = printing::BLACK;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (ppdFindChoice(color_model, printing::kGray))
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *color_model_for_black = printing::GRAY;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (ppdFindChoice(color_model, printing::kGrayscale))
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *color_model_for_black = printing::GRAYSCALE;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ppdFindChoice(color_model, printing::kColor))
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *color_model_for_color = printing::COLOR;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (ppdFindChoice(color_model, printing::kCMYK))
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *color_model_for_color = printing::CMYK;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (ppdFindChoice(color_model, printing::kRGB))
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *color_model_for_color = printing::RGB;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (ppdFindChoice(color_model, printing::kRGBA))
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *color_model_for_color = printing::RGBA;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (ppdFindChoice(color_model, printing::kRGB16))
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *color_model_for_color = printing::RGB16;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (ppdFindChoice(color_model, printing::kCMY))
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *color_model_for_color = printing::CMY;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (ppdFindChoice(color_model, printing::kKCMY))
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *color_model_for_color = printing::KCMY;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (ppdFindChoice(color_model, printing::kCMY_K))
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *color_model_for_color = printing::CMY_K;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ppd_choice_t* marked_choice = ppdFindMarkedChoice(ppd, kColorModel);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!marked_choice)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    marked_choice = ppdFindChoice(color_model, color_model->defchoice);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (marked_choice) {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *color_is_default =
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (base::strcasecmp(marked_choice->choice, printing::kBlack) != 0) &&
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (base::strcasecmp(marked_choice->choice, printing::kGray) != 0) &&
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (base::strcasecmp(marked_choice->choice, printing::kGrayscale) != 0);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetPrintOutModeColorSettings(ppd_file_t* ppd,
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  int* color_model_for_black,
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  int* color_model_for_color,
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  bool* color_is_default) {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ppd_option_t* printout_mode = ppdFindOption(ppd, kPrintoutMode);
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!printout_mode)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *color_model_for_color = printing::PRINTOUTMODE_NORMAL;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *color_model_for_black = printing::PRINTOUTMODE_NORMAL;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check to see if NORMAL_GRAY value is supported by PrintoutMode.
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If NORMAL_GRAY is not supported, NORMAL value is used to
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // represent grayscale. If NORMAL_GRAY is supported, NORMAL is used to
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // represent color.
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ppdFindChoice(printout_mode, printing::kNormalGray))
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *color_model_for_black = printing::PRINTOUTMODE_NORMAL_GRAY;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the default marked choice to identify the default color setting
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // value.
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ppd_choice_t* printout_mode_choice = ppdFindMarkedChoice(ppd, kPrintoutMode);
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!printout_mode_choice) {
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printout_mode_choice = ppdFindChoice(printout_mode,
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           printout_mode->defchoice);
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (printout_mode_choice) {
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((base::strcasecmp(printout_mode_choice->choice,
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          printing::kNormalGray) == 0) ||
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (base::strcasecmp(printout_mode_choice->choice, kHighGray) == 0) ||
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (base::strcasecmp(printout_mode_choice->choice, kDraftGray) == 0)) {
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *color_model_for_black = printing::PRINTOUTMODE_NORMAL_GRAY;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *color_is_default = false;
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetColorModeSettings(ppd_file_t* ppd,
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          int* color_model_for_black,
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          int* color_model_for_color,
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          bool* color_is_default) {
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Samsung printers use "ColorMode" attribute in their ppds.
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ppd_option_t* color_mode_option = ppdFindOption(ppd, kColorMode);
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!color_mode_option)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ppdFindChoice(color_mode_option, printing::kColor))
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *color_model_for_color = printing::COLORMODE_COLOR;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ppdFindChoice(color_mode_option, printing::kMonochrome))
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *color_model_for_black = printing::COLORMODE_MONOCHROME;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ppd_choice_t* mode_choice = ppdFindMarkedChoice(ppd, kColorMode);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!mode_choice) {
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mode_choice = ppdFindChoice(color_mode_option,
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                color_mode_option->defchoice);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (mode_choice) {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *color_is_default =
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (base::strcasecmp(mode_choice->choice, printing::kColor) == 0);
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetHPColorSettings(ppd_file_t* ppd,
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        int* color_model_for_black,
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        int* color_model_for_color,
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        bool* color_is_default) {
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // HP printers use "Color/Color Model" attribute in their ppds.
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ppd_option_t* color_mode_option = ppdFindOption(ppd, printing::kColor);
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!color_mode_option)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ppdFindChoice(color_mode_option, printing::kColor))
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *color_model_for_color = printing::HP_COLOR_COLOR;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ppdFindChoice(color_mode_option, printing::kBlack))
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *color_model_for_black = printing::HP_COLOR_BLACK;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ppd_choice_t* mode_choice = ppdFindMarkedChoice(ppd, kColorMode);
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!mode_choice) {
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mode_choice = ppdFindChoice(color_mode_option,
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                color_mode_option->defchoice);
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (mode_choice) {
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *color_is_default =
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (base::strcasecmp(mode_choice->choice, printing::kColor) == 0);
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetProcessColorModelSettings(ppd_file_t* ppd,
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  int* color_model_for_black,
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  int* color_model_for_color,
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  bool* color_is_default) {
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Canon printers use "ProcessColorModel" attribute in their ppds.
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ppd_option_t* color_mode_option =  ppdFindOption(ppd, kProcessColorModel);
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!color_mode_option)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ppdFindChoice(color_mode_option, printing::kRGB))
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *color_model_for_color = printing::PROCESSCOLORMODEL_RGB;
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (ppdFindChoice(color_mode_option, printing::kCMYK))
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *color_model_for_color = printing::PROCESSCOLORMODEL_CMYK;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ppdFindChoice(color_mode_option, printing::kGreyscale))
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *color_model_for_black = printing::PROCESSCOLORMODEL_GREYSCALE;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ppd_choice_t* mode_choice = ppdFindMarkedChoice(ppd, kProcessColorModel);
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!mode_choice) {
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mode_choice = ppdFindChoice(color_mode_option,
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                color_mode_option->defchoice);
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (mode_choice) {
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *color_is_default =
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (base::strcasecmp(mode_choice->choice, printing::kGreyscale) != 0);
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetColorModelSettings(ppd_file_t* ppd,
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           int* cm_black,
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           int* cm_color,
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           bool* is_color) {
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_color_device = false;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ppd_attr_t* attr = ppdFindAttr(ppd, kColorDevice, NULL);
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (attr && attr->value)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    is_color_device = ppd->color_device;
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *is_color = is_color_device;
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (is_color_device &&
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          GetBasicColorModelSettings(ppd, cm_black, cm_color, is_color)) ||
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetPrintOutModeColorSettings(ppd, cm_black, cm_color, is_color) ||
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetColorModeSettings(ppd, cm_black, cm_color, is_color) ||
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetHPColorSettings(ppd, cm_black, cm_color, is_color) ||
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetProcessColorModelSettings(ppd, cm_black, cm_color, is_color);
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace printing {
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Default port for IPP print servers.
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kDefaultIPPServerPort = 631;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper wrapper around http_t structure, with connection and cleanup
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// functionality.
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpConnectionCUPS::HttpConnectionCUPS(const GURL& print_server_url,
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       http_encryption_t encryption)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : http_(NULL) {
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we have an empty url, use default print server.
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (print_server_url.is_empty())
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int port = print_server_url.IntPort();
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (port == url_parse::PORT_UNSPECIFIED)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    port = kDefaultIPPServerPort;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  http_ = httpConnectEncrypt(print_server_url.host().c_str(), port,
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             encryption);
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (http_ == NULL) {
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "CP_CUPS: Failed connecting to print server: " <<
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               print_server_url;
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpConnectionCUPS::~HttpConnectionCUPS() {
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (http_ != NULL)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    httpClose(http_);
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpConnectionCUPS::SetBlocking(bool blocking) {
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  httpBlocking(http_, blocking ?  1 : 0);
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)http_t* HttpConnectionCUPS::http() {
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return http_;
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool parsePpdCapabilities(
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& printer_name,
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& printer_capabilities,
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrinterSemanticCapsAndDefaults* printer_info) {
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath ppd_file_path;
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!file_util::CreateTemporaryFile(&ppd_file_path))
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int data_size = printer_capabilities.length();
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (data_size != file_util::WriteFile(
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       ppd_file_path,
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       printer_capabilities.data(),
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       data_size)) {
3537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    base::DeleteFile(ppd_file_path, false);
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ppd_file_t* ppd = ppdOpenFile(ppd_file_path.value().c_str());
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ppd)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printing::PrinterSemanticCapsAndDefaults caps;
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_MACOSX)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MarkLpOptions(printer_name, &ppd);
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ppd_choice_t* duplex_choice = ppdFindMarkedChoice(ppd, kDuplex);
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!duplex_choice) {
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ppd_option_t* option = ppdFindOption(ppd, kDuplex);
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (option)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      duplex_choice = ppdFindChoice(option, option->defchoice);
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (duplex_choice) {
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    caps.duplex_capable = true;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (base::strcasecmp(duplex_choice->choice, kDuplexNone) != 0)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      caps.duplex_default = printing::LONG_EDGE;
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      caps.duplex_default = printing::SIMPLEX;
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_color = false;
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int cm_color = 0, cm_black = 0;
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!GetColorModelSettings(ppd, &cm_black, &cm_color, &is_color)) {
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Unknown printer color model";
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  caps.color_changeable = (cm_color && cm_black && (cm_color != cm_black));
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  caps.color_default = is_color;
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ppdClose(ppd);
3907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  base::DeleteFile(ppd_file_path, false);
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *printer_info = caps;
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace printing
397