summaryrefslogtreecommitdiffstats
path: root/chrome/service
diff options
context:
space:
mode:
authorgene@google.com <gene@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-03 21:53:40 +0000
committergene@google.com <gene@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-03 21:53:40 +0000
commit3296839602c5c54cae0b0fb0a9d6623a5ba65895 (patch)
treed040575a060360dc0be71908f747a00cd8020b82 /chrome/service
parent192c08625449016b0a9f5ab9bb40e298c0bbd00f (diff)
downloadchromium_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.cc6
-rw-r--r--chrome/service/cloud_print/print_system.h19
-rw-r--r--chrome/service/cloud_print/print_system_cups.cc556
-rw-r--r--chrome/service/cloud_print/print_system_win.cc29
-rw-r--r--chrome/service/cloud_print/printer_job_handler.cc4
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) {