Home | History | Annotate | Download | only in printing
      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