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(), |