| 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 | 
|---|