| Index: chrome/browser/chromeos/printing/cups_print_job_manager_impl.cc
|
| diff --git a/chrome/browser/chromeos/printing/cups_print_job_manager_impl.cc b/chrome/browser/chromeos/printing/cups_print_job_manager_impl.cc
|
| index 15df1907e77a75084a418b050532548f1f6f47ba..f6bcfc02904a761bf8f986027abe6636c2a6b7cb 100644
|
| --- a/chrome/browser/chromeos/printing/cups_print_job_manager_impl.cc
|
| +++ b/chrome/browser/chromeos/printing/cups_print_job_manager_impl.cc
|
| @@ -2,7 +2,7 @@
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| -#include "chrome/browser/chromeos/printing/cups_print_job_manager_impl.h"
|
| +#include "chrome/browser/chromeos/printing/cups_print_job_manager.h"
|
|
|
| #include <cups/cups.h>
|
| #include <algorithm>
|
| @@ -208,304 +208,353 @@ bool UpdatePrintJob(const ::printing::PrinterStatus& printer_status,
|
|
|
| namespace chromeos {
|
|
|
| -QueryResult::QueryResult() = default;
|
| +struct QueryResult {
|
| + QueryResult() = default;
|
| + QueryResult(const QueryResult& other) = default;
|
| + ~QueryResult() = default;
|
|
|
| -QueryResult::QueryResult(const QueryResult& other) = default;
|
| -
|
| -QueryResult::~QueryResult() = default;
|
| + bool success;
|
| + std::vector<::printing::QueueStatus> queues;
|
| +};
|
|
|
| -CupsWrapper::CupsWrapper()
|
| - : cups_connection_(GURL(), HTTP_ENCRYPT_NEVER, false) {
|
| - DETACH_FROM_SEQUENCE(sequence_checker_);
|
| -}
|
| +// A wrapper around the CUPS connection to ensure that it's always accessed on
|
| +// the same sequence.
|
| +class CupsWrapper {
|
| + public:
|
| + CupsWrapper() : cups_connection_(GURL(), HTTP_ENCRYPT_NEVER, false) {
|
| + DETACH_FROM_SEQUENCE(sequence_checker_);
|
| + }
|
|
|
| -CupsWrapper::~CupsWrapper() = default;
|
| + ~CupsWrapper() = default;
|
|
|
| -void CupsWrapper::QueryCups(const std::vector<std::string>& printer_ids,
|
| - QueryResult* result) {
|
| - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
| - base::ThreadRestrictions::AssertIOAllowed();
|
| + // Query CUPS for the current jobs for the given |printer_ids|. Writes result
|
| + // to |result|.
|
| + void QueryCups(const std::vector<std::string>& printer_ids,
|
| + QueryResult* result) {
|
| + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
| + base::ThreadRestrictions::AssertIOAllowed();
|
|
|
| - result->success = cups_connection_.GetJobs(printer_ids, &result->queues);
|
| -}
|
| + result->success = cups_connection_.GetJobs(printer_ids, &result->queues);
|
| + }
|
|
|
| -void CupsWrapper::CancelJobImpl(const std::string& printer_id,
|
| - const int job_id) {
|
| - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
| - base::ThreadRestrictions::AssertIOAllowed();
|
| + // Cancel the print job on the blocking thread.
|
| + void CancelJobImpl(const std::string& printer_id, const int job_id) {
|
| + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
| + base::ThreadRestrictions::AssertIOAllowed();
|
|
|
| - std::unique_ptr<::printing::CupsPrinter> printer =
|
| - cups_connection_.GetPrinter(printer_id);
|
| - if (!printer) {
|
| - LOG(WARNING) << "Printer not found: " << printer_id;
|
| - return;
|
| - }
|
| + std::unique_ptr<::printing::CupsPrinter> printer =
|
| + cups_connection_.GetPrinter(printer_id);
|
| + if (!printer) {
|
| + LOG(WARNING) << "Printer not found: " << printer_id;
|
| + return;
|
| + }
|
|
|
| - if (!printer->CancelJob(job_id)) {
|
| - // This is not expected to fail but log it if it does.
|
| - LOG(WARNING) << "Cancelling job failed. Job may be stuck in queue.";
|
| + if (!printer->CancelJob(job_id)) {
|
| + // This is not expected to fail but log it if it does.
|
| + LOG(WARNING) << "Cancelling job failed. Job may be stuck in queue.";
|
| + }
|
| }
|
| -}
|
|
|
| -CupsPrintJobManagerImpl::CupsPrintJobManagerImpl(Profile* profile)
|
| - : CupsPrintJobManager(profile),
|
| - query_runner_(base::CreateSequencedTaskRunnerWithTraits(
|
| - base::TaskTraits(base::TaskPriority::BACKGROUND,
|
| - base::MayBlock(),
|
| - base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN))),
|
| - cups_wrapper_(new CupsWrapper(),
|
| - base::OnTaskRunnerDeleter(query_runner_)),
|
| - weak_ptr_factory_(this) {
|
| - registrar_.Add(this, chrome::NOTIFICATION_PRINT_JOB_EVENT,
|
| - content::NotificationService::AllSources());
|
| -}
|
| -
|
| -CupsPrintJobManagerImpl::~CupsPrintJobManagerImpl() {}
|
| + private:
|
| + ::printing::CupsConnection cups_connection_;
|
| + SEQUENCE_CHECKER(sequence_checker_);
|
|
|
| -// Must be run from the UI thread.
|
| -void CupsPrintJobManagerImpl::CancelPrintJob(CupsPrintJob* job) {
|
| - DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| + DISALLOW_COPY_AND_ASSIGN(CupsWrapper);
|
| +};
|
|
|
| - // Copy job_id and printer_id. |job| is about to be freed.
|
| - const int job_id = job->job_id();
|
| - const std::string printer_id = job->printer().id();
|
| +class CupsPrintJobManagerImpl : public CupsPrintJobManager,
|
| + public content::NotificationObserver {
|
| + public:
|
| + explicit CupsPrintJobManagerImpl(Profile* profile)
|
| + : CupsPrintJobManager(profile),
|
| + query_runner_(base::CreateSequencedTaskRunnerWithTraits(
|
| + base::TaskTraits(base::TaskPriority::BACKGROUND,
|
| + base::MayBlock(),
|
| + base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN))),
|
| + cups_wrapper_(new CupsWrapper(),
|
| + base::OnTaskRunnerDeleter(query_runner_)),
|
| + weak_ptr_factory_(this) {
|
| + registrar_.Add(this, chrome::NOTIFICATION_PRINT_JOB_EVENT,
|
| + content::NotificationService::AllSources());
|
| + }
|
|
|
| - // Stop montioring jobs after we cancel them. The user no longer cares.
|
| - jobs_.erase(job->GetUniqueId());
|
| + ~CupsPrintJobManagerImpl() override = default;
|
|
|
| - query_runner_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&CupsWrapper::CancelJobImpl,
|
| - base::Unretained(cups_wrapper_.get()), printer_id, job_id));
|
| -}
|
| + // CupsPrintJobManager overrides:
|
| + // Must be run from the UI thread.
|
| + void CancelPrintJob(CupsPrintJob* job) override {
|
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
|
|
| -bool CupsPrintJobManagerImpl::SuspendPrintJob(CupsPrintJob* job) {
|
| - NOTREACHED() << "Pause printer is not implemented";
|
| - return false;
|
| -}
|
| + // Copy job_id and printer_id. |job| is about to be freed.
|
| + const int job_id = job->job_id();
|
| + const std::string printer_id = job->printer().id();
|
|
|
| -bool CupsPrintJobManagerImpl::ResumePrintJob(CupsPrintJob* job) {
|
| - NOTREACHED() << "Resume printer is not implemented";
|
| - return false;
|
| -}
|
| + // Stop montioring jobs after we cancel them. The user no longer cares.
|
| + jobs_.erase(job->GetUniqueId());
|
|
|
| -void CupsPrintJobManagerImpl::Observe(
|
| - int type,
|
| - const content::NotificationSource& source,
|
| - const content::NotificationDetails& details) {
|
| - DCHECK_EQ(chrome::NOTIFICATION_PRINT_JOB_EVENT, type);
|
| -
|
| - content::Details<::printing::JobEventDetails> job_details(details);
|
| -
|
| - // DOC_DONE occurs after the print job has been successfully sent to the
|
| - // spooler which is when we begin tracking the print queue.
|
| - if (job_details->type() == ::printing::JobEventDetails::DOC_DONE) {
|
| - const ::printing::PrintedDocument* document = job_details->document();
|
| - DCHECK(document);
|
| - CreatePrintJob(base::UTF16ToUTF8(document->settings().device_name()),
|
| - base::UTF16ToUTF8(document->settings().title()),
|
| - job_details->job_id(), document->page_count());
|
| + query_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&CupsWrapper::CancelJobImpl,
|
| + base::Unretained(cups_wrapper_.get()), printer_id, job_id));
|
| }
|
| -}
|
|
|
| -bool CupsPrintJobManagerImpl::CreatePrintJob(const std::string& printer_name,
|
| - const std::string& title,
|
| - int job_id,
|
| - int total_page_number) {
|
| - DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| -
|
| - auto printer =
|
| - PrintersManagerFactory::GetForBrowserContext(profile_)->GetPrinter(
|
| - printer_name);
|
| - if (!printer) {
|
| - LOG(WARNING) << "Printer was removed while job was in progress. It cannot "
|
| - "be tracked";
|
| + bool SuspendPrintJob(CupsPrintJob* job) override {
|
| + NOTREACHED() << "Pause printer is not implemented";
|
| return false;
|
| }
|
|
|
| - // Records the number of jobs we're currently tracking when a new job is
|
| - // started. This is equivalent to print queue size in the current
|
| - // implementation.
|
| - UMA_HISTOGRAM_EXACT_LINEAR("Printing.CUPS.PrintJobsQueued", jobs_.size(), 20);
|
| -
|
| - // Create a new print job.
|
| - auto cpj = base::MakeUnique<CupsPrintJob>(*printer, job_id, title,
|
| - total_page_number);
|
| - std::string key = cpj->GetUniqueId();
|
| - jobs_[key] = std::move(cpj);
|
| + bool ResumePrintJob(CupsPrintJob* job) override {
|
| + NOTREACHED() << "Resume printer is not implemented";
|
| + return false;
|
| + }
|
|
|
| - CupsPrintJob* job = jobs_[key].get();
|
| - NotifyJobCreated(job);
|
| + // NotificationObserver overrides:
|
| + void Observe(int type,
|
| + const content::NotificationSource& source,
|
| + const content::NotificationDetails& details) override {
|
| + DCHECK_EQ(chrome::NOTIFICATION_PRINT_JOB_EVENT, type);
|
| +
|
| + content::Details<::printing::JobEventDetails> job_details(details);
|
| +
|
| + // DOC_DONE occurs after the print job has been successfully sent to the
|
| + // spooler which is when we begin tracking the print queue.
|
| + if (job_details->type() == ::printing::JobEventDetails::DOC_DONE) {
|
| + const ::printing::PrintedDocument* document = job_details->document();
|
| + DCHECK(document);
|
| + CreatePrintJob(base::UTF16ToUTF8(document->settings().device_name()),
|
| + base::UTF16ToUTF8(document->settings().title()),
|
| + job_details->job_id(), document->page_count());
|
| + }
|
| + }
|
|
|
| - // Always start jobs in the waiting state.
|
| - job->set_state(CupsPrintJob::State::STATE_WAITING);
|
| - NotifyJobUpdated(job);
|
| + private:
|
| + // Begin monitoring a print job for a given |printer_name| with the given
|
| + // |title| with the pages |total_page_number|.
|
| + bool CreatePrintJob(const std::string& printer_name,
|
| + const std::string& title,
|
| + int job_id,
|
| + int total_page_number) {
|
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| +
|
| + auto printer =
|
| + PrintersManagerFactory::GetForBrowserContext(profile_)->GetPrinter(
|
| + printer_name);
|
| + if (!printer) {
|
| + LOG(WARNING)
|
| + << "Printer was removed while job was in progress. It cannot "
|
| + "be tracked";
|
| + return false;
|
| + }
|
|
|
| - ScheduleQuery(base::TimeDelta());
|
| + // Records the number of jobs we're currently tracking when a new job is
|
| + // started. This is equivalent to print queue size in the current
|
| + // implementation.
|
| + UMA_HISTOGRAM_EXACT_LINEAR("Printing.CUPS.PrintJobsQueued", jobs_.size(),
|
| + 20);
|
|
|
| - return true;
|
| -}
|
| + // Create a new print job.
|
| + auto cpj = base::MakeUnique<CupsPrintJob>(*printer, job_id, title,
|
| + total_page_number);
|
| + std::string key = cpj->GetUniqueId();
|
| + jobs_[key] = std::move(cpj);
|
|
|
| -void CupsPrintJobManagerImpl::ScheduleQuery() {
|
| - ScheduleQuery(base::TimeDelta::FromMilliseconds(kPollRate));
|
| -}
|
| + CupsPrintJob* job = jobs_[key].get();
|
| + NotifyJobCreated(job);
|
|
|
| -void CupsPrintJobManagerImpl::ScheduleQuery(const base::TimeDelta& delay) {
|
| - DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| + // Always start jobs in the waiting state.
|
| + job->set_state(CupsPrintJob::State::STATE_WAITING);
|
| + NotifyJobUpdated(job);
|
|
|
| - if (!in_query_) {
|
| - in_query_ = true;
|
| + ScheduleQuery(base::TimeDelta());
|
|
|
| - content::BrowserThread::PostDelayedTask(
|
| - content::BrowserThread::UI, FROM_HERE,
|
| - base::Bind(&CupsPrintJobManagerImpl::PostQuery,
|
| - weak_ptr_factory_.GetWeakPtr()),
|
| - delay);
|
| + return true;
|
| }
|
| -}
|
|
|
| -void CupsPrintJobManagerImpl::PostQuery() {
|
| - DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| -
|
| - // The set of active printers is expected to be small.
|
| - std::set<std::string> printer_ids;
|
| - for (const auto& entry : jobs_) {
|
| - printer_ids.insert(entry.second->printer().id());
|
| + // Schedule a query of CUPS for print job status with the default delay.
|
| + void ScheduleQuery() {
|
| + ScheduleQuery(base::TimeDelta::FromMilliseconds(kPollRate));
|
| }
|
| - std::vector<std::string> ids{printer_ids.begin(), printer_ids.end()};
|
| -
|
| - auto result = base::MakeUnique<QueryResult>();
|
| - QueryResult* result_ptr = result.get();
|
| - // Runs a query on |query_runner_| which will rejoin this sequnece on
|
| - // completion.
|
| - query_runner_->PostTaskAndReply(
|
| - FROM_HERE,
|
| - base::Bind(&CupsWrapper::QueryCups, base::Unretained(cups_wrapper_.get()),
|
| - ids, result_ptr),
|
| - base::Bind(&CupsPrintJobManagerImpl::UpdateJobs,
|
| - weak_ptr_factory_.GetWeakPtr(), base::Passed(&result)));
|
| -}
|
|
|
| -// Use job information to update local job states. Previously completed jobs
|
| -// could be in |jobs| but those are ignored as we will not emit updates for
|
| -// them after they are completed.
|
| -void CupsPrintJobManagerImpl::UpdateJobs(std::unique_ptr<QueryResult> result) {
|
| - DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| + // Schedule a query of CUPS for print job status with a delay of |delay|.
|
| + void ScheduleQuery(const base::TimeDelta& delay) {
|
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
|
|
| - const std::vector<::printing::QueueStatus>& queues = result->queues;
|
| + if (!in_query_) {
|
| + in_query_ = true;
|
|
|
| - // Query has completed. Allow more queries.
|
| - in_query_ = false;
|
| + content::BrowserThread::PostDelayedTask(
|
| + content::BrowserThread::UI, FROM_HERE,
|
| + base::Bind(&CupsPrintJobManagerImpl::PostQuery,
|
| + weak_ptr_factory_.GetWeakPtr()),
|
| + delay);
|
| + }
|
| + }
|
|
|
| - // If the query failed, either retry or purge.
|
| - if (!result->success) {
|
| - retry_count_++;
|
| - LOG(WARNING) << "Failed to query CUPS for queue status. Schedule retry ("
|
| - << retry_count_ << ")";
|
| - if (retry_count_ > kRetryMax) {
|
| - LOG(ERROR) << "CUPS is unreachable. Giving up on all jobs.";
|
| - PurgeJobs();
|
| - } else {
|
| - // Schedule another query with a larger delay.
|
| - DCHECK_GE(1, retry_count_);
|
| - ScheduleQuery(
|
| - base::TimeDelta::FromMilliseconds(kPollRate * retry_count_));
|
| + // Schedule the CUPS query off the UI thread. Posts results back to UI thread
|
| + // to UpdateJobs.
|
| + void PostQuery() {
|
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| +
|
| + // The set of active printers is expected to be small.
|
| + std::set<std::string> printer_ids;
|
| + for (const auto& entry : jobs_) {
|
| + printer_ids.insert(entry.second->printer().id());
|
| }
|
| - return;
|
| + std::vector<std::string> ids{printer_ids.begin(), printer_ids.end()};
|
| +
|
| + auto result = base::MakeUnique<QueryResult>();
|
| + QueryResult* result_ptr = result.get();
|
| + // Runs a query on |query_runner_| which will rejoin this sequnece on
|
| + // completion.
|
| + query_runner_->PostTaskAndReply(
|
| + FROM_HERE,
|
| + base::Bind(&CupsWrapper::QueryCups,
|
| + base::Unretained(cups_wrapper_.get()), ids, result_ptr),
|
| + base::Bind(&CupsPrintJobManagerImpl::UpdateJobs,
|
| + weak_ptr_factory_.GetWeakPtr(), base::Passed(&result)));
|
| }
|
|
|
| - // A query has completed. Reset retry counter.
|
| - retry_count_ = 0;
|
| + // Process jobs from CUPS and perform notifications.
|
| + // Use job information to update local job states. Previously completed jobs
|
| + // could be in |jobs| but those are ignored as we will not emit updates for
|
| + // them after they are completed.
|
| + void UpdateJobs(std::unique_ptr<QueryResult> result) {
|
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| +
|
| + const std::vector<::printing::QueueStatus>& queues = result->queues;
|
| +
|
| + // Query has completed. Allow more queries.
|
| + in_query_ = false;
|
| +
|
| + // If the query failed, either retry or purge.
|
| + if (!result->success) {
|
| + retry_count_++;
|
| + LOG(WARNING) << "Failed to query CUPS for queue status. Schedule retry ("
|
| + << retry_count_ << ")";
|
| + if (retry_count_ > kRetryMax) {
|
| + LOG(ERROR) << "CUPS is unreachable. Giving up on all jobs.";
|
| + PurgeJobs();
|
| + } else {
|
| + // Schedule another query with a larger delay.
|
| + DCHECK_GE(1, retry_count_);
|
| + ScheduleQuery(
|
| + base::TimeDelta::FromMilliseconds(kPollRate * retry_count_));
|
| + }
|
| + return;
|
| + }
|
| +
|
| + // A query has completed. Reset retry counter.
|
| + retry_count_ = 0;
|
|
|
| - std::vector<std::string> active_jobs;
|
| - for (const auto& queue : queues) {
|
| - for (auto& job : queue.jobs) {
|
| - std::string key = CupsPrintJob::GetUniqueId(job.printer_id, job.id);
|
| - const auto& entry = jobs_.find(key);
|
| - if (entry == jobs_.end())
|
| - continue;
|
| + std::vector<std::string> active_jobs;
|
| + for (const auto& queue : queues) {
|
| + for (auto& job : queue.jobs) {
|
| + std::string key = CupsPrintJob::GetUniqueId(job.printer_id, job.id);
|
| + const auto& entry = jobs_.find(key);
|
| + if (entry == jobs_.end())
|
| + continue;
|
|
|
| - CupsPrintJob* print_job = entry->second.get();
|
| + CupsPrintJob* print_job = entry->second.get();
|
|
|
| - if (UpdatePrintJob(queue.printer_status, job, print_job)) {
|
| - // The state of the job changed, notify observers.
|
| - NotifyJobStateUpdate(print_job);
|
| - }
|
| + if (UpdatePrintJob(queue.printer_status, job, print_job)) {
|
| + // The state of the job changed, notify observers.
|
| + NotifyJobStateUpdate(print_job);
|
| + }
|
|
|
| - if (print_job->expired()) {
|
| - // Job needs to be forcibly cancelled.
|
| - RecordJobResult(TIMEOUT_CANCEL);
|
| - CancelPrintJob(print_job);
|
| - // Beware, print_job was removed from jobs_ and deleted.
|
| - } else if (print_job->IsJobFinished()) {
|
| - // Cleanup completed jobs.
|
| - RecordJobResult(ResultForHistogram(print_job->state()));
|
| - jobs_.erase(entry);
|
| - } else {
|
| - active_jobs.push_back(key);
|
| + if (print_job->expired()) {
|
| + // Job needs to be forcibly cancelled.
|
| + RecordJobResult(TIMEOUT_CANCEL);
|
| + CancelPrintJob(print_job);
|
| + // Beware, print_job was removed from jobs_ and deleted.
|
| + } else if (print_job->IsJobFinished()) {
|
| + // Cleanup completed jobs.
|
| + RecordJobResult(ResultForHistogram(print_job->state()));
|
| + jobs_.erase(entry);
|
| + } else {
|
| + active_jobs.push_back(key);
|
| + }
|
| }
|
| }
|
| +
|
| + // Keep polling until all jobs complete or error.
|
| + if (!active_jobs.empty()) {
|
| + // During normal operations, we poll at the default rate.
|
| + ScheduleQuery();
|
| + } else if (!jobs_.empty()) {
|
| + // We're tracking jobs that we didn't receive an update for. Something
|
| + // bad has happened.
|
| + LOG(ERROR) << "Lost track of (" << jobs_.size() << ") jobs";
|
| + PurgeJobs();
|
| + }
|
| }
|
|
|
| - // Keep polling until all jobs complete or error.
|
| - if (!active_jobs.empty()) {
|
| - // During normal operations, we poll at the default rate.
|
| - ScheduleQuery();
|
| - } else if (!jobs_.empty()) {
|
| - // We're tracking jobs that we didn't receive an update for. Something
|
| - // bad has happened.
|
| - LOG(ERROR) << "Lost track of (" << jobs_.size() << ") jobs";
|
| - PurgeJobs();
|
| + // Mark remaining jobs as errors and remove active jobs.
|
| + void PurgeJobs() {
|
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| +
|
| + for (const auto& entry : jobs_) {
|
| + // Declare all lost jobs errors.
|
| + RecordJobResult(LOST);
|
| + CupsPrintJob* job = entry.second.get();
|
| + job->set_state(CupsPrintJob::State::STATE_ERROR);
|
| + NotifyJobStateUpdate(job);
|
| + }
|
| +
|
| + jobs_.clear();
|
| }
|
| -}
|
|
|
| -void CupsPrintJobManagerImpl::PurgeJobs() {
|
| - DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| + // Notify observers that a state update has occured for |job|.
|
| + void NotifyJobStateUpdate(CupsPrintJob* job) {
|
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
|
|
| - for (const auto& entry : jobs_) {
|
| - // Declare all lost jobs errors.
|
| - RecordJobResult(LOST);
|
| - CupsPrintJob* job = entry.second.get();
|
| - job->set_state(CupsPrintJob::State::STATE_ERROR);
|
| - NotifyJobStateUpdate(job);
|
| + switch (job->state()) {
|
| + case State::STATE_NONE:
|
| + // State does not require notification.
|
| + break;
|
| + case State::STATE_WAITING:
|
| + NotifyJobUpdated(job);
|
| + break;
|
| + case State::STATE_STARTED:
|
| + NotifyJobStarted(job);
|
| + break;
|
| + case State::STATE_PAGE_DONE:
|
| + NotifyJobUpdated(job);
|
| + break;
|
| + case State::STATE_RESUMED:
|
| + NotifyJobResumed(job);
|
| + break;
|
| + case State::STATE_SUSPENDED:
|
| + NotifyJobSuspended(job);
|
| + break;
|
| + case State::STATE_CANCELLED:
|
| + NotifyJobCanceled(job);
|
| + break;
|
| + case State::STATE_ERROR:
|
| + NotifyJobError(job);
|
| + break;
|
| + case State::STATE_DOCUMENT_DONE:
|
| + NotifyJobDone(job);
|
| + break;
|
| + }
|
| }
|
|
|
| - jobs_.clear();
|
| -}
|
| + // Ongoing print jobs.
|
| + std::map<std::string, std::unique_ptr<CupsPrintJob>> jobs_;
|
|
|
| -void CupsPrintJobManagerImpl::NotifyJobStateUpdate(CupsPrintJob* job) {
|
| - DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| + // Prevents multiple queries from being scheduled simultaneously.
|
| + bool in_query_ = false;
|
|
|
| - switch (job->state()) {
|
| - case State::STATE_NONE:
|
| - // State does not require notification.
|
| - break;
|
| - case State::STATE_WAITING:
|
| - NotifyJobUpdated(job);
|
| - break;
|
| - case State::STATE_STARTED:
|
| - NotifyJobStarted(job);
|
| - break;
|
| - case State::STATE_PAGE_DONE:
|
| - NotifyJobUpdated(job);
|
| - break;
|
| - case State::STATE_RESUMED:
|
| - NotifyJobResumed(job);
|
| - break;
|
| - case State::STATE_SUSPENDED:
|
| - NotifyJobSuspended(job);
|
| - break;
|
| - case State::STATE_CANCELLED:
|
| - NotifyJobCanceled(job);
|
| - break;
|
| - case State::STATE_ERROR:
|
| - NotifyJobError(job);
|
| - break;
|
| - case State::STATE_DOCUMENT_DONE:
|
| - NotifyJobDone(job);
|
| - break;
|
| - }
|
| -}
|
| + // Records the number of consecutive times the GetJobs query has failed.
|
| + int retry_count_ = 0;
|
| +
|
| + content::NotificationRegistrar registrar_;
|
| + // Task runner for queries to CUPS.
|
| + scoped_refptr<base::SequencedTaskRunner> query_runner_;
|
| + std::unique_ptr<CupsWrapper, base::OnTaskRunnerDeleter> cups_wrapper_;
|
| + base::WeakPtrFactory<CupsPrintJobManagerImpl> weak_ptr_factory_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(CupsPrintJobManagerImpl);
|
| +};
|
|
|
| // static
|
| CupsPrintJobManager* CupsPrintJobManager::CreateInstance(Profile* profile) {
|
|
|