Avoid crashing when going back/forward to debug URLs on a sad WebUI tab.
[chromium-blink-merge.git] / chrome / service / cloud_print / printer_job_queue_handler.cc
blobe3a70b35e27b0a1706228b497b508364f5277526
1 // Copyright (c) 2013 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.
5 #include "chrome/service/cloud_print/printer_job_queue_handler.h"
7 #include <math.h>
9 #include <algorithm>
11 #include "base/values.h"
13 namespace cloud_print {
15 class TimeProviderImpl : public PrinterJobQueueHandler::TimeProvider {
16 public:
17 base::Time GetNow() override;
20 base::Time TimeProviderImpl::GetNow() {
21 return base::Time::Now();
24 JobDetails::JobDetails() {}
26 JobDetails::~JobDetails() {}
28 void JobDetails::Clear() {
29 job_id_.clear();
30 job_title_.clear();
31 job_owner_.clear();
32 print_ticket_.clear();
33 print_ticket_mime_type_.clear();
34 print_data_mime_type_.clear();
35 print_data_file_path_ = base::FilePath();
36 print_data_url_.clear();
37 print_ticket_url_.clear();
38 tags_.clear();
39 time_remaining_ = base::TimeDelta();
42 // static
43 bool JobDetails::ordering(const JobDetails& first, const JobDetails& second) {
44 return first.time_remaining_ < second.time_remaining_;
47 PrinterJobQueueHandler::PrinterJobQueueHandler(TimeProvider* time_provider)
48 : time_provider_(time_provider) {}
50 PrinterJobQueueHandler::PrinterJobQueueHandler()
51 : time_provider_(new TimeProviderImpl()) {}
53 PrinterJobQueueHandler::~PrinterJobQueueHandler() {}
55 void PrinterJobQueueHandler::ConstructJobDetailsFromJson(
56 const base::DictionaryValue* job_data,
57 JobDetails* job_details) {
58 job_details->Clear();
60 job_data->GetString(kIdValue, &job_details->job_id_);
61 job_data->GetString(kTitleValue, &job_details->job_title_);
62 job_data->GetString(kOwnerValue, &job_details->job_owner_);
64 job_data->GetString(kTicketUrlValue, &job_details->print_ticket_url_);
65 job_data->GetString(kFileUrlValue, &job_details->print_data_url_);
67 // Get tags for print job.
68 const base::ListValue* tags = NULL;
69 if (job_data->GetList(kTagsValue, &tags)) {
70 for (size_t i = 0; i < tags->GetSize(); i++) {
71 std::string value;
72 if (tags->GetString(i, &value))
73 job_details->tags_.push_back(value);
78 base::TimeDelta PrinterJobQueueHandler::ComputeBackoffTime(
79 const std::string& job_id) {
80 FailedJobMap::const_iterator job_location = failed_job_map_.find(job_id);
81 if (job_location == failed_job_map_.end()) {
82 return base::TimeDelta();
85 base::TimeDelta backoff_time =
86 base::TimeDelta::FromSeconds(kJobFirstWaitTimeSecs);
87 backoff_time *=
88 // casting argument to double and result to uint64 to avoid compilation
89 // issues
90 static_cast<int64>(pow(
91 static_cast<long double>(kJobWaitTimeExponentialMultiplier),
92 job_location->second.retries_) + 0.5);
93 base::Time scheduled_retry =
94 job_location->second.last_retry_ + backoff_time;
95 base::Time now = time_provider_->GetNow();
96 base::TimeDelta time_remaining;
98 if (scheduled_retry < now) {
99 return base::TimeDelta();
101 return scheduled_retry - now;
104 void PrinterJobQueueHandler::GetJobsFromQueue(
105 const base::DictionaryValue* json_data,
106 std::vector<JobDetails>* jobs) {
107 std::vector<JobDetails> jobs_with_timeouts;
109 jobs->clear();
111 const base::ListValue* job_list = NULL;
112 if (!json_data->GetList(kJobListValue, &job_list)) {
113 return;
116 size_t list_size = job_list->GetSize();
117 for (size_t cur_job = 0; cur_job < list_size; cur_job++) {
118 const base::DictionaryValue* job_data = NULL;
119 if (job_list->GetDictionary(cur_job, &job_data)) {
120 JobDetails job_details_current;
121 ConstructJobDetailsFromJson(job_data, &job_details_current);
123 job_details_current.time_remaining_ =
124 ComputeBackoffTime(job_details_current.job_id_);
126 if (job_details_current.time_remaining_ == base::TimeDelta()) {
127 jobs->push_back(job_details_current);
128 } else {
129 jobs_with_timeouts.push_back(job_details_current);
134 sort(jobs_with_timeouts.begin(), jobs_with_timeouts.end(),
135 &JobDetails::ordering);
136 jobs->insert(jobs->end(), jobs_with_timeouts.begin(),
137 jobs_with_timeouts.end());
140 void PrinterJobQueueHandler::JobDone(const std::string& job_id) {
141 failed_job_map_.erase(job_id);
144 bool PrinterJobQueueHandler::JobFetchFailed(const std::string& job_id) {
145 FailedJobMetadata metadata;
146 metadata.retries_ = 0;
147 metadata.last_retry_ = time_provider_->GetNow();
149 std::pair<FailedJobMap::iterator, bool> job_found =
150 failed_job_map_.insert(FailedJobPair(job_id, metadata));
152 // If the job has already failed once, increment the number of retries.
153 // If it has failed too many times, remove it from the map and tell the caller
154 // to report a failure.
155 if (!job_found.second) {
156 if (job_found.first->second.retries_ >= kNumRetriesBeforeAbandonJob) {
157 failed_job_map_.erase(job_found.first);
158 return false;
161 job_found.first->second.retries_ += 1;
162 job_found.first->second.last_retry_ = time_provider_->GetNow();
165 return true;
168 } // namespace cloud_print