OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/service/cloud_print/print_system.h" | 5 #include "chrome/service/cloud_print/print_system.h" |
6 | 6 |
7 #include <cups/cups.h> | 7 #include <cups/cups.h> |
8 #include <dlfcn.h> | 8 #include <dlfcn.h> |
9 #include <errno.h> | 9 #include <errno.h> |
10 #include <pthread.h> | 10 #include <pthread.h> |
11 | 11 |
12 #include <algorithm> | 12 #include <algorithm> |
13 #include <list> | 13 #include <list> |
14 #include <map> | 14 #include <map> |
15 | 15 |
| 16 #include "base/bind.h" |
16 #include "base/file_path.h" | 17 #include "base/file_path.h" |
17 #include "base/json/json_reader.h" | 18 #include "base/json/json_reader.h" |
18 #include "base/logging.h" | 19 #include "base/logging.h" |
19 #include "base/md5.h" | 20 #include "base/md5.h" |
20 #include "base/memory/scoped_ptr.h" | 21 #include "base/memory/scoped_ptr.h" |
21 #include "base/message_loop.h" | 22 #include "base/message_loop.h" |
22 #include "base/rand_util.h" | 23 #include "base/rand_util.h" |
23 #include "base/string_number_conversions.h" | 24 #include "base/string_number_conversions.h" |
24 #include "base/string_util.h" | 25 #include "base/string_util.h" |
25 #include "base/task.h" | 26 #include "base/task.h" |
(...skipping 17 matching lines...) Expand all Loading... |
43 static const char kCUPSPrintServerURLs[] = "print_server_urls"; | 44 static const char kCUPSPrintServerURLs[] = "print_server_urls"; |
44 static const char kCUPSUpdateTimeoutMs[] = "update_timeout_ms"; | 45 static const char kCUPSUpdateTimeoutMs[] = "update_timeout_ms"; |
45 static const char kCUPSNotifyDelete[] = "notify_delete"; | 46 static const char kCUPSNotifyDelete[] = "notify_delete"; |
46 | 47 |
47 // Default port for IPP print servers. | 48 // Default port for IPP print servers. |
48 static const int kDefaultIPPServerPort = 631; | 49 static const int kDefaultIPPServerPort = 631; |
49 | 50 |
50 // Time interval to check for printer's updates. | 51 // Time interval to check for printer's updates. |
51 const int kCheckForPrinterUpdatesMs = 5*60*1000; | 52 const int kCheckForPrinterUpdatesMs = 5*60*1000; |
52 | 53 |
53 // Job update timeput | 54 // Job update timeout |
54 const int kJobUpdateTimeoutMs = 5000; | 55 const int kJobUpdateTimeoutMs = 5000; |
55 | 56 |
56 // Job id for dry run (it should not affect CUPS job ids, since 0 job-id is | 57 // Job id for dry run (it should not affect CUPS job ids, since 0 job-id is |
57 // invalid in CUPS. | 58 // invalid in CUPS. |
58 const int kDryRunJobId = 0; | 59 const int kDryRunJobId = 0; |
59 | 60 |
60 } // namespace | 61 } // namespace |
61 | 62 |
62 namespace cloud_print { | 63 namespace cloud_print { |
63 | 64 |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
178 } | 179 } |
179 ~PrintServerWatcherCUPS() { | 180 ~PrintServerWatcherCUPS() { |
180 StopWatching(); | 181 StopWatching(); |
181 } | 182 } |
182 | 183 |
183 // PrintSystem::PrintServerWatcher interface | 184 // PrintSystem::PrintServerWatcher interface |
184 virtual bool StartWatching( | 185 virtual bool StartWatching( |
185 PrintSystem::PrintServerWatcher::Delegate* delegate) { | 186 PrintSystem::PrintServerWatcher::Delegate* delegate) { |
186 delegate_ = delegate; | 187 delegate_ = delegate; |
187 printers_hash_ = GetPrintersHash(); | 188 printers_hash_ = GetPrintersHash(); |
188 MessageLoop::current()->PostDelayedTask(FROM_HERE, | 189 MessageLoop::current()->PostDelayedTask( |
189 NewRunnableMethod(this, &PrintServerWatcherCUPS::CheckForUpdates), | 190 FROM_HERE, |
| 191 base::Bind(&PrintServerWatcherCUPS::CheckForUpdates, this), |
190 print_system_->GetUpdateTimeoutMs()); | 192 print_system_->GetUpdateTimeoutMs()); |
191 return true; | 193 return true; |
192 } | 194 } |
193 virtual bool StopWatching() { | 195 virtual bool StopWatching() { |
194 delegate_ = NULL; | 196 delegate_ = NULL; |
195 return true; | 197 return true; |
196 } | 198 } |
197 | 199 |
198 void CheckForUpdates() { | 200 void CheckForUpdates() { |
199 if (delegate_ == NULL) | 201 if (delegate_ == NULL) |
200 return; // Orphan call. We have been stopped already. | 202 return; // Orphan call. We have been stopped already. |
201 VLOG(1) << "CP_CUPS: Checking for new printers"; | 203 VLOG(1) << "CP_CUPS: Checking for new printers"; |
202 std::string new_hash = GetPrintersHash(); | 204 std::string new_hash = GetPrintersHash(); |
203 if (printers_hash_ != new_hash) { | 205 if (printers_hash_ != new_hash) { |
204 printers_hash_ = new_hash; | 206 printers_hash_ = new_hash; |
205 delegate_->OnPrinterAdded(); | 207 delegate_->OnPrinterAdded(); |
206 } | 208 } |
207 MessageLoop::current()->PostDelayedTask(FROM_HERE, | 209 MessageLoop::current()->PostDelayedTask( |
208 NewRunnableMethod(this, &PrintServerWatcherCUPS::CheckForUpdates), | 210 FROM_HERE, |
| 211 base::Bind(&PrintServerWatcherCUPS::CheckForUpdates, this), |
209 print_system_->GetUpdateTimeoutMs()); | 212 print_system_->GetUpdateTimeoutMs()); |
210 } | 213 } |
211 private: | 214 private: |
212 std::string GetPrintersHash() { | 215 std::string GetPrintersHash() { |
213 printing::PrinterList printer_list; | 216 printing::PrinterList printer_list; |
214 print_system_->EnumeratePrinters(&printer_list); | 217 print_system_->EnumeratePrinters(&printer_list); |
215 | 218 |
216 // Sort printer names. | 219 // Sort printer names. |
217 std::vector<std::string> printers; | 220 std::vector<std::string> printers; |
218 printing::PrinterList::iterator it; | 221 printing::PrinterList::iterator it; |
(...skipping 28 matching lines...) Expand all Loading... |
247 } | 250 } |
248 | 251 |
249 // PrintSystem::PrinterWatcher interface | 252 // PrintSystem::PrinterWatcher interface |
250 virtual bool StartWatching( | 253 virtual bool StartWatching( |
251 PrintSystem::PrinterWatcher::Delegate* delegate) { | 254 PrintSystem::PrinterWatcher::Delegate* delegate) { |
252 if (delegate_ != NULL) | 255 if (delegate_ != NULL) |
253 StopWatching(); | 256 StopWatching(); |
254 delegate_ = delegate; | 257 delegate_ = delegate; |
255 settings_hash_ = GetSettingsHash(); | 258 settings_hash_ = GetSettingsHash(); |
256 // Schedule next job status update. | 259 // Schedule next job status update. |
257 MessageLoop::current()->PostDelayedTask(FROM_HERE, | 260 MessageLoop::current()->PostDelayedTask( |
258 NewRunnableMethod(this, &PrinterWatcherCUPS::JobStatusUpdate), | 261 FROM_HERE, |
| 262 base::Bind(&PrinterWatcherCUPS::JobStatusUpdate, this), |
259 kJobUpdateTimeoutMs); | 263 kJobUpdateTimeoutMs); |
260 // Schedule next printer check. | 264 // Schedule next printer check. |
261 // TODO(gene): Randomize time for the next printer update. | 265 // TODO(gene): Randomize time for the next printer update. |
262 MessageLoop::current()->PostDelayedTask(FROM_HERE, | 266 MessageLoop::current()->PostDelayedTask( |
263 NewRunnableMethod(this, &PrinterWatcherCUPS::PrinterUpdate), | 267 FROM_HERE, |
| 268 base::Bind(&PrinterWatcherCUPS::PrinterUpdate, this), |
264 print_system_->GetUpdateTimeoutMs()); | 269 print_system_->GetUpdateTimeoutMs()); |
265 return true; | 270 return true; |
266 } | 271 } |
267 virtual bool StopWatching() { | 272 virtual bool StopWatching() { |
268 delegate_ = NULL; | 273 delegate_ = NULL; |
269 return true; | 274 return true; |
270 } | 275 } |
271 bool GetCurrentPrinterInfo(printing::PrinterBasicInfo* printer_info) { | 276 bool GetCurrentPrinterInfo(printing::PrinterBasicInfo* printer_info) { |
272 DCHECK(printer_info); | 277 DCHECK(printer_info); |
273 return print_system_->GetPrinterInfo(printer_name_, printer_info); | 278 return print_system_->GetPrinterInfo(printer_name_, printer_info); |
274 } | 279 } |
275 | 280 |
276 void JobStatusUpdate() { | 281 void JobStatusUpdate() { |
277 if (delegate_ == NULL) | 282 if (delegate_ == NULL) |
278 return; // Orphan call. We have been stopped already. | 283 return; // Orphan call. We have been stopped already. |
279 // For CUPS proxy, we are going to fire OnJobChanged notification | 284 // For CUPS proxy, we are going to fire OnJobChanged notification |
280 // periodically. Higher level will check if there are any outstanding | 285 // periodically. Higher level will check if there are any outstanding |
281 // jobs for this printer and check their status. If printer has no | 286 // jobs for this printer and check their status. If printer has no |
282 // outstanding jobs, OnJobChanged() will do nothing. | 287 // outstanding jobs, OnJobChanged() will do nothing. |
283 delegate_->OnJobChanged(); | 288 delegate_->OnJobChanged(); |
284 MessageLoop::current()->PostDelayedTask(FROM_HERE, | 289 MessageLoop::current()->PostDelayedTask( |
285 NewRunnableMethod(this, &PrinterWatcherCUPS::JobStatusUpdate), | 290 FROM_HERE, |
| 291 base::Bind(&PrinterWatcherCUPS::JobStatusUpdate, this), |
286 kJobUpdateTimeoutMs); | 292 kJobUpdateTimeoutMs); |
287 } | 293 } |
288 | 294 |
289 void PrinterUpdate() { | 295 void PrinterUpdate() { |
290 if (delegate_ == NULL) | 296 if (delegate_ == NULL) |
291 return; // Orphan call. We have been stopped already. | 297 return; // Orphan call. We have been stopped already. |
292 VLOG(1) << "CP_CUPS: Checking for printer updates: " << printer_name_; | 298 VLOG(1) << "CP_CUPS: Checking for printer updates: " << printer_name_; |
293 if (print_system_->NotifyDelete() && | 299 if (print_system_->NotifyDelete() && |
294 !print_system_->IsValidPrinter(printer_name_)) { | 300 !print_system_->IsValidPrinter(printer_name_)) { |
295 delegate_->OnPrinterDeleted(); | 301 delegate_->OnPrinterDeleted(); |
296 VLOG(1) << "CP_CUPS: Printer deleted: " << printer_name_; | 302 VLOG(1) << "CP_CUPS: Printer deleted: " << printer_name_; |
297 } else { | 303 } else { |
298 std::string new_hash = GetSettingsHash(); | 304 std::string new_hash = GetSettingsHash(); |
299 if (settings_hash_ != new_hash) { | 305 if (settings_hash_ != new_hash) { |
300 settings_hash_ = new_hash; | 306 settings_hash_ = new_hash; |
301 delegate_->OnPrinterChanged(); | 307 delegate_->OnPrinterChanged(); |
302 VLOG(1) << "CP_CUPS: Printer update detected for: " << printer_name_; | 308 VLOG(1) << "CP_CUPS: Printer update detected for: " << printer_name_; |
303 } | 309 } |
304 } | 310 } |
305 MessageLoop::current()->PostDelayedTask(FROM_HERE, | 311 MessageLoop::current()->PostDelayedTask( |
306 NewRunnableMethod(this, &PrinterWatcherCUPS::PrinterUpdate), | 312 FROM_HERE, |
| 313 base::Bind(&PrinterWatcherCUPS::PrinterUpdate, this), |
307 print_system_->GetUpdateTimeoutMs()); | 314 print_system_->GetUpdateTimeoutMs()); |
308 } | 315 } |
309 private: | 316 private: |
310 std::string GetSettingsHash() { | 317 std::string GetSettingsHash() { |
311 printing::PrinterBasicInfo info; | 318 printing::PrinterBasicInfo info; |
312 if (!print_system_->GetPrinterInfo(printer_name_, &info)) | 319 if (!print_system_->GetPrinterInfo(printer_name_, &info)) |
313 return std::string(); | 320 return std::string(); |
314 | 321 |
315 printing::PrinterCapsAndDefaults caps; | 322 printing::PrinterCapsAndDefaults caps; |
316 if (!print_system_->GetPrinterCapsAndDefaults(printer_name_, &caps)) | 323 if (!print_system_->GetPrinterCapsAndDefaults(printer_name_, &caps)) |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
351 const std::string& print_data_mime_type, | 358 const std::string& print_data_mime_type, |
352 const std::string& printer_name, | 359 const std::string& printer_name, |
353 const std::string& job_title, | 360 const std::string& job_title, |
354 const std::vector<std::string>& tags, | 361 const std::vector<std::string>& tags, |
355 JobSpooler::Delegate* delegate) { | 362 JobSpooler::Delegate* delegate) { |
356 DCHECK(delegate); | 363 DCHECK(delegate); |
357 bool dry_run = false; | 364 bool dry_run = false; |
358 int job_id = print_system_->SpoolPrintJob( | 365 int job_id = print_system_->SpoolPrintJob( |
359 print_ticket, print_data_file_path, print_data_mime_type, | 366 print_ticket, print_data_file_path, print_data_mime_type, |
360 printer_name, job_title, tags, &dry_run); | 367 printer_name, job_title, tags, &dry_run); |
361 MessageLoop::current()->PostTask(FROM_HERE, | 368 MessageLoop::current()->PostTask( |
362 NewRunnableFunction( | 369 FROM_HERE, |
363 &JobSpoolerCUPS::NotifyDelegate, | 370 base::Bind(&JobSpoolerCUPS::NotifyDelegate, delegate, job_id, dry_run)); |
364 delegate, | |
365 job_id, | |
366 dry_run)); | |
367 return true; | 371 return true; |
368 } | 372 } |
369 | 373 |
370 static void NotifyDelegate(JobSpooler::Delegate* delegate, | 374 static void NotifyDelegate(JobSpooler::Delegate* delegate, |
371 int job_id, bool dry_run) { | 375 int job_id, bool dry_run) { |
372 if (dry_run || job_id) | 376 if (dry_run || job_id) |
373 delegate->OnJobSpoolSucceeded(job_id); | 377 delegate->OnJobSpoolSucceeded(job_id); |
374 else | 378 else |
375 delegate->OnJobSpoolFailed(); | 379 delegate->OnJobSpoolFailed(); |
376 } | 380 } |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
450 for (printer_it = it->printers.begin(); | 454 for (printer_it = it->printers.begin(); |
451 printer_it != it->printers.end(); ++printer_it) { | 455 printer_it != it->printers.end(); ++printer_it) { |
452 printer_it->printer_name = MakeFullPrinterName(it->url, | 456 printer_it->printer_name = MakeFullPrinterName(it->url, |
453 printer_it->printer_name); | 457 printer_it->printer_name); |
454 } | 458 } |
455 VLOG(1) << "CUPS: Updated printer list for url: " << it->url | 459 VLOG(1) << "CUPS: Updated printer list for url: " << it->url |
456 << " Number of printers: " << it->printers.size(); | 460 << " Number of printers: " << it->printers.size(); |
457 } | 461 } |
458 | 462 |
459 // Schedule next update. | 463 // Schedule next update. |
460 MessageLoop::current()->PostDelayedTask(FROM_HERE, | 464 MessageLoop::current()->PostDelayedTask( |
461 NewRunnableMethod(this, &PrintSystemCUPS::UpdatePrinters), | 465 FROM_HERE, |
462 GetUpdateTimeoutMs()); | 466 base::Bind(&PrintSystemCUPS::UpdatePrinters, this), GetUpdateTimeoutMs()); |
463 } | 467 } |
464 | 468 |
465 PrintSystem::PrintSystemResult PrintSystemCUPS::EnumeratePrinters( | 469 PrintSystem::PrintSystemResult PrintSystemCUPS::EnumeratePrinters( |
466 printing::PrinterList* printer_list) { | 470 printing::PrinterList* printer_list) { |
467 DCHECK(initialized_); | 471 DCHECK(initialized_); |
468 printer_list->clear(); | 472 printer_list->clear(); |
469 PrintServerList::iterator it; | 473 PrintServerList::iterator it; |
470 for (it = print_servers_.begin(); it != print_servers_.end(); ++it) { | 474 for (it = print_servers_.begin(); it != print_servers_.end(); ++it) { |
471 printer_list->insert(printer_list->end(), | 475 printer_list->insert(printer_list->end(), |
472 it->printers.begin(), it->printers.end()); | 476 it->printers.begin(), it->printers.end()); |
473 } | 477 } |
474 VLOG(1) << "CUPS: Total " << printer_list->size() << " printers enumerated."; | 478 VLOG(1) << "CUPS: Total " << printer_list->size() << " printers enumerated."; |
475 // TODO(sanjeevr): Maybe some day we want to report the actual server names | 479 // TODO(sanjeevr): Maybe some day we want to report the actual server names |
476 // for which the enumeration failed. | 480 // for which the enumeration failed. |
477 return PrintSystemResult(printer_enum_succeeded_, std::string()); | 481 return PrintSystemResult(printer_enum_succeeded_, std::string()); |
478 } | 482 } |
479 | 483 |
480 void PrintSystemCUPS::GetPrinterCapsAndDefaults( | 484 void PrintSystemCUPS::GetPrinterCapsAndDefaults( |
481 const std::string& printer_name, | 485 const std::string& printer_name, |
482 PrinterCapsAndDefaultsCallback* callback) { | 486 PrinterCapsAndDefaultsCallback* callback) { |
483 printing::PrinterCapsAndDefaults printer_info; | 487 printing::PrinterCapsAndDefaults printer_info; |
484 bool succeeded = GetPrinterCapsAndDefaults(printer_name, &printer_info); | 488 bool succeeded = GetPrinterCapsAndDefaults(printer_name, &printer_info); |
485 MessageLoop::current()->PostTask( | 489 MessageLoop::current()->PostTask( |
486 FROM_HERE, | 490 FROM_HERE, |
487 NewRunnableFunction(&PrintSystemCUPS::RunCapsCallback, | 491 base::Bind(&PrintSystemCUPS::RunCapsCallback, callback, succeeded, |
488 callback, | 492 printer_name, printer_info)); |
489 succeeded, | |
490 printer_name, | |
491 printer_info)); | |
492 } | 493 } |
493 | 494 |
494 bool PrintSystemCUPS::IsValidPrinter(const std::string& printer_name) { | 495 bool PrintSystemCUPS::IsValidPrinter(const std::string& printer_name) { |
495 return GetPrinterInfo(printer_name, NULL); | 496 return GetPrinterInfo(printer_name, NULL); |
496 } | 497 } |
497 | 498 |
498 bool PrintSystemCUPS::ValidatePrintTicket(const std::string& printer_name, | 499 bool PrintSystemCUPS::ValidatePrintTicket(const std::string& printer_name, |
499 const std::string& print_ticket_data) { | 500 const std::string& print_ticket_data) { |
500 DCHECK(initialized_); | 501 DCHECK(initialized_); |
501 scoped_ptr<Value> ticket_value(base::JSONReader::Read(print_ticket_data, | 502 scoped_ptr<Value> ticket_value(base::JSONReader::Read(print_ticket_data, |
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
811 void PrintSystemCUPS::RunCapsCallback( | 812 void PrintSystemCUPS::RunCapsCallback( |
812 PrinterCapsAndDefaultsCallback* callback, | 813 PrinterCapsAndDefaultsCallback* callback, |
813 bool succeeded, | 814 bool succeeded, |
814 const std::string& printer_name, | 815 const std::string& printer_name, |
815 const printing::PrinterCapsAndDefaults& printer_info) { | 816 const printing::PrinterCapsAndDefaults& printer_info) { |
816 callback->Run(succeeded, printer_name, printer_info); | 817 callback->Run(succeeded, printer_name, printer_info); |
817 delete callback; | 818 delete callback; |
818 } | 819 } |
819 | 820 |
820 } // namespace cloud_print | 821 } // namespace cloud_print |
OLD | NEW |