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 3 // found in the LICENSE file. 4 5 #include "chrome/browser/printing/print_job_manager.h" 6 7 #include "chrome/browser/browser_process.h" 8 #include "chrome/browser/prefs/pref_service.h" 9 #include "chrome/browser/printing/print_job.h" 10 #include "chrome/browser/printing/printer_query.h" 11 #include "chrome/common/pref_names.h" 12 #include "content/common/notification_service.h" 13 #include "printing/printed_document.h" 14 #include "printing/printed_page.h" 15 16 namespace printing { 17 18 PrintJobManager::PrintJobManager() { 19 registrar_.Add(this, NotificationType::PRINT_JOB_EVENT, 20 NotificationService::AllSources()); 21 } 22 23 PrintJobManager::~PrintJobManager() { 24 base::AutoLock lock(lock_); 25 queued_queries_.clear(); 26 } 27 28 void PrintJobManager::OnQuit() { 29 #if defined(OS_MACOSX) 30 // OnQuit is too late to try to wait for jobs on the Mac, since the runloop 31 // has already been torn down; instead, StopJobs(true) is called earlier in 32 // the shutdown process, and this is just here in case something sneaks 33 // in after that. 34 StopJobs(false); 35 #else 36 StopJobs(true); 37 #endif 38 registrar_.RemoveAll(); 39 } 40 41 void PrintJobManager::StopJobs(bool wait_for_finish) { 42 if (current_jobs_.empty()) 43 return; 44 { 45 // Copy the array since it can be modified in transit. 46 PrintJobs current_jobs(current_jobs_); 47 // Wait for each job to finish. 48 for (size_t i = 0; i < current_jobs.size(); ++i) { 49 PrintJob* job = current_jobs[i]; 50 if (!job) 51 continue; 52 // Wait for 120 seconds for the print job to be spooled. 53 if (wait_for_finish) 54 job->FlushJob(120000); 55 job->Stop(); 56 } 57 } 58 current_jobs_.clear(); 59 } 60 61 void PrintJobManager::QueuePrinterQuery(PrinterQuery* job) { 62 base::AutoLock lock(lock_); 63 DCHECK(job); 64 queued_queries_.push_back(make_scoped_refptr(job)); 65 DCHECK(job->is_valid()); 66 } 67 68 void PrintJobManager::PopPrinterQuery(int document_cookie, 69 scoped_refptr<PrinterQuery>* job) { 70 base::AutoLock lock(lock_); 71 for (PrinterQueries::iterator itr = queued_queries_.begin(); 72 itr != queued_queries_.end(); 73 ++itr) { 74 PrinterQuery* current_query = *itr; 75 if (current_query->cookie() == document_cookie && 76 !current_query->is_callback_pending()) { 77 *job = current_query; 78 queued_queries_.erase(itr); 79 DCHECK(current_query->is_valid()); 80 return; 81 } 82 } 83 } 84 85 86 void PrintJobManager::Observe(NotificationType type, 87 const NotificationSource& source, 88 const NotificationDetails& details) { 89 switch (type.value) { 90 case NotificationType::PRINT_JOB_EVENT: { 91 OnPrintJobEvent(Source<PrintJob>(source).ptr(), 92 *Details<JobEventDetails>(details).ptr()); 93 break; 94 } 95 case NotificationType::PREF_CHANGED: { 96 const std::string* pref_name = Details<std::string>(details).ptr(); 97 if (*pref_name == prefs::kPrintingEnabled) { 98 PrefService *local_state = g_browser_process->local_state(); 99 set_printing_enabled(local_state->GetBoolean(prefs::kPrintingEnabled)); 100 } 101 break; 102 } 103 default: { 104 NOTREACHED(); 105 break; 106 } 107 } 108 } 109 110 void PrintJobManager::OnPrintJobEvent( 111 PrintJob* print_job, 112 const JobEventDetails& event_details) { 113 switch (event_details.type()) { 114 case JobEventDetails::NEW_DOC: { 115 DCHECK(current_jobs_.end() == std::find(current_jobs_.begin(), 116 current_jobs_.end(), 117 print_job)); 118 // Causes a AddRef(). 119 current_jobs_.push_back(make_scoped_refptr(print_job)); 120 break; 121 } 122 case JobEventDetails::JOB_DONE: { 123 PrintJobs::iterator itr = std::find(current_jobs_.begin(), 124 current_jobs_.end(), 125 print_job); 126 DCHECK(current_jobs_.end() != itr); 127 current_jobs_.erase(itr); 128 DCHECK(current_jobs_.end() == std::find(current_jobs_.begin(), 129 current_jobs_.end(), 130 print_job)); 131 break; 132 } 133 case JobEventDetails::FAILED: { 134 PrintJobs::iterator itr = std::find(current_jobs_.begin(), 135 current_jobs_.end(), 136 print_job); 137 // A failed job may have never started. 138 if (current_jobs_.end() != itr) { 139 current_jobs_.erase(itr); 140 DCHECK(current_jobs_.end() == 141 std::find(current_jobs_.begin(), 142 current_jobs_.end(), 143 print_job)); 144 } 145 break; 146 } 147 case JobEventDetails::USER_INIT_DONE: 148 case JobEventDetails::USER_INIT_CANCELED: 149 case JobEventDetails::DEFAULT_INIT_DONE: 150 case JobEventDetails::NEW_PAGE: 151 case JobEventDetails::PAGE_DONE: 152 case JobEventDetails::DOC_DONE: 153 case JobEventDetails::ALL_PAGES_REQUESTED: { 154 // Don't care. 155 break; 156 } 157 default: { 158 NOTREACHED(); 159 break; 160 } 161 } 162 } 163 164 bool PrintJobManager::printing_enabled() { 165 base::AutoLock lock(enabled_lock_); 166 return printing_enabled_; 167 } 168 169 void PrintJobManager::set_printing_enabled(bool printing_enabled) { 170 base::AutoLock lock(enabled_lock_); 171 printing_enabled_ = printing_enabled; 172 } 173 174 } // namespace printing 175