| 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
|
|
|
|
|