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::SetDestination(PrintDestinationInterface* destination) {
     26   base::AutoLock lock(lock_);
     27   destination_ = destination;
     28 }
     29 
     30 void PrintQueriesQueue::QueuePrinterQuery(PrinterQuery* job) {
     31   base::AutoLock lock(lock_);
     32   DCHECK(job);
     33   queued_queries_.push_back(make_scoped_refptr(job));
     34   DCHECK(job->is_valid());
     35 }
     36 
     37 scoped_refptr<PrinterQuery> PrintQueriesQueue::PopPrinterQuery(
     38     int document_cookie) {
     39   base::AutoLock lock(lock_);
     40   for (PrinterQueries::iterator itr = queued_queries_.begin();
     41        itr != queued_queries_.end(); ++itr) {
     42     if ((*itr)->cookie() == document_cookie && !(*itr)->is_callback_pending()) {
     43       scoped_refptr<printing::PrinterQuery> current_query(*itr);
     44       queued_queries_.erase(itr);
     45       DCHECK(current_query->is_valid());
     46       return current_query;
     47     }
     48   }
     49   return NULL;
     50 }
     51 
     52 scoped_refptr<PrinterQuery> PrintQueriesQueue::CreatePrinterQuery() {
     53   scoped_refptr<PrinterQuery> job = new printing::PrinterQuery;
     54   base::AutoLock lock(lock_);
     55   job->SetWorkerDestination(destination_);
     56   return job;
     57 }
     58 
     59 void PrintQueriesQueue::Shutdown() {
     60   PrinterQueries queries_to_stop;
     61   {
     62     base::AutoLock lock(lock_);
     63     queued_queries_.swap(queries_to_stop);
     64     destination_ = NULL;
     65   }
     66   // Stop all pending queries, requests to generate print preview do not have
     67   // corresponding PrintJob, so any pending preview requests are not covered
     68   // by PrintJobManager::StopJobs and should be stopped explicitly.
     69   for (PrinterQueries::iterator itr = queries_to_stop.begin();
     70        itr != queries_to_stop.end(); ++itr) {
     71     (*itr)->message_loop()->PostTask(
     72         FROM_HERE, base::Bind(&PrinterQuery::StopWorker, *itr));
     73   }
     74 }
     75 
     76 PrintJobManager::PrintJobManager() : is_shutdown_(false) {
     77   registrar_.Add(this, chrome::NOTIFICATION_PRINT_JOB_EVENT,
     78                  content::NotificationService::AllSources());
     79 }
     80 
     81 PrintJobManager::~PrintJobManager() {
     82 }
     83 
     84 scoped_refptr<PrintQueriesQueue> PrintJobManager::queue() {
     85   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
     86   if (!queue_)
     87     queue_ = new PrintQueriesQueue();
     88   return queue_;
     89 }
     90 
     91 void PrintJobManager::Shutdown() {
     92   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
     93   DCHECK(!is_shutdown_);
     94   is_shutdown_ = true;
     95   registrar_.RemoveAll();
     96   StopJobs(true);
     97   if (queue_)
     98     queue_->Shutdown();
     99   queue_ = NULL;
    100 }
    101 
    102 void PrintJobManager::StopJobs(bool wait_for_finish) {
    103   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
    104   // Copy the array since it can be modified in transit.
    105   PrintJobs to_stop;
    106   to_stop.swap(current_jobs_);
    107 
    108   for (PrintJobs::const_iterator job = to_stop.begin(); job != to_stop.end();
    109        ++job) {
    110     // Wait for two minutes for the print job to be spooled.
    111     if (wait_for_finish)
    112       (*job)->FlushJob(base::TimeDelta::FromMinutes(2));
    113     (*job)->Stop();
    114   }
    115 }
    116 
    117 void PrintJobManager::Observe(int type,
    118                               const content::NotificationSource& source,
    119                               const content::NotificationDetails& details) {
    120   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
    121   switch (type) {
    122     case chrome::NOTIFICATION_PRINT_JOB_EVENT: {
    123       OnPrintJobEvent(content::Source<PrintJob>(source).ptr(),
    124                       *content::Details<JobEventDetails>(details).ptr());
    125       break;
    126     }
    127     default: {
    128       NOTREACHED();
    129       break;
    130     }
    131   }
    132 }
    133 
    134 void PrintJobManager::OnPrintJobEvent(
    135     PrintJob* print_job,
    136     const JobEventDetails& event_details) {
    137   switch (event_details.type()) {
    138     case JobEventDetails::NEW_DOC: {
    139       DCHECK(current_jobs_.end() == current_jobs_.find(print_job));
    140       // Causes a AddRef().
    141       current_jobs_.insert(print_job);
    142       break;
    143     }
    144     case JobEventDetails::JOB_DONE: {
    145       DCHECK(current_jobs_.end() != current_jobs_.find(print_job));
    146       current_jobs_.erase(print_job);
    147       break;
    148     }
    149     case JobEventDetails::FAILED: {
    150       current_jobs_.erase(print_job);
    151       break;
    152     }
    153     case JobEventDetails::USER_INIT_DONE:
    154     case JobEventDetails::USER_INIT_CANCELED:
    155     case JobEventDetails::DEFAULT_INIT_DONE:
    156     case JobEventDetails::NEW_PAGE:
    157     case JobEventDetails::PAGE_DONE:
    158     case JobEventDetails::DOC_DONE:
    159     case JobEventDetails::ALL_PAGES_REQUESTED: {
    160       // Don't care.
    161       break;
    162     }
    163     default: {
    164       NOTREACHED();
    165       break;
    166     }
    167   }
    168 }
    169 
    170 }  // namespace printing
    171