diff options
author | gene@google.com <gene@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-03 21:53:40 +0000 |
---|---|---|
committer | gene@google.com <gene@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-03 21:53:40 +0000 |
commit | 3296839602c5c54cae0b0fb0a9d6623a5ba65895 (patch) | |
tree | d040575a060360dc0be71908f747a00cd8020b82 /chrome/service | |
parent | 192c08625449016b0a9f5ab9bb40e298c0bbd00f (diff) | |
download | chromium_src-3296839602c5c54cae0b0fb0a9d6623a5ba65895.zip chromium_src-3296839602c5c54cae0b0fb0a9d6623a5ba65895.tar.gz chromium_src-3296839602c5c54cae0b0fb0a9d6623a5ba65895.tar.bz2 |
Make CUPS cloud print proxy to support multiple print servers.
Add notifications for printer settings changed, and periodic update to check for new printers.
BUG=none
TEST=Make sure CP proxy works on Linux.
Review URL: http://codereview.chromium.org/4233004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@64970 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/service')
-rw-r--r-- | chrome/service/cloud_print/cloud_print_proxy_backend.cc | 6 | ||||
-rw-r--r-- | chrome/service/cloud_print/print_system.h | 19 | ||||
-rw-r--r-- | chrome/service/cloud_print/print_system_cups.cc | 556 | ||||
-rw-r--r-- | chrome/service/cloud_print/print_system_win.cc | 29 | ||||
-rw-r--r-- | chrome/service/cloud_print/printer_job_handler.cc | 4 |
5 files changed, 446 insertions, 168 deletions
diff --git a/chrome/service/cloud_print/cloud_print_proxy_backend.cc b/chrome/service/cloud_print/cloud_print_proxy_backend.cc index 3307ccc..7d1d404 100644 --- a/chrome/service/cloud_print/cloud_print_proxy_backend.cc +++ b/chrome/service/cloud_print/cloud_print_proxy_backend.cc @@ -327,6 +327,8 @@ void CloudPrintProxyBackend::Core::DoInitializeWithToken( return; // No print system available, fail initalization. } + print_system_->Init(); + // TODO(sanjeevr): Validate the tokens. auth_token_ = cloud_print_token; @@ -385,7 +387,7 @@ CloudPrintProxyBackend::Core::CreateDefaultRetryPolicy() { void CloudPrintProxyBackend::Core::StartRegistration() { DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop()); printer_list_.clear(); - print_system_->GetPrintBackend()->EnumeratePrinters(&printer_list_); + print_system_->EnumeratePrinters(&printer_list_); // Now we need to ask the server about printers that were registered on the // server so that we can trim this list. GetRegisteredPrinters(); @@ -454,7 +456,7 @@ void CloudPrintProxyBackend::Core::RegisterNextPrinter() { // and defaults again. if (info.printer_name != last_uploaded_printer_name_) { have_printer_info = - print_system_->GetPrintBackend()->GetPrinterCapsAndDefaults( + print_system_->GetPrinterCapsAndDefaults( info.printer_name.c_str(), &last_uploaded_printer_info_); } if (have_printer_info) { diff --git a/chrome/service/cloud_print/print_system.h b/chrome/service/cloud_print/print_system.h index c6949bd..5a98f2c 100644 --- a/chrome/service/cloud_print/print_system.h +++ b/chrome/service/cloud_print/print_system.h @@ -12,12 +12,15 @@ #include "base/ref_counted.h" +#include "printing/backend/print_backend.h" + class DictionaryValue; class FilePath; namespace printing { class PrintBackend; struct PrinterBasicInfo; +struct PrinterCapsAndDefaults; } // This is the interface for platform-specific code for cloud print @@ -128,8 +131,20 @@ class PrintSystem : public base::RefCountedThreadSafe<PrintSystem> { virtual ~PrintSystem(); - // Get the printing backend. - virtual printing::PrintBackend* GetPrintBackend() = 0; + // Initialize print system. This need to be called before any other function + // of PrintSystem. + virtual void Init() = 0; + + // Enumerates the list of installed local and network printers. + virtual void EnumeratePrinters(printing::PrinterList* printer_list) = 0; + + // Gets the capabilities and defaults for a specific printer. + virtual bool GetPrinterCapsAndDefaults( + const std::string& printer_name, + printing::PrinterCapsAndDefaults* printer_info) = 0; + + // Returns true if printer_name points to a valid printer. + virtual bool IsValidPrinter(const std::string& printer_name) = 0; // Returns true if ticket is valid. virtual bool ValidatePrintTicket(const std::string& printer_name, diff --git a/chrome/service/cloud_print/print_system_cups.cc b/chrome/service/cloud_print/print_system_cups.cc index 45d1803..50d79dc 100644 --- a/chrome/service/cloud_print/print_system_cups.cc +++ b/chrome/service/cloud_print/print_system_cups.cc @@ -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,22 +29,51 @@ #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 @@ class PrintSystemCUPS : public PrintSystem { 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 @@ class PrintSystemCUPS : public PrintSystem { 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 InitPrintBackends(const DictionaryValue* print_system_settings); + void AddPrintServer(const std::string& url); + + 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_; +}; + +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 Init(const DictionaryValue* print_system_settings); + 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; + } - GURL print_server_url_; - scoped_refptr<printing::PrintBackend> print_backend_; + 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); }; -PrintSystemCUPS::PrintSystemCUPS(const GURL& print_server_url, - const DictionaryValue* print_system_settings) - : print_server_url_(print_server_url) { - Init(print_system_settings); +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::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()); } -void PrintSystemCUPS::Init(const DictionaryValue* print_system_settings) { - print_backend_ = - printing::PrintBackend::CreateInstance(print_system_settings); +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); } -printing::PrintBackend* PrintSystemCUPS::GetPrintBackend() { - return print_backend_; +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); @@ -236,10 +475,15 @@ bool PrintSystemCUPS::ParsePrintTicket(const std::string& print_ticket, 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 +526,19 @@ bool PrintSystemCUPS::GetJobDetails(const std::string& printer_name, 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 +547,19 @@ bool PrintSystemCUPS::GetPrinterInfo(const std::string& printer_name, 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 +574,27 @@ std::string PrintSystem::GenerateProxyId() { 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) { + 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) { + 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 +605,13 @@ PlatformJobId PrintSystemCUPS::SpoolPrintJob( 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 +628,8 @@ PlatformJobId PrintSystemCUPS::SpoolPrintJob( 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(), diff --git a/chrome/service/cloud_print/print_system_win.cc b/chrome/service/cloud_print/print_system_win.cc index 77272d6..ea5ede2 100644 --- a/chrome/service/cloud_print/print_system_win.cc +++ b/chrome/service/cloud_print/print_system_win.cc @@ -239,7 +239,15 @@ class PrintSystemWin : public PrintSystem { PrintSystemWin(); // 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); @@ -508,21 +516,28 @@ class PrintSystemWin : public PrintSystem { virtual PrintSystem::JobSpooler* CreateJobSpooler(); private: - void Init(); - scoped_refptr<printing::PrintBackend> print_backend_; }; PrintSystemWin::PrintSystemWin() { - Init(); + print_backend_ = printing::PrintBackend::CreateInstance(NULL); } void PrintSystemWin::Init() { - print_backend_ = printing::PrintBackend::CreateInstance(NULL); } -printing::PrintBackend* PrintSystemWin::GetPrintBackend() { - return print_backend_; +void PrintSystemWin::EnumeratePrinters(printing::PrinterList* printer_list) { + print_backend_->EnumeratePrinters(printer_list); +} + +bool PrintSystemWin::GetPrinterCapsAndDefaults( + const std::string& printer_name, + printing::PrinterCapsAndDefaults* printer_info) { + return print_backend_->GetPrinterCapsAndDefaults(printer_name, printer_info); +} + +bool PrintSystemWin::IsValidPrinter(const std::string& printer_name) { + return print_backend_->IsValidPrinter(printer_name); } bool PrintSystemWin::ValidatePrintTicket( diff --git a/chrome/service/cloud_print/printer_job_handler.cc b/chrome/service/cloud_print/printer_job_handler.cc index a1c7768..e25faa4 100644 --- a/chrome/service/cloud_print/printer_job_handler.cc +++ b/chrome/service/cloud_print/printer_job_handler.cc @@ -45,7 +45,7 @@ PrinterJobHandler::PrinterJobHandler( } bool PrinterJobHandler::Initialize() { - if (print_system_->GetPrintBackend()->IsValidPrinter( + if (print_system_->IsValidPrinter( printer_info_.printer_name)) { printer_watcher_ = print_system_->CreatePrinterWatcher( printer_info_.printer_name); @@ -145,7 +145,7 @@ bool PrinterJobHandler::UpdatePrinterInfo() { std::string post_data; std::string mime_boundary; CloudPrintHelpers::CreateMimeBoundaryForUpload(&mime_boundary); - if (print_system_->GetPrintBackend()->GetPrinterCapsAndDefaults( + if (print_system_->GetPrinterCapsAndDefaults( printer_info.printer_name, &printer_caps)) { std::string caps_hash = MD5String(printer_caps.printer_capabilities); if (caps_hash != printer_info_cloud_.caps_hash) { |