print_job_manager.cc 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  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.
  4. #include "chrome/browser/printing/print_job_manager.h"
  5. #include "chrome/browser/chrome_notification_types.h"
  6. #include "chrome/browser/printing/print_job.h"
  7. #include "chrome/browser/printing/printer_query.h"
  8. #include "content/public/browser/browser_thread.h"
  9. #include "content/public/browser/notification_service.h"
  10. #include "printing/printed_document.h"
  11. #include "printing/printed_page.h"
  12. namespace printing {
  13. PrintQueriesQueue::PrintQueriesQueue() {}
  14. PrintQueriesQueue::~PrintQueriesQueue() {
  15. base::AutoLock lock(lock_);
  16. queued_queries_.clear();
  17. }
  18. void PrintQueriesQueue::QueuePrinterQuery(PrinterQuery* job) {
  19. base::AutoLock lock(lock_);
  20. DCHECK(job);
  21. queued_queries_.push_back(WrapRefCounted(job));
  22. DCHECK(job->is_valid());
  23. }
  24. scoped_refptr<PrinterQuery> PrintQueriesQueue::PopPrinterQuery(
  25. int document_cookie) {
  26. base::AutoLock lock(lock_);
  27. for (PrinterQueries::iterator itr = queued_queries_.begin();
  28. itr != queued_queries_.end(); ++itr) {
  29. if ((*itr)->cookie() == document_cookie && !(*itr)->is_callback_pending()) {
  30. scoped_refptr<PrinterQuery> current_query(*itr);
  31. queued_queries_.erase(itr);
  32. DCHECK(current_query->is_valid());
  33. return current_query;
  34. }
  35. }
  36. return NULL;
  37. }
  38. scoped_refptr<PrinterQuery> PrintQueriesQueue::CreatePrinterQuery(
  39. int render_process_id,
  40. int render_frame_id) {
  41. return WrapRefCounted(new PrinterQuery(render_process_id, render_frame_id));
  42. }
  43. void PrintQueriesQueue::Shutdown() {
  44. PrinterQueries queries_to_stop;
  45. {
  46. base::AutoLock lock(lock_);
  47. queued_queries_.swap(queries_to_stop);
  48. }
  49. // Stop all pending queries, requests to generate print preview do not have
  50. // corresponding PrintJob, so any pending preview requests are not covered
  51. // by PrintJobManager::StopJobs and should be stopped explicitly.
  52. for (PrinterQueries::iterator itr = queries_to_stop.begin();
  53. itr != queries_to_stop.end(); ++itr) {
  54. (*itr)->PostTask(FROM_HERE, base::Bind(&PrinterQuery::StopWorker, *itr));
  55. }
  56. }
  57. PrintJobManager::PrintJobManager() : is_shutdown_(false) {
  58. registrar_.Add(this, chrome::NOTIFICATION_PRINT_JOB_EVENT,
  59. content::NotificationService::AllSources());
  60. }
  61. PrintJobManager::~PrintJobManager() {}
  62. scoped_refptr<PrintQueriesQueue> PrintJobManager::queue() {
  63. DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  64. if (!queue_.get())
  65. queue_ = new PrintQueriesQueue();
  66. return queue_;
  67. }
  68. void PrintJobManager::Shutdown() {
  69. DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  70. DCHECK(!is_shutdown_);
  71. is_shutdown_ = true;
  72. registrar_.RemoveAll();
  73. StopJobs(true);
  74. if (queue_.get())
  75. queue_->Shutdown();
  76. queue_ = NULL;
  77. }
  78. void PrintJobManager::StopJobs(bool wait_for_finish) {
  79. DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  80. // Copy the array since it can be modified in transit.
  81. PrintJobs to_stop;
  82. to_stop.swap(current_jobs_);
  83. for (PrintJobs::const_iterator job = to_stop.begin(); job != to_stop.end();
  84. ++job) {
  85. // Wait for two minutes for the print job to be spooled.
  86. if (wait_for_finish)
  87. (*job)->FlushJob(base::TimeDelta::FromMinutes(2));
  88. (*job)->Stop();
  89. }
  90. }
  91. void PrintJobManager::Observe(int type,
  92. const content::NotificationSource& source,
  93. const content::NotificationDetails& details) {
  94. DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  95. DCHECK_EQ(chrome::NOTIFICATION_PRINT_JOB_EVENT, type);
  96. OnPrintJobEvent(content::Source<PrintJob>(source).ptr(),
  97. *content::Details<JobEventDetails>(details).ptr());
  98. }
  99. void PrintJobManager::OnPrintJobEvent(PrintJob* print_job,
  100. const JobEventDetails& event_details) {
  101. switch (event_details.type()) {
  102. case JobEventDetails::NEW_DOC: {
  103. DCHECK(current_jobs_.end() == current_jobs_.find(print_job));
  104. // Causes a AddRef().
  105. current_jobs_.insert(print_job);
  106. break;
  107. }
  108. case JobEventDetails::JOB_DONE: {
  109. DCHECK(current_jobs_.end() != current_jobs_.find(print_job));
  110. current_jobs_.erase(print_job);
  111. break;
  112. }
  113. case JobEventDetails::FAILED: {
  114. current_jobs_.erase(print_job);
  115. break;
  116. }
  117. case JobEventDetails::USER_INIT_DONE:
  118. case JobEventDetails::USER_INIT_CANCELED:
  119. case JobEventDetails::DEFAULT_INIT_DONE:
  120. case JobEventDetails::NEW_PAGE:
  121. case JobEventDetails::PAGE_DONE:
  122. case JobEventDetails::DOC_DONE:
  123. case JobEventDetails::ALL_PAGES_REQUESTED: {
  124. // Don't care.
  125. break;
  126. }
  127. default: {
  128. NOTREACHED();
  129. break;
  130. }
  131. }
  132. }
  133. } // namespace printing