diff options
author | scottbyer@chromium.org <scottbyer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-09 17:48:29 +0000 |
---|---|---|
committer | scottbyer@chromium.org <scottbyer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-09 17:48:29 +0000 |
commit | e4ef3ba2250a995ec54cf21252b3c398bba334af (patch) | |
tree | f38278c679e8db4c45bb37a7c301bb9ff6c1ffb5 /chrome | |
parent | 3726e12c766353b0cc6aa0ecf8d0f38b62932766 (diff) | |
download | chromium_src-e4ef3ba2250a995ec54cf21252b3c398bba334af.zip chromium_src-e4ef3ba2250a995ec54cf21252b3c398bba334af.tar.gz chromium_src-e4ef3ba2250a995ec54cf21252b3c398bba334af.tar.bz2 |
On behalf of gene@chromium.org. Redesign cloud printing subsystem layer. Make it a class, and allow to have internal state. Also, some minor improvements.
BUG=none
TEST=Try run Windows cloud print proxy and confirm documents get printed.
Committed: http://src.chromium.org/viewvc/chrome?view=rev&revision=49200
Review URL: http://codereview.chromium.org/2519002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@49281 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
15 files changed, 698 insertions, 547 deletions
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 195d4bf..b2ac50a 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -990,8 +990,8 @@ 'service/cloud_print/cloud_print_proxy_backend.h', 'service/cloud_print/job_status_updater.cc', 'service/cloud_print/job_status_updater.h', - 'service/cloud_print/printer_info_dummy.cc', - 'service/cloud_print/printer_info.h', + 'service/cloud_print/print_system_dummy.cc', + 'service/cloud_print/print_system.h', 'service/cloud_print/printer_job_handler.cc', 'service/cloud_print/printer_job_handler.h', 'service/gaia/service_gaia_authenticator.cc', @@ -1012,7 +1012,7 @@ 'CP_PRINT_SYSTEM_AVAILABLE', ], 'sources': [ - 'service/cloud_print/printer_info_win.cc', + 'service/cloud_print/print_system_win.cc', ], }], ['OS=="linux"', { @@ -1032,7 +1032,7 @@ 'CP_PRINT_SYSTEM_AVAILABLE', ], 'sources': [ - 'service/cloud_print/printer_info_cups.cc', + 'service/cloud_print/print_system_cups.cc', ], }], ], diff --git a/chrome/service/cloud_print/cloud_print_helpers.h b/chrome/service/cloud_print/cloud_print_helpers.h index 55fd601..5c79b6e 100644 --- a/chrome/service/cloud_print/cloud_print_helpers.h +++ b/chrome/service/cloud_print/cloud_print_helpers.h @@ -7,7 +7,7 @@ #include <string> -#include "chrome/service/cloud_print/printer_info.h" +#include "chrome/service/cloud_print/print_system.h" #include "googleurl/src/gurl.h" class DictionaryValue; diff --git a/chrome/service/cloud_print/cloud_print_proxy.cc b/chrome/service/cloud_print/cloud_print_proxy.cc index c006e12..3be2f49 100644 --- a/chrome/service/cloud_print/cloud_print_proxy.cc +++ b/chrome/service/cloud_print/cloud_print_proxy.cc @@ -30,7 +30,7 @@ void CloudPrintProxy::EnableForUser(const std::string& lsid) { std::string proxy_id; service_prefs_->prefs()->GetString(prefs::kCloudPrintProxyId, &proxy_id); if (proxy_id.empty()) { - proxy_id = cloud_print::GenerateProxyId(); + proxy_id = cloud_print::PrintSystem::GenerateProxyId(); service_prefs_->prefs()->SetString(prefs::kCloudPrintProxyId, proxy_id); service_prefs_->WritePrefs(); } diff --git a/chrome/service/cloud_print/cloud_print_proxy_backend.cc b/chrome/service/cloud_print/cloud_print_proxy_backend.cc index cad6f38..719ecb5 100644 --- a/chrome/service/cloud_print/cloud_print_proxy_backend.cc +++ b/chrome/service/cloud_print/cloud_print_proxy_backend.cc @@ -24,12 +24,13 @@ class CloudPrintProxyBackend::Core : public base::RefCountedThreadSafe<CloudPrintProxyBackend::Core>, public URLFetcherDelegate, - public cloud_print::PrinterChangeNotifierDelegate, + public cloud_print::PrintServerWatcherDelegate, public PrinterJobHandlerDelegate, public notifier::TalkMediator::Delegate { public: explicit Core(CloudPrintProxyBackend* backend, const GURL& cloud_print_server_url); + // Note: // // The Do* methods are the various entry points from CloudPrintProxyBackend @@ -59,14 +60,8 @@ class CloudPrintProxyBackend::Core int response_code, const ResponseCookies& cookies, const std::string& data); -// cloud_print::PrinterChangeNotifier::Delegate implementation + // cloud_print::PrintServerWatcherDelegate implementation virtual void OnPrinterAdded(); - virtual void OnPrinterDeleted() { - } - virtual void OnPrinterChanged() { - } - virtual void OnJobChanged() { - } // PrinterJobHandler::Delegate implementation void OnPrinterJobHandlerShutdown(PrinterJobHandler* job_handler, const std::string& printer_id); @@ -131,6 +126,8 @@ class CloudPrintProxyBackend::Core CloudPrintProxyBackend* backend_; GURL cloud_print_server_url_; + // Pointer to current print system. + scoped_refptr<cloud_print::PrintSystem> print_system_; // The list of printers to be registered with the cloud print server. // To begin with,this list is initialized with the list of local and network // printers available. Then we query the server for the list of printers @@ -159,7 +156,8 @@ class CloudPrintProxyBackend::Core JobHandlerMap; JobHandlerMap job_handler_map_; ResponseHandler next_response_handler_; - cloud_print::PrinterChangeNotifier printer_change_notifier_; + scoped_refptr<cloud_print::PrintSystem::PrintServerWatcher> + print_server_watcher_; bool new_printers_available_; // Notification (xmpp) handler. scoped_ptr<notifier::TalkMediator> talk_mediator_; @@ -235,7 +233,7 @@ CloudPrintProxyBackend::Core::Core(CloudPrintProxyBackend* backend, const GURL& cloud_print_server_url) : backend_(backend), cloud_print_server_url_(cloud_print_server_url), next_upload_index_(0), server_error_count_(0), - next_response_handler_(NULL), new_printers_available_(false) { + next_response_handler_(NULL), new_printers_available_(false) { } void CloudPrintProxyBackend::Core::DoInitializeWithLsid( @@ -279,6 +277,13 @@ void CloudPrintProxyBackend::Core::DoInitializeWithToken( const std::string cloud_print_xmpp_token, const std::string email, const std::string& proxy_id) { DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop()); + + print_system_ = cloud_print::PrintSystem::CreateInstance(); + if (!print_system_.get()) { + NOTREACHED(); + return; // No print system available, fail initalization. + } + // TODO(sanjeevr): Validate the tokens. auth_token_ = cloud_print_token; talk_mediator_.reset(new notifier::TalkMediatorImpl( @@ -288,14 +293,17 @@ void CloudPrintProxyBackend::Core::DoInitializeWithToken( talk_mediator_->SetAuthToken(email, cloud_print_xmpp_token, kSyncGaiaServiceId); talk_mediator_->Login(); - printer_change_notifier_.StartWatching(std::string(), this); + + print_server_watcher_ = print_system_->CreatePrintServerWatcher(); + print_server_watcher_->StartWatching(this); + proxy_id_ = proxy_id; StartRegistration(); } void CloudPrintProxyBackend::Core::StartRegistration() { printer_list_.clear(); - cloud_print::EnumeratePrinters(&printer_list_); + print_system_->EnumeratePrinters(&printer_list_); server_error_count_ = 0; // Now we need to ask the server about printers that were registered on the // server so that we can trim this list. @@ -311,6 +319,9 @@ void CloudPrintProxyBackend::Core::EndRegistration() { } void CloudPrintProxyBackend::Core::DoShutdown() { + if (print_server_watcher_ != NULL) + print_server_watcher_->StopWatching(); + // Need to kill all running jobs. while (!job_handler_map_.empty()) { JobHandlerMap::iterator index = job_handler_map_.begin(); @@ -322,6 +333,8 @@ void CloudPrintProxyBackend::Core::DoShutdown() { void CloudPrintProxyBackend::Core::DoRegisterSelectedPrinters( const cloud_print::PrinterList& printer_list) { + if (!print_system_.get()) + return; // No print system available. server_error_count_ = 0; printer_list_.assign(printer_list.begin(), printer_list.end()); DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop()); @@ -358,7 +371,7 @@ void CloudPrintProxyBackend::Core::RegisterNextPrinter() { // If we are retrying a previous upload, we don't need to fetch the caps // and defaults again. if (info.printer_name != last_uploaded_printer_name_) { - have_printer_info = cloud_print::GetPrinterCapsAndDefaults( + have_printer_info = print_system_->GetPrinterCapsAndDefaults( info.printer_name.c_str(), &last_uploaded_printer_info_); } if (have_printer_info) { @@ -423,7 +436,10 @@ void CloudPrintProxyBackend::Core::RegisterNextPrinter() { &CloudPrintProxyBackend::Core::HandleRegisterPrinterResponse; request_->Start(); } else { - NOTREACHED(); + LOG(ERROR) << "CP: Failed to get printer info for: " << info.printer_name; + next_upload_index_++; + MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(this, + &CloudPrintProxyBackend::Core::RegisterNextPrinter)); } } else { EndRegistration(); @@ -525,7 +541,7 @@ void CloudPrintProxyBackend::Core::InitJobHandlerForPrinter( scoped_refptr<PrinterJobHandler> job_handler; job_handler = new PrinterJobHandler(printer_info, printer_id, caps_hash, auth_token_, cloud_print_server_url_, - this); + print_system_.get(), this); job_handler_map_[printer_id] = job_handler; job_handler->Initialize(); } diff --git a/chrome/service/cloud_print/cloud_print_proxy_backend.h b/chrome/service/cloud_print/cloud_print_proxy_backend.h index 7464aba..bc7da23 100644 --- a/chrome/service/cloud_print/cloud_print_proxy_backend.h +++ b/chrome/service/cloud_print/cloud_print_proxy_backend.h @@ -9,7 +9,7 @@ #include <string> #include "base/thread.h" -#include "chrome/service/cloud_print/printer_info.h" +#include "chrome/service/cloud_print/print_system.h" #include "chrome/common/net/url_fetcher.h" #include "googleurl/src/gurl.h" diff --git a/chrome/service/cloud_print/job_status_updater.cc b/chrome/service/cloud_print/job_status_updater.cc index 9c22f56..808b209 100644 --- a/chrome/service/cloud_print/job_status_updater.cc +++ b/chrome/service/cloud_print/job_status_updater.cc @@ -13,15 +13,16 @@ #include "googleurl/src/gurl.h" JobStatusUpdater::JobStatusUpdater(const std::string& printer_name, - const std::string& job_id, - cloud_print::PlatformJobId& local_job_id, - const std::string& auth_token, - const GURL& cloud_print_server_url, - Delegate* delegate) + const std::string& job_id, + cloud_print::PlatformJobId& local_job_id, + const std::string& auth_token, + const GURL& cloud_print_server_url, + cloud_print::PrintSystem* print_system, + Delegate* delegate) : printer_name_(printer_name), job_id_(job_id), local_job_id_(local_job_id), auth_token_(auth_token), cloud_print_server_url_(cloud_print_server_url), - delegate_(delegate), stopped_(false) { + print_system_(print_system), delegate_(delegate), stopped_(false) { DCHECK(delegate_); } @@ -39,7 +40,8 @@ void JobStatusUpdater::UpdateStatus() { need_update = true; } else { cloud_print::PrintJobDetails details; - if (cloud_print::GetJobDetails(printer_name_, local_job_id_, &details)) { + if (print_system_->GetJobDetails(printer_name_, local_job_id_, + &details)) { if (details != last_job_details_) { last_job_details_ = details; need_update = true; diff --git a/chrome/service/cloud_print/job_status_updater.h b/chrome/service/cloud_print/job_status_updater.h index 870869b..ed4ab21 100644 --- a/chrome/service/cloud_print/job_status_updater.h +++ b/chrome/service/cloud_print/job_status_updater.h @@ -10,7 +10,7 @@ #include "base/file_path.h" #include "base/ref_counted.h" #include "base/thread.h" -#include "chrome/service/cloud_print/printer_info.h" +#include "chrome/service/cloud_print/print_system.h" #include "chrome/common/net/url_fetcher.h" #include "googleurl/src/gurl.h" #include "net/url_request/url_request_status.h" @@ -32,6 +32,7 @@ class JobStatusUpdater : public base::RefCountedThreadSafe<JobStatusUpdater>, cloud_print::PlatformJobId& local_job_id, const std::string& auth_token, const GURL& cloud_print_server_url, + cloud_print::PrintSystem* print_system, Delegate* delegate); // Checks the status of the local print job and sends an update. void UpdateStatus(); @@ -50,6 +51,7 @@ class JobStatusUpdater : public base::RefCountedThreadSafe<JobStatusUpdater>, scoped_ptr<URLFetcher> request_; std::string auth_token_; GURL cloud_print_server_url_; + scoped_refptr<cloud_print::PrintSystem> print_system_; Delegate* delegate_; // A flag that is set to true in Stop() and will ensure the next scheduled // task will do nothing. diff --git a/chrome/service/cloud_print/print_system.h b/chrome/service/cloud_print/print_system.h new file mode 100644 index 0000000..579026c --- /dev/null +++ b/chrome/service/cloud_print/print_system.h @@ -0,0 +1,168 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_SERVICE_CLOUD_PRINT_PRINT_SYSTEM_H_ +#define CHROME_SERVICE_CLOUD_PRINT_PRINT_SYSTEM_H_ + +#include <map> +#include <string> +#include <vector> + +#include "base/file_path.h" +#include "base/ref_counted.h" + +// This is the interface for platform-specific code for cloud print +namespace cloud_print { + +typedef int PlatformJobId; + +struct PrinterBasicInfo { + std::string printer_name; + std::string printer_description; + int printer_status; + std::map<std::string, std::string> options; + PrinterBasicInfo() : printer_status(0) { + } +}; + +typedef std::vector<PrinterBasicInfo> PrinterList; + +struct PrinterCapsAndDefaults { + std::string printer_capabilities; + std::string caps_mime_type; + std::string printer_defaults; + std::string defaults_mime_type; +}; + +enum PrintJobStatus { + PRINT_JOB_STATUS_INVALID, + PRINT_JOB_STATUS_IN_PROGRESS, + PRINT_JOB_STATUS_ERROR, + PRINT_JOB_STATUS_COMPLETED +}; + +struct PrintJobDetails { + PrintJobStatus status; + int platform_status_flags; + std::string status_message; + int total_pages; + int pages_printed; + PrintJobDetails() : status(PRINT_JOB_STATUS_INVALID), + platform_status_flags(0), total_pages(0), + pages_printed(0) { + } + void Clear() { + status = PRINT_JOB_STATUS_INVALID; + platform_status_flags = 0; + status_message.clear(); + total_pages = 0; + pages_printed = 0; + } + bool operator ==(const PrintJobDetails& other) const { + return (status == other.status) && + (platform_status_flags == other.platform_status_flags) && + (status_message == other.status_message) && + (total_pages == other.total_pages) && + (pages_printed == other.pages_printed); + } + bool operator !=(const PrintJobDetails& other) const { + return !(*this == other); + } +}; + +// PrintSystem class will provide interface for different printing systems +// (Windows, CUPS) to implement. User will call CreateInstance() to +// obtain available printing system. +// Please note, that PrintSystem is not platform specific, but rather +// print system specific. For example, CUPS is available on both Linux and Mac, +// but not avaialble on ChromeOS, etc. This design allows us to add more +// functionality on some platforms, while reusing core (CUPS) functions. +class PrintSystem : public base::RefCountedThreadSafe<PrintSystem> { + public: + virtual ~PrintSystem() {} + + // Enumerates the list of installed local and network printers. + virtual void EnumeratePrinters(PrinterList* printer_list) = 0; + + // Gets the capabilities and defaults for a specific printer. + virtual bool GetPrinterCapsAndDefaults(const std::string& printer_name, + PrinterCapsAndDefaults* printer_info) = 0; + + // Returns true if ticket is valid. + virtual bool ValidatePrintTicket(const std::string& printer_name, + const std::string& print_ticket_data) = 0; + + // Send job to the printer. + 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) = 0; + + // Get details for already spooled job. + virtual bool GetJobDetails(const std::string& printer_name, + PlatformJobId job_id, + PrintJobDetails *job_details) = 0; + + // Returns true if printer_name points to a valid printer. + virtual bool IsValidPrinter(const std::string& printer_name) = 0; + + class PrintServerWatcher + : public base::RefCountedThreadSafe<PrintServerWatcher> { + public: + // Callback interface for new printer notifications. + class Delegate { + public: + virtual void OnPrinterAdded() = 0; + // TODO(gene): Do we need OnPrinterDeleted notification here? + }; + + virtual ~PrintServerWatcher() {} + virtual bool StartWatching(PrintServerWatcher::Delegate* delegate) = 0; + virtual bool StopWatching() = 0; + }; + + class PrinterWatcher : public base::RefCountedThreadSafe<PrinterWatcher> { + public: + // Callback interface for printer updates notifications. + class Delegate { + public: + virtual void OnPrinterDeleted() = 0; + virtual void OnPrinterChanged() = 0; + virtual void OnJobChanged() = 0; + }; + + virtual ~PrinterWatcher() {} + virtual bool StartWatching(PrinterWatcher::Delegate* delegate) = 0; + virtual bool StopWatching() = 0; + virtual bool GetCurrentPrinterInfo(PrinterBasicInfo* printer_info) = 0; + }; + + // Factory methods to create corresponding watcher. Callee is responsible + // for deleting objects. Return NULL if failed. + virtual PrintServerWatcher* CreatePrintServerWatcher() = 0; + virtual PrinterWatcher* CreatePrinterWatcher( + const std::string& printer_name) = 0; + + // Generate unique for proxy. + static std::string GenerateProxyId(); + + // Call this function to obtain current printing system. Return NULL if no + // print system available. Delete returned PrintSystem pointer using delete. + static scoped_refptr<PrintSystem> CreateInstance(); +}; + + +// This typedef is to workaround the issue with certain versions of +// Visual Studio where it gets confused between multiple Delegate +// classes and gives a C2500 error. (I saw this error on the try bots - +// the workaround was not needed for my machine). +typedef PrintSystem::PrintServerWatcher::Delegate PrintServerWatcherDelegate; +typedef PrintSystem::PrinterWatcher::Delegate PrinterWatcherDelegate; + +} // namespace cloud_print + +#endif // CHROME_SERVICE_CLOUD_PRINT_PRINT_SYSTEM_H_ + diff --git a/chrome/service/cloud_print/printer_info_cups.cc b/chrome/service/cloud_print/print_system_cups.cc index 38be60b..4e3e324 100644 --- a/chrome/service/cloud_print/printer_info_cups.cc +++ b/chrome/service/cloud_print/print_system_cups.cc @@ -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 @@ namespace cloud_print { 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 @@ void EnumeratePrinters(PrinterList* printer_list) { 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 @@ bool GetPrinterCapsAndDefaults(const std::string& printer_name, 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 @@ bool ParsePrintTicket(const std::string& print_ticket, 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 @@ bool SpoolPrintJob(const std::string& print_ticket, 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 @@ bool SpoolPrintJob(const std::string& print_ticket, 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 @@ bool GetJobDetails(const std::string& printer_name, 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 @@ bool GetPrinterInfo(const std::string& printer_name, PrinterBasicInfo* info) { 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 diff --git a/chrome/service/cloud_print/print_system_dummy.cc b/chrome/service/cloud_print/print_system_dummy.cc new file mode 100644 index 0000000..49e481d --- /dev/null +++ b/chrome/service/cloud_print/print_system_dummy.cc @@ -0,0 +1,27 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This is dummy implementation for all configurations where print system +// for cloud print is not available. +#if !defined(CP_PRINT_SYSTEM_AVAILABLE) + +#include "chrome/service/cloud_print/print_system.h" + +#include "base/logging.h" + +namespace cloud_print { + +std::string PrintSystem::GenerateProxyId() { + NOTREACHED(); + return std::string(); +} + +scoped_refptr<PrintSystem> PrintSystem::CreateInstance() { + NOTREACHED(); + return NULL; +} +} // namespace cloud_print + +#endif // CP_PRINT_SYSTEM_AVAILABLE + diff --git a/chrome/service/cloud_print/printer_info_win.cc b/chrome/service/cloud_print/print_system_win.cc index 4839d60..58a27fa 100644 --- a/chrome/service/cloud_print/printer_info_win.cc +++ b/chrome/service/cloud_print/print_system_win.cc @@ -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 <windows.h> #include <objidl.h> @@ -128,7 +128,233 @@ HRESULT PrintPdf2DC(HDC dc, const FilePath& pdf_filename) { namespace cloud_print { -void EnumeratePrinters(PrinterList* printer_list) { +class PrintSystemWatcherWin + : public base::ObjectWatcher::Delegate { + public: + PrintSystemWatcherWin() + : printer_(NULL), printer_change_(NULL), delegate_(NULL) { + } + ~PrintSystemWatcherWin() { + Stop(); + } + + class Delegate { + public: + virtual void OnPrinterAdded() = 0; + virtual void OnPrinterDeleted() = 0; + virtual void OnPrinterChanged() = 0; + virtual void OnJobChanged() = 0; + }; + + bool Start(const std::string& printer_name, Delegate* delegate) { + delegate_ = delegate; + // An empty printer name means watch the current server, we need to pass + // NULL to OpenPrinter. + LPTSTR printer_name_to_use = NULL; + std::wstring printer_name_wide; + if (!printer_name.empty()) { + printer_name_wide = UTF8ToWide(printer_name); + printer_name_to_use = const_cast<LPTSTR>(printer_name_wide.c_str()); + } + bool ret = false; + OpenPrinter(printer_name_to_use, &printer_, NULL); + if (printer_) { + printer_change_ = FindFirstPrinterChangeNotification( + printer_, PRINTER_CHANGE_PRINTER|PRINTER_CHANGE_JOB, 0, NULL); + if (printer_change_) { + ret = watcher_.StartWatching(printer_change_, this); + } + } + if (!ret) { + Stop(); + } + return ret; + } + bool Stop() { + watcher_.StopWatching(); + if (printer_) { + ClosePrinter(printer_); + printer_ = NULL; + } + if (printer_change_) { + FindClosePrinterChangeNotification(printer_change_); + printer_change_ = NULL; + } + return true; + } + + // base::ObjectWatcher::Delegate method + virtual void OnObjectSignaled(HANDLE object) { + DWORD change = 0; + FindNextPrinterChangeNotification(object, &change, NULL, NULL); + + if (change != ((PRINTER_CHANGE_PRINTER|PRINTER_CHANGE_JOB) & + (~PRINTER_CHANGE_FAILED_CONNECTION_PRINTER))) { + // For printer connections, we get spurious change notifications with + // all flags set except PRINTER_CHANGE_FAILED_CONNECTION_PRINTER. + // Ignore these. + if (change & PRINTER_CHANGE_ADD_PRINTER) { + delegate_->OnPrinterAdded(); + } else if (change & PRINTER_CHANGE_DELETE_PRINTER) { + delegate_->OnPrinterDeleted(); + } else if (change & PRINTER_CHANGE_SET_PRINTER) { + delegate_->OnPrinterChanged(); + } + if (change & PRINTER_CHANGE_JOB) { + delegate_->OnJobChanged(); + } + } + watcher_.StartWatching(printer_change_, this); + } + + bool GetCurrentPrinterInfo(PrinterBasicInfo* printer_info) { + DCHECK(printer_info); + if (!printer_) + return false; + + DWORD bytes_needed = 0; + bool ret = false; + GetPrinter(printer_, 2, NULL, 0, &bytes_needed); + if (0 != bytes_needed) { + scoped_ptr<BYTE> printer_info_buffer(new BYTE[bytes_needed]); + if (GetPrinter(printer_, 2, printer_info_buffer.get(), + bytes_needed, &bytes_needed)) { + PRINTER_INFO_2* printer_info_win = + reinterpret_cast<PRINTER_INFO_2*>(printer_info_buffer.get()); + printer_info->printer_name = WideToUTF8(printer_info_win->pPrinterName); + printer_info->printer_description = + WideToUTF8(printer_info_win->pComment); + printer_info->printer_status = printer_info_win->Status; + ret = true; + } + } + return ret; + } + + private: + base::ObjectWatcher watcher_; + HANDLE printer_; // The printer being watched + HANDLE printer_change_; // Returned by FindFirstPrinterChangeNotifier + Delegate* delegate_; // Delegate to notify + bool did_signal_; // DoneWaiting was called +}; + +// This typedef is to workaround the issue with certain versions of +// Visual Studio where it gets confused between multiple Delegate. +// In this case, some compilers get confused and inherit +// PrintSystemWin watchers from wrong Delegate, giving C2664 and C2259 errors. +typedef PrintSystemWatcherWin::Delegate PrintSystemWatcherWinDelegate; + +class PrintSystemWin : 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); + + class PrintServerWatcherWin + : public PrintSystem::PrintServerWatcher, + public PrintSystemWatcherWinDelegate { + public: + PrintServerWatcherWin() {} + + // PrintSystem::PrintServerWatcher interface + virtual bool StartWatching( + PrintSystem::PrintServerWatcher::Delegate* delegate) { + delegate_ = delegate; + return watcher_.Start(std::string(), this); + } + virtual bool StopWatching() { + bool ret = watcher_.Stop(); + delegate_ = NULL; + return ret; + } + + // PrintSystemWatcherWin::Delegate interface + virtual void OnPrinterAdded() { + delegate_->OnPrinterAdded(); + } + virtual void OnPrinterDeleted() { + NOTREACHED(); + } + virtual void OnPrinterChanged() { + NOTREACHED(); + } + virtual void OnJobChanged() { + NOTREACHED(); + } + + private: + PrintSystem::PrintServerWatcher::Delegate* delegate_; + PrintSystemWatcherWin watcher_; + DISALLOW_COPY_AND_ASSIGN(PrintServerWatcherWin); + }; + + class PrinterWatcherWin + : public PrintSystem::PrinterWatcher, + public PrintSystemWatcherWinDelegate { + public: + explicit PrinterWatcherWin(const std::string& printer_name) + : printer_name_(printer_name) {} + + // PrintSystem::PrinterWatcher interface + virtual bool StartWatching( + PrintSystem::PrinterWatcher::Delegate* delegate) { + delegate_ = delegate; + return watcher_.Start(printer_name_, this); + } + virtual bool StopWatching() { + bool ret = watcher_.Stop(); + delegate_ = NULL; + return ret; + } + virtual bool GetCurrentPrinterInfo(PrinterBasicInfo* printer_info) { + return watcher_.GetCurrentPrinterInfo(printer_info); + } + + // PrintSystemWatcherWin::Delegate interface + virtual void OnPrinterAdded() { + NOTREACHED(); + } + virtual void OnPrinterDeleted() { + delegate_->OnPrinterDeleted(); + } + virtual void OnPrinterChanged() { + delegate_->OnPrinterChanged(); + } + virtual void OnJobChanged() { + delegate_->OnJobChanged(); + } + + private: + std::string printer_name_; + PrintSystem::PrinterWatcher::Delegate* delegate_; + PrintSystemWatcherWin watcher_; + DISALLOW_COPY_AND_ASSIGN(PrinterWatcherWin); + }; + + virtual PrintSystem::PrintServerWatcher* CreatePrintServerWatcher(); + virtual PrintSystem::PrinterWatcher* CreatePrinterWatcher( + const std::string& printer_name); +}; + +void PrintSystemWin::EnumeratePrinters(PrinterList* printer_list) { DCHECK(printer_list); DWORD bytes_needed = 0; DWORD count_returned = 0; @@ -153,8 +379,9 @@ void EnumeratePrinters(PrinterList* printer_list) { } } -bool GetPrinterCapsAndDefaults(const std::string& printer_name, - PrinterCapsAndDefaults* printer_info) { +bool PrintSystemWin::GetPrinterCapsAndDefaults( + const std::string& printer_name, + PrinterCapsAndDefaults* printer_info) { if (!InitXPSModule()) { // TODO(sanjeevr): Handle legacy proxy case (with no prntvpt.dll) return false; @@ -224,8 +451,9 @@ bool GetPrinterCapsAndDefaults(const std::string& printer_name, return true; } -bool ValidatePrintTicket(const std::string& printer_name, - const std::string& print_ticket_data) { +bool PrintSystemWin::ValidatePrintTicket( + const std::string& printer_name, + const std::string& print_ticket_data) { if (!InitXPSModule()) { // TODO(sanjeevr): Handle legacy proxy case (with no prntvpt.dll) return false; @@ -258,25 +486,12 @@ bool ValidatePrintTicket(const std::string& printer_name, return ret; } -std::string GenerateProxyId() { - GUID proxy_id = {0}; - HRESULT hr = UuidCreate(&proxy_id); - DCHECK(SUCCEEDED(hr)); - wchar_t* proxy_id_as_string = NULL; - UuidToString(&proxy_id, reinterpret_cast<RPC_WSTR *>(&proxy_id_as_string)); - DCHECK(proxy_id_as_string); - std::string ret; - WideToUTF8(proxy_id_as_string, wcslen(proxy_id_as_string), &ret); - RpcStringFree(reinterpret_cast<RPC_WSTR *>(&proxy_id_as_string)); - return ret; -} - -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 PrintSystemWin::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) { if (!InitXPSModule()) { // TODO(sanjeevr): Handle legacy proxy case (with no prntvpt.dll) return false; @@ -313,9 +528,9 @@ bool SpoolPrintJob(const std::string& print_ticket, return SUCCEEDED(hr); } -bool GetJobDetails(const std::string& printer_name, - PlatformJobId job_id, - PrintJobDetails *job_details) { +bool PrintSystemWin::GetJobDetails(const std::string& printer_name, + PlatformJobId job_id, + PrintJobDetails *job_details) { DCHECK(job_details); HANDLE printer_handle = NULL; std::wstring printer_name_wide = UTF8ToWide(printer_name); @@ -358,7 +573,7 @@ bool GetJobDetails(const std::string& printer_name, return ret; } -bool IsValidPrinter(const std::string& printer_name) { +bool PrintSystemWin::IsValidPrinter(const std::string& printer_name) { std::wstring printer_name_wide = UTF8ToWide(printer_name); HANDLE printer_handle = NULL; OpenPrinter(const_cast<LPTSTR>(printer_name_wide.c_str()), &printer_handle, @@ -371,139 +586,33 @@ bool IsValidPrinter(const std::string& printer_name) { return ret; } -class PrinterChangeNotifier::NotificationState - : public base::ObjectWatcher::Delegate { - public: - NotificationState() : printer_(NULL), printer_change_(NULL), delegate_(NULL) { - } - ~NotificationState() { - Stop(); - } - bool Start(const std::string& printer_name, - PrinterChangeNotifier::Delegate* delegate) { - delegate_ = delegate; - // An empty printer name means watch the current server, we need to pass - // NULL to OpenPrinter. - LPTSTR printer_name_to_use = NULL; - std::wstring printer_name_wide; - if (!printer_name.empty()) { - printer_name_wide = UTF8ToWide(printer_name); - printer_name_to_use = const_cast<LPTSTR>(printer_name_wide.c_str()); - } - bool ret = false; - OpenPrinter(printer_name_to_use, &printer_, NULL); - if (printer_) { - printer_change_ = FindFirstPrinterChangeNotification( - printer_, PRINTER_CHANGE_PRINTER|PRINTER_CHANGE_JOB, 0, NULL); - if (printer_change_) { - ret = watcher_.StartWatching(printer_change_, this); - } - } - if (!ret) { - Stop(); - } - return ret; - } - bool Stop() { - watcher_.StopWatching(); - if (printer_) { - ClosePrinter(printer_); - printer_ = NULL; - } - if (printer_change_) { - FindClosePrinterChangeNotification(printer_change_); - printer_change_ = NULL; - } - return true; - } - - void OnObjectSignaled(HANDLE object) { - DWORD change = 0; - FindNextPrinterChangeNotification(object, &change, NULL, NULL); - - if (change != ((PRINTER_CHANGE_PRINTER|PRINTER_CHANGE_JOB) & - (~PRINTER_CHANGE_FAILED_CONNECTION_PRINTER))) { - // For printer connections, we get spurious change notifications with - // all flags set except PRINTER_CHANGE_FAILED_CONNECTION_PRINTER. - // Ignore these. - if (change & PRINTER_CHANGE_ADD_PRINTER) { - delegate_->OnPrinterAdded(); - } else if (change & PRINTER_CHANGE_DELETE_PRINTER) { - delegate_->OnPrinterDeleted(); - } else if (change & PRINTER_CHANGE_SET_PRINTER) { - delegate_->OnPrinterChanged(); - } - if (change & PRINTER_CHANGE_JOB) { - delegate_->OnJobChanged(); - } - } - watcher_.StartWatching(printer_change_, this); - } - HANDLE printer_handle() const { - return printer_; - } - private: - base::ObjectWatcher watcher_; - HANDLE printer_; // The printer being watched - HANDLE printer_change_; // Returned by FindFirstPrinterChangeNotifier - PrinterChangeNotifier::Delegate* delegate_; // Delegate to notify - bool did_signal_; // DoneWaiting was called -}; - -PrinterChangeNotifier::PrinterChangeNotifier() : state_(NULL) { +PrintSystem::PrintServerWatcher* +PrintSystemWin::CreatePrintServerWatcher() { + return new PrintServerWatcherWin(); } -PrinterChangeNotifier::~PrinterChangeNotifier() { - StopWatching(); +PrintSystem::PrinterWatcher* PrintSystemWin::CreatePrinterWatcher( + const std::string& printer_name) { + DCHECK(!printer_name.empty()); + return new PrinterWatcherWin(printer_name); } -bool PrinterChangeNotifier::StartWatching(const std::string& printer_name, - Delegate* delegate) { - if (state_) { - NOTREACHED(); - return false; - } - state_ = new NotificationState; - if (!state_->Start(printer_name, delegate)) { - StopWatching(); - return false; - } - return true; +std::string PrintSystem::GenerateProxyId() { + GUID proxy_id = {0}; + HRESULT hr = UuidCreate(&proxy_id); + DCHECK(SUCCEEDED(hr)); + wchar_t* proxy_id_as_string = NULL; + UuidToString(&proxy_id, reinterpret_cast<RPC_WSTR *>(&proxy_id_as_string)); + DCHECK(proxy_id_as_string); + std::string ret; + WideToUTF8(proxy_id_as_string, wcslen(proxy_id_as_string), &ret); + RpcStringFree(reinterpret_cast<RPC_WSTR *>(&proxy_id_as_string)); + return ret; } -bool PrinterChangeNotifier::StopWatching() { - if (!state_) { - return false; - } - state_->Stop(); - delete state_; - state_ = NULL; - return true; +scoped_refptr<PrintSystem> PrintSystem::CreateInstance() { + return new PrintSystemWin; } -bool PrinterChangeNotifier::GetCurrentPrinterInfo( - PrinterBasicInfo* printer_info) { - if (!state_) { - return false; - } - DCHECK(printer_info); - DWORD bytes_needed = 0; - bool ret = false; - GetPrinter(state_->printer_handle(), 2, NULL, 0, &bytes_needed); - if (0 != bytes_needed) { - scoped_ptr<BYTE> printer_info_buffer(new BYTE[bytes_needed]); - if (GetPrinter(state_->printer_handle(), 2, printer_info_buffer.get(), - bytes_needed, &bytes_needed)) { - PRINTER_INFO_2* printer_info_win = - reinterpret_cast<PRINTER_INFO_2*>(printer_info_buffer.get()); - printer_info->printer_name = WideToUTF8(printer_info_win->pPrinterName); - printer_info->printer_description = - WideToUTF8(printer_info_win->pComment); - printer_info->printer_status = printer_info_win->Status; - ret = true; - } - } - return ret; -} } // namespace cloud_print diff --git a/chrome/service/cloud_print/printer_info.h b/chrome/service/cloud_print/printer_info.h deleted file mode 100644 index 4823037..0000000 --- a/chrome/service/cloud_print/printer_info.h +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_SERVICE_CLOUD_PRINT_PRINTER_INFO_H_ -#define CHROME_SERVICE_CLOUD_PRINT_PRINTER_INFO_H_ - -#include <map> -#include <string> -#include <vector> - -#include "base/file_path.h" - -// This is the interface for platform-specific code for cloud print -namespace cloud_print { - -typedef int PlatformJobId; - -struct PrinterBasicInfo { - std::string printer_name; - std::string printer_description; - int printer_status; - std::map<std::string, std::string> options; - PrinterBasicInfo() : printer_status(0) { - } -}; - -typedef std::vector<PrinterBasicInfo> PrinterList; - -struct PrinterCapsAndDefaults { - std::string printer_capabilities; - std::string caps_mime_type; - std::string printer_defaults; - std::string defaults_mime_type; -}; - -enum PrintJobStatus { - PRINT_JOB_STATUS_INVALID, - PRINT_JOB_STATUS_IN_PROGRESS, - PRINT_JOB_STATUS_ERROR, - PRINT_JOB_STATUS_COMPLETED -}; - -struct PrintJobDetails { - PrintJobStatus status; - int platform_status_flags; - std::string status_message; - int total_pages; - int pages_printed; - PrintJobDetails() : status(PRINT_JOB_STATUS_INVALID), - platform_status_flags(0), total_pages(0), - pages_printed(0) { - } - void Clear() { - status = PRINT_JOB_STATUS_INVALID; - platform_status_flags = 0; - status_message.clear(); - total_pages = 0; - pages_printed = 0; - } - bool operator ==(const PrintJobDetails& other) const { - return (status == other.status) && - (platform_status_flags == other.platform_status_flags) && - (status_message == other.status_message) && - (total_pages == other.total_pages) && - (pages_printed == other.pages_printed); - } - bool operator !=(const PrintJobDetails& other) const { - return !(*this == other); - } -}; - -// Enumerates the list of installed local and network printers. -void EnumeratePrinters(PrinterList* printer_list); -// Gets the capabilities and defaults for a specific printer. -bool GetPrinterCapsAndDefaults(const std::string& printer_name, - PrinterCapsAndDefaults* printer_info); -bool ValidatePrintTicket(const std::string& printer_name, - const std::string& print_ticket_data); -std::string GenerateProxyId(); -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 GetJobDetails(const std::string& printer_name, - PlatformJobId job_id, - PrintJobDetails *job_details); -bool IsValidPrinter(const std::string& printer_name); - -// A class that watches changes to a printer or a print server. -// The set of notifications are very coarse-grained (even though the Windows -// API allows for listening to fine-grained details about a printer, this class -// does not support that level of fine-grained control. -class PrinterChangeNotifier { - public: - class Delegate { - public: - virtual void OnPrinterAdded() = 0; - virtual void OnPrinterDeleted() = 0; - virtual void OnPrinterChanged() = 0; - virtual void OnJobChanged() = 0; - }; - PrinterChangeNotifier(); - ~PrinterChangeNotifier(); - bool StartWatching(const std::string& printer_name, Delegate* delegate); - bool StopWatching(); - bool GetCurrentPrinterInfo(PrinterBasicInfo* printer_info); - private: - // Internal state maintained by the PrinterChangeNotifier class. - class NotificationState; - NotificationState* state_; - DISALLOW_COPY_AND_ASSIGN(PrinterChangeNotifier); -}; - -// This typedef is to workaround the issue with certain versions of -// Visual Studio where it gets confused between multiple Delegate -// classes and gives a C2500 error. (I saw this error on the try bots - -// the workaround was not needed for my machine). -typedef PrinterChangeNotifier::Delegate PrinterChangeNotifierDelegate; - -} // namespace cloud_print - -#endif // CHROME_SERVICE_CLOUD_PRINT_PRINTER_INFO_H_ - diff --git a/chrome/service/cloud_print/printer_info_dummy.cc b/chrome/service/cloud_print/printer_info_dummy.cc deleted file mode 100644 index 2d2f25a..0000000 --- a/chrome/service/cloud_print/printer_info_dummy.cc +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This is dummy implementation for all configurations where print system -// for cloud print is not available. -#if !defined(CP_PRINT_SYSTEM_AVAILABLE) - -#include "chrome/service/cloud_print/printer_info.h" - -#include "base/logging.h" - -namespace cloud_print { - -void EnumeratePrinters(PrinterList* printer_list) { - DCHECK(printer_list); - NOTIMPLEMENTED(); -} - -bool GetPrinterCapsAndDefaults(const std::string& printer_name, - PrinterCapsAndDefaults* printer_info) { - NOTIMPLEMENTED(); - return false; -} - -bool ValidatePrintTicket(const std::string& printer_name, - const std::string& print_ticket_data) { - NOTIMPLEMENTED(); - return false; -} - -std::string GenerateProxyId() { - NOTIMPLEMENTED(); - return std::string(); -} - -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) { - NOTIMPLEMENTED(); - return false; -} - -bool GetJobDetails(const std::string& printer_name, - PlatformJobId job_id, - PrintJobDetails *job_details) { - NOTIMPLEMENTED(); - return false; -} - -bool IsValidPrinter(const std::string& printer_name) { - NOTIMPLEMENTED(); - return false; -} - -PrinterChangeNotifier::PrinterChangeNotifier() : state_(NULL) { -} - -PrinterChangeNotifier::~PrinterChangeNotifier() { - StopWatching(); -} - -bool PrinterChangeNotifier::StartWatching(const std::string& printer_name, - Delegate* delegate) { - NOTIMPLEMENTED(); - return false; -} - -bool PrinterChangeNotifier::StopWatching() { - NOTIMPLEMENTED(); - return false; -} - -bool PrinterChangeNotifier::GetCurrentPrinterInfo( - PrinterBasicInfo* printer_info) { - NOTIMPLEMENTED(); - return false; -} -} // namespace cloud_print - -#endif // CP_PRINT_SYSTEM_AVAILABLE - diff --git a/chrome/service/cloud_print/printer_job_handler.cc b/chrome/service/cloud_print/printer_job_handler.cc index 8ae919b..2fbd60b 100644 --- a/chrome/service/cloud_print/printer_job_handler.cc +++ b/chrome/service/cloud_print/printer_job_handler.cc @@ -22,8 +22,10 @@ PrinterJobHandler::PrinterJobHandler( const std::string& caps_hash, const std::string& auth_token, const GURL& cloud_print_server_url, + cloud_print::PrintSystem* print_system, Delegate* delegate) - : printer_info_(printer_info), + : print_system_(print_system), + printer_info_(printer_info), printer_id_(printer_id), auth_token_(auth_token), last_caps_hash_(caps_hash), @@ -41,8 +43,10 @@ PrinterJobHandler::PrinterJobHandler( } bool PrinterJobHandler::Initialize() { - if (cloud_print::IsValidPrinter(printer_info_.printer_name)) { - printer_change_notifier_.StartWatching(printer_info_.printer_name, this); + if (print_system_->IsValidPrinter(printer_info_.printer_name)) { + printer_watcher_ = print_system_->CreatePrinterWatcher( + printer_info_.printer_name); + printer_watcher_->StartWatching(this); NotifyJobAvailable(); } else { // This printer does not exist any more. Delete it from the server. @@ -52,7 +56,7 @@ bool PrinterJobHandler::Initialize() { } PrinterJobHandler::~PrinterJobHandler() { - printer_change_notifier_.StopWatching(); + printer_watcher_->StopWatching(); } void PrinterJobHandler::Reset() { @@ -118,12 +122,12 @@ bool PrinterJobHandler::UpdatePrinterInfo() { // We need to update the parts of the printer info that have changed // (could be printer name, description, status or capabilities). cloud_print::PrinterBasicInfo printer_info; - printer_change_notifier_.GetCurrentPrinterInfo(&printer_info); + printer_watcher_->GetCurrentPrinterInfo(&printer_info); cloud_print::PrinterCapsAndDefaults printer_caps; std::string post_data; std::string mime_boundary; - if (cloud_print::GetPrinterCapsAndDefaults(printer_info.printer_name, - &printer_caps)) { + if (print_system_->GetPrinterCapsAndDefaults(printer_info.printer_name, + &printer_caps)) { std::string caps_hash = MD5String(printer_caps.printer_capabilities); CloudPrintHelpers::CreateMimeBoundaryForUpload(&mime_boundary); if (caps_hash != last_caps_hash_) { @@ -213,12 +217,6 @@ bool PrinterJobHandler::OnJobCompleted(JobStatusUpdater* updater) { return ret; } - // cloud_print::PrinterChangeNotifier::Delegate implementation -void PrinterJobHandler::OnPrinterAdded() { - // Should never get this notification for a printer - NOTREACHED(); -} - void PrinterJobHandler::OnPrinterDeleted() { printer_delete_pending_ = true; if (!task_in_progress_) { @@ -356,7 +354,7 @@ bool PrinterJobHandler::HandlePrintTicketResponse( if (!status.is_success() || (response_code != 200)) { return false; } - if (cloud_print::ValidatePrintTicket(printer_info_.printer_name, data)) { + if (print_system_->ValidatePrintTicket(printer_info_.printer_name, data)) { job_details_.print_ticket_ = data; MessageLoop::current()->PostTask( FROM_HERE, @@ -416,7 +414,8 @@ void PrinterJobHandler::StartPrinting() { print_thread_.message_loop()->PostTask( FROM_HERE, NewRunnableFunction(&PrinterJobHandler::DoPrint, job_details_, - printer_info_.printer_name, this, + printer_info_.printer_name, + print_system_, this, MessageLoop::current())); } } @@ -494,7 +493,7 @@ bool PrinterJobHandler::HandleSuccessStatusUpdateResponse( scoped_refptr<JobStatusUpdater> job_status_updater = new JobStatusUpdater(printer_info_.printer_name, job_details_.job_id_, local_job_id_, auth_token_, cloud_print_server_url_, - this); + print_system_.get(), this); job_status_updater_list_.push_back(job_status_updater); MessageLoop::current()->PostTask( FROM_HERE, NewRunnableMethod(job_status_updater.get(), @@ -543,17 +542,18 @@ bool PrinterJobHandler::HavePendingTasks() { void PrinterJobHandler::DoPrint(const JobDetails& job_details, - const std::string& printer_name, - PrinterJobHandler* job_handler, - MessageLoop* job_message_loop) { + const std::string& printer_name, + scoped_refptr<cloud_print::PrintSystem> print_system, + PrinterJobHandler* job_handler, + MessageLoop* job_message_loop) { DCHECK(job_handler); DCHECK(job_message_loop); cloud_print::PlatformJobId job_id = -1; - if (cloud_print::SpoolPrintJob(job_details.print_ticket_, - job_details.print_data_file_path_, - job_details.print_data_mime_type_, - printer_name, - job_details.job_title_, &job_id)) { + if (print_system->SpoolPrintJob(job_details.print_ticket_, + job_details.print_data_file_path_, + job_details.print_data_mime_type_, + printer_name, + job_details.job_title_, &job_id)) { job_message_loop->PostTask(FROM_HERE, NewRunnableMethod(job_handler, &PrinterJobHandler::JobSpooled, diff --git a/chrome/service/cloud_print/printer_job_handler.h b/chrome/service/cloud_print/printer_job_handler.h index 8be2b95..948021b 100644 --- a/chrome/service/cloud_print/printer_job_handler.h +++ b/chrome/service/cloud_print/printer_job_handler.h @@ -12,7 +12,7 @@ #include "base/ref_counted.h" #include "base/thread.h" #include "chrome/service/cloud_print/job_status_updater.h" -#include "chrome/service/cloud_print/printer_info.h" +#include "chrome/service/cloud_print/print_system.h" #include "chrome/common/net/url_fetcher.h" #include "googleurl/src/gurl.h" #include "net/url_request/url_request_status.h" @@ -61,7 +61,7 @@ typedef URLFetcher::Delegate URLFetcherDelegate; class PrinterJobHandler : public base::RefCountedThreadSafe<PrinterJobHandler>, public URLFetcherDelegate, public JobStatusUpdaterDelegate, - public cloud_print::PrinterChangeNotifierDelegate { + public cloud_print::PrinterWatcherDelegate { enum PrintJobError { SUCCESS, JOB_DOWNLOAD_FAILED, @@ -92,11 +92,12 @@ class PrinterJobHandler : public base::RefCountedThreadSafe<PrinterJobHandler>, // Begin public interface PrinterJobHandler(const cloud_print::PrinterBasicInfo& printer_info, - const std::string& printer_id, - const std::string& caps_hash, - const std::string& auth_token, - const GURL& cloud_print_server_url, - Delegate* delegate); + const std::string& printer_id, + const std::string& caps_hash, + const std::string& auth_token, + const GURL& cloud_print_server_url, + cloud_print::PrintSystem* print_system, + Delegate* delegate); ~PrinterJobHandler(); bool Initialize(); // Notifies the JobHandler that a job is available @@ -115,8 +116,7 @@ class PrinterJobHandler : public base::RefCountedThreadSafe<PrinterJobHandler>, const std::string& data); // JobStatusUpdater::Delegate implementation virtual bool OnJobCompleted(JobStatusUpdater* updater); - // cloud_print::PrinterChangeNotifier::Delegate implementation - virtual void OnPrinterAdded(); + // cloud_print::PrinterWatcherDelegate implementation virtual void OnPrinterDeleted(); virtual void OnPrinterChanged(); virtual void OnJobChanged(); @@ -194,11 +194,12 @@ class PrinterJobHandler : public base::RefCountedThreadSafe<PrinterJobHandler>, static void DoPrint(const JobDetails& job_details, const std::string& printer_name, + scoped_refptr<cloud_print::PrintSystem> print_system, PrinterJobHandler* job_handler, MessageLoop* job_message_loop); - scoped_ptr<URLFetcher> request_; + scoped_refptr<cloud_print::PrintSystem> print_system_; cloud_print::PrinterBasicInfo printer_info_; std::string printer_id_; std::string auth_token_; @@ -226,7 +227,7 @@ class PrinterJobHandler : public base::RefCountedThreadSafe<PrinterJobHandler>, // Some task in the state machine is in progress. bool task_in_progress_; - cloud_print::PrinterChangeNotifier printer_change_notifier_; + scoped_refptr<cloud_print::PrintSystem::PrinterWatcher> printer_watcher_; typedef std::list< scoped_refptr<JobStatusUpdater> > JobStatusUpdaterList; JobStatusUpdaterList job_status_updater_list_; |