| 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 |