| 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);
|
| }
|
| }
|
|
|