print_job_manager.cc revision d0247b1b59f9c528cb6df88b4f2b9afaf80d181e
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
15namespace printing {
16
17PrintQueriesQueue::PrintQueriesQueue() {
18}
19
20PrintQueriesQueue::~PrintQueriesQueue() {
21  base::AutoLock lock(lock_);
22  queued_queries_.clear();
23}
24
25void PrintQueriesQueue::SetDestination(PrintDestinationInterface* destination) {
26  base::AutoLock lock(lock_);
27  destination_ = destination;
28}
29
30void 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
37scoped_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
52scoped_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
59void PrintQueriesQueue::Shutdown() {
60  base::AutoLock lock(lock_);
61  queued_queries_.clear();
62  destination_ = NULL;
63}
64
65PrintJobManager::PrintJobManager() : is_shutdown_(false) {
66  registrar_.Add(this, chrome::NOTIFICATION_PRINT_JOB_EVENT,
67                 content::NotificationService::AllSources());
68}
69
70PrintJobManager::~PrintJobManager() {
71}
72
73scoped_refptr<PrintQueriesQueue> PrintJobManager::queue() {
74  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
75  if (!queue_)
76    queue_ = new PrintQueriesQueue();
77  return queue_;
78}
79
80void PrintJobManager::Shutdown() {
81  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
82  DCHECK(!is_shutdown_);
83  is_shutdown_ = true;
84  registrar_.RemoveAll();
85  StopJobs(true);
86  if (queue_)
87    queue_->Shutdown();
88  queue_ = NULL;
89}
90
91void PrintJobManager::StopJobs(bool wait_for_finish) {
92  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
93  // Copy the array since it can be modified in transit.
94  PrintJobs to_stop;
95  to_stop.swap(current_jobs_);
96
97  for (PrintJobs::const_iterator job = to_stop.begin(); job != to_stop.end();
98       ++job) {
99    // Wait for two minutes for the print job to be spooled.
100    if (wait_for_finish)
101      (*job)->FlushJob(base::TimeDelta::FromMinutes(2));
102    (*job)->Stop();
103  }
104}
105
106void PrintJobManager::Observe(int type,
107                              const content::NotificationSource& source,
108                              const content::NotificationDetails& details) {
109  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
110  switch (type) {
111    case chrome::NOTIFICATION_PRINT_JOB_EVENT: {
112      OnPrintJobEvent(content::Source<PrintJob>(source).ptr(),
113                      *content::Details<JobEventDetails>(details).ptr());
114      break;
115    }
116    default: {
117      NOTREACHED();
118      break;
119    }
120  }
121}
122
123void PrintJobManager::OnPrintJobEvent(
124    PrintJob* print_job,
125    const JobEventDetails& event_details) {
126  switch (event_details.type()) {
127    case JobEventDetails::NEW_DOC: {
128      DCHECK(current_jobs_.end() == current_jobs_.find(print_job));
129      // Causes a AddRef().
130      current_jobs_.insert(print_job);
131      break;
132    }
133    case JobEventDetails::JOB_DONE: {
134      DCHECK(current_jobs_.end() != current_jobs_.find(print_job));
135      current_jobs_.erase(print_job);
136      break;
137    }
138    case JobEventDetails::FAILED: {
139      current_jobs_.erase(print_job);
140      break;
141    }
142    case JobEventDetails::USER_INIT_DONE:
143    case JobEventDetails::USER_INIT_CANCELED:
144    case JobEventDetails::DEFAULT_INIT_DONE:
145    case JobEventDetails::NEW_PAGE:
146    case JobEventDetails::PAGE_DONE:
147    case JobEventDetails::DOC_DONE:
148    case JobEventDetails::ALL_PAGES_REQUESTED: {
149      // Don't care.
150      break;
151    }
152    default: {
153      NOTREACHED();
154      break;
155    }
156  }
157}
158
159}  // namespace printing
160