| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "printing/backend/print_backend.h" | 5 #include "printing/backend/print_backend.h" |
| 6 | 6 |
| 7 #include <dlfcn.h> | 7 #include <dlfcn.h> |
| 8 #include <errno.h> | 8 #include <errno.h> |
| 9 #include <pthread.h> | 9 #include <pthread.h> |
| 10 | 10 |
| 11 #include "base/debug/leak_annotations.h" | 11 #include "base/debug/leak_annotations.h" |
| 12 #include "base/files/file_util.h" | 12 #include "base/files/file_util.h" |
| 13 #include "base/lazy_instance.h" | 13 #include "base/lazy_instance.h" |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/strings/string_number_conversions.h" | 15 #include "base/strings/string_number_conversions.h" |
| 16 #include "base/synchronization/lock.h" | 16 #include "base/synchronization/lock.h" |
| 17 #include "base/values.h" | 17 #include "base/values.h" |
| 18 #include "printing/backend/cups_helper.h" | 18 #include "printing/backend/cups_helper.h" |
| 19 #include "printing/backend/print_backend_consts.h" | 19 #include "printing/backend/print_backend_consts.h" |
| 20 #include "url/gurl.h" | 20 #include "url/gurl.h" |
| 21 | 21 |
| 22 namespace printing { | 22 namespace printing { |
| 23 | 23 |
| 24 static const char kCUPSPrinterInfoOpt[] = "printer-info"; | 24 namespace { |
| 25 static const char kCUPSPrinterStateOpt[] = "printer-state"; | 25 |
| 26 static const char kCUPSPrinterTypeOpt[] = "printer-type"; | 26 const char kCUPSPrinterInfoOpt[] = "printer-info"; |
| 27 static const char kCUPSPrinterMakeModelOpt[] = "printer-make-and-model"; | 27 const char kCUPSPrinterStateOpt[] = "printer-state"; |
| 28 const char kCUPSPrinterTypeOpt[] = "printer-type"; |
| 29 const char kCUPSPrinterMakeModelOpt[] = "printer-make-and-model"; |
| 30 |
| 31 bool PrinterBasicInfoFromCUPS(const cups_dest_t& printer, |
| 32 PrinterBasicInfo* printer_info) { |
| 33 // CUPS can have 'printers' that are actually scanners. (not MFC) |
| 34 // At least on Mac. Check for scanners and skip them. |
| 35 const char* type_str = |
| 36 cupsGetOption(kCUPSPrinterTypeOpt, printer.num_options, printer.options); |
| 37 if (type_str) { |
| 38 int type; |
| 39 if (base::StringToInt(type_str, &type) && (type & CUPS_PRINTER_SCANNER)) |
| 40 return false; |
| 41 } |
| 42 |
| 43 printer_info->printer_name = printer.name; |
| 44 printer_info->is_default = printer.is_default; |
| 45 |
| 46 const char* info = |
| 47 cupsGetOption(kCUPSPrinterInfoOpt, printer.num_options, printer.options); |
| 48 if (info) |
| 49 printer_info->printer_description = info; |
| 50 |
| 51 const char* state = |
| 52 cupsGetOption(kCUPSPrinterStateOpt, printer.num_options, printer.options); |
| 53 if (state) |
| 54 base::StringToInt(state, &printer_info->printer_status); |
| 55 |
| 56 const char* drv_info = cupsGetOption(kCUPSPrinterMakeModelOpt, |
| 57 printer.num_options, printer.options); |
| 58 if (drv_info) |
| 59 printer_info->options[kDriverInfoTagName] = *drv_info; |
| 60 |
| 61 // Store printer options. |
| 62 for (int opt_index = 0; opt_index < printer.num_options; ++opt_index) { |
| 63 printer_info->options[printer.options[opt_index].name] = |
| 64 printer.options[opt_index].value; |
| 65 } |
| 66 return true; |
| 67 } |
| 68 |
| 69 } // namespace |
| 28 | 70 |
| 29 class PrintBackendCUPS : public PrintBackend { | 71 class PrintBackendCUPS : public PrintBackend { |
| 30 public: | 72 public: |
| 31 PrintBackendCUPS(const GURL& print_server_url, | 73 PrintBackendCUPS(const GURL& print_server_url, |
| 32 http_encryption_t encryption, bool blocking); | 74 http_encryption_t encryption, bool blocking); |
| 33 | 75 |
| 34 private: | 76 private: |
| 35 ~PrintBackendCUPS() override {} | 77 ~PrintBackendCUPS() override {} |
| 36 | 78 |
| 37 // PrintBackend implementation. | 79 // PrintBackend implementation. |
| 38 bool EnumeratePrinters(PrinterList* printer_list) override; | 80 bool EnumeratePrinters(PrinterList* printer_list) override; |
| 39 std::string GetDefaultPrinterName() override; | 81 std::string GetDefaultPrinterName() override; |
| 82 bool GetPrinterBasicInfo(const std::string& printer_name, |
| 83 PrinterBasicInfo* printer_info) override; |
| 40 bool GetPrinterSemanticCapsAndDefaults( | 84 bool GetPrinterSemanticCapsAndDefaults( |
| 41 const std::string& printer_name, | 85 const std::string& printer_name, |
| 42 PrinterSemanticCapsAndDefaults* printer_info) override; | 86 PrinterSemanticCapsAndDefaults* printer_info) override; |
| 43 bool GetPrinterCapsAndDefaults(const std::string& printer_name, | 87 bool GetPrinterCapsAndDefaults(const std::string& printer_name, |
| 44 PrinterCapsAndDefaults* printer_info) override; | 88 PrinterCapsAndDefaults* printer_info) override; |
| 45 std::string GetPrinterDriverInfo(const std::string& printer_name) override; | 89 std::string GetPrinterDriverInfo(const std::string& printer_name) override; |
| 46 bool IsValidPrinter(const std::string& printer_name) override; | 90 bool IsValidPrinter(const std::string& printer_name) override; |
| 47 | 91 |
| 48 // The following functions are wrappers around corresponding CUPS functions. | 92 // The following functions are wrappers around corresponding CUPS functions. |
| 49 // <functions>2() are called when print server is specified, and plain version | 93 // <functions>2() are called when print server is specified, and plain version |
| (...skipping 28 matching lines...) Expand all Loading... |
| 78 if (!num_dests && cupsLastError() > IPP_OK_EVENTS_COMPLETE) { | 122 if (!num_dests && cupsLastError() > IPP_OK_EVENTS_COMPLETE) { |
| 79 VLOG(1) << "CUPS: Error getting printers from CUPS server" | 123 VLOG(1) << "CUPS: Error getting printers from CUPS server" |
| 80 << ", server: " << print_server_url_ | 124 << ", server: " << print_server_url_ |
| 81 << ", error: " << static_cast<int>(cupsLastError()); | 125 << ", error: " << static_cast<int>(cupsLastError()); |
| 82 return false; | 126 return false; |
| 83 } | 127 } |
| 84 | 128 |
| 85 for (int printer_index = 0; printer_index < num_dests; ++printer_index) { | 129 for (int printer_index = 0; printer_index < num_dests; ++printer_index) { |
| 86 const cups_dest_t& printer = destinations[printer_index]; | 130 const cups_dest_t& printer = destinations[printer_index]; |
| 87 | 131 |
| 88 // CUPS can have 'printers' that are actually scanners. (not MFC) | |
| 89 // At least on Mac. Check for scanners and skip them. | |
| 90 const char* type_str = cupsGetOption(kCUPSPrinterTypeOpt, | |
| 91 printer.num_options, printer.options); | |
| 92 if (type_str) { | |
| 93 int type; | |
| 94 if (base::StringToInt(type_str, &type) && (type & CUPS_PRINTER_SCANNER)) | |
| 95 continue; | |
| 96 } | |
| 97 | |
| 98 PrinterBasicInfo printer_info; | 132 PrinterBasicInfo printer_info; |
| 99 printer_info.printer_name = printer.name; | 133 if (PrinterBasicInfoFromCUPS(printer, &printer_info)) |
| 100 printer_info.is_default = printer.is_default; | 134 printer_list->push_back(printer_info); |
| 101 | |
| 102 const char* info = cupsGetOption(kCUPSPrinterInfoOpt, | |
| 103 printer.num_options, printer.options); | |
| 104 if (info) | |
| 105 printer_info.printer_description = info; | |
| 106 | |
| 107 const char* state = cupsGetOption(kCUPSPrinterStateOpt, | |
| 108 printer.num_options, printer.options); | |
| 109 if (state) | |
| 110 base::StringToInt(state, &printer_info.printer_status); | |
| 111 | |
| 112 const char* drv_info = cupsGetOption(kCUPSPrinterMakeModelOpt, | |
| 113 printer.num_options, | |
| 114 printer.options); | |
| 115 if (drv_info) | |
| 116 printer_info.options[kDriverInfoTagName] = *drv_info; | |
| 117 | |
| 118 // Store printer options. | |
| 119 for (int opt_index = 0; opt_index < printer.num_options; ++opt_index) { | |
| 120 printer_info.options[printer.options[opt_index].name] = | |
| 121 printer.options[opt_index].value; | |
| 122 } | |
| 123 | |
| 124 printer_list->push_back(printer_info); | |
| 125 } | 135 } |
| 126 | 136 |
| 127 cupsFreeDests(num_dests, destinations); | 137 cupsFreeDests(num_dests, destinations); |
| 128 | 138 |
| 129 VLOG(1) << "CUPS: Enumerated printers, server: " << print_server_url_ | 139 VLOG(1) << "CUPS: Enumerated printers, server: " << print_server_url_ |
| 130 << ", # of printers: " << printer_list->size(); | 140 << ", # of printers: " << printer_list->size(); |
| 131 return true; | 141 return true; |
| 132 } | 142 } |
| 133 | 143 |
| 134 std::string PrintBackendCUPS::GetDefaultPrinterName() { | 144 std::string PrintBackendCUPS::GetDefaultPrinterName() { |
| 135 // Not using cupsGetDefault() because it lies about the default printer. | 145 // Not using cupsGetDefault() because it lies about the default printer. |
| 136 cups_dest_t* dests; | 146 cups_dest_t* dests; |
| 137 int num_dests = GetDests(&dests); | 147 int num_dests = GetDests(&dests); |
| 138 cups_dest_t* dest = cupsGetDest(nullptr, nullptr, num_dests, dests); | 148 cups_dest_t* dest = cupsGetDest(nullptr, nullptr, num_dests, dests); |
| 139 std::string name = dest ? std::string(dest->name) : std::string(); | 149 std::string name = dest ? std::string(dest->name) : std::string(); |
| 140 cupsFreeDests(num_dests, dests); | 150 cupsFreeDests(num_dests, dests); |
| 141 return name; | 151 return name; |
| 142 } | 152 } |
| 143 | 153 |
| 154 bool PrintBackendCUPS::GetPrinterBasicInfo(const std::string& printer_name, |
| 155 PrinterBasicInfo* printer_info) { |
| 156 cups_dest_t* dest = GetNamedDest(printer_name); |
| 157 if (!dest) |
| 158 return false; |
| 159 |
| 160 DCHECK_EQ(printer_name, dest->name); |
| 161 bool ret = PrinterBasicInfoFromCUPS(*dest, printer_info); |
| 162 cupsFreeDests(1, dest); |
| 163 return ret; |
| 164 } |
| 165 |
| 144 bool PrintBackendCUPS::GetPrinterSemanticCapsAndDefaults( | 166 bool PrintBackendCUPS::GetPrinterSemanticCapsAndDefaults( |
| 145 const std::string& printer_name, | 167 const std::string& printer_name, |
| 146 PrinterSemanticCapsAndDefaults* printer_info) { | 168 PrinterSemanticCapsAndDefaults* printer_info) { |
| 147 PrinterCapsAndDefaults info; | 169 PrinterCapsAndDefaults info; |
| 148 if (!GetPrinterCapsAndDefaults(printer_name, &info) ) | 170 if (!GetPrinterCapsAndDefaults(printer_name, &info) ) |
| 149 return false; | 171 return false; |
| 150 | 172 |
| 151 return ParsePpdCapabilities( | 173 return ParsePpdCapabilities( |
| 152 printer_name, info.printer_capabilities, printer_info); | 174 printer_name, info.printer_capabilities, printer_info); |
| 153 } | 175 } |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 296 // Use default (local) print server. | 318 // Use default (local) print server. |
| 297 if (print_server_url_.is_empty()) | 319 if (print_server_url_.is_empty()) |
| 298 return cupsGetNamedDest(CUPS_HTTP_DEFAULT, printer_name.c_str(), nullptr); | 320 return cupsGetNamedDest(CUPS_HTTP_DEFAULT, printer_name.c_str(), nullptr); |
| 299 | 321 |
| 300 HttpConnectionCUPS http(print_server_url_, cups_encryption_); | 322 HttpConnectionCUPS http(print_server_url_, cups_encryption_); |
| 301 http.SetBlocking(blocking_); | 323 http.SetBlocking(blocking_); |
| 302 return cupsGetNamedDest(http.http(), printer_name.c_str(), nullptr); | 324 return cupsGetNamedDest(http.http(), printer_name.c_str(), nullptr); |
| 303 } | 325 } |
| 304 | 326 |
| 305 } // namespace printing | 327 } // namespace printing |
| OLD | NEW |