Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(961)

Side by Side Diff: chrome/browser/chromeos/printing/cups_print_job_manager_impl.cc

Issue 2691093006: Implement IPP Get-Jobs and Get-Printer-Attributes requests. (Closed)
Patch Set: use a const array Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/browser/chromeos/printing/cups_print_job_manager_impl.h ('k') | printing/BUILD.gn » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/chromeos/printing/cups_print_job_manager_impl.h" 5 #include "chrome/browser/chromeos/printing/cups_print_job_manager_impl.h"
6 6
7 #include <cups/cups.h> 7 #include <cups/cups.h>
8 #include <set> 8 #include <set>
9 #include <string> 9 #include <string>
10 #include <utility> 10 #include <utility>
(...skipping 15 matching lines...) Expand all
26 #include "content/public/browser/notification_registrar.h" 26 #include "content/public/browser/notification_registrar.h"
27 #include "content/public/browser/notification_service.h" 27 #include "content/public/browser/notification_service.h"
28 #include "printing/backend/cups_connection.h" 28 #include "printing/backend/cups_connection.h"
29 #include "printing/printed_document.h" 29 #include "printing/printed_document.h"
30 30
31 namespace { 31 namespace {
32 32
33 // The rate in milliseconds at which we will poll CUPS for print job updates. 33 // The rate in milliseconds at which we will poll CUPS for print job updates.
34 const int kPollRate = 1000; 34 const int kPollRate = 1000;
35 35
36 // Threshold for giving up on communicating with CUPS.
37 const int kRetryMax = 6;
38
36 // Returns the equivalient CupsPrintJob#State from a CupsJob#JobState. 39 // Returns the equivalient CupsPrintJob#State from a CupsJob#JobState.
37 chromeos::CupsPrintJob::State ConvertState(printing::CupsJob::JobState state) { 40 chromeos::CupsPrintJob::State ConvertState(printing::CupsJob::JobState state) {
38 using cpj = chromeos::CupsPrintJob::State; 41 using cpj = chromeos::CupsPrintJob::State;
39 42
40 switch (state) { 43 switch (state) {
41 case printing::CupsJob::PENDING: 44 case printing::CupsJob::PENDING:
42 return cpj::STATE_WAITING; 45 return cpj::STATE_WAITING;
43 case printing::CupsJob::HELD: 46 case printing::CupsJob::HELD:
44 return cpj::STATE_SUSPENDED; 47 return cpj::STATE_SUSPENDED;
45 case printing::CupsJob::PROCESSING: 48 case printing::CupsJob::PROCESSING:
46 return cpj::STATE_STARTED; 49 return cpj::STATE_STARTED;
47 case printing::CupsJob::CANCELED: 50 case printing::CupsJob::CANCELED:
48 return cpj::STATE_CANCELLED; 51 return cpj::STATE_CANCELLED;
49 case printing::CupsJob::COMPLETED: 52 case printing::CupsJob::COMPLETED:
50 return cpj::STATE_DOCUMENT_DONE; 53 return cpj::STATE_DOCUMENT_DONE;
51 case printing::CupsJob::STOPPED: 54 case printing::CupsJob::STOPPED:
52 return cpj::STATE_SUSPENDED; 55 return cpj::STATE_SUSPENDED;
53 case printing::CupsJob::ABORTED: 56 case printing::CupsJob::ABORTED:
54 return cpj::STATE_ERROR; 57 return cpj::STATE_ERROR;
55 case printing::CupsJob::UNKNOWN: 58 case printing::CupsJob::UNKNOWN:
56 break; 59 break;
57 } 60 }
58 61
59 NOTREACHED(); 62 NOTREACHED();
60 63
61 return cpj::STATE_NONE; 64 return cpj::STATE_NONE;
62 } 65 }
63 66
67 chromeos::QueryResult QueryCups(::printing::CupsConnection* connection,
68 const std::vector<std::string>& printer_ids) {
69 chromeos::QueryResult result;
70 result.success = connection->GetJobs(printer_ids, &result.queues);
71 return result;
72 }
73
64 } // namespace 74 } // namespace
65 75
66 namespace chromeos { 76 namespace chromeos {
67 77
68 CupsPrintJobManagerImpl::CupsPrintJobManagerImpl(Profile* profile) 78 CupsPrintJobManagerImpl::CupsPrintJobManagerImpl(Profile* profile)
69 : CupsPrintJobManager(profile), 79 : CupsPrintJobManager(profile),
70 cups_connection_(GURL(), HTTP_ENCRYPT_NEVER, false), 80 cups_connection_(GURL(), HTTP_ENCRYPT_NEVER, false),
71 weak_ptr_factory_(this) { 81 weak_ptr_factory_(this) {
72 registrar_.Add(this, chrome::NOTIFICATION_PRINT_JOB_EVENT, 82 registrar_.Add(this, chrome::NOTIFICATION_PRINT_JOB_EVENT,
73 content::NotificationService::AllSources()); 83 content::NotificationService::AllSources());
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
127 LOG(WARNING) << "Printer was removed while job was in progress. It cannot " 137 LOG(WARNING) << "Printer was removed while job was in progress. It cannot "
128 "be tracked"; 138 "be tracked";
129 return false; 139 return false;
130 } 140 }
131 141
132 // Create a new print job. 142 // Create a new print job.
133 auto cpj = base::MakeUnique<CupsPrintJob>(*printer, job_id, title, 143 auto cpj = base::MakeUnique<CupsPrintJob>(*printer, job_id, title,
134 total_page_number); 144 total_page_number);
135 std::string key = cpj->GetUniqueId(); 145 std::string key = cpj->GetUniqueId();
136 jobs_[key] = std::move(cpj); 146 jobs_[key] = std::move(cpj);
147
137 CupsPrintJob* job = jobs_[key].get(); 148 CupsPrintJob* job = jobs_[key].get();
138 NotifyJobCreated(job); 149 NotifyJobCreated(job);
139 150
140 // Always start jobs in the waiting state. 151 // Always start jobs in the waiting state.
141 job->set_state(CupsPrintJob::State::STATE_WAITING); 152 job->set_state(CupsPrintJob::State::STATE_WAITING);
142 NotifyJobUpdated(job); 153 NotifyJobUpdated(job);
143 154
144 ScheduleQuery(base::TimeDelta()); 155 ScheduleQuery(base::TimeDelta());
145 156
146 return true; 157 return true;
147 } 158 }
148 159
149 void CupsPrintJobManagerImpl::ScheduleQuery() { 160 void CupsPrintJobManagerImpl::ScheduleQuery() {
150 ScheduleQuery(base::TimeDelta::FromMilliseconds(kPollRate)); 161 ScheduleQuery(base::TimeDelta::FromMilliseconds(kPollRate));
151 } 162 }
152 163
153 void CupsPrintJobManagerImpl::ScheduleQuery(const base::TimeDelta& delay) { 164 void CupsPrintJobManagerImpl::ScheduleQuery(const base::TimeDelta& delay) {
154 if (!in_query_) { 165 if (!in_query_) {
155 in_query_ = true; 166 in_query_ = true;
156 content::BrowserThread::PostDelayedTask( 167
157 content::BrowserThread::FILE_USER_BLOCKING, FROM_HERE, 168 base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
158 base::Bind(&CupsPrintJobManagerImpl::QueryCups, 169 FROM_HERE,
170 base::Bind(&CupsPrintJobManagerImpl::PostQuery,
159 weak_ptr_factory_.GetWeakPtr()), 171 weak_ptr_factory_.GetWeakPtr()),
160 base::TimeDelta::FromMilliseconds(kPollRate)); 172 delay);
161 } 173 }
162 } 174 }
163 175
164 // Query CUPS asynchronously. Post results back to UI thread. 176 void CupsPrintJobManagerImpl::PostQuery() {
165 void CupsPrintJobManagerImpl::QueryCups() { 177 // The set of active printers is expected to be small.
166 std::vector<::printing::CupsJob> jobs = cups_connection_.GetJobs(); 178 std::set<std::string> printer_ids;
179 for (const auto& entry : jobs_) {
180 printer_ids.insert(entry.second->printer().id());
181 }
182 std::vector<std::string> ids{printer_ids.begin(), printer_ids.end()};
167 183
168 content::BrowserThread::PostTask( 184 content::BrowserThread::PostTaskAndReplyWithResult(
169 content::BrowserThread::ID::UI, FROM_HERE, 185 content::BrowserThread::FILE_USER_BLOCKING, FROM_HERE,
186 base::Bind(&QueryCups, &cups_connection_, ids),
170 base::Bind(&CupsPrintJobManagerImpl::UpdateJobs, 187 base::Bind(&CupsPrintJobManagerImpl::UpdateJobs,
171 weak_ptr_factory_.GetWeakPtr(), jobs)); 188 weak_ptr_factory_.GetWeakPtr()));
172 } 189 }
173 190
174 // Use job information to update local job states. Previously completed jobs 191 // Use job information to update local job states. Previously completed jobs
175 // could be in |jobs| but those are ignored as we will not emit updates for them 192 // could be in |jobs| but those are ignored as we will not emit updates for them
176 // after they are completed. 193 // after they are completed.
177 void CupsPrintJobManagerImpl::UpdateJobs( 194 void CupsPrintJobManagerImpl::UpdateJobs(const QueryResult& result) {
178 const std::vector<::printing::CupsJob>& jobs) { 195 const std::vector<::printing::QueueStatus>& queues = result.queues;
196
197 // Query has completed. Allow more queries.
179 in_query_ = false; 198 in_query_ = false;
180 199
200 // If the query failed, either retry or purge.
201 if (!result.success) {
202 retry_count_++;
203 LOG(WARNING) << "Failed to query CUPS for queue status. Schedule retry ("
204 << retry_count_ << ")";
205 if (retry_count_ > kRetryMax) {
206 LOG(ERROR) << "CUPS is unreachable. Giving up on all jobs.";
207 PurgeJobs();
208 } else {
209 // Schedule another query with a larger delay.
210 DCHECK_GE(1, retry_count_);
211 ScheduleQuery(
212 base::TimeDelta::FromMilliseconds(kPollRate * retry_count_));
213 }
214 return;
215 }
216
217 // A query has completed. Reset retry counter.
218 retry_count_ = 0;
219
181 std::vector<std::string> active_jobs; 220 std::vector<std::string> active_jobs;
182 for (auto& job : jobs) { 221 for (const auto& queue : queues) {
183 std::string key = CupsPrintJob::GetUniqueId(job.printer_id, job.id); 222 for (auto& job : queue.jobs) {
184 const auto& entry = jobs_.find(key); 223 std::string key = CupsPrintJob::GetUniqueId(job.printer_id, job.id);
185 if (entry != jobs_.end()) { 224 const auto& entry = jobs_.find(key);
225 if (entry == jobs_.end())
226 continue;
227
186 CupsPrintJob* print_job = entry->second.get(); 228 CupsPrintJob* print_job = entry->second.get();
187 229
188 // Update a job we're tracking. 230 // Update a job we're tracking.
189 JobStateUpdated(print_job, ConvertState(job.state)); 231 JobStateUpdated(print_job, ConvertState(job.state));
190 232
191 // Cleanup completed jobs. 233 // Cleanup completed jobs.
192 if (print_job->IsJobFinished()) { 234 if (print_job->IsJobFinished()) {
193 jobs_.erase(entry); 235 jobs_.erase(entry);
194 } else { 236 } else {
195 active_jobs.push_back(key); 237 active_jobs.push_back(key);
196 } 238 }
197 } 239 }
198 } 240 }
199 241
200 // Keep polling until all jobs complete or error. 242 // Keep polling until all jobs complete or error.
201 if (!active_jobs.empty()) { 243 if (!active_jobs.empty()) {
244 // During normal operations, we poll at the default rate.
202 ScheduleQuery(); 245 ScheduleQuery();
203 } else if (!jobs_.empty()) { 246 } else if (!jobs_.empty()) {
204 // We're tracking jobs that we didn't receive an update for. Something bad 247 // We're tracking jobs that we didn't receive an update for. Something bad
205 // has happened. 248 // has happened.
206 LOG(ERROR) << "Lost track of (" << jobs_.size() << ") jobs"; 249 LOG(ERROR) << "Lost track of (" << jobs_.size() << ") jobs";
207 for (const auto& entry : jobs_) { 250 PurgeJobs();
208 // Declare all lost jobs errors.
209 JobStateUpdated(entry.second.get(), CupsPrintJob::State::STATE_ERROR);
210 }
211
212 jobs_.clear();
213 } 251 }
214 } 252 }
215 253
254 void CupsPrintJobManagerImpl::PurgeJobs() {
255 for (const auto& entry : jobs_) {
256 // Declare all lost jobs errors.
257 JobStateUpdated(entry.second.get(), CupsPrintJob::State::STATE_ERROR);
258 }
259
260 jobs_.clear();
261 }
262
216 void CupsPrintJobManagerImpl::JobStateUpdated(CupsPrintJob* job, 263 void CupsPrintJobManagerImpl::JobStateUpdated(CupsPrintJob* job,
217 CupsPrintJob::State new_state) { 264 CupsPrintJob::State new_state) {
218 if (job->state() == new_state) 265 if (job->state() == new_state)
219 return; 266 return;
220 267
221 // We don't track state transitions because some of them might be missed due 268 // We don't track state transitions because some of them might be missed due
222 // to how we query jobs. 269 // to how we query jobs.
223 job->set_state(new_state); 270 job->set_state(new_state);
224 switch (new_state) { 271 switch (new_state) {
225 case CupsPrintJob::State::STATE_NONE: 272 case CupsPrintJob::State::STATE_NONE:
(...skipping 25 matching lines...) Expand all
251 break; 298 break;
252 } 299 }
253 } 300 }
254 301
255 // static 302 // static
256 CupsPrintJobManager* CupsPrintJobManager::CreateInstance(Profile* profile) { 303 CupsPrintJobManager* CupsPrintJobManager::CreateInstance(Profile* profile) {
257 return new CupsPrintJobManagerImpl(profile); 304 return new CupsPrintJobManagerImpl(profile);
258 } 305 }
259 306
260 } // namespace chromeos 307 } // namespace chromeos
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/printing/cups_print_job_manager_impl.h ('k') | printing/BUILD.gn » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698