| Index: chrome/service/cloud_print/print_system_cups.cc
|
| ===================================================================
|
| --- chrome/service/cloud_print/print_system_cups.cc (revision 64663)
|
| +++ chrome/service/cloud_print/print_system_cups.cc (working copy)
|
| @@ -9,6 +9,7 @@
|
| #include <errno.h>
|
| #include <pthread.h>
|
|
|
| +#include <algorithm>
|
| #include <list>
|
| #include <map>
|
|
|
| @@ -16,6 +17,7 @@
|
| #include "base/json/json_reader.h"
|
| #include "base/lock.h"
|
| #include "base/logging.h"
|
| +#include "base/md5.h"
|
| #include "base/message_loop.h"
|
| #include "base/rand_util.h"
|
| #include "base/string_number_conversions.h"
|
| @@ -27,23 +29,52 @@
|
| #include "printing/backend/cups_helper.h"
|
| #include "printing/backend/print_backend.h"
|
|
|
| -namespace cloud_print {
|
| -
|
| +namespace {
|
| static const char kCUPSPrinterInfoOpt[] = "printer-info";
|
| static const char kCUPSPrinterStateOpt[] = "printer-state";
|
| -static const char kCUPSPrintServerURL[] = "print_server_url";
|
| +static const char kCUPSPrintServerURLs[] = "print_server_urls";
|
| +static const char kCUPSUpdateTimeoutMs[] = "update_timeout_ms";
|
| +static const char kCUPSPrintBackendServerURL[] = "print_server_url";
|
|
|
| // Default port for IPP print servers.
|
| static const int kDefaultIPPServerPort = 631;
|
|
|
| +// Time interval to check for printer's updates.
|
| +const int kCheckForPrinterUpdatesMs = 6*60*60*1000;
|
| +
|
| +// Job update timeput
|
| +const int kJobUpdateTimeoutMs = 5000;
|
| +
|
| +struct PrintServerInfoCUPS {
|
| + GURL url;
|
| + scoped_refptr<printing::PrintBackend> backend;
|
| + printing::PrinterList printers;
|
| + // CapsMap cache PPD until the next update and give a fast access to it by
|
| + // printer name. PPD request is relatively expensive and this should minimize
|
| + // the number of requests.
|
| + typedef std::map<std::string, printing::PrinterCapsAndDefaults> CapsMap;
|
| + CapsMap caps_cache;
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| +namespace cloud_print {
|
| +
|
| class PrintSystemCUPS : public PrintSystem {
|
| public:
|
| - PrintSystemCUPS(const GURL& print_server_url,
|
| - const DictionaryValue* print_system_settings);
|
| + explicit PrintSystemCUPS(const DictionaryValue* print_system_settings);
|
|
|
| // PrintSystem implementation.
|
| - virtual printing::PrintBackend* GetPrintBackend();
|
| + virtual void Init();
|
|
|
| + virtual void EnumeratePrinters(printing::PrinterList* printer_list);
|
| +
|
| + virtual bool GetPrinterCapsAndDefaults(
|
| + const std::string& printer_name,
|
| + printing::PrinterCapsAndDefaults* printer_info);
|
| +
|
| + virtual bool IsValidPrinter(const std::string& printer_name);
|
| +
|
| virtual bool ValidatePrintTicket(const std::string& printer_name,
|
| const std::string& print_ticket_data);
|
|
|
| @@ -51,111 +82,6 @@
|
| PlatformJobId job_id,
|
| PrintJobDetails *job_details);
|
|
|
| - // TODO(gene): Add implementation for CUPS print server watcher.
|
| - class PrintServerWatcherCUPS
|
| - : public PrintSystem::PrintServerWatcher {
|
| - public:
|
| - PrintServerWatcherCUPS() {}
|
| -
|
| - // PrintSystem::PrintServerWatcher interface
|
| - virtual bool StartWatching(
|
| - PrintSystem::PrintServerWatcher::Delegate* delegate) {
|
| - NOTIMPLEMENTED();
|
| - return true;
|
| - }
|
| - virtual bool StopWatching() {
|
| - NOTIMPLEMENTED();
|
| - return true;
|
| - }
|
| - };
|
| -
|
| - class PrinterWatcherCUPS
|
| - : public PrintSystem::PrinterWatcher {
|
| - public:
|
| - explicit PrinterWatcherCUPS(PrintSystemCUPS* print_system,
|
| - const std::string& printer_name)
|
| - : printer_name_(printer_name),
|
| - delegate_(NULL),
|
| - print_system_(print_system) {
|
| - }
|
| -
|
| - // PrintSystem::PrinterWatcher interface
|
| - virtual bool StartWatching(
|
| - PrintSystem::PrinterWatcher::Delegate* delegate) {
|
| - if (delegate_ != NULL)
|
| - StopWatching();
|
| - delegate_ = delegate;
|
| - MessageLoop::current()->PostDelayedTask(FROM_HERE,
|
| - NewRunnableMethod(this,
|
| - &PrintSystemCUPS::PrinterWatcherCUPS::Update), 5000);
|
| - return true;
|
| - }
|
| - virtual bool StopWatching() {
|
| - delegate_ = NULL;
|
| - return true;
|
| - }
|
| - bool GetCurrentPrinterInfo(printing::PrinterBasicInfo* printer_info) {
|
| - DCHECK(printer_info);
|
| - return print_system_->GetPrinterInfo(printer_name_, printer_info);
|
| - }
|
| -
|
| - void Update() {
|
| - if (delegate_ == NULL)
|
| - return; // Orphan call. We have been stopped already.
|
| - // For CUPS proxy, we are going to fire OnJobChanged notification
|
| - // periodically. Higher level will check if there are any outstanding
|
| - // jobs for this printer and check their status. If printer has no
|
| - // outstanding jobs, OnJobChanged() will do nothing.
|
| - delegate_->OnJobChanged();
|
| - MessageLoop::current()->PostDelayedTask(FROM_HERE,
|
| - NewRunnableMethod(this,
|
| - &PrintSystemCUPS::PrinterWatcherCUPS::Update),
|
| - kNotificationTimeout);
|
| - }
|
| - private:
|
| - static const int kNotificationTimeout = 5000; // in ms
|
| - std::string printer_name_;
|
| - PrintSystem::PrinterWatcher::Delegate* delegate_;
|
| - scoped_refptr<PrintSystemCUPS> print_system_;
|
| - DISALLOW_COPY_AND_ASSIGN(PrinterWatcherCUPS);
|
| - };
|
| -
|
| - class JobSpoolerCUPS : public PrintSystem::JobSpooler {
|
| - public:
|
| - explicit JobSpoolerCUPS(PrintSystemCUPS* print_system)
|
| - : print_system_(print_system) {
|
| - DCHECK(print_system_.get());
|
| - }
|
| - // PrintSystem::JobSpooler implementation.
|
| - virtual bool Spool(const std::string& print_ticket,
|
| - const FilePath& print_data_file_path,
|
| - const std::string& print_data_mime_type,
|
| - const std::string& printer_name,
|
| - const std::string& job_title,
|
| - JobSpooler::Delegate* delegate) {
|
| - DCHECK(delegate);
|
| - int job_id = print_system_->SpoolPrintJob(
|
| - print_ticket, print_data_file_path, print_data_mime_type,
|
| - printer_name, job_title);
|
| - MessageLoop::current()->PostTask(FROM_HERE,
|
| - NewRunnableFunction(
|
| - &JobSpoolerCUPS::NotifyDelegate,
|
| - delegate,
|
| - job_id));
|
| - return true;
|
| - }
|
| -
|
| - static void NotifyDelegate(JobSpooler::Delegate* delegate, int job_id) {
|
| - if (job_id)
|
| - delegate->OnJobSpoolSucceeded(job_id);
|
| - else
|
| - delegate->OnJobSpoolFailed();
|
| - }
|
| - private:
|
| - scoped_refptr<PrintSystemCUPS> print_system_;
|
| - DISALLOW_COPY_AND_ASSIGN(JobSpoolerCUPS);
|
| - };
|
| -
|
| virtual PrintSystem::PrintServerWatcher* CreatePrintServerWatcher();
|
| virtual PrintSystem::PrinterWatcher* CreatePrinterWatcher(
|
| const std::string& printer_name);
|
| @@ -172,39 +98,352 @@
|
| bool ParsePrintTicket(const std::string& print_ticket,
|
| std::map<std::string, std::string>* options);
|
|
|
| + int GetUpdateTimeoutMs() const {
|
| + return update_timeout_;
|
| + }
|
| +
|
| private:
|
| // Following functions are wrappers around corresponding CUPS functions.
|
| // <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 GetJobs(cups_job_t** jobs, const char* name,
|
| + int GetJobs(cups_job_t** jobs, const GURL& url, 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);
|
| + int PrintFile(const GURL& url, const char* name, const char* filename,
|
| + const char* title, int num_options, cups_option_t* options);
|
|
|
| - void Init(const DictionaryValue* print_system_settings);
|
| + void InitPrintBackends(const DictionaryValue* print_system_settings);
|
| + void AddPrintServer(const std::string& url);
|
|
|
| - GURL print_server_url_;
|
| - scoped_refptr<printing::PrintBackend> print_backend_;
|
| + void UpdatePrinters();
|
| +
|
| + // PrintServerList contains information about all print servers and backends
|
| + // this proxy is connected to.
|
| + typedef std::list<PrintServerInfoCUPS> PrintServerList;
|
| + // PrintersMap provides fast check for printer existence and access to
|
| + // printer information by printer name. (optimization).
|
| + typedef std::map<std::string, PrintServerInfoCUPS*> PrintersMap;
|
| + PrintServerList print_servers_;
|
| + PrintersMap printer_map_;
|
| +
|
| + int update_timeout_;
|
| + bool initialized_;
|
| };
|
|
|
| -PrintSystemCUPS::PrintSystemCUPS(const GURL& print_server_url,
|
| - const DictionaryValue* print_system_settings)
|
| - : print_server_url_(print_server_url) {
|
| - Init(print_system_settings);
|
| +class PrintServerWatcherCUPS
|
| + : public PrintSystem::PrintServerWatcher {
|
| + public:
|
| + explicit PrintServerWatcherCUPS(PrintSystemCUPS* print_system)
|
| + : print_system_(print_system) {
|
| + }
|
| + ~PrintServerWatcherCUPS() {
|
| + StopWatching();
|
| + }
|
| +
|
| + // PrintSystem::PrintServerWatcher interface
|
| + virtual bool StartWatching(
|
| + PrintSystem::PrintServerWatcher::Delegate* delegate) {
|
| + delegate_ = delegate;
|
| + printers_hash_ = GetPrintersHash();
|
| + MessageLoop::current()->PostDelayedTask(FROM_HERE,
|
| + NewRunnableMethod(this, &PrintServerWatcherCUPS::CheckForUpdates),
|
| + print_system_->GetUpdateTimeoutMs());
|
| + return true;
|
| + }
|
| + virtual bool StopWatching() {
|
| + delegate_ = NULL;
|
| + return true;
|
| + }
|
| +
|
| + void CheckForUpdates() {
|
| + if (delegate_ == NULL)
|
| + return; // Orphan call. We have been stopped already.
|
| + VLOG(1) << "CP_CUPS: Checking for new printers";
|
| + std::string new_hash = GetPrintersHash();
|
| + if (printers_hash_ != new_hash) {
|
| + printers_hash_ = new_hash;
|
| + delegate_->OnPrinterAdded();
|
| + }
|
| + MessageLoop::current()->PostDelayedTask(FROM_HERE,
|
| + NewRunnableMethod(this, &PrintServerWatcherCUPS::CheckForUpdates),
|
| + print_system_->GetUpdateTimeoutMs());
|
| + }
|
| + private:
|
| + std::string GetPrintersHash() {
|
| + printing::PrinterList printer_list;
|
| + print_system_->EnumeratePrinters(&printer_list);
|
| +
|
| + // Sort printer names.
|
| + std::vector<std::string> printers;
|
| + printing::PrinterList::iterator it;
|
| + for (it = printer_list.begin(); it != printer_list.end(); ++it)
|
| + printers.push_back(it->printer_name);
|
| + std::sort(printers.begin(), printers.end());
|
| +
|
| + std::string to_hash;
|
| + for (size_t i = 0; i < printers.size(); i++)
|
| + to_hash += printers[i];
|
| +
|
| + return MD5String(to_hash);
|
| + }
|
| +
|
| + scoped_refptr<PrintSystemCUPS> print_system_;
|
| + PrintSystem::PrintServerWatcher::Delegate* delegate_;
|
| + std::string printers_hash_;
|
| + DISALLOW_COPY_AND_ASSIGN(PrintServerWatcherCUPS);
|
| +};
|
| +
|
| +class PrinterWatcherCUPS
|
| + : public PrintSystem::PrinterWatcher {
|
| + public:
|
| + explicit PrinterWatcherCUPS(PrintSystemCUPS* print_system,
|
| + const std::string& printer_name)
|
| + : printer_name_(printer_name),
|
| + delegate_(NULL),
|
| + print_system_(print_system) {
|
| + }
|
| + ~PrinterWatcherCUPS() {
|
| + StopWatching();
|
| + }
|
| +
|
| + // PrintSystem::PrinterWatcher interface
|
| + virtual bool StartWatching(
|
| + PrintSystem::PrinterWatcher::Delegate* delegate) {
|
| + if (delegate_ != NULL)
|
| + StopWatching();
|
| + delegate_ = delegate;
|
| + settings_hash_ = GetSettingsHash();
|
| + // Schedule next job status update.
|
| + MessageLoop::current()->PostDelayedTask(FROM_HERE,
|
| + NewRunnableMethod(this, &PrinterWatcherCUPS::JobStatusUpdate),
|
| + kJobUpdateTimeoutMs);
|
| + // Schedule next printer check.
|
| + // TODO(gene): Randomize time for the next printer update.
|
| + MessageLoop::current()->PostDelayedTask(FROM_HERE,
|
| + NewRunnableMethod(this, &PrinterWatcherCUPS::PrinterUpdate),
|
| + print_system_->GetUpdateTimeoutMs());
|
| + return true;
|
| + }
|
| + virtual bool StopWatching() {
|
| + delegate_ = NULL;
|
| + return true;
|
| + }
|
| + bool GetCurrentPrinterInfo(printing::PrinterBasicInfo* printer_info) {
|
| + DCHECK(printer_info);
|
| + return print_system_->GetPrinterInfo(printer_name_, printer_info);
|
| + }
|
| +
|
| + void JobStatusUpdate() {
|
| + if (delegate_ == NULL)
|
| + return; // Orphan call. We have been stopped already.
|
| + // For CUPS proxy, we are going to fire OnJobChanged notification
|
| + // periodically. Higher level will check if there are any outstanding
|
| + // jobs for this printer and check their status. If printer has no
|
| + // outstanding jobs, OnJobChanged() will do nothing.
|
| + delegate_->OnJobChanged();
|
| + MessageLoop::current()->PostDelayedTask(FROM_HERE,
|
| + NewRunnableMethod(this, &PrinterWatcherCUPS::JobStatusUpdate),
|
| + kJobUpdateTimeoutMs);
|
| + }
|
| +
|
| + void PrinterUpdate() {
|
| + if (delegate_ == NULL)
|
| + return; // Orphan call. We have been stopped already.
|
| + VLOG(1) << "CP_CUPS: Checking for printer updates: " << printer_name_;
|
| + std::string new_hash = GetSettingsHash();
|
| + if (settings_hash_ != new_hash) {
|
| + settings_hash_ = new_hash;
|
| + delegate_->OnPrinterChanged();
|
| + VLOG(1) << "CP_CUPS: Printer update detected for: " << printer_name_;
|
| + }
|
| + MessageLoop::current()->PostDelayedTask(FROM_HERE,
|
| + NewRunnableMethod(this, &PrinterWatcherCUPS::PrinterUpdate),
|
| + print_system_->GetUpdateTimeoutMs());
|
| + }
|
| + private:
|
| + std::string GetSettingsHash() {
|
| + printing::PrinterBasicInfo info;
|
| + if (!print_system_->GetPrinterInfo(printer_name_, &info))
|
| + return std::string();
|
| +
|
| + printing::PrinterCapsAndDefaults caps;
|
| + if (!print_system_->GetPrinterCapsAndDefaults(printer_name_, &caps))
|
| + return std::string();
|
| +
|
| + std::string to_hash(info.printer_name);
|
| + to_hash += info.printer_description;
|
| + std::map<std::string, std::string>::const_iterator it;
|
| + for (it = info.options.begin(); it != info.options.end(); ++it) {
|
| + to_hash += it->first;
|
| + to_hash += it->second;
|
| + }
|
| +
|
| + to_hash += caps.printer_capabilities;
|
| + to_hash += caps.caps_mime_type;
|
| + to_hash += caps.printer_defaults;
|
| + to_hash += caps.defaults_mime_type;
|
| +
|
| + return MD5String(to_hash);
|
| + }
|
| +
|
| + std::string printer_name_;
|
| + PrintSystem::PrinterWatcher::Delegate* delegate_;
|
| + scoped_refptr<PrintSystemCUPS> print_system_;
|
| + std::string settings_hash_;
|
| + DISALLOW_COPY_AND_ASSIGN(PrinterWatcherCUPS);
|
| +};
|
| +
|
| +class JobSpoolerCUPS : public PrintSystem::JobSpooler {
|
| + public:
|
| + explicit JobSpoolerCUPS(PrintSystemCUPS* print_system)
|
| + : print_system_(print_system) {
|
| + DCHECK(print_system_.get());
|
| + }
|
| + // PrintSystem::JobSpooler implementation.
|
| + virtual bool Spool(const std::string& print_ticket,
|
| + const FilePath& print_data_file_path,
|
| + const std::string& print_data_mime_type,
|
| + const std::string& printer_name,
|
| + const std::string& job_title,
|
| + JobSpooler::Delegate* delegate) {
|
| + DCHECK(delegate);
|
| + int job_id = print_system_->SpoolPrintJob(
|
| + print_ticket, print_data_file_path, print_data_mime_type,
|
| + printer_name, job_title);
|
| + MessageLoop::current()->PostTask(FROM_HERE,
|
| + NewRunnableFunction(
|
| + &JobSpoolerCUPS::NotifyDelegate,
|
| + delegate,
|
| + job_id));
|
| + return true;
|
| + }
|
| +
|
| + static void NotifyDelegate(JobSpooler::Delegate* delegate, int job_id) {
|
| + if (job_id)
|
| + delegate->OnJobSpoolSucceeded(job_id);
|
| + else
|
| + delegate->OnJobSpoolFailed();
|
| + }
|
| + private:
|
| + scoped_refptr<PrintSystemCUPS> print_system_;
|
| + DISALLOW_COPY_AND_ASSIGN(JobSpoolerCUPS);
|
| +};
|
| +
|
| +PrintSystemCUPS::PrintSystemCUPS(const DictionaryValue* print_system_settings)
|
| + : update_timeout_(kCheckForPrinterUpdatesMs), initialized_(false) {
|
| + if (print_system_settings) {
|
| + int timeout;
|
| + if (print_system_settings->GetInteger(kCUPSUpdateTimeoutMs, &timeout))
|
| + update_timeout_ = timeout;
|
| + }
|
| +
|
| + InitPrintBackends(print_system_settings);
|
| }
|
|
|
| -void PrintSystemCUPS::Init(const DictionaryValue* print_system_settings) {
|
| - print_backend_ =
|
| - printing::PrintBackend::CreateInstance(print_system_settings);
|
| +void PrintSystemCUPS::InitPrintBackends(
|
| + const DictionaryValue* print_system_settings) {
|
| + ListValue* url_list;
|
| + if (print_system_settings &&
|
| + print_system_settings->GetList(kCUPSPrintServerURLs, &url_list)) {
|
| + for (size_t i = 0; i < url_list->GetSize(); i++) {
|
| + std::string print_server_url;
|
| + if (url_list->GetString(i, &print_server_url))
|
| + AddPrintServer(print_server_url);
|
| + }
|
| + }
|
| +
|
| + // If server list is empty, use default print server.
|
| + if (print_servers_.empty())
|
| + AddPrintServer(std::string());
|
| }
|
|
|
| -printing::PrintBackend* PrintSystemCUPS::GetPrintBackend() {
|
| - return print_backend_;
|
| +void PrintSystemCUPS::AddPrintServer(const std::string& url) {
|
| + if (url.empty())
|
| + LOG(WARNING) << "No print server specified. Using default print server.";
|
| +
|
| + // Get Print backend for the specific print server.
|
| + DictionaryValue backend_settings;
|
| + backend_settings.SetString(kCUPSPrintBackendServerURL, url);
|
| +
|
| + PrintServerInfoCUPS print_server;
|
| + print_server.backend =
|
| + printing::PrintBackend::CreateInstance(&backend_settings);
|
| + print_server.url = GURL(url.c_str());
|
| +
|
| + print_servers_.push_back(print_server);
|
| }
|
|
|
| +void PrintSystemCUPS::Init() {
|
| + UpdatePrinters();
|
| + initialized_ = true;
|
| +}
|
| +
|
| +void PrintSystemCUPS::UpdatePrinters() {
|
| + printer_map_.clear();
|
| + PrintServerList::iterator it;
|
| + for (it = print_servers_.begin(); it != print_servers_.end(); ++it) {
|
| + it->backend->EnumeratePrinters(&it->printers);
|
| + it->caps_cache.clear();
|
| + printing::PrinterList::const_iterator printer_it;
|
| + for (printer_it = it->printers.begin();
|
| + printer_it != it->printers.end(); ++printer_it) {
|
| + printer_map_[printer_it->printer_name] = &(*it);
|
| + }
|
| + VLOG(1) << "CUPS: Updated printer list for url: " << it->url
|
| + << " Number of printers: " << it->printers.size();
|
| + }
|
| +
|
| + // Schedule next update.
|
| + MessageLoop::current()->PostDelayedTask(FROM_HERE,
|
| + NewRunnableMethod(this, &PrintSystemCUPS::UpdatePrinters),
|
| + GetUpdateTimeoutMs());
|
| +}
|
| +
|
| +void PrintSystemCUPS::EnumeratePrinters(printing::PrinterList* printer_list) {
|
| + DCHECK(initialized_);
|
| + printer_list->clear();
|
| + PrintServerList::iterator it;
|
| + for (it = print_servers_.begin(); it != print_servers_.end(); ++it) {
|
| + printer_list->insert(printer_list->end(),
|
| + it->printers.begin(), it->printers.end());
|
| + }
|
| + VLOG(1) << "CUPS: Total " << printer_list->size() << " printers enumerated.";
|
| +}
|
| +
|
| +bool PrintSystemCUPS::GetPrinterCapsAndDefaults(
|
| + const std::string& printer_name,
|
| + printing::PrinterCapsAndDefaults* printer_info) {
|
| + DCHECK(initialized_);
|
| + PrintersMap::iterator it = printer_map_.find(printer_name);
|
| + if (it == printer_map_.end())
|
| + return false;
|
| +
|
| + PrintServerInfoCUPS::CapsMap::iterator caps_it =
|
| + it->second->caps_cache.find(printer_name);
|
| + if (caps_it != it->second->caps_cache.end()) {
|
| + *printer_info = caps_it->second;
|
| + return true;
|
| + }
|
| +
|
| + // TODO(gene): Retry multiple times in case of error.
|
| + if (!it->second->backend->GetPrinterCapsAndDefaults(printer_name,
|
| + printer_info) ) {
|
| + return false;
|
| + }
|
| +
|
| + it->second->caps_cache[printer_name] = *printer_info;
|
| + return true;
|
| +}
|
| +
|
| +bool PrintSystemCUPS::IsValidPrinter(const std::string& printer_name) {
|
| + DCHECK(initialized_);
|
| + PrintersMap::iterator it = printer_map_.find(printer_name);
|
| + return it != printer_map_.end();
|
| +}
|
| +
|
| bool PrintSystemCUPS::ValidatePrintTicket(const std::string& printer_name,
|
| const std::string& print_ticket_data) {
|
| + DCHECK(initialized_);
|
| scoped_ptr<Value> ticket_value(base::JSONReader::Read(print_ticket_data,
|
| false));
|
| return ticket_value != NULL && ticket_value->IsType(Value::TYPE_DICTIONARY);
|
| @@ -213,6 +452,7 @@
|
| // Print ticket on linux is a JSON string containing only one dictionary.
|
| bool PrintSystemCUPS::ParsePrintTicket(const std::string& print_ticket,
|
| std::map<std::string, std::string>* options) {
|
| + DCHECK(initialized_);
|
| DCHECK(options);
|
| scoped_ptr<Value> ticket_value(base::JSONReader::Read(print_ticket, false));
|
| if (ticket_value == NULL || !ticket_value->IsType(Value::TYPE_DICTIONARY))
|
| @@ -236,10 +476,15 @@
|
| bool PrintSystemCUPS::GetJobDetails(const std::string& printer_name,
|
| PlatformJobId job_id,
|
| PrintJobDetails *job_details) {
|
| + DCHECK(initialized_);
|
| DCHECK(job_details);
|
|
|
| + PrintersMap::iterator it = printer_map_.find(printer_name);
|
| + if (it == printer_map_.end())
|
| + return false;
|
| +
|
| cups_job_t* jobs = NULL;
|
| - int num_jobs = GetJobs(&jobs, printer_name.c_str(), 1, -1);
|
| + int num_jobs = GetJobs(&jobs, it->second->url, printer_name.c_str(), 1, -1);
|
|
|
| bool found = false;
|
| for (int i = 0; i < num_jobs; i++) {
|
| @@ -282,20 +527,19 @@
|
|
|
| bool PrintSystemCUPS::GetPrinterInfo(const std::string& printer_name,
|
| printing::PrinterBasicInfo* info) {
|
| + DCHECK(initialized_);
|
| DCHECK(info);
|
| -
|
| VLOG(1) << "CP_CUPS: Getting printer info for: " << printer_name;
|
|
|
| - // 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).
|
| - printing::PrinterList printer_list;
|
| - print_backend_->EnumeratePrinters(&printer_list);
|
| + PrintersMap::iterator it = printer_map_.find(printer_name);
|
| + if (it == printer_map_.end())
|
| + return false;
|
|
|
| - printing::PrinterList::iterator it;
|
| - for (it = printer_list.begin(); it != printer_list.end(); ++it) {
|
| - if (it->printer_name == printer_name) {
|
| - *info = *it;
|
| + printing::PrinterList::iterator printer_it;
|
| + for (printer_it = it->second->printers.begin();
|
| + printer_it != it->second->printers.end(); ++printer_it) {
|
| + if (printer_it->printer_name == printer_name) {
|
| + *info = *printer_it;
|
| return true;
|
| }
|
| }
|
| @@ -304,16 +548,19 @@
|
|
|
| PrintSystem::PrintServerWatcher*
|
| PrintSystemCUPS::CreatePrintServerWatcher() {
|
| - return new PrintServerWatcherCUPS();
|
| + DCHECK(initialized_);
|
| + return new PrintServerWatcherCUPS(this);
|
| }
|
|
|
| PrintSystem::PrinterWatcher* PrintSystemCUPS::CreatePrinterWatcher(
|
| const std::string& printer_name) {
|
| + DCHECK(initialized_);
|
| DCHECK(!printer_name.empty());
|
| return new PrinterWatcherCUPS(this, printer_name);
|
| }
|
|
|
| PrintSystem::JobSpooler* PrintSystemCUPS::CreateJobSpooler() {
|
| + DCHECK(initialized_);
|
| return new JobSpoolerCUPS(this);
|
| }
|
|
|
| @@ -328,33 +575,29 @@
|
|
|
| scoped_refptr<PrintSystem> PrintSystem::CreateInstance(
|
| const DictionaryValue* print_system_settings) {
|
| - std::string print_server_url_str;
|
| - if (print_system_settings) {
|
| - 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, print_system_settings);
|
| + return new PrintSystemCUPS(print_system_settings);
|
| }
|
|
|
| -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.
|
| +int PrintSystemCUPS::PrintFile(const GURL& url, const char* name,
|
| + const char* filename, const char* title,
|
| + int num_options, cups_option_t* options) {
|
| + DCHECK(initialized_);
|
| + if (url.is_empty()) { // Use default (local) print server.
|
| return cupsPrintFile(name, filename, title, num_options, options);
|
| } else {
|
| - printing::HttpConnectionCUPS http(print_server_url_);
|
| + printing::HttpConnectionCUPS http(url);
|
| return cupsPrintFile2(http.http(), name, filename,
|
| title, num_options, options);
|
| }
|
| }
|
|
|
| -int PrintSystemCUPS::GetJobs(cups_job_t** jobs, const char* name,
|
| - int myjobs, int whichjobs) {
|
| - if (print_server_url_.is_empty()) { // Use default (local) print server.
|
| +int PrintSystemCUPS::GetJobs(cups_job_t** jobs, const GURL& url,
|
| + const char* name, int myjobs, int whichjobs) {
|
| + DCHECK(initialized_);
|
| + if (url.is_empty()) { // Use default (local) print server.
|
| return cupsGetJobs(jobs, name, myjobs, whichjobs);
|
| } else {
|
| - printing::HttpConnectionCUPS http(print_server_url_);
|
| + printing::HttpConnectionCUPS http(url);
|
| return cupsGetJobs2(http.http(), jobs, name, myjobs, whichjobs);
|
| }
|
| }
|
| @@ -365,8 +608,13 @@
|
| const std::string& print_data_mime_type,
|
| const std::string& printer_name,
|
| const std::string& job_title) {
|
| + DCHECK(initialized_);
|
| VLOG(1) << "CP_CUPS: Spooling print job for: " << printer_name;
|
|
|
| + PrintersMap::iterator print_server = printer_map_.find(printer_name);
|
| + if (print_server == printer_map_.end())
|
| + return 0;
|
| +
|
| // We need to store options as char* string for the duration of the
|
| // cupsPrintFile2 call. We'll use map here to store options, since
|
| // Dictionary value from JSON parser returns wchat_t.
|
| @@ -383,7 +631,8 @@
|
| cups_options.push_back(opt);
|
| }
|
|
|
| - int job_id = PrintFile(printer_name.c_str(),
|
| + int job_id = PrintFile(print_server->second->url,
|
| + printer_name.c_str(),
|
| print_data_file_path.value().c_str(),
|
| job_title.c_str(),
|
| cups_options.size(),
|
|
|