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