| 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 "build/build_config.h" | 7 #include "build/build_config.h" |
| 8 | 8 |
| 9 #include <dlfcn.h> | 9 #include <dlfcn.h> |
| 10 #include <errno.h> | 10 #include <errno.h> |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 121 | 121 |
| 122 protected: | 122 protected: |
| 123 virtual ~PrintBackendCUPS() {} | 123 virtual ~PrintBackendCUPS() {} |
| 124 | 124 |
| 125 private: | 125 private: |
| 126 // Following functions are wrappers around corresponding CUPS functions. | 126 // Following functions are wrappers around corresponding CUPS functions. |
| 127 // <functions>2() are called when print server is specified, and plain | 127 // <functions>2() are called when print server is specified, and plain |
| 128 // version in another case. There is an issue specifing CUPS_HTTP_DEFAULT | 128 // version in another case. There is an issue specifing CUPS_HTTP_DEFAULT |
| 129 // in the <functions>2(), it does not work in CUPS prior to 1.4. | 129 // in the <functions>2(), it does not work in CUPS prior to 1.4. |
| 130 int GetDests(cups_dest_t** dests); | 130 int GetDests(cups_dest_t** dests); |
| 131 FilePath GetPPD(const char* name); | 131 base::FilePath GetPPD(const char* name); |
| 132 | 132 |
| 133 GURL print_server_url_; | 133 GURL print_server_url_; |
| 134 http_encryption_t cups_encryption_; | 134 http_encryption_t cups_encryption_; |
| 135 bool blocking_; | 135 bool blocking_; |
| 136 }; | 136 }; |
| 137 | 137 |
| 138 PrintBackendCUPS::PrintBackendCUPS(const GURL& print_server_url, | 138 PrintBackendCUPS::PrintBackendCUPS(const GURL& print_server_url, |
| 139 http_encryption_t encryption, | 139 http_encryption_t encryption, |
| 140 bool blocking) | 140 bool blocking) |
| 141 : print_server_url_(print_server_url), | 141 : print_server_url_(print_server_url), |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 228 } | 228 } |
| 229 | 229 |
| 230 bool PrintBackendCUPS::GetPrinterCapsAndDefaults( | 230 bool PrintBackendCUPS::GetPrinterCapsAndDefaults( |
| 231 const std::string& printer_name, | 231 const std::string& printer_name, |
| 232 PrinterCapsAndDefaults* printer_info) { | 232 PrinterCapsAndDefaults* printer_info) { |
| 233 DCHECK(printer_info); | 233 DCHECK(printer_info); |
| 234 | 234 |
| 235 VLOG(1) << "CUPS: Getting caps and defaults" | 235 VLOG(1) << "CUPS: Getting caps and defaults" |
| 236 << ", printer name: " << printer_name; | 236 << ", printer name: " << printer_name; |
| 237 | 237 |
| 238 FilePath ppd_path(GetPPD(printer_name.c_str())); | 238 base::FilePath ppd_path(GetPPD(printer_name.c_str())); |
| 239 // In some cases CUPS failed to get ppd file. | 239 // In some cases CUPS failed to get ppd file. |
| 240 if (ppd_path.empty()) { | 240 if (ppd_path.empty()) { |
| 241 LOG(ERROR) << "CUPS: Failed to get PPD" | 241 LOG(ERROR) << "CUPS: Failed to get PPD" |
| 242 << ", printer name: " << printer_name; | 242 << ", printer name: " << printer_name; |
| 243 return false; | 243 return false; |
| 244 } | 244 } |
| 245 | 245 |
| 246 std::string content; | 246 std::string content; |
| 247 bool res = file_util::ReadFileToString(ppd_path, &content); | 247 bool res = file_util::ReadFileToString(ppd_path, &content); |
| 248 | 248 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 325 http.SetBlocking(blocking_); | 325 http.SetBlocking(blocking_); |
| 326 return cupsGetDests2(http.http(), dests); | 326 return cupsGetDests2(http.http(), dests); |
| 327 } | 327 } |
| 328 } | 328 } |
| 329 | 329 |
| 330 FilePath PrintBackendCUPS::GetPPD(const char* name) { | 330 FilePath PrintBackendCUPS::GetPPD(const char* name) { |
| 331 // cupsGetPPD returns a filename stored in a static buffer in CUPS. | 331 // cupsGetPPD returns a filename stored in a static buffer in CUPS. |
| 332 // Protect this code with lock. | 332 // Protect this code with lock. |
| 333 CR_DEFINE_STATIC_LOCAL(base::Lock, ppd_lock, ()); | 333 CR_DEFINE_STATIC_LOCAL(base::Lock, ppd_lock, ()); |
| 334 base::AutoLock ppd_autolock(ppd_lock); | 334 base::AutoLock ppd_autolock(ppd_lock); |
| 335 FilePath ppd_path; | 335 base::FilePath ppd_path; |
| 336 const char* ppd_file_path = NULL; | 336 const char* ppd_file_path = NULL; |
| 337 if (print_server_url_.is_empty()) { // Use default (local) print server. | 337 if (print_server_url_.is_empty()) { // Use default (local) print server. |
| 338 ppd_file_path = cupsGetPPD(name); | 338 ppd_file_path = cupsGetPPD(name); |
| 339 if (ppd_file_path) | 339 if (ppd_file_path) |
| 340 ppd_path = FilePath(ppd_file_path); | 340 ppd_path = base::FilePath(ppd_file_path); |
| 341 } else { | 341 } else { |
| 342 // cupsGetPPD2 gets stuck sometimes in an infinite time due to network | 342 // cupsGetPPD2 gets stuck sometimes in an infinite time due to network |
| 343 // configuration/issues. To prevent that, use non-blocking http connection | 343 // configuration/issues. To prevent that, use non-blocking http connection |
| 344 // here. | 344 // here. |
| 345 // Note: After looking at CUPS sources, it looks like non-blocking | 345 // Note: After looking at CUPS sources, it looks like non-blocking |
| 346 // connection will timeout after 10 seconds of no data period. And it will | 346 // connection will timeout after 10 seconds of no data period. And it will |
| 347 // return the same way as if data was completely and sucessfully downloaded. | 347 // return the same way as if data was completely and sucessfully downloaded. |
| 348 HttpConnectionCUPS http(print_server_url_, cups_encryption_); | 348 HttpConnectionCUPS http(print_server_url_, cups_encryption_); |
| 349 http.SetBlocking(blocking_); | 349 http.SetBlocking(blocking_); |
| 350 ppd_file_path = cupsGetPPD2(http.http(), name); | 350 ppd_file_path = cupsGetPPD2(http.http(), name); |
| 351 // Check if the get full PPD, since non-blocking call may simply return | 351 // Check if the get full PPD, since non-blocking call may simply return |
| 352 // normally after timeout expired. | 352 // normally after timeout expired. |
| 353 if (ppd_file_path) { | 353 if (ppd_file_path) { |
| 354 // There is no reliable way right now to detect full and complete PPD | 354 // There is no reliable way right now to detect full and complete PPD |
| 355 // get downloaded. If we reach http timeout, it may simply return | 355 // get downloaded. If we reach http timeout, it may simply return |
| 356 // downloaded part as a full response. It might be good enough to check | 356 // downloaded part as a full response. It might be good enough to check |
| 357 // http->data_remaining or http->_data_remaining, unfortunately http_t | 357 // http->data_remaining or http->_data_remaining, unfortunately http_t |
| 358 // is an internal structure and fields are not exposed in CUPS headers. | 358 // is an internal structure and fields are not exposed in CUPS headers. |
| 359 // httpGetLength or httpGetLength2 returning the full content size. | 359 // httpGetLength or httpGetLength2 returning the full content size. |
| 360 // Comparing file size against that content length might be unreliable | 360 // Comparing file size against that content length might be unreliable |
| 361 // since some http reponses are encoded and content_length > file size. | 361 // since some http reponses are encoded and content_length > file size. |
| 362 // Let's just check for the obvious CUPS and http errors here. | 362 // Let's just check for the obvious CUPS and http errors here. |
| 363 ppd_path = FilePath(ppd_file_path); | 363 ppd_path = base::FilePath(ppd_file_path); |
| 364 ipp_status_t error_code = cupsLastError(); | 364 ipp_status_t error_code = cupsLastError(); |
| 365 int http_error = httpError(http.http()); | 365 int http_error = httpError(http.http()); |
| 366 if (error_code > IPP_OK_EVENTS_COMPLETE || http_error != 0) { | 366 if (error_code > IPP_OK_EVENTS_COMPLETE || http_error != 0) { |
| 367 LOG(ERROR) << "Error downloading PPD file" | 367 LOG(ERROR) << "Error downloading PPD file" |
| 368 << ", name: " << name | 368 << ", name: " << name |
| 369 << ", CUPS error: " << static_cast<int>(error_code) | 369 << ", CUPS error: " << static_cast<int>(error_code) |
| 370 << ", HTTP error: " << http_error; | 370 << ", HTTP error: " << http_error; |
| 371 file_util::Delete(ppd_path, false); | 371 file_util::Delete(ppd_path, false); |
| 372 ppd_path.clear(); | 372 ppd_path.clear(); |
| 373 } | 373 } |
| 374 } | 374 } |
| 375 } | 375 } |
| 376 return ppd_path; | 376 return ppd_path; |
| 377 } | 377 } |
| 378 | 378 |
| 379 } // namespace printing | 379 } // namespace printing |
| OLD | NEW |