summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorscottbyer@chromium.org <scottbyer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-06-09 17:48:29 +0000
committerscottbyer@chromium.org <scottbyer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-06-09 17:48:29 +0000
commite4ef3ba2250a995ec54cf21252b3c398bba334af (patch)
treef38278c679e8db4c45bb37a7c301bb9ff6c1ffb5 /chrome
parent3726e12c766353b0cc6aa0ecf8d0f38b62932766 (diff)
downloadchromium_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')
-rw-r--r--chrome/chrome.gyp8
-rw-r--r--chrome/service/cloud_print/cloud_print_helpers.h2
-rw-r--r--chrome/service/cloud_print/cloud_print_proxy.cc2
-rw-r--r--chrome/service/cloud_print/cloud_print_proxy_backend.cc46
-rw-r--r--chrome/service/cloud_print/cloud_print_proxy_backend.h2
-rw-r--r--chrome/service/cloud_print/job_status_updater.cc16
-rw-r--r--chrome/service/cloud_print/job_status_updater.h4
-rw-r--r--chrome/service/cloud_print/print_system.h168
-rw-r--r--chrome/service/cloud_print/print_system_cups.cc (renamed from chrome/service/cloud_print/printer_info_cups.cc)268
-rw-r--r--chrome/service/cloud_print/print_system_dummy.cc27
-rw-r--r--chrome/service/cloud_print/print_system_win.cc (renamed from chrome/service/cloud_print/printer_info_win.cc)419
-rw-r--r--chrome/service/cloud_print/printer_info.h127
-rw-r--r--chrome/service/cloud_print/printer_info_dummy.cc85
-rw-r--r--chrome/service/cloud_print/printer_job_handler.cc48
-rw-r--r--chrome/service/cloud_print/printer_job_handler.h23
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_;