Index: chrome/service/cloud_print/print_system_cups.cc |
=================================================================== |
--- chrome/service/cloud_print/print_system_cups.cc (revision 48641) |
+++ chrome/service/cloud_print/print_system_cups.cc (working copy) |
@@ -2,7 +2,7 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
-#include "chrome/service/cloud_print/printer_info.h" |
+#include "chrome/service/cloud_print/print_system.h" |
#include <cups/cups.h> |
#include <list> |
@@ -25,7 +25,107 @@ |
static const char kCUPSPrinterInfoOpt[] = "printer-info"; |
static const char kCUPSPrinterStateOpt[] = "printer-state"; |
-void EnumeratePrinters(PrinterList* printer_list) { |
+class PrintSystemCUPS : public PrintSystem { |
+ public: |
+ virtual void EnumeratePrinters(PrinterList* printer_list); |
+ |
+ virtual bool GetPrinterCapsAndDefaults(const std::string& printer_name, |
+ PrinterCapsAndDefaults* printer_info); |
+ |
+ virtual bool ValidatePrintTicket(const std::string& printer_name, |
+ const std::string& print_ticket_data); |
+ |
+ virtual bool SpoolPrintJob(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, |
+ PlatformJobId* job_id_ret); |
+ |
+ virtual bool GetJobDetails(const std::string& printer_name, |
+ PlatformJobId job_id, |
+ PrintJobDetails *job_details); |
+ |
+ virtual bool IsValidPrinter(const std::string& printer_name); |
+ |
+ // TODO(gene): Add implementation for CUPS print server watcher. |
+ class PrintServerWatcherCUPS |
+ : public PrintSystem::PrintServerWatcher { |
+ 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), 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(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); |
+ }; |
+ |
+ virtual PrintSystem::PrintServerWatcher* CreatePrintServerWatcher(); |
+ virtual PrintSystem::PrinterWatcher* CreatePrinterWatcher( |
+ const std::string& printer_name); |
+ |
+ // Helper functions. |
+ bool GetPrinterInfo(const std::string& printer_name, PrinterBasicInfo* info); |
+ bool ParsePrintTicket(const std::string& print_ticket, |
+ std::map<std::string, std::string>* options); |
+}; |
+ |
+void PrintSystemCUPS::EnumeratePrinters(PrinterList* printer_list) { |
DCHECK(printer_list); |
printer_list->clear(); |
@@ -59,22 +159,31 @@ |
cupsFreeDests(num_dests, destinations); |
- DLOG(INFO) << "Enumerated " << printer_list->size() << " printers."; |
+ DLOG(INFO) << "CP_CUPS: Enumerated " << printer_list->size() << " printers."; |
} |
-bool GetPrinterCapsAndDefaults(const std::string& printer_name, |
- PrinterCapsAndDefaults* printer_info) { |
+bool PrintSystemCUPS::GetPrinterCapsAndDefaults(const std::string& printer_name, |
+ PrinterCapsAndDefaults* printer_info) { |
DCHECK(printer_info); |
- DLOG(INFO) << "Getting Caps and Defaults for: " << printer_name; |
+ DLOG(INFO) << "CP_CUPS: Getting Caps and Defaults for: " << printer_name; |
static Lock ppd_lock; |
// cupsGetPPD returns a filename stored in a static buffer in CUPS. |
// Protect this code with lock. |
ppd_lock.Acquire(); |
- FilePath ppd_path(cupsGetPPD(printer_name.c_str())); |
+ FilePath ppd_path; |
+ const char* ppd_file_path = cupsGetPPD(printer_name.c_str()); |
+ if (ppd_file_path) |
+ ppd_path = FilePath(ppd_file_path); |
ppd_lock.Release(); |
+ // In some cases CUPS failed to get ppd file. |
+ if (ppd_path.empty()) { |
+ DLOG(ERROR) << "CP_CUPS: Failed to get PPD for: " << printer_name; |
+ return false; |
+ } |
+ |
std::string content; |
bool res = file_util::ReadFileToString(ppd_path, &content); |
@@ -91,25 +200,16 @@ |
return res; |
} |
-bool ValidatePrintTicket(const std::string& printer_name, |
- const std::string& print_ticket_data) { |
+bool PrintSystemCUPS::ValidatePrintTicket(const std::string& printer_name, |
+ const std::string& print_ticket_data) { |
scoped_ptr<Value> ticket_value(base::JSONReader::Read(print_ticket_data, |
false)); |
return ticket_value != NULL && ticket_value->IsType(Value::TYPE_DICTIONARY); |
} |
-std::string GenerateProxyId() { |
- // TODO(gene): This code should generate a unique id for proxy. ID should be |
- // unique for this user. Rand may return the same number. We'll need to change |
- // this in the future. |
- std::string id("CP_PROXY_"); |
- id += Uint64ToString(base::RandUint64()); |
- return id; |
-} |
- |
// Print ticket on linux is a JSON string containing only one dictionary. |
-bool ParsePrintTicket(const std::string& print_ticket, |
- std::map<std::string, std::string>* options) { |
+bool PrintSystemCUPS::ParsePrintTicket(const std::string& print_ticket, |
+ std::map<std::string, std::string>* options) { |
DCHECK(options); |
scoped_ptr<Value> ticket_value(base::JSONReader::Read(print_ticket, false)); |
if (ticket_value == NULL || !ticket_value->IsType(Value::TYPE_DICTIONARY)) |
@@ -130,15 +230,15 @@ |
return true; |
} |
-bool SpoolPrintJob(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, |
- PlatformJobId* job_id_ret) { |
+bool PrintSystemCUPS::SpoolPrintJob(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, |
+ PlatformJobId* job_id_ret) { |
DCHECK(job_id_ret); |
- DLOG(INFO) << "Spooling print job for: " << printer_name; |
+ DLOG(INFO) << "CP_CUPS: Spooling print job for: " << printer_name; |
// We need to store options as char* string for the duration of the |
// cupsPrintFile call. We'll use map here to store options, since |
@@ -162,6 +262,8 @@ |
cups_options.size(), |
&(cups_options[0])); |
+ DLOG(INFO) << "CP_CUPS: Job spooled, id: " << job_id; |
+ |
if (job_id == 0) |
return false; |
@@ -169,12 +271,12 @@ |
return true; |
} |
-bool GetJobDetails(const std::string& printer_name, |
- PlatformJobId job_id, |
- PrintJobDetails *job_details) { |
+bool PrintSystemCUPS::GetJobDetails(const std::string& printer_name, |
+ PlatformJobId job_id, |
+ PrintJobDetails *job_details) { |
DCHECK(job_details); |
- DLOG(INFO) << "Getting job details for: " << printer_name << |
+ DLOG(INFO) << "CP_CUPS: Getting job details for: " << printer_name << |
" job_id: " << job_id; |
cups_job_t* jobs = NULL; |
@@ -212,10 +314,11 @@ |
return found; |
} |
-bool GetPrinterInfo(const std::string& printer_name, PrinterBasicInfo* info) { |
+bool PrintSystemCUPS::GetPrinterInfo(const std::string& printer_name, |
+ PrinterBasicInfo* info) { |
DCHECK(info); |
- DLOG(INFO) << "Getting printer info for: " << printer_name; |
+ DLOG(INFO) << "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 |
@@ -233,99 +336,34 @@ |
return false; |
} |
-bool IsValidPrinter(const std::string& printer_name) { |
+bool PrintSystemCUPS::IsValidPrinter(const std::string& printer_name) { |
PrinterBasicInfo info; |
return GetPrinterInfo(printer_name, &info); |
} |
-class PrinterChangeNotifier::NotificationState |
- : public base::RefCountedThreadSafe< |
- PrinterChangeNotifier::NotificationState> { |
- public: |
- NotificationState() : delegate_(NULL) {} |
- bool Start(const std::string& printer_name, |
- PrinterChangeNotifier::Delegate* delegate) { |
- if (delegate_ != NULL) |
- Stop(); |
- |
- printer_name_ = printer_name; |
- delegate_ = delegate; |
- |
- MessageLoop::current()->PostDelayedTask(FROM_HERE, |
- NewRunnableMethod(this, |
- &PrinterChangeNotifier::NotificationState::Update), 5000); |
- return true; |
- } |
- bool Stop() { |
- delegate_ = NULL; |
- return true; |
- } |
- 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, |
- &PrinterChangeNotifier::NotificationState::Update), |
- kNotificationTimeout); |
- } |
- std::string printer_name() const { |
- return printer_name_; |
- } |
- private: |
- friend class base::RefCountedThreadSafe< |
- PrinterChangeNotifier::NotificationState>; |
- ~NotificationState() { |
- Stop(); |
- } |
- static const int kNotificationTimeout = 5000; // in ms |
- std::string printer_name_; // The printer being watched |
- PrinterChangeNotifier::Delegate* delegate_; // Delegate to notify |
-}; |
- |
-PrinterChangeNotifier::PrinterChangeNotifier() : state_(NULL) { |
+PrintSystem::PrintServerWatcher* |
+PrintSystemCUPS::CreatePrintServerWatcher() { |
+ return new PrintServerWatcherCUPS(); |
} |
-PrinterChangeNotifier::~PrinterChangeNotifier() { |
- StopWatching(); |
+PrintSystem::PrinterWatcher* PrintSystemCUPS::CreatePrinterWatcher( |
+ const std::string& printer_name) { |
+ DCHECK(!printer_name.empty()); |
+ return new PrinterWatcherCUPS(this, printer_name); |
} |
-bool PrinterChangeNotifier::StartWatching(const std::string& printer_name, |
- Delegate* delegate) { |
- if (state_) { |
- NOTREACHED(); |
- return false; |
- } |
- state_ = new NotificationState; |
- state_->AddRef(); |
- if (!state_->Start(printer_name, delegate)) { |
- StopWatching(); |
- return false; |
- } |
- return true; |
+std::string PrintSystem::GenerateProxyId() { |
+ // TODO(gene): This code should generate a unique id for proxy. ID should be |
+ // unique for this user. Rand may return the same number. We'll need to change |
+ // this in the future. |
+ std::string id("CP_PROXY_"); |
+ id += Uint64ToString(base::RandUint64()); |
+ return id; |
} |
-bool PrinterChangeNotifier::StopWatching() { |
- if (!state_) { |
- return false; |
- } |
- state_->Stop(); |
- state_->Release(); |
- state_ = NULL; |
- return true; |
+scoped_refptr<PrintSystem> PrintSystem::CreateInstance() { |
+ return new PrintSystemCUPS; |
} |
-bool PrinterChangeNotifier::GetCurrentPrinterInfo( |
- PrinterBasicInfo* printer_info) { |
- if (!state_) { |
- return false; |
- } |
- DCHECK(printer_info); |
- return GetPrinterInfo(state_->printer_name(), printer_info); |
-} |
} // namespace cloud_print |