| OLD | NEW |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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/browser/chromeos/printing/cups_print_job_manager_impl.h" | 5 #include "chrome/browser/chromeos/printing/cups_print_job_manager_impl.h" |
| 6 | 6 |
| 7 #include <cups/cups.h> | 7 #include <cups/cups.h> |
| 8 #include <algorithm> | 8 #include <algorithm> |
| 9 #include <set> | 9 #include <set> |
| 10 #include <string> | 10 #include <string> |
| 11 #include <utility> | 11 #include <utility> |
| 12 #include <vector> | 12 #include <vector> |
| 13 | 13 |
| 14 #include "base/bind.h" | 14 #include "base/bind.h" |
| 15 #include "base/memory/ptr_util.h" | 15 #include "base/memory/ptr_util.h" |
| 16 #include "base/metrics/histogram_macros.h" |
| 16 #include "base/stl_util.h" | 17 #include "base/stl_util.h" |
| 17 #include "base/strings/utf_string_conversions.h" | 18 #include "base/strings/utf_string_conversions.h" |
| 18 #include "base/threading/sequenced_task_runner_handle.h" | 19 #include "base/threading/sequenced_task_runner_handle.h" |
| 19 #include "base/threading/sequenced_worker_pool.h" | 20 #include "base/threading/sequenced_worker_pool.h" |
| 20 #include "chrome/browser/chrome_notification_types.h" | 21 #include "chrome/browser/chrome_notification_types.h" |
| 21 #include "chrome/browser/chromeos/printing/cups_print_job.h" | 22 #include "chrome/browser/chromeos/printing/cups_print_job.h" |
| 22 #include "chrome/browser/chromeos/printing/printers_manager.h" | 23 #include "chrome/browser/chromeos/printing/printers_manager.h" |
| 23 #include "chrome/browser/chromeos/printing/printers_manager_factory.h" | 24 #include "chrome/browser/chromeos/printing/printers_manager_factory.h" |
| 24 #include "chrome/browser/printing/print_job.h" | 25 #include "chrome/browser/printing/print_job.h" |
| 25 #include "chrome/browser/profiles/profile.h" | 26 #include "chrome/browser/profiles/profile.h" |
| (...skipping 13 matching lines...) Expand all Loading... |
| 39 const int kConnectingTimeout = 20; | 40 const int kConnectingTimeout = 20; |
| 40 | 41 |
| 41 // Threshold for giving up on communicating with CUPS. | 42 // Threshold for giving up on communicating with CUPS. |
| 42 const int kRetryMax = 6; | 43 const int kRetryMax = 6; |
| 43 | 44 |
| 44 using State = chromeos::CupsPrintJob::State; | 45 using State = chromeos::CupsPrintJob::State; |
| 45 using ErrorCode = chromeos::CupsPrintJob::ErrorCode; | 46 using ErrorCode = chromeos::CupsPrintJob::ErrorCode; |
| 46 | 47 |
| 47 using PrinterReason = printing::PrinterStatus::PrinterReason; | 48 using PrinterReason = printing::PrinterStatus::PrinterReason; |
| 48 | 49 |
| 50 // Enumeration of print job results for histograms. Do not modify! |
| 51 enum JobResultForHistogram { |
| 52 UNKNOWN = 0, // unidentified result |
| 53 FINISHED = 1, // successful completion of job |
| 54 TIMEOUT_CANCEL = 2, // cancelled due to timeout |
| 55 PRINTER_CANCEL = 3, // cancelled by printer |
| 56 LOST = 4, // final state never received |
| 57 RESULT_MAX |
| 58 }; |
| 59 |
| 60 // Returns the appropriate JobResultForHistogram for a given |state|. Only |
| 61 // FINISHED and PRINTER_CANCEL are derived from CupsPrintJob::State. |
| 62 JobResultForHistogram ResultForHistogram(State state) { |
| 63 switch (state) { |
| 64 case State::STATE_DOCUMENT_DONE: |
| 65 return FINISHED; |
| 66 case State::STATE_CANCELLED: |
| 67 return PRINTER_CANCEL; |
| 68 default: |
| 69 break; |
| 70 } |
| 71 |
| 72 return UNKNOWN; |
| 73 } |
| 74 |
| 75 void RecordJobResult(JobResultForHistogram result) { |
| 76 UMA_HISTOGRAM_ENUMERATION("Printing.CUPS.JobResult", TIMEOUT_CANCEL, |
| 77 RESULT_MAX); |
| 78 } |
| 79 |
| 49 // Returns the equivalient CupsPrintJob#State from a CupsJob#JobState. | 80 // Returns the equivalient CupsPrintJob#State from a CupsJob#JobState. |
| 50 chromeos::CupsPrintJob::State ConvertState(printing::CupsJob::JobState state) { | 81 chromeos::CupsPrintJob::State ConvertState(printing::CupsJob::JobState state) { |
| 51 switch (state) { | 82 switch (state) { |
| 52 case printing::CupsJob::PENDING: | 83 case printing::CupsJob::PENDING: |
| 53 return State::STATE_WAITING; | 84 return State::STATE_WAITING; |
| 54 case printing::CupsJob::HELD: | 85 case printing::CupsJob::HELD: |
| 55 return State::STATE_SUSPENDED; | 86 return State::STATE_SUSPENDED; |
| 56 case printing::CupsJob::PROCESSING: | 87 case printing::CupsJob::PROCESSING: |
| 57 return State::STATE_STARTED; | 88 return State::STATE_STARTED; |
| 58 case printing::CupsJob::CANCELED: | 89 case printing::CupsJob::CANCELED: |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 216 int total_page_number) { | 247 int total_page_number) { |
| 217 auto printer = | 248 auto printer = |
| 218 PrintersManagerFactory::GetForBrowserContext(profile_)->GetPrinter( | 249 PrintersManagerFactory::GetForBrowserContext(profile_)->GetPrinter( |
| 219 printer_name); | 250 printer_name); |
| 220 if (!printer) { | 251 if (!printer) { |
| 221 LOG(WARNING) << "Printer was removed while job was in progress. It cannot " | 252 LOG(WARNING) << "Printer was removed while job was in progress. It cannot " |
| 222 "be tracked"; | 253 "be tracked"; |
| 223 return false; | 254 return false; |
| 224 } | 255 } |
| 225 | 256 |
| 257 // Records the number of jobs we're currently tracking when a new job is |
| 258 // started. This is equivalent to print queue size in the current |
| 259 // implementation. |
| 260 UMA_HISTOGRAM_EXACT_LINEAR("Printing.CUPS.PrintJobsQueued", jobs_.size(), 20); |
| 261 |
| 226 // Create a new print job. | 262 // Create a new print job. |
| 227 auto cpj = base::MakeUnique<CupsPrintJob>(*printer, job_id, title, | 263 auto cpj = base::MakeUnique<CupsPrintJob>(*printer, job_id, title, |
| 228 total_page_number); | 264 total_page_number); |
| 229 std::string key = cpj->GetUniqueId(); | 265 std::string key = cpj->GetUniqueId(); |
| 230 jobs_[key] = std::move(cpj); | 266 jobs_[key] = std::move(cpj); |
| 231 | 267 |
| 232 CupsPrintJob* job = jobs_[key].get(); | 268 CupsPrintJob* job = jobs_[key].get(); |
| 233 NotifyJobCreated(job); | 269 NotifyJobCreated(job); |
| 234 | 270 |
| 235 // Always start jobs in the waiting state. | 271 // Always start jobs in the waiting state. |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 347 | 383 |
| 348 CupsPrintJob* print_job = entry->second.get(); | 384 CupsPrintJob* print_job = entry->second.get(); |
| 349 | 385 |
| 350 if (UpdatePrintJob(queue.printer_status, job, print_job)) { | 386 if (UpdatePrintJob(queue.printer_status, job, print_job)) { |
| 351 // The state of the job changed, notify observers. | 387 // The state of the job changed, notify observers. |
| 352 NotifyJobStateUpdate(print_job); | 388 NotifyJobStateUpdate(print_job); |
| 353 } | 389 } |
| 354 | 390 |
| 355 if (print_job->expired()) { | 391 if (print_job->expired()) { |
| 356 // Job needs to be forcibly cancelled. | 392 // Job needs to be forcibly cancelled. |
| 393 RecordJobResult(TIMEOUT_CANCEL); |
| 357 CancelPrintJob(print_job); | 394 CancelPrintJob(print_job); |
| 358 // Beware, print_job was removed from jobs_ and deleted. | 395 // Beware, print_job was removed from jobs_ and deleted. |
| 359 } else if (print_job->IsJobFinished()) { | 396 } else if (print_job->IsJobFinished()) { |
| 360 // Cleanup completed jobs. | 397 // Cleanup completed jobs. |
| 398 RecordJobResult(ResultForHistogram(print_job->state())); |
| 361 jobs_.erase(entry); | 399 jobs_.erase(entry); |
| 362 } else { | 400 } else { |
| 363 active_jobs.push_back(key); | 401 active_jobs.push_back(key); |
| 364 } | 402 } |
| 365 } | 403 } |
| 366 } | 404 } |
| 367 | 405 |
| 368 // Keep polling until all jobs complete or error. | 406 // Keep polling until all jobs complete or error. |
| 369 if (!active_jobs.empty()) { | 407 if (!active_jobs.empty()) { |
| 370 // During normal operations, we poll at the default rate. | 408 // During normal operations, we poll at the default rate. |
| 371 ScheduleQuery(); | 409 ScheduleQuery(); |
| 372 } else if (!jobs_.empty()) { | 410 } else if (!jobs_.empty()) { |
| 373 // We're tracking jobs that we didn't receive an update for. Something bad | 411 // We're tracking jobs that we didn't receive an update for. Something bad |
| 374 // has happened. | 412 // has happened. |
| 375 LOG(ERROR) << "Lost track of (" << jobs_.size() << ") jobs"; | 413 LOG(ERROR) << "Lost track of (" << jobs_.size() << ") jobs"; |
| 376 PurgeJobs(); | 414 PurgeJobs(); |
| 377 } | 415 } |
| 378 } | 416 } |
| 379 | 417 |
| 380 void CupsPrintJobManagerImpl::PurgeJobs() { | 418 void CupsPrintJobManagerImpl::PurgeJobs() { |
| 381 for (const auto& entry : jobs_) { | 419 for (const auto& entry : jobs_) { |
| 382 // Declare all lost jobs errors. | 420 // Declare all lost jobs errors. |
| 421 RecordJobResult(LOST); |
| 383 CupsPrintJob* job = entry.second.get(); | 422 CupsPrintJob* job = entry.second.get(); |
| 384 job->set_state(CupsPrintJob::State::STATE_ERROR); | 423 job->set_state(CupsPrintJob::State::STATE_ERROR); |
| 385 NotifyJobStateUpdate(job); | 424 NotifyJobStateUpdate(job); |
| 386 } | 425 } |
| 387 | 426 |
| 388 jobs_.clear(); | 427 jobs_.clear(); |
| 389 } | 428 } |
| 390 | 429 |
| 391 void CupsPrintJobManagerImpl::CancelJobImpl(const std::string& printer_id, | 430 void CupsPrintJobManagerImpl::CancelJobImpl(const std::string& printer_id, |
| 392 const int job_id) { | 431 const int job_id) { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 434 break; | 473 break; |
| 435 } | 474 } |
| 436 } | 475 } |
| 437 | 476 |
| 438 // static | 477 // static |
| 439 CupsPrintJobManager* CupsPrintJobManager::CreateInstance(Profile* profile) { | 478 CupsPrintJobManager* CupsPrintJobManager::CreateInstance(Profile* profile) { |
| 440 return new CupsPrintJobManagerImpl(profile); | 479 return new CupsPrintJobManagerImpl(profile); |
| 441 } | 480 } |
| 442 | 481 |
| 443 } // namespace chromeos | 482 } // namespace chromeos |
| OLD | NEW |