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/notification_service.h"
11#include "printing/printed_document.h"
12#include "printing/printed_page.h"
13
14namespace printing {
15
16PrintJobManager::PrintJobManager() {
17  registrar_.Add(this, chrome::NOTIFICATION_PRINT_JOB_EVENT,
18                 content::NotificationService::AllSources());
19}
20
21PrintJobManager::~PrintJobManager() {
22  base::AutoLock lock(lock_);
23  queued_queries_.clear();
24}
25
26void PrintJobManager::OnQuit() {
27  StopJobs(true);
28  registrar_.RemoveAll();
29}
30
31void PrintJobManager::StopJobs(bool wait_for_finish) {
32  // Copy the array since it can be modified in transit.
33  PrintJobs to_stop;
34  to_stop.swap(current_jobs_);
35
36  for (PrintJobs::const_iterator job = to_stop.begin(); job != to_stop.end();
37       ++job) {
38    // Wait for two minutes for the print job to be spooled.
39    if (wait_for_finish)
40      (*job)->FlushJob(base::TimeDelta::FromMinutes(2));
41    (*job)->Stop();
42  }
43}
44
45void PrintJobManager::SetPrintDestination(
46    PrintDestinationInterface* destination) {
47  destination_ = destination;
48}
49
50void PrintJobManager::QueuePrinterQuery(PrinterQuery* job) {
51  base::AutoLock lock(lock_);
52  DCHECK(job);
53  queued_queries_.push_back(make_scoped_refptr(job));
54  DCHECK(job->is_valid());
55}
56
57void PrintJobManager::PopPrinterQuery(int document_cookie,
58                                      scoped_refptr<PrinterQuery>* job) {
59  base::AutoLock lock(lock_);
60  for (PrinterQueries::iterator itr = queued_queries_.begin();
61       itr != queued_queries_.end();
62       ++itr) {
63    PrinterQuery* current_query = itr->get();
64    if (current_query->cookie() == document_cookie &&
65        !current_query->is_callback_pending()) {
66      *job = current_query;
67      queued_queries_.erase(itr);
68      DCHECK(current_query->is_valid());
69      return;
70    }
71  }
72}
73
74void PrintJobManager::Observe(int type,
75                              const content::NotificationSource& source,
76                              const content::NotificationDetails& details) {
77  switch (type) {
78    case chrome::NOTIFICATION_PRINT_JOB_EVENT: {
79      OnPrintJobEvent(content::Source<PrintJob>(source).ptr(),
80                      *content::Details<JobEventDetails>(details).ptr());
81      break;
82    }
83    default: {
84      NOTREACHED();
85      break;
86    }
87  }
88}
89
90void PrintJobManager::OnPrintJobEvent(
91    PrintJob* print_job,
92    const JobEventDetails& event_details) {
93  switch (event_details.type()) {
94    case JobEventDetails::NEW_DOC: {
95      DCHECK(current_jobs_.end() == current_jobs_.find(print_job));
96      // Causes a AddRef().
97      current_jobs_.insert(print_job);
98      break;
99    }
100    case JobEventDetails::JOB_DONE: {
101      DCHECK(current_jobs_.end() != current_jobs_.find(print_job));
102      current_jobs_.erase(print_job);
103      break;
104    }
105    case JobEventDetails::FAILED: {
106      current_jobs_.erase(print_job);
107      break;
108    }
109    case JobEventDetails::USER_INIT_DONE:
110    case JobEventDetails::USER_INIT_CANCELED:
111    case JobEventDetails::DEFAULT_INIT_DONE:
112    case JobEventDetails::NEW_PAGE:
113    case JobEventDetails::PAGE_DONE:
114    case JobEventDetails::DOC_DONE:
115    case JobEventDetails::ALL_PAGES_REQUESTED: {
116      // Don't care.
117      break;
118    }
119    default: {
120      NOTREACHED();
121      break;
122    }
123  }
124}
125
126}  // namespace printing
127