Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / service / cloud_print / print_system_win.cc
blobf46c2af7dfba1c83959243cbf6c9496cc94541f4
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/service/cloud_print/print_system_win.h"
7 #include "base/strings/utf_string_conversions.h"
8 #include "base/win/object_watcher.h"
9 #include "chrome/common/crash_keys.h"
10 #include "printing/backend/win_helper.h"
12 namespace cloud_print {
14 namespace {
16 class PrintSystemWatcherWin : public base::win::ObjectWatcher::Delegate {
17 public:
18 PrintSystemWatcherWin()
19 : delegate_(NULL),
20 did_signal_(false) {
22 ~PrintSystemWatcherWin() {
23 Stop();
26 class Delegate {
27 public:
28 virtual ~Delegate() {}
29 virtual void OnPrinterAdded() = 0;
30 virtual void OnPrinterDeleted() = 0;
31 virtual void OnPrinterChanged() = 0;
32 virtual void OnJobChanged() = 0;
35 bool Start(const std::string& printer_name, Delegate* delegate) {
36 scoped_refptr<printing::PrintBackend> print_backend(
37 printing::PrintBackend::CreateInstance(NULL));
38 printer_info_ = print_backend->GetPrinterDriverInfo(printer_name);
39 crash_keys::ScopedPrinterInfo crash_key(printer_info_);
41 delegate_ = delegate;
42 // An empty printer name means watch the current server, we need to pass
43 // NULL to OpenPrinter.
44 LPTSTR printer_name_to_use = NULL;
45 std::wstring printer_name_wide;
46 if (!printer_name.empty()) {
47 printer_name_wide = base::UTF8ToWide(printer_name);
48 printer_name_to_use = const_cast<LPTSTR>(printer_name_wide.c_str());
50 bool ret = false;
51 if (printer_.OpenPrinter(printer_name_to_use)) {
52 printer_change_.Set(FindFirstPrinterChangeNotification(
53 printer_, PRINTER_CHANGE_PRINTER|PRINTER_CHANGE_JOB, 0, NULL));
54 if (printer_change_.IsValid()) {
55 ret = watcher_.StartWatching(printer_change_, this);
58 if (!ret) {
59 Stop();
61 return ret;
64 bool Stop() {
65 watcher_.StopWatching();
66 printer_.Close();
67 printer_change_.Close();
68 return true;
71 // base::ObjectWatcher::Delegate method
72 virtual void OnObjectSignaled(HANDLE object) {
73 crash_keys::ScopedPrinterInfo crash_key(printer_info_);
74 DWORD change = 0;
75 FindNextPrinterChangeNotification(object, &change, NULL, NULL);
77 if (change != ((PRINTER_CHANGE_PRINTER|PRINTER_CHANGE_JOB) &
78 (~PRINTER_CHANGE_FAILED_CONNECTION_PRINTER))) {
79 // For printer connections, we get spurious change notifications with
80 // all flags set except PRINTER_CHANGE_FAILED_CONNECTION_PRINTER.
81 // Ignore these.
82 if (change & PRINTER_CHANGE_ADD_PRINTER) {
83 delegate_->OnPrinterAdded();
84 } else if (change & PRINTER_CHANGE_DELETE_PRINTER) {
85 delegate_->OnPrinterDeleted();
86 } else if (change & PRINTER_CHANGE_SET_PRINTER) {
87 delegate_->OnPrinterChanged();
89 if (change & PRINTER_CHANGE_JOB) {
90 delegate_->OnJobChanged();
93 watcher_.StartWatching(printer_change_, this);
96 bool GetCurrentPrinterInfo(printing::PrinterBasicInfo* printer_info) {
97 DCHECK(printer_info);
98 return InitBasicPrinterInfo(printer_, printer_info);
101 private:
102 base::win::ObjectWatcher watcher_;
103 printing::ScopedPrinterHandle printer_; // The printer being watched
104 // Returned by FindFirstPrinterChangeNotifier.
105 printing::ScopedPrinterChangeHandle printer_change_;
106 Delegate* delegate_; // Delegate to notify
107 bool did_signal_; // DoneWaiting was called
108 std::string printer_info_; // For crash reporting.
111 class PrintServerWatcherWin
112 : public PrintSystem::PrintServerWatcher,
113 public PrintSystemWatcherWin::Delegate {
114 public:
115 PrintServerWatcherWin() : delegate_(NULL) {}
117 // PrintSystem::PrintServerWatcher implementation.
118 virtual bool StartWatching(
119 PrintSystem::PrintServerWatcher::Delegate* delegate) OVERRIDE{
120 delegate_ = delegate;
121 return watcher_.Start(std::string(), this);
124 virtual bool StopWatching() OVERRIDE{
125 bool ret = watcher_.Stop();
126 delegate_ = NULL;
127 return ret;
130 // PrintSystemWatcherWin::Delegate implementation.
131 virtual void OnPrinterAdded() OVERRIDE {
132 delegate_->OnPrinterAdded();
134 virtual void OnPrinterDeleted() OVERRIDE {}
135 virtual void OnPrinterChanged() OVERRIDE {}
136 virtual void OnJobChanged() OVERRIDE {}
138 protected:
139 virtual ~PrintServerWatcherWin() {}
141 private:
142 PrintSystem::PrintServerWatcher::Delegate* delegate_;
143 PrintSystemWatcherWin watcher_;
145 DISALLOW_COPY_AND_ASSIGN(PrintServerWatcherWin);
148 class PrinterWatcherWin
149 : public PrintSystem::PrinterWatcher,
150 public PrintSystemWatcherWin::Delegate {
151 public:
152 explicit PrinterWatcherWin(const std::string& printer_name)
153 : printer_name_(printer_name),
154 delegate_(NULL) {
157 // PrintSystem::PrinterWatcher implementation.
158 virtual bool StartWatching(
159 PrintSystem::PrinterWatcher::Delegate* delegate) OVERRIDE {
160 delegate_ = delegate;
161 return watcher_.Start(printer_name_, this);
164 virtual bool StopWatching() OVERRIDE {
165 bool ret = watcher_.Stop();
166 delegate_ = NULL;
167 return ret;
170 virtual bool GetCurrentPrinterInfo(
171 printing::PrinterBasicInfo* printer_info) OVERRIDE {
172 return watcher_.GetCurrentPrinterInfo(printer_info);
175 // PrintSystemWatcherWin::Delegate implementation.
176 virtual void OnPrinterAdded() OVERRIDE {
177 NOTREACHED();
179 virtual void OnPrinterDeleted() OVERRIDE {
180 delegate_->OnPrinterDeleted();
182 virtual void OnPrinterChanged() OVERRIDE {
183 delegate_->OnPrinterChanged();
185 virtual void OnJobChanged() OVERRIDE {
186 delegate_->OnJobChanged();
189 protected:
190 virtual ~PrinterWatcherWin() {}
192 private:
193 std::string printer_name_;
194 PrintSystem::PrinterWatcher::Delegate* delegate_;
195 PrintSystemWatcherWin watcher_;
197 DISALLOW_COPY_AND_ASSIGN(PrinterWatcherWin);
200 } // namespace
202 PrintSystemWin::PrintSystemWin() {
203 print_backend_ = printing::PrintBackend::CreateInstance(NULL);
206 PrintSystemWin::~PrintSystemWin() {
209 PrintSystem::PrintSystemResult PrintSystemWin::EnumeratePrinters(
210 printing::PrinterList* printer_list) {
211 bool ret = print_backend_->EnumeratePrinters(printer_list);
212 return PrintSystemResult(ret, std::string());
215 bool PrintSystemWin::IsValidPrinter(const std::string& printer_name) {
216 return print_backend_->IsValidPrinter(printer_name);
219 bool PrintSystemWin::GetJobDetails(const std::string& printer_name,
220 PlatformJobId job_id,
221 PrintJobDetails *job_details) {
222 crash_keys::ScopedPrinterInfo crash_key(
223 print_backend_->GetPrinterDriverInfo(printer_name));
224 DCHECK(job_details);
225 printing::ScopedPrinterHandle printer_handle;
226 std::wstring printer_name_wide = base::UTF8ToWide(printer_name);
227 printer_handle.OpenPrinter(printer_name_wide.c_str());
228 DCHECK(printer_handle.IsValid());
229 bool ret = false;
230 if (printer_handle.IsValid()) {
231 DWORD bytes_needed = 0;
232 GetJob(printer_handle, job_id, 1, NULL, 0, &bytes_needed);
233 DWORD last_error = GetLastError();
234 if (ERROR_INVALID_PARAMETER != last_error) {
235 // ERROR_INVALID_PARAMETER normally means that the job id is not valid.
236 DCHECK(last_error == ERROR_INSUFFICIENT_BUFFER);
237 scoped_ptr<BYTE[]> job_info_buffer(new BYTE[bytes_needed]);
238 if (GetJob(printer_handle, job_id, 1, job_info_buffer.get(), bytes_needed,
239 &bytes_needed)) {
240 JOB_INFO_1 *job_info =
241 reinterpret_cast<JOB_INFO_1 *>(job_info_buffer.get());
242 if (job_info->pStatus) {
243 base::WideToUTF8(job_info->pStatus, wcslen(job_info->pStatus),
244 &job_details->status_message);
246 job_details->platform_status_flags = job_info->Status;
247 if ((job_info->Status & JOB_STATUS_COMPLETE) ||
248 (job_info->Status & JOB_STATUS_PRINTED)) {
249 job_details->status = PRINT_JOB_STATUS_COMPLETED;
250 } else if (job_info->Status & JOB_STATUS_ERROR) {
251 job_details->status = PRINT_JOB_STATUS_ERROR;
252 } else {
253 job_details->status = PRINT_JOB_STATUS_IN_PROGRESS;
255 job_details->total_pages = job_info->TotalPages;
256 job_details->pages_printed = job_info->PagesPrinted;
257 ret = true;
261 return ret;
264 PrintSystem::PrintServerWatcher*
265 PrintSystemWin::CreatePrintServerWatcher() {
266 return new PrintServerWatcherWin();
269 PrintSystem::PrinterWatcher* PrintSystemWin::CreatePrinterWatcher(
270 const std::string& printer_name) {
271 DCHECK(!printer_name.empty());
272 return new PrinterWatcherWin(printer_name);
275 std::string PrintSystemWin::GetPrinterDriverInfo(
276 const std::string& printer_name) const {
277 return print_backend_->GetPrinterDriverInfo(printer_name);
280 } // namespace cloud_print