2014-08-21 07:38:20 +00:00
|
|
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file.
|
|
|
|
|
|
|
|
#include "chrome/browser/printing/print_job_manager.h"
|
|
|
|
|
|
|
|
#include "chrome/browser/chrome_notification_types.h"
|
|
|
|
#include "chrome/browser/printing/print_job.h"
|
|
|
|
#include "chrome/browser/printing/printer_query.h"
|
|
|
|
#include "content/public/browser/browser_thread.h"
|
|
|
|
#include "content/public/browser/notification_service.h"
|
|
|
|
#include "printing/printed_document.h"
|
|
|
|
#include "printing/printed_page.h"
|
|
|
|
|
|
|
|
namespace printing {
|
|
|
|
|
|
|
|
PrintQueriesQueue::PrintQueriesQueue() {
|
|
|
|
}
|
|
|
|
|
|
|
|
PrintQueriesQueue::~PrintQueriesQueue() {
|
|
|
|
base::AutoLock lock(lock_);
|
|
|
|
queued_queries_.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void PrintQueriesQueue::QueuePrinterQuery(PrinterQuery* job) {
|
|
|
|
base::AutoLock lock(lock_);
|
|
|
|
DCHECK(job);
|
|
|
|
queued_queries_.push_back(make_scoped_refptr(job));
|
|
|
|
DCHECK(job->is_valid());
|
|
|
|
}
|
|
|
|
|
|
|
|
scoped_refptr<PrinterQuery> PrintQueriesQueue::PopPrinterQuery(
|
|
|
|
int document_cookie) {
|
|
|
|
base::AutoLock lock(lock_);
|
|
|
|
for (PrinterQueries::iterator itr = queued_queries_.begin();
|
|
|
|
itr != queued_queries_.end(); ++itr) {
|
|
|
|
if ((*itr)->cookie() == document_cookie && !(*itr)->is_callback_pending()) {
|
2017-01-31 08:38:05 +00:00
|
|
|
scoped_refptr<PrinterQuery> current_query(*itr);
|
2014-08-21 07:38:20 +00:00
|
|
|
queued_queries_.erase(itr);
|
|
|
|
DCHECK(current_query->is_valid());
|
|
|
|
return current_query;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2014-12-07 14:55:40 +00:00
|
|
|
scoped_refptr<PrinterQuery> PrintQueriesQueue::CreatePrinterQuery(
|
|
|
|
int render_process_id,
|
2017-01-31 08:38:05 +00:00
|
|
|
int render_frame_id) {
|
|
|
|
return make_scoped_refptr(
|
|
|
|
new PrinterQuery(render_process_id, render_frame_id));
|
2014-08-21 07:38:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void PrintQueriesQueue::Shutdown() {
|
2014-12-07 14:55:40 +00:00
|
|
|
PrinterQueries queries_to_stop;
|
|
|
|
{
|
|
|
|
base::AutoLock lock(lock_);
|
|
|
|
queued_queries_.swap(queries_to_stop);
|
|
|
|
}
|
|
|
|
// Stop all pending queries, requests to generate print preview do not have
|
|
|
|
// corresponding PrintJob, so any pending preview requests are not covered
|
|
|
|
// by PrintJobManager::StopJobs and should be stopped explicitly.
|
|
|
|
for (PrinterQueries::iterator itr = queries_to_stop.begin();
|
|
|
|
itr != queries_to_stop.end(); ++itr) {
|
|
|
|
(*itr)->PostTask(FROM_HERE, base::Bind(&PrinterQuery::StopWorker, *itr));
|
|
|
|
}
|
2014-08-21 07:38:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
PrintJobManager::PrintJobManager() : is_shutdown_(false) {
|
|
|
|
registrar_.Add(this, chrome::NOTIFICATION_PRINT_JOB_EVENT,
|
|
|
|
content::NotificationService::AllSources());
|
|
|
|
}
|
|
|
|
|
|
|
|
PrintJobManager::~PrintJobManager() {
|
|
|
|
}
|
|
|
|
|
|
|
|
scoped_refptr<PrintQueriesQueue> PrintJobManager::queue() {
|
2017-01-31 08:38:05 +00:00
|
|
|
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
2014-12-07 14:55:40 +00:00
|
|
|
if (!queue_.get())
|
2014-08-21 07:38:20 +00:00
|
|
|
queue_ = new PrintQueriesQueue();
|
|
|
|
return queue_;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PrintJobManager::Shutdown() {
|
2017-01-31 08:38:05 +00:00
|
|
|
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
2014-08-21 07:38:20 +00:00
|
|
|
DCHECK(!is_shutdown_);
|
|
|
|
is_shutdown_ = true;
|
|
|
|
registrar_.RemoveAll();
|
|
|
|
StopJobs(true);
|
2014-12-07 14:55:40 +00:00
|
|
|
if (queue_.get())
|
2014-08-21 07:38:20 +00:00
|
|
|
queue_->Shutdown();
|
|
|
|
queue_ = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PrintJobManager::StopJobs(bool wait_for_finish) {
|
2017-01-31 08:38:05 +00:00
|
|
|
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
2014-08-21 07:38:20 +00:00
|
|
|
// Copy the array since it can be modified in transit.
|
|
|
|
PrintJobs to_stop;
|
|
|
|
to_stop.swap(current_jobs_);
|
|
|
|
|
|
|
|
for (PrintJobs::const_iterator job = to_stop.begin(); job != to_stop.end();
|
|
|
|
++job) {
|
|
|
|
// Wait for two minutes for the print job to be spooled.
|
|
|
|
if (wait_for_finish)
|
|
|
|
(*job)->FlushJob(base::TimeDelta::FromMinutes(2));
|
|
|
|
(*job)->Stop();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PrintJobManager::Observe(int type,
|
|
|
|
const content::NotificationSource& source,
|
|
|
|
const content::NotificationDetails& details) {
|
2017-01-31 08:38:05 +00:00
|
|
|
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
|
|
|
DCHECK_EQ(chrome::NOTIFICATION_PRINT_JOB_EVENT, type);
|
|
|
|
|
|
|
|
OnPrintJobEvent(content::Source<PrintJob>(source).ptr(),
|
|
|
|
*content::Details<JobEventDetails>(details).ptr());
|
2014-08-21 07:38:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void PrintJobManager::OnPrintJobEvent(
|
|
|
|
PrintJob* print_job,
|
|
|
|
const JobEventDetails& event_details) {
|
|
|
|
switch (event_details.type()) {
|
|
|
|
case JobEventDetails::NEW_DOC: {
|
|
|
|
DCHECK(current_jobs_.end() == current_jobs_.find(print_job));
|
|
|
|
// Causes a AddRef().
|
|
|
|
current_jobs_.insert(print_job);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case JobEventDetails::JOB_DONE: {
|
|
|
|
DCHECK(current_jobs_.end() != current_jobs_.find(print_job));
|
|
|
|
current_jobs_.erase(print_job);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case JobEventDetails::FAILED: {
|
|
|
|
current_jobs_.erase(print_job);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case JobEventDetails::USER_INIT_DONE:
|
|
|
|
case JobEventDetails::USER_INIT_CANCELED:
|
|
|
|
case JobEventDetails::DEFAULT_INIT_DONE:
|
|
|
|
case JobEventDetails::NEW_PAGE:
|
|
|
|
case JobEventDetails::PAGE_DONE:
|
|
|
|
case JobEventDetails::DOC_DONE:
|
|
|
|
case JobEventDetails::ALL_PAGES_REQUESTED: {
|
|
|
|
// Don't care.
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default: {
|
|
|
|
NOTREACHED();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace printing
|