• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
PrintQueriesQueue()17 PrintQueriesQueue::PrintQueriesQueue() {
18 }
19 
~PrintQueriesQueue()20 PrintQueriesQueue::~PrintQueriesQueue() {
21   base::AutoLock lock(lock_);
22   queued_queries_.clear();
23 }
24 
QueuePrinterQuery(PrinterQuery * job)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 
PopPrinterQuery(int document_cookie)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 
CreatePrinterQuery(int render_process_id,int render_view_id)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 
Shutdown()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 
PrintJobManager()70 PrintJobManager::PrintJobManager() : is_shutdown_(false) {
71   registrar_.Add(this, chrome::NOTIFICATION_PRINT_JOB_EVENT,
72                  content::NotificationService::AllSources());
73 }
74 
~PrintJobManager()75 PrintJobManager::~PrintJobManager() {
76 }
77 
queue()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 
Shutdown()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 
StopJobs(bool wait_for_finish)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 
Observe(int type,const content::NotificationSource & source,const content::NotificationDetails & details)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 
OnPrintJobEvent(PrintJob * print_job,const JobEventDetails & event_details)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