Index: chrome/service/cloud_print/print_system_cups.cc |
=================================================================== |
--- chrome/service/cloud_print/print_system_cups.cc (revision 63553) |
+++ chrome/service/cloud_print/print_system_cups.cc (working copy) |
@@ -14,7 +14,6 @@ |
#include <map> |
#include "base/file_path.h" |
-#include "base/file_util.h" |
#include "base/json/json_reader.h" |
#include "base/lock.h" |
#include "base/logging.h" |
@@ -26,59 +25,9 @@ |
#include "base/values.h" |
#include "base/utf_string_conversions.h" |
#include "googleurl/src/gurl.h" |
+#include "printing/backend/cups_helper.h" |
+#include "printing/backend/print_backend.h" |
-namespace { |
- |
-// Init GCrypt library (needed for CUPS) using pthreads. |
-// I've hit a bug in CUPS library, when it crashed with: "ath.c:184: |
-// _gcry_ath_mutex_lock: Assertion `*lock == ((ath_mutex_t) 0)' failed." |
-// It happened whe multiple threads tried printing simultaneously. |
-// Google search for 'gnutls thread safety' provided with following solution |
-// where we initialize gcrypt by initializing gnutls. |
-// |
-// Initially, we linked with -lgnutls and simply called gnutls_global_init(), |
-// but this did not work well since we build one binary on Ubuntu Hardy and |
-// expect it to run on many Linux distros. (See http://crbug.com/46954) |
-// So instead we use dlopen() and dlsym() to dynamically load and call |
-// gnutls_global_init(). |
- |
-GCRY_THREAD_OPTION_PTHREAD_IMPL; |
- |
-bool init_gnutls() { |
- const char* kGnuTlsFile = "libgnutls.so"; |
- void* gnutls_lib = dlopen(kGnuTlsFile, RTLD_NOW); |
- if (!gnutls_lib) { |
- LOG(ERROR) << "Cannot load " << kGnuTlsFile; |
- return false; |
- } |
- const char* kGnuTlsInitFuncName = "gnutls_global_init"; |
- int (*pgnutls_global_init)(void) = reinterpret_cast<int(*)()>( |
- dlsym(gnutls_lib, kGnuTlsInitFuncName)); |
- if (!pgnutls_global_init) { |
- LOG(ERROR) << "Could not find " << kGnuTlsInitFuncName |
- << " in " << kGnuTlsFile; |
- return false; |
- } |
- return ((*pgnutls_global_init)() == 0); |
-} |
- |
-void init_gcrypt() { |
- // The gnutls_global_init() man page warns it's not thread safe. Locking this |
- // entire function just to be on the safe side. |
- static Lock init_gcrypt_lock; |
- AutoLock init_gcrypt_autolock(init_gcrypt_lock); |
- static bool gcrypt_initialized = false; |
- if (!gcrypt_initialized) { |
- gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); |
- gcrypt_initialized = init_gnutls(); |
- if (!gcrypt_initialized) { |
- LOG(ERROR) << "Gcrypt initialization failed"; |
- } |
- } |
-} |
- |
-} // namespace |
- |
namespace cloud_print { |
static const char kCUPSPrinterInfoOpt[] = "printer-info"; |
@@ -88,50 +37,14 @@ |
// Default port for IPP print servers. |
static const int kDefaultIPPServerPort = 631; |
-// Helper wrapper around http_t structure, with connection and cleanup |
-// functionality. |
-class HttpConnectionCUPS { |
- public: |
- explicit HttpConnectionCUPS(const GURL& print_server_url) : http_(NULL) { |
- // If we have an empty url, use default print server. |
- if (print_server_url.is_empty()) |
- return; |
- |
- int port = print_server_url.IntPort(); |
- if (port == url_parse::PORT_UNSPECIFIED) |
- port = kDefaultIPPServerPort; |
- |
- http_ = httpConnectEncrypt(print_server_url.host().c_str(), port, |
- HTTP_ENCRYPT_NEVER); |
- if (http_ == NULL) { |
- LOG(ERROR) << "CP_CUPS: Failed connecting to print server: " << |
- print_server_url; |
- } |
- } |
- |
- ~HttpConnectionCUPS() { |
- if (http_ != NULL) |
- httpClose(http_); |
- } |
- |
- http_t* http() { |
- return http_; |
- } |
- |
- private: |
- http_t* http_; |
-}; |
- |
class PrintSystemCUPS : public PrintSystem { |
public: |
- explicit PrintSystemCUPS(const GURL& print_server_url); |
+ PrintSystemCUPS(const GURL& print_server_url, |
+ const DictionaryValue* print_system_settings); |
// PrintSystem implementation. |
- virtual void EnumeratePrinters(PrinterList* printer_list); |
+ virtual printing::PrintBackend* GetPrintBackend(); |
- virtual bool GetPrinterCapsAndDefaults(const std::string& printer_name, |
- PrinterCapsAndDefaults* printer_info); |
- |
virtual bool ValidatePrintTicket(const std::string& printer_name, |
const std::string& print_ticket_data); |
@@ -139,9 +52,6 @@ |
PlatformJobId job_id, |
PrintJobDetails *job_details); |
- virtual bool IsValidPrinter(const std::string& printer_name); |
- |
- |
// TODO(gene): Add implementation for CUPS print server watcher. |
class PrintServerWatcherCUPS |
: public PrintSystem::PrintServerWatcher { |
@@ -185,7 +95,7 @@ |
delegate_ = NULL; |
return true; |
} |
- bool GetCurrentPrinterInfo(PrinterBasicInfo* printer_info) { |
+ bool GetCurrentPrinterInfo(printing::PrinterBasicInfo* printer_info) { |
DCHECK(printer_info); |
return print_system_->GetPrinterInfo(printer_name_, printer_info); |
} |
@@ -258,7 +168,8 @@ |
const std::string& print_data_mime_type, |
const std::string& printer_name, |
const std::string& job_title); |
- bool GetPrinterInfo(const std::string& printer_name, PrinterBasicInfo* info); |
+ bool GetPrinterInfo(const std::string& printer_name, |
+ printing::PrinterBasicInfo* info); |
bool ParsePrintTicket(const std::string& print_ticket, |
std::map<std::string, std::string>* options); |
@@ -267,84 +178,30 @@ |
// <functions>2() are called when print server is specified, and plain |
// version in another case. There is an issue specifing CUPS_HTTP_DEFAULT |
// in the <functions>2(), it does not work in CUPS prior to 1.4. |
- int GetDests(cups_dest_t** dests); |
- FilePath GetPPD(const char* name); |
int GetJobs(cups_job_t** jobs, const char* name, |
int myjobs, int whichjobs); |
int PrintFile(const char* name, const char* filename, const char* title, |
int num_options, cups_option_t* options); |
+ void Init(const DictionaryValue* print_system_settings); |
+ |
GURL print_server_url_; |
+ scoped_refptr<printing::PrintBackend> print_backend_; |
}; |
-PrintSystemCUPS::PrintSystemCUPS(const GURL& print_server_url) |
+PrintSystemCUPS::PrintSystemCUPS(const GURL& print_server_url, |
+ const DictionaryValue* print_system_settings) |
: print_server_url_(print_server_url) { |
+ Init(print_system_settings); |
} |
-void PrintSystemCUPS::EnumeratePrinters(PrinterList* printer_list) { |
- DCHECK(printer_list); |
- printer_list->clear(); |
- |
- cups_dest_t* destinations = NULL; |
- int num_dests = GetDests(&destinations); |
- |
- for (int printer_index = 0; printer_index < num_dests; printer_index++) { |
- const cups_dest_t& printer = destinations[printer_index]; |
- |
- PrinterBasicInfo printer_info; |
- printer_info.printer_name = printer.name; |
- |
- const char* info = cupsGetOption(kCUPSPrinterInfoOpt, |
- printer.num_options, printer.options); |
- if (info != NULL) |
- printer_info.printer_description = info; |
- |
- const char* state = cupsGetOption(kCUPSPrinterStateOpt, |
- printer.num_options, printer.options); |
- if (state != NULL) |
- base::StringToInt(state, &printer_info.printer_status); |
- |
- // Store printer options. |
- for (int opt_index = 0; opt_index < printer.num_options; opt_index++) { |
- printer_info.options[printer.options[opt_index].name] = |
- printer.options[opt_index].value; |
- } |
- |
- printer_list->push_back(printer_info); |
- } |
- |
- cupsFreeDests(num_dests, destinations); |
- |
- LOG(INFO) << "CP_CUPS: Enumerated " << printer_list->size() << " printers."; |
+void PrintSystemCUPS::Init(const DictionaryValue* print_system_settings) { |
+ print_backend_ = |
+ printing::PrintBackend::CreateInstance(print_system_settings); |
} |
-bool PrintSystemCUPS::GetPrinterCapsAndDefaults(const std::string& printer_name, |
- PrinterCapsAndDefaults* printer_info) { |
- DCHECK(printer_info); |
- |
- LOG(INFO) << "CP_CUPS: Getting Caps and Defaults for: " << printer_name; |
- |
- FilePath ppd_path(GetPPD(printer_name.c_str())); |
- // In some cases CUPS failed to get ppd file. |
- if (ppd_path.empty()) { |
- LOG(ERROR) << "CP_CUPS: Failed to get PPD for: " << printer_name; |
- return false; |
- } |
- |
- std::string content; |
- bool res = file_util::ReadFileToString(ppd_path, &content); |
- |
- file_util::Delete(ppd_path, false); |
- |
- if (res) { |
- printer_info->printer_capabilities.swap(content); |
- printer_info->caps_mime_type = "application/pagemaker"; |
- // In CUPS, printer defaults is a part of PPD file. Nothing to upload here. |
- printer_info->printer_defaults.clear(); |
- printer_info->defaults_mime_type.clear(); |
- } |
- |
- return res; |
+printing::PrintBackend* PrintSystemCUPS::GetPrintBackend() { |
+ return print_backend_; |
} |
bool PrintSystemCUPS::ValidatePrintTicket(const std::string& printer_name, |
@@ -425,7 +282,7 @@ |
} |
bool PrintSystemCUPS::GetPrinterInfo(const std::string& printer_name, |
- PrinterBasicInfo* info) { |
+ printing::PrinterBasicInfo* info) { |
DCHECK(info); |
LOG(INFO) << "CP_CUPS: Getting printer info for: " << printer_name; |
@@ -433,10 +290,10 @@ |
// This is not very efficient way to get specific printer info. CUPS 1.4 |
// supports cupsGetNamedDest() function. However, CUPS 1.4 is not available |
// everywhere (for example, it supported from Mac OS 10.6 only). |
- PrinterList printer_list; |
- EnumeratePrinters(&printer_list); |
+ printing::PrinterList printer_list; |
+ print_backend_->EnumeratePrinters(&printer_list); |
- PrinterList::iterator it; |
+ printing::PrinterList::iterator it; |
for (it = printer_list.begin(); it != printer_list.end(); ++it) { |
if (it->printer_name == printer_name) { |
*info = *it; |
@@ -446,11 +303,6 @@ |
return false; |
} |
-bool PrintSystemCUPS::IsValidPrinter(const std::string& printer_name) { |
- PrinterBasicInfo info; |
- return GetPrinterInfo(printer_name, &info); |
-} |
- |
PrintSystem::PrintServerWatcher* |
PrintSystemCUPS::CreatePrintServerWatcher() { |
return new PrintServerWatcherCUPS(); |
@@ -477,52 +329,22 @@ |
scoped_refptr<PrintSystem> PrintSystem::CreateInstance( |
const DictionaryValue* print_system_settings) { |
- // Initialize gcrypt library. |
- init_gcrypt(); |
- |
std::string print_server_url_str; |
if (print_system_settings) { |
- print_system_settings->GetString( |
- kCUPSPrintServerURL, &print_server_url_str); |
+ print_system_settings->GetString(kCUPSPrintServerURL, |
+ &print_server_url_str); |
} |
GURL print_server_url(print_server_url_str.c_str()); |
- return new PrintSystemCUPS(print_server_url); |
+ return new PrintSystemCUPS(print_server_url, print_system_settings); |
} |
-int PrintSystemCUPS::GetDests(cups_dest_t** dests) { |
- if (print_server_url_.is_empty()) { // Use default (local) print server. |
- return cupsGetDests(dests); |
- } else { |
- HttpConnectionCUPS http(print_server_url_); |
- return cupsGetDests2(http.http(), dests); |
- } |
-} |
- |
-FilePath PrintSystemCUPS::GetPPD(const char* name) { |
- // cupsGetPPD returns a filename stored in a static buffer in CUPS. |
- // Protect this code with lock. |
- static Lock ppd_lock; |
- AutoLock ppd_autolock(ppd_lock); |
- FilePath ppd_path; |
- const char* ppd_file_path = NULL; |
- if (print_server_url_.is_empty()) { // Use default (local) print server. |
- ppd_file_path = cupsGetPPD(name); |
- } else { |
- HttpConnectionCUPS http(print_server_url_); |
- ppd_file_path = cupsGetPPD2(http.http(), name); |
- } |
- if (ppd_file_path) |
- ppd_path = FilePath(ppd_file_path); |
- return ppd_path; |
-} |
- |
int PrintSystemCUPS::PrintFile(const char* name, const char* filename, |
const char* title, int num_options, |
cups_option_t* options) { |
if (print_server_url_.is_empty()) { // Use default (local) print server. |
return cupsPrintFile(name, filename, title, num_options, options); |
} else { |
- HttpConnectionCUPS http(print_server_url_); |
+ printing::HttpConnectionCUPS http(print_server_url_); |
return cupsPrintFile2(http.http(), name, filename, |
title, num_options, options); |
} |
@@ -533,7 +355,7 @@ |
if (print_server_url_.is_empty()) { // Use default (local) print server. |
return cupsGetJobs(jobs, name, myjobs, whichjobs); |
} else { |
- HttpConnectionCUPS http(print_server_url_); |
+ printing::HttpConnectionCUPS http(print_server_url_); |
return cupsGetJobs2(http.http(), jobs, name, myjobs, whichjobs); |
} |
} |