diff options
15 files changed, 547 insertions, 689 deletions
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index ccb858e..a1800d3f 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -980,8 +980,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/print_system_dummy.cc', - 'service/cloud_print/print_system.h', + 'service/cloud_print/printer_info_dummy.cc', + 'service/cloud_print/printer_info.h', 'service/cloud_print/printer_job_handler.cc', 'service/cloud_print/printer_job_handler.h', 'service/gaia/service_gaia_authenticator.cc', @@ -1002,7 +1002,7 @@ 'CP_PRINT_SYSTEM_AVAILABLE', ], 'sources': [ - 'service/cloud_print/print_system_win.cc', + 'service/cloud_print/printer_info_win.cc', ], }], ['OS=="linux"', { @@ -1022,7 +1022,7 @@ 'CP_PRINT_SYSTEM_AVAILABLE', ], 'sources': [ - 'service/cloud_print/print_system_cups.cc', + 'service/cloud_print/printer_info_cups.cc', ], }], ], diff --git a/chrome/service/cloud_print/cloud_print_helpers.h b/chrome/service/cloud_print/cloud_print_helpers.h index 5c79b6e..55fd601 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/print_system.h" +#include "chrome/service/cloud_print/printer_info.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 3be2f49..c006e12 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::PrintSystem::GenerateProxyId(); + proxy_id = cloud_print::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 719ecb5..cad6f38 100644 --- a/chrome/service/cloud_print/cloud_print_proxy_backend.cc +++ b/chrome/service/cloud_print/cloud_print_proxy_backend.cc @@ -24,13 +24,12 @@ class CloudPrintProxyBackend::Core : public base::RefCountedThreadSafe<CloudPrintProxyBackend::Core>, public URLFetcherDelegate, - public cloud_print::PrintServerWatcherDelegate, + public cloud_print::PrinterChangeNotifierDelegate, 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 @@ -60,8 +59,14 @@ class CloudPrintProxyBackend::Core int response_code, const ResponseCookies& cookies, const std::string& data); - // cloud_print::PrintServerWatcherDelegate implementation +// cloud_print::PrinterChangeNotifier::Delegate 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); @@ -126,8 +131,6 @@ 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 @@ -156,8 +159,7 @@ class CloudPrintProxyBackend::Core JobHandlerMap; JobHandlerMap job_handler_map_; ResponseHandler next_response_handler_; - scoped_refptr<cloud_print::PrintSystem::PrintServerWatcher> - print_server_watcher_; + cloud_print::PrinterChangeNotifier printer_change_notifier_; bool new_printers_available_; // Notification (xmpp) handler. scoped_ptr<notifier::TalkMediator> talk_mediator_; @@ -233,7 +235,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( @@ -277,13 +279,6 @@ 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( @@ -293,17 +288,14 @@ void CloudPrintProxyBackend::Core::DoInitializeWithToken( talk_mediator_->SetAuthToken(email, cloud_print_xmpp_token, kSyncGaiaServiceId); talk_mediator_->Login(); - - print_server_watcher_ = print_system_->CreatePrintServerWatcher(); - print_server_watcher_->StartWatching(this); - + printer_change_notifier_.StartWatching(std::string(), this); proxy_id_ = proxy_id; StartRegistration(); } void CloudPrintProxyBackend::Core::StartRegistration() { printer_list_.clear(); - print_system_->EnumeratePrinters(&printer_list_); + cloud_print::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. @@ -319,9 +311,6 @@ 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(); @@ -333,8 +322,6 @@ 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()); @@ -371,7 +358,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 = print_system_->GetPrinterCapsAndDefaults( + have_printer_info = cloud_print::GetPrinterCapsAndDefaults( info.printer_name.c_str(), &last_uploaded_printer_info_); } if (have_printer_info) { @@ -436,10 +423,7 @@ void CloudPrintProxyBackend::Core::RegisterNextPrinter() { &CloudPrintProxyBackend::Core::HandleRegisterPrinterResponse; request_->Start(); } else { - 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)); + NOTREACHED(); } } else { EndRegistration(); @@ -541,7 +525,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_, - print_system_.get(), this); + 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 bc7da23..7464aba 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/print_system.h" +#include "chrome/service/cloud_print/printer_info.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 808b209..9c22f56 100644 --- a/chrome/service/cloud_print/job_status_updater.cc +++ b/chrome/service/cloud_print/job_status_updater.cc @@ -13,16 +13,15 @@ #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, - cloud_print::PrintSystem* print_system, - Delegate* delegate) + const std::string& job_id, + cloud_print::PlatformJobId& local_job_id, + const std::string& auth_token, + const GURL& cloud_print_server_url, + 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), - print_system_(print_system), delegate_(delegate), stopped_(false) { + delegate_(delegate), stopped_(false) { DCHECK(delegate_); } @@ -40,8 +39,7 @@ void JobStatusUpdater::UpdateStatus() { need_update = true; } else { cloud_print::PrintJobDetails details; - if (print_system_->GetJobDetails(printer_name_, local_job_id_, - &details)) { + if (cloud_print::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 ed4ab21..870869b 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/print_system.h" +#include "chrome/service/cloud_print/printer_info.h" #include "chrome/common/net/url_fetcher.h" #include "googleurl/src/gurl.h" #include "net/url_request/url_request_status.h" @@ -32,7 +32,6 @@ 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(); @@ -51,7 +50,6 @@ 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 deleted file mode 100644 index 579026c..0000000 --- a/chrome/service/cloud_print/print_system.h +++ /dev/null @@ -1,168 +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_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/print_system_dummy.cc b/chrome/service/cloud_print/print_system_dummy.cc deleted file mode 100644 index 49e481d..0000000 --- a/chrome/service/cloud_print/print_system_dummy.cc +++ /dev/null @@ -1,27 +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/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.h b/chrome/service/cloud_print/printer_info.h new file mode 100644 index 0000000..4823037 --- /dev/null +++ b/chrome/service/cloud_print/printer_info.h @@ -0,0 +1,127 @@ +// 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/print_system_cups.cc b/chrome/service/cloud_print/printer_info_cups.cc index 4e3e324..38be60b 100644 --- a/chrome/service/cloud_print/print_system_cups.cc +++ b/chrome/service/cloud_print/printer_info_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/print_system.h" +#include "chrome/service/cloud_print/printer_info.h" #include <cups/cups.h> #include <list> @@ -25,107 +25,7 @@ namespace cloud_print { static const char kCUPSPrinterInfoOpt[] = "printer-info"; static const char kCUPSPrinterStateOpt[] = "printer-state"; -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) { +void EnumeratePrinters(PrinterList* printer_list) { DCHECK(printer_list); printer_list->clear(); @@ -159,31 +59,22 @@ void PrintSystemCUPS::EnumeratePrinters(PrinterList* printer_list) { cupsFreeDests(num_dests, destinations); - DLOG(INFO) << "CP_CUPS: Enumerated " << printer_list->size() << " printers."; + DLOG(INFO) << "Enumerated " << printer_list->size() << " printers."; } -bool PrintSystemCUPS::GetPrinterCapsAndDefaults(const std::string& printer_name, - PrinterCapsAndDefaults* printer_info) { +bool GetPrinterCapsAndDefaults(const std::string& printer_name, + PrinterCapsAndDefaults* printer_info) { DCHECK(printer_info); - DLOG(INFO) << "CP_CUPS: Getting Caps and Defaults for: " << printer_name; + DLOG(INFO) << "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; - const char* ppd_file_path = cupsGetPPD(printer_name.c_str()); - if (ppd_file_path) - ppd_path = FilePath(ppd_file_path); + FilePath ppd_path(cupsGetPPD(printer_name.c_str())); 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); @@ -200,16 +91,25 @@ bool PrintSystemCUPS::GetPrinterCapsAndDefaults(const std::string& printer_name, return res; } -bool PrintSystemCUPS::ValidatePrintTicket(const std::string& printer_name, - const std::string& print_ticket_data) { +bool 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 PrintSystemCUPS::ParsePrintTicket(const std::string& print_ticket, - std::map<std::string, std::string>* options) { +bool 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)) @@ -230,15 +130,15 @@ bool PrintSystemCUPS::ParsePrintTicket(const std::string& print_ticket, return true; } -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) { +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) { DCHECK(job_id_ret); - DLOG(INFO) << "CP_CUPS: Spooling print job for: " << printer_name; + DLOG(INFO) << "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 @@ -262,8 +162,6 @@ bool PrintSystemCUPS::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; @@ -271,12 +169,12 @@ bool PrintSystemCUPS::SpoolPrintJob(const std::string& print_ticket, return true; } -bool PrintSystemCUPS::GetJobDetails(const std::string& printer_name, - PlatformJobId job_id, - PrintJobDetails *job_details) { +bool GetJobDetails(const std::string& printer_name, + PlatformJobId job_id, + PrintJobDetails *job_details) { DCHECK(job_details); - DLOG(INFO) << "CP_CUPS: Getting job details for: " << printer_name << + DLOG(INFO) << "Getting job details for: " << printer_name << " job_id: " << job_id; cups_job_t* jobs = NULL; @@ -314,11 +212,10 @@ bool PrintSystemCUPS::GetJobDetails(const std::string& printer_name, return found; } -bool PrintSystemCUPS::GetPrinterInfo(const std::string& printer_name, - PrinterBasicInfo* info) { +bool GetPrinterInfo(const std::string& printer_name, PrinterBasicInfo* info) { DCHECK(info); - DLOG(INFO) << "CP_CUPS: Getting printer info for: " << printer_name; + DLOG(INFO) << "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 @@ -336,34 +233,99 @@ bool PrintSystemCUPS::GetPrinterInfo(const std::string& printer_name, return false; } -bool PrintSystemCUPS::IsValidPrinter(const std::string& printer_name) { +bool IsValidPrinter(const std::string& printer_name) { PrinterBasicInfo info; return GetPrinterInfo(printer_name, &info); } -PrintSystem::PrintServerWatcher* -PrintSystemCUPS::CreatePrintServerWatcher() { - return new PrintServerWatcherCUPS(); +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::PrinterWatcher* PrintSystemCUPS::CreatePrinterWatcher( - const std::string& printer_name) { - DCHECK(!printer_name.empty()); - return new PrinterWatcherCUPS(this, printer_name); +PrinterChangeNotifier::~PrinterChangeNotifier() { + StopWatching(); } -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::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; } -scoped_refptr<PrintSystem> PrintSystem::CreateInstance() { - return new PrintSystemCUPS; +bool PrinterChangeNotifier::StopWatching() { + if (!state_) { + return false; + } + state_->Stop(); + state_->Release(); + state_ = NULL; + return true; } +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/printer_info_dummy.cc b/chrome/service/cloud_print/printer_info_dummy.cc new file mode 100644 index 0000000..2d2f25a --- /dev/null +++ b/chrome/service/cloud_print/printer_info_dummy.cc @@ -0,0 +1,85 @@ +// 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/print_system_win.cc b/chrome/service/cloud_print/printer_info_win.cc index 5f79d9c..4839d60 100644 --- a/chrome/service/cloud_print/print_system_win.cc +++ b/chrome/service/cloud_print/printer_info_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/print_system.h" +#include "chrome/service/cloud_print/printer_info.h" #include <windows.h> #include <objidl.h> @@ -128,224 +128,7 @@ HRESULT PrintPdf2DC(HDC dc, const FilePath& pdf_filename) { namespace cloud_print { -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; - } - - 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 -}; - -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, PrintSystemWatcherWin::Delegate { - 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, PrintSystemWatcherWin::Delegate { - 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) { +void EnumeratePrinters(PrinterList* printer_list) { DCHECK(printer_list); DWORD bytes_needed = 0; DWORD count_returned = 0; @@ -370,9 +153,8 @@ void PrintSystemWin::EnumeratePrinters(PrinterList* printer_list) { } } -bool PrintSystemWin::GetPrinterCapsAndDefaults( - const std::string& printer_name, - PrinterCapsAndDefaults* printer_info) { +bool GetPrinterCapsAndDefaults(const std::string& printer_name, + PrinterCapsAndDefaults* printer_info) { if (!InitXPSModule()) { // TODO(sanjeevr): Handle legacy proxy case (with no prntvpt.dll) return false; @@ -442,9 +224,8 @@ bool PrintSystemWin::GetPrinterCapsAndDefaults( return true; } -bool PrintSystemWin::ValidatePrintTicket( - const std::string& printer_name, - const std::string& print_ticket_data) { +bool 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; @@ -477,12 +258,25 @@ bool PrintSystemWin::ValidatePrintTicket( return 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) { +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) { if (!InitXPSModule()) { // TODO(sanjeevr): Handle legacy proxy case (with no prntvpt.dll) return false; @@ -519,9 +313,9 @@ bool PrintSystemWin::SpoolPrintJob(const std::string& print_ticket, return SUCCEEDED(hr); } -bool PrintSystemWin::GetJobDetails(const std::string& printer_name, - PlatformJobId job_id, - PrintJobDetails *job_details) { +bool 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); @@ -564,7 +358,7 @@ bool PrintSystemWin::GetJobDetails(const std::string& printer_name, return ret; } -bool PrintSystemWin::IsValidPrinter(const std::string& printer_name) { +bool 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, @@ -577,33 +371,139 @@ bool PrintSystemWin::IsValidPrinter(const std::string& printer_name) { return ret; } -PrintSystem::PrintServerWatcher* -PrintSystemWin::CreatePrintServerWatcher() { - return new PrintServerWatcherWin(); +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::PrinterWatcher* PrintSystemWin::CreatePrinterWatcher( - const std::string& printer_name) { - DCHECK(!printer_name.empty()); - return new PrinterWatcherWin(printer_name); +PrinterChangeNotifier::~PrinterChangeNotifier() { + StopWatching(); } -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::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; } -scoped_refptr<PrintSystem> PrintSystem::CreateInstance() { - return new PrintSystemWin; +bool PrinterChangeNotifier::StopWatching() { + if (!state_) { + return false; + } + state_->Stop(); + delete state_; + state_ = NULL; + return true; } +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_job_handler.cc b/chrome/service/cloud_print/printer_job_handler.cc index 2fbd60b..8ae919b 100644 --- a/chrome/service/cloud_print/printer_job_handler.cc +++ b/chrome/service/cloud_print/printer_job_handler.cc @@ -22,10 +22,8 @@ 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) - : print_system_(print_system), - printer_info_(printer_info), + : printer_info_(printer_info), printer_id_(printer_id), auth_token_(auth_token), last_caps_hash_(caps_hash), @@ -43,10 +41,8 @@ PrinterJobHandler::PrinterJobHandler( } bool PrinterJobHandler::Initialize() { - if (print_system_->IsValidPrinter(printer_info_.printer_name)) { - printer_watcher_ = print_system_->CreatePrinterWatcher( - printer_info_.printer_name); - printer_watcher_->StartWatching(this); + if (cloud_print::IsValidPrinter(printer_info_.printer_name)) { + printer_change_notifier_.StartWatching(printer_info_.printer_name, this); NotifyJobAvailable(); } else { // This printer does not exist any more. Delete it from the server. @@ -56,7 +52,7 @@ bool PrinterJobHandler::Initialize() { } PrinterJobHandler::~PrinterJobHandler() { - printer_watcher_->StopWatching(); + printer_change_notifier_.StopWatching(); } void PrinterJobHandler::Reset() { @@ -122,12 +118,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_watcher_->GetCurrentPrinterInfo(&printer_info); + printer_change_notifier_.GetCurrentPrinterInfo(&printer_info); cloud_print::PrinterCapsAndDefaults printer_caps; std::string post_data; std::string mime_boundary; - if (print_system_->GetPrinterCapsAndDefaults(printer_info.printer_name, - &printer_caps)) { + if (cloud_print::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_) { @@ -217,6 +213,12 @@ 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_) { @@ -354,7 +356,7 @@ bool PrinterJobHandler::HandlePrintTicketResponse( if (!status.is_success() || (response_code != 200)) { return false; } - if (print_system_->ValidatePrintTicket(printer_info_.printer_name, data)) { + if (cloud_print::ValidatePrintTicket(printer_info_.printer_name, data)) { job_details_.print_ticket_ = data; MessageLoop::current()->PostTask( FROM_HERE, @@ -414,8 +416,7 @@ void PrinterJobHandler::StartPrinting() { print_thread_.message_loop()->PostTask( FROM_HERE, NewRunnableFunction(&PrinterJobHandler::DoPrint, job_details_, - printer_info_.printer_name, - print_system_, this, + printer_info_.printer_name, this, MessageLoop::current())); } } @@ -493,7 +494,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_, - print_system_.get(), this); + this); job_status_updater_list_.push_back(job_status_updater); MessageLoop::current()->PostTask( FROM_HERE, NewRunnableMethod(job_status_updater.get(), @@ -542,18 +543,17 @@ bool PrinterJobHandler::HavePendingTasks() { void PrinterJobHandler::DoPrint(const JobDetails& job_details, - const std::string& printer_name, - scoped_refptr<cloud_print::PrintSystem> print_system, - PrinterJobHandler* job_handler, - MessageLoop* job_message_loop) { + const std::string& printer_name, + PrinterJobHandler* job_handler, + MessageLoop* job_message_loop) { DCHECK(job_handler); DCHECK(job_message_loop); cloud_print::PlatformJobId job_id = -1; - 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)) { + 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)) { 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 948021b..8be2b95 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/print_system.h" +#include "chrome/service/cloud_print/printer_info.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::PrinterWatcherDelegate { + public cloud_print::PrinterChangeNotifierDelegate { enum PrintJobError { SUCCESS, JOB_DOWNLOAD_FAILED, @@ -92,12 +92,11 @@ 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, - cloud_print::PrintSystem* print_system, - Delegate* delegate); + const std::string& printer_id, + const std::string& caps_hash, + const std::string& auth_token, + const GURL& cloud_print_server_url, + Delegate* delegate); ~PrinterJobHandler(); bool Initialize(); // Notifies the JobHandler that a job is available @@ -116,7 +115,8 @@ class PrinterJobHandler : public base::RefCountedThreadSafe<PrinterJobHandler>, const std::string& data); // JobStatusUpdater::Delegate implementation virtual bool OnJobCompleted(JobStatusUpdater* updater); - // cloud_print::PrinterWatcherDelegate implementation + // cloud_print::PrinterChangeNotifier::Delegate implementation + virtual void OnPrinterAdded(); virtual void OnPrinterDeleted(); virtual void OnPrinterChanged(); virtual void OnJobChanged(); @@ -194,12 +194,11 @@ 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_; @@ -227,7 +226,7 @@ class PrinterJobHandler : public base::RefCountedThreadSafe<PrinterJobHandler>, // Some task in the state machine is in progress. bool task_in_progress_; - scoped_refptr<cloud_print::PrintSystem::PrinterWatcher> printer_watcher_; + cloud_print::PrinterChangeNotifier printer_change_notifier_; typedef std::list< scoped_refptr<JobStatusUpdater> > JobStatusUpdaterList; JobStatusUpdaterList job_status_updater_list_; |