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

Side by Side Diff: chrome/service/cloud_print/printer_job_handler.cc

Issue 4165013: Re-landing issue 4202006 (http://codereview.chromium.org/4202006/show) which ... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 10 years, 1 month 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 | Annotate | Revision Log
« no previous file with comments | « chrome/service/cloud_print/printer_job_handler.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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/service/cloud_print/printer_job_handler.h" 5 #include "chrome/service/cloud_print/printer_job_handler.h"
6 6
7 #include "base/file_util.h" 7 #include "base/file_util.h"
8 #include "base/json/json_reader.h" 8 #include "base/json/json_reader.h"
9 #include "base/md5.h" 9 #include "base/md5.h"
10 #include "base/string_util.h" 10 #include "base/string_util.h"
(...skipping 13 matching lines...) Expand all
24 const GURL& cloud_print_server_url, 24 const GURL& cloud_print_server_url,
25 cloud_print::PrintSystem* print_system, 25 cloud_print::PrintSystem* print_system,
26 Delegate* delegate) 26 Delegate* delegate)
27 : print_system_(print_system), 27 : print_system_(print_system),
28 printer_info_(printer_info), 28 printer_info_(printer_info),
29 printer_info_cloud_(printer_info_cloud), 29 printer_info_cloud_(printer_info_cloud),
30 auth_token_(auth_token), 30 auth_token_(auth_token),
31 cloud_print_server_url_(cloud_print_server_url), 31 cloud_print_server_url_(cloud_print_server_url),
32 delegate_(delegate), 32 delegate_(delegate),
33 local_job_id_(-1), 33 local_job_id_(-1),
34 next_response_handler_(NULL), 34 next_json_data_handler_(NULL),
35 next_failure_handler_(NULL), 35 next_data_handler_(NULL),
36 server_error_count_(0), 36 server_error_count_(0),
37 print_thread_("Chrome_CloudPrintJobPrintThread"), 37 print_thread_("Chrome_CloudPrintJobPrintThread"),
38 job_handler_message_loop_proxy_( 38 job_handler_message_loop_proxy_(
39 base::MessageLoopProxy::CreateForCurrentThread()), 39 base::MessageLoopProxy::CreateForCurrentThread()),
40 shutting_down_(false), 40 shutting_down_(false),
41 server_job_available_(false), 41 server_job_available_(false),
42 printer_update_pending_(true), 42 printer_update_pending_(true),
43 printer_delete_pending_(false), 43 printer_delete_pending_(false),
44 task_in_progress_(false) { 44 task_in_progress_(false) {
45 } 45 }
(...skipping 13 matching lines...) Expand all
59 } 59 }
60 60
61 PrinterJobHandler::~PrinterJobHandler() { 61 PrinterJobHandler::~PrinterJobHandler() {
62 if (printer_watcher_) 62 if (printer_watcher_)
63 printer_watcher_->StopWatching(); 63 printer_watcher_->StopWatching();
64 } 64 }
65 65
66 void PrinterJobHandler::Reset() { 66 void PrinterJobHandler::Reset() {
67 print_data_url_.clear(); 67 print_data_url_.clear();
68 job_details_.Clear(); 68 job_details_.Clear();
69 request_.reset(); 69 request_ = NULL;
70 print_thread_.Stop(); 70 print_thread_.Stop();
71 } 71 }
72 72
73 void PrinterJobHandler::Start() { 73 void PrinterJobHandler::Start() {
74 VLOG(1) << "CP_PROXY: Start printer job handler, id: " 74 VLOG(1) << "CP_PROXY: Start printer job handler, id: "
75 << printer_info_cloud_.printer_id 75 << printer_info_cloud_.printer_id
76 << ", task in progress: " << task_in_progress_; 76 << ", task in progress: " << task_in_progress_;
77 if (task_in_progress_) { 77 if (task_in_progress_) {
78 // Multiple Starts can get posted because of multiple notifications 78 // Multiple Starts can get posted because of multiple notifications
79 // We want to ignore the other ones that happen when a task is in progress. 79 // We want to ignore the other ones that happen when a task is in progress.
80 return; 80 return;
81 } 81 }
82 Reset(); 82 Reset();
83 if (!shutting_down_) { 83 if (!shutting_down_) {
84 // Check if we have work to do. 84 // Check if we have work to do.
85 if (HavePendingTasks()) { 85 if (HavePendingTasks()) {
86 if (printer_delete_pending_) { 86 if (printer_delete_pending_) {
87 printer_delete_pending_ = false; 87 printer_delete_pending_ = false;
88 task_in_progress_ = true; 88 task_in_progress_ = true;
89 MakeServerRequest( 89 SetNextJSONHandler(&PrinterJobHandler::HandlePrinterDeleteResponse);
90 request_ = new CloudPrintURLFetcher;
91 request_->StartGetRequest(
90 CloudPrintHelpers::GetUrlForPrinterDelete( 92 CloudPrintHelpers::GetUrlForPrinterDelete(
91 cloud_print_server_url_, printer_info_cloud_.printer_id), 93 cloud_print_server_url_, printer_info_cloud_.printer_id),
92 &PrinterJobHandler::HandlePrinterDeleteResponse, 94 this, auth_token_, kCloudPrintAPIRetryPolicy);
93 &PrinterJobHandler::Stop);
94 } 95 }
95 if (!task_in_progress_ && printer_update_pending_) { 96 if (!task_in_progress_ && printer_update_pending_) {
96 printer_update_pending_ = false; 97 printer_update_pending_ = false;
97 task_in_progress_ = UpdatePrinterInfo(); 98 task_in_progress_ = UpdatePrinterInfo();
98 } 99 }
99 if (!task_in_progress_ && server_job_available_) { 100 if (!task_in_progress_ && server_job_available_) {
100 task_in_progress_ = true; 101 task_in_progress_ = true;
101 server_job_available_ = false; 102 server_job_available_ = false;
102 // We need to fetch any pending jobs for this printer 103 // We need to fetch any pending jobs for this printer
103 MakeServerRequest( 104 SetNextJSONHandler(&PrinterJobHandler::HandleJobMetadataResponse);
105 request_ = new CloudPrintURLFetcher;
106 request_->StartGetRequest(
104 CloudPrintHelpers::GetUrlForJobFetch( 107 CloudPrintHelpers::GetUrlForJobFetch(
105 cloud_print_server_url_, printer_info_cloud_.printer_id), 108 cloud_print_server_url_, printer_info_cloud_.printer_id),
106 &PrinterJobHandler::HandleJobMetadataResponse, 109 this, auth_token_, kCloudPrintAPIRetryPolicy);
107 &PrinterJobHandler::Stop);
108 } 110 }
109 } 111 }
110 } 112 }
111 } 113 }
112 114
113 void PrinterJobHandler::Stop() { 115 void PrinterJobHandler::Stop() {
114 VLOG(1) << "CP_PROXY: Stop printer job handler, id: " 116 VLOG(1) << "CP_PROXY: Stop printer job handler, id: "
115 << printer_info_cloud_.printer_id; 117 << printer_info_cloud_.printer_id;
116 task_in_progress_ = false; 118 task_in_progress_ = false;
117 Reset(); 119 Reset();
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 kPrinterStatusValue, StringPrintf("%d", printer_info.printer_status), 194 kPrinterStatusValue, StringPrintf("%d", printer_info.printer_status),
193 mime_boundary, std::string(), &post_data); 195 mime_boundary, std::string(), &post_data);
194 } 196 }
195 printer_info_ = printer_info; 197 printer_info_ = printer_info;
196 bool ret = false; 198 bool ret = false;
197 if (!post_data.empty()) { 199 if (!post_data.empty()) {
198 // Terminate the request body 200 // Terminate the request body
199 post_data.append("--" + mime_boundary + "--\r\n"); 201 post_data.append("--" + mime_boundary + "--\r\n");
200 std::string mime_type("multipart/form-data; boundary="); 202 std::string mime_type("multipart/form-data; boundary=");
201 mime_type += mime_boundary; 203 mime_type += mime_boundary;
202 request_.reset( 204 SetNextJSONHandler(&PrinterJobHandler::HandlePrinterUpdateResponse);
203 new URLFetcher(CloudPrintHelpers::GetUrlForPrinterUpdate( 205 request_ = new CloudPrintURLFetcher;
204 cloud_print_server_url_, 206 request_->StartPostRequest(
205 printer_info_cloud_.printer_id), 207 CloudPrintHelpers::GetUrlForPrinterUpdate(
206 URLFetcher::POST, this)); 208 cloud_print_server_url_, printer_info_cloud_.printer_id),
207 CloudPrintHelpers::PrepCloudPrintRequest(request_.get(), auth_token_); 209 this, auth_token_, kCloudPrintAPIRetryPolicy, mime_type, post_data);
208 request_->set_upload_data(mime_type, post_data);
209 next_response_handler_ = &PrinterJobHandler::HandlePrinterUpdateResponse;
210 next_failure_handler_ = &PrinterJobHandler::Stop;
211 request_->Start();
212 ret = true; 210 ret = true;
213 } 211 }
214 return ret; 212 return ret;
215 } 213 }
216 214
217 // URLFetcher::Delegate implementation. 215 // CloudPrintURLFetcher::Delegate implementation.
218 void PrinterJobHandler::OnURLFetchComplete( 216 CloudPrintURLFetcher::ResponseAction PrinterJobHandler::HandleRawData(
219 const URLFetcher* source, 217 const URLFetcher* source,
220 const GURL& url, 218 const GURL& url,
221 const URLRequestStatus& status,
222 int response_code,
223 const ResponseCookies& cookies,
224 const std::string& data) { 219 const std::string& data) {
225 VLOG(1) << "CP_PROXY: Printer job handler, OnURLFetchComplete, url: " << url 220 if (!next_data_handler_)
226 << ", response code: " << response_code; 221 return CloudPrintURLFetcher::CONTINUE_PROCESSING;
227 // If there was an auth error, we are done. 222 return (this->*next_data_handler_)(source, url, data);
228 if (RC_FORBIDDEN == response_code) { 223 }
229 OnAuthError(); 224
230 return; 225 CloudPrintURLFetcher::ResponseAction PrinterJobHandler::HandleJSONData(
231 } 226 const URLFetcher* source,
232 if (!shutting_down_) { 227 const GURL& url,
233 DCHECK(source == request_.get()); 228 DictionaryValue* json_data,
234 // We need a next response handler because we are strictly a sequential 229 bool succeeded) {
235 // state machine. We need each response handler to tell us which state to 230 DCHECK(next_json_data_handler_);
236 // advance to next. 231 return (this->*next_json_data_handler_)(source,
237 DCHECK(next_response_handler_); 232 url,
238 if (!(this->*next_response_handler_)(source, url, status, 233 json_data,
239 response_code, cookies, data)) { 234 succeeded);
240 // By contract, if the response handler returns false, it wants us to 235 }
241 // retry the request (upto the usual limit after which we give up and 236
242 // send the state machine to the Stop state); 237 void PrinterJobHandler::OnRequestGiveUp() {
243 HandleServerError(url); 238 MessageLoop::current()->PostTask(
244 } 239 FROM_HERE,
245 } 240 NewRunnableMethod(this, &PrinterJobHandler::Stop));
241 }
242
243 void PrinterJobHandler::OnRequestAuthError() {
244 OnAuthError();
246 } 245 }
247 246
248 // JobStatusUpdater::Delegate implementation 247 // JobStatusUpdater::Delegate implementation
249 bool PrinterJobHandler::OnJobCompleted(JobStatusUpdater* updater) { 248 bool PrinterJobHandler::OnJobCompleted(JobStatusUpdater* updater) {
250 bool ret = false; 249 bool ret = false;
251 for (JobStatusUpdaterList::iterator index = job_status_updater_list_.begin(); 250 for (JobStatusUpdaterList::iterator index = job_status_updater_list_.begin();
252 index != job_status_updater_list_.end(); index++) { 251 index != job_status_updater_list_.end(); index++) {
253 if (index->get() == updater) { 252 if (index->get() == updater) {
254 job_status_updater_list_.erase(index); 253 job_status_updater_list_.erase(index);
255 ret = true; 254 ret = true;
(...skipping 28 matching lines...) Expand all
284 // Some job on the printer changed. Loop through all our JobStatusUpdaters 283 // Some job on the printer changed. Loop through all our JobStatusUpdaters
285 // and have them check for updates. 284 // and have them check for updates.
286 for (JobStatusUpdaterList::iterator index = job_status_updater_list_.begin(); 285 for (JobStatusUpdaterList::iterator index = job_status_updater_list_.begin();
287 index != job_status_updater_list_.end(); index++) { 286 index != job_status_updater_list_.end(); index++) {
288 MessageLoop::current()->PostTask( 287 MessageLoop::current()->PostTask(
289 FROM_HERE, NewRunnableMethod(index->get(), 288 FROM_HERE, NewRunnableMethod(index->get(),
290 &JobStatusUpdater::UpdateStatus)); 289 &JobStatusUpdater::UpdateStatus));
291 } 290 }
292 } 291 }
293 292
294 bool PrinterJobHandler::HandlePrinterUpdateResponse( 293 // Begin Response handlers
294 CloudPrintURLFetcher::ResponseAction
295 PrinterJobHandler::HandlePrinterUpdateResponse(
295 const URLFetcher* source, 296 const URLFetcher* source,
296 const GURL& url, 297 const GURL& url,
297 const URLRequestStatus& status, 298 DictionaryValue* json_data,
298 int response_code, 299 bool succeeded) {
299 const ResponseCookies& cookies,
300 const std::string& data) {
301 bool ret = false;
302 VLOG(1) << "CP_PROXY: Handle printer update response, id: " 300 VLOG(1) << "CP_PROXY: Handle printer update response, id: "
303 << printer_info_cloud_.printer_id; 301 << printer_info_cloud_.printer_id;
304 // If there was a network error or a non-200 response (which, for our purposes 302 // We are done here. Go to the Stop state
305 // is the same as a network error), we want to retry. 303 MessageLoop::current()->PostTask(
306 if (status.is_success() && (response_code == 200)) { 304 FROM_HERE, NewRunnableMethod(this, &PrinterJobHandler::Stop));
307 bool succeeded = false; 305 return CloudPrintURLFetcher::STOP_PROCESSING;
308 DictionaryValue* response_dict = NULL;
309 CloudPrintHelpers::ParseResponseJSON(data, &succeeded, &response_dict);
310 // If we get valid JSON back, we are done.
311 if (NULL != response_dict) {
312 ret = true;
313 }
314 }
315 if (ret) {
316 // We are done here. Go to the Stop state
317 MessageLoop::current()->PostTask(
318 FROM_HERE, NewRunnableMethod(this, &PrinterJobHandler::Stop));
319 } else {
320 // Since we failed to update the server, set the flag again.
321 printer_update_pending_ = true;
322 }
323 return ret;
324 } 306 }
325 307
326 bool PrinterJobHandler::HandlePrinterDeleteResponse( 308 CloudPrintURLFetcher::ResponseAction
309 PrinterJobHandler::HandlePrinterDeleteResponse(
327 const URLFetcher* source, 310 const URLFetcher* source,
328 const GURL& url, 311 const GURL& url,
329 const URLRequestStatus& status, 312 DictionaryValue* json_data,
330 int response_code, 313 bool succeeded) {
331 const ResponseCookies& cookies,
332 const std::string& data) {
333 bool ret = false;
334 VLOG(1) << "CP_PROXY: Handler printer delete response, id: " 314 VLOG(1) << "CP_PROXY: Handler printer delete response, id: "
335 << printer_info_cloud_.printer_id; 315 << printer_info_cloud_.printer_id;
336 // If there was a network error or a non-200 response (which, for our purposes 316 // The printer has been deleted. Shutdown the handler class.
337 // is the same as a network error), we want to retry. 317 MessageLoop::current()->PostTask(
338 if (status.is_success() && (response_code == 200)) { 318 FROM_HERE, NewRunnableMethod(this, &PrinterJobHandler::Shutdown));
339 bool succeeded = false; 319 return CloudPrintURLFetcher::STOP_PROCESSING;
340 DictionaryValue* response_dict = NULL;
341 CloudPrintHelpers::ParseResponseJSON(data, &succeeded, &response_dict);
342 // If we get valid JSON back, we are done.
343 if (NULL != response_dict) {
344 ret = true;
345 }
346 }
347 if (ret) {
348 // The printer has been deleted. Shutdown the handler class.
349 MessageLoop::current()->PostTask(
350 FROM_HERE, NewRunnableMethod(this, &PrinterJobHandler::Shutdown));
351 } else {
352 // Since we failed to update the server, set the flag again.
353 printer_delete_pending_ = true;
354 }
355 return ret;
356 } 320 }
357 321
358 bool PrinterJobHandler::HandleJobMetadataResponse( 322 CloudPrintURLFetcher::ResponseAction
323 PrinterJobHandler::HandleJobMetadataResponse(
359 const URLFetcher* source, 324 const URLFetcher* source,
360 const GURL& url, 325 const GURL& url,
361 const URLRequestStatus& status, 326 DictionaryValue* json_data,
362 int response_code, 327 bool succeeded) {
363 const ResponseCookies& cookies,
364 const std::string& data) {
365 VLOG(1) << "CP_PROXY: Handle job metadata response, id: " 328 VLOG(1) << "CP_PROXY: Handle job metadata response, id: "
366 << printer_info_cloud_.printer_id; 329 << printer_info_cloud_.printer_id;
367 // If there was a network error or a non-200 response (which, for our purposes 330 bool job_available = false;
368 // is the same as a network error), we want to retry.
369 if (!status.is_success() || (response_code != 200)) {
370 return false;
371 }
372 bool succeeded = false;
373 DictionaryValue* response_dict = NULL;
374 CloudPrintHelpers::ParseResponseJSON(data, &succeeded, &response_dict);
375 if (NULL == response_dict) {
376 // If we did not get a valid JSON response, we need to retry.
377 return false;
378 }
379 Task* next_task = NULL;
380 if (succeeded) { 331 if (succeeded) {
381 ListValue* job_list = NULL; 332 ListValue* job_list = NULL;
382 response_dict->GetList(kJobListValue, &job_list); 333 json_data->GetList(kJobListValue, &job_list);
383 if (job_list) { 334 if (job_list) {
384 // Even though it is a job list, for now we are only interested in the 335 // Even though it is a job list, for now we are only interested in the
385 // first job 336 // first job
386 DictionaryValue* job_data = NULL; 337 DictionaryValue* job_data = NULL;
387 if (job_list->GetDictionary(0, &job_data)) { 338 if (job_list->GetDictionary(0, &job_data)) {
339 job_available = true;
388 job_data->GetString(kIdValue, &job_details_.job_id_); 340 job_data->GetString(kIdValue, &job_details_.job_id_);
389 job_data->GetString(kTitleValue, &job_details_.job_title_); 341 job_data->GetString(kTitleValue, &job_details_.job_title_);
390 std::string print_ticket_url; 342 std::string print_ticket_url;
391 job_data->GetString(kTicketUrlValue, &print_ticket_url); 343 job_data->GetString(kTicketUrlValue, &print_ticket_url);
392 job_data->GetString(kFileUrlValue, &print_data_url_); 344 job_data->GetString(kFileUrlValue, &print_data_url_);
393 next_task = NewRunnableMethod( 345 SetNextDataHandler(&PrinterJobHandler::HandlePrintTicketResponse);
394 this, &PrinterJobHandler::MakeServerRequest, 346 request_ = new CloudPrintURLFetcher;
395 GURL(print_ticket_url.c_str()), 347 request_->StartGetRequest(GURL(print_ticket_url.c_str()),
396 &PrinterJobHandler::HandlePrintTicketResponse, 348 this,
397 &PrinterJobHandler::FailedFetchingJobData); 349 auth_token_,
350 kCloudPrintAPIRetryPolicy);
398 } 351 }
399 } 352 }
400 } 353 }
401 if (!next_task) { 354 // If no jobs are available, go to the Stop state.
402 // If we got a valid JSON but there were no jobs, we are done 355 if (!job_available)
403 next_task = NewRunnableMethod(this, &PrinterJobHandler::Stop); 356 MessageLoop::current()->PostTask(
404 } 357 FROM_HERE, NewRunnableMethod(this, &PrinterJobHandler::Stop));
405 delete response_dict; 358 return CloudPrintURLFetcher::STOP_PROCESSING;
406 DCHECK(next_task);
407 MessageLoop::current()->PostTask(FROM_HERE, next_task);
408 return true;
409 } 359 }
410 360
411 bool PrinterJobHandler::HandlePrintTicketResponse( 361 CloudPrintURLFetcher::ResponseAction
412 const URLFetcher* source, const GURL& url, const URLRequestStatus& status, 362 PrinterJobHandler::HandlePrintTicketResponse(const URLFetcher* source,
413 int response_code, const ResponseCookies& cookies, 363 const GURL& url,
414 const std::string& data) { 364 const std::string& data) {
415 VLOG(1) << "CP_PROXY: Handle print ticket response, id: " 365 VLOG(1) << "CP_PROXY: Handle print ticket response, id: "
416 << printer_info_cloud_.printer_id; 366 << printer_info_cloud_.printer_id;
417 // If there was a network error or a non-200 response (which, for our purposes
418 // is the same as a network error), we want to retry.
419 if (!status.is_success() || (response_code != 200)) {
420 return false;
421 }
422 if (print_system_->ValidatePrintTicket(printer_info_.printer_name, data)) { 367 if (print_system_->ValidatePrintTicket(printer_info_.printer_name, data)) {
423 job_details_.print_ticket_ = data; 368 job_details_.print_ticket_ = data;
424 MessageLoop::current()->PostTask( 369 SetNextDataHandler(&PrinterJobHandler::HandlePrintDataResponse);
425 FROM_HERE, 370 request_ = new CloudPrintURLFetcher;
426 NewRunnableMethod(this, 371 request_->StartGetRequest(GURL(print_data_url_.c_str()),
427 &PrinterJobHandler::MakeServerRequest, 372 this,
428 GURL(print_data_url_.c_str()), 373 auth_token_,
429 &PrinterJobHandler::HandlePrintDataResponse, 374 kJobDataRetryPolicy);
430 &PrinterJobHandler::FailedFetchingJobData));
431 } else { 375 } else {
432 // The print ticket was not valid. We are done here. 376 // The print ticket was not valid. We are done here.
433 FailedFetchingJobData(); 377 FailedFetchingJobData();
434 } 378 }
435 return true; 379 return CloudPrintURLFetcher::STOP_PROCESSING;
436 } 380 }
437 381
438 bool PrinterJobHandler::HandlePrintDataResponse(const URLFetcher* source, 382 CloudPrintURLFetcher::ResponseAction
439 const GURL& url, 383 PrinterJobHandler::HandlePrintDataResponse(const URLFetcher* source,
440 const URLRequestStatus& status, 384 const GURL& url,
441 int response_code, 385 const std::string& data) {
442 const ResponseCookies& cookies,
443 const std::string& data) {
444 VLOG(1) << "CP_PROXY: Handle print data response, id: " 386 VLOG(1) << "CP_PROXY: Handle print data response, id: "
445 << printer_info_cloud_.printer_id; 387 << printer_info_cloud_.printer_id;
446 // If there was a network error or a non-200 response (which, for our purposes
447 // is the same as a network error), we want to retry.
448 if (!status.is_success() || (response_code != 200)) {
449 return false;
450 }
451 Task* next_task = NULL; 388 Task* next_task = NULL;
452 if (file_util::CreateTemporaryFile(&job_details_.print_data_file_path_)) { 389 if (file_util::CreateTemporaryFile(&job_details_.print_data_file_path_)) {
453 int ret = file_util::WriteFile(job_details_.print_data_file_path_, 390 int ret = file_util::WriteFile(job_details_.print_data_file_path_,
454 data.c_str(), 391 data.c_str(),
455 data.length()); 392 data.length());
456 source->response_headers()->GetMimeType( 393 source->response_headers()->GetMimeType(
457 &job_details_.print_data_mime_type_); 394 &job_details_.print_data_mime_type_);
458 DCHECK(ret == static_cast<int>(data.length())); 395 DCHECK(ret == static_cast<int>(data.length()));
459 if (ret == static_cast<int>(data.length())) { 396 if (ret == static_cast<int>(data.length())) {
460 next_task = NewRunnableMethod(this, &PrinterJobHandler::StartPrinting); 397 next_task = NewRunnableMethod(this, &PrinterJobHandler::StartPrinting);
461 } 398 }
462 } 399 }
463 // If there was no task allocated above, then there was an error in 400 // If there was no task allocated above, then there was an error in
464 // saving the print data, bail out here. 401 // saving the print data, bail out here.
465 if (!next_task) { 402 if (!next_task) {
466 next_task = NewRunnableMethod(this, &PrinterJobHandler::JobFailed, 403 next_task = NewRunnableMethod(this, &PrinterJobHandler::JobFailed,
467 JOB_DOWNLOAD_FAILED); 404 JOB_DOWNLOAD_FAILED);
468 } 405 }
469 MessageLoop::current()->PostTask(FROM_HERE, next_task); 406 MessageLoop::current()->PostTask(FROM_HERE, next_task);
470 return true; 407 return CloudPrintURLFetcher::STOP_PROCESSING;
471 } 408 }
472 409
410 CloudPrintURLFetcher::ResponseAction
411 PrinterJobHandler::HandleSuccessStatusUpdateResponse(
412 const URLFetcher* source,
413 const GURL& url,
414 DictionaryValue* json_data,
415 bool succeeded) {
416 VLOG(1) << "CP_PROXY: Handle success status update response, id: "
417 << printer_info_cloud_.printer_id;
418 // The print job has been spooled locally. We now need to create an object
419 // that monitors the status of the job and updates the server.
420 scoped_refptr<JobStatusUpdater> job_status_updater =
421 new JobStatusUpdater(printer_info_.printer_name, job_details_.job_id_,
422 local_job_id_, auth_token_, cloud_print_server_url_,
423 print_system_.get(), this);
424 job_status_updater_list_.push_back(job_status_updater);
425 MessageLoop::current()->PostTask(
426 FROM_HERE, NewRunnableMethod(job_status_updater.get(),
427 &JobStatusUpdater::UpdateStatus));
428 if (succeeded) {
429 // Since we just printed successfully, we want to look for more jobs.
430 server_job_available_ = true;
431 }
432 MessageLoop::current()->PostTask(
433 FROM_HERE, NewRunnableMethod(this, &PrinterJobHandler::Stop));
434 return CloudPrintURLFetcher::STOP_PROCESSING;
435 }
436
437 CloudPrintURLFetcher::ResponseAction
438 PrinterJobHandler::HandleFailureStatusUpdateResponse(
439 const URLFetcher* source,
440 const GURL& url,
441 DictionaryValue* json_data,
442 bool succeeded) {
443 VLOG(1) << "CP_PROXY: Handle failure status update response, id: "
444 << printer_info_cloud_.printer_id;
445 MessageLoop::current()->PostTask(
446 FROM_HERE, NewRunnableMethod(this, &PrinterJobHandler::Stop));
447 return CloudPrintURLFetcher::STOP_PROCESSING;
448 }
449 // End Response handlers
450
473 void PrinterJobHandler::StartPrinting() { 451 void PrinterJobHandler::StartPrinting() {
474 VLOG(1) << "CP_PROXY: Start printing, id: " << printer_info_cloud_.printer_id; 452 VLOG(1) << "CP_PROXY: Start printing, id: " << printer_info_cloud_.printer_id;
475 // We are done with the request object for now. 453 // We are done with the request object for now.
476 request_.reset(); 454 request_ = NULL;
477 if (!shutting_down_) { 455 if (!shutting_down_) {
478 if (!print_thread_.Start()) { 456 if (!print_thread_.Start()) {
479 JobFailed(PRINT_FAILED); 457 JobFailed(PRINT_FAILED);
480 } else { 458 } else {
481 print_thread_.message_loop()->PostTask( 459 print_thread_.message_loop()->PostTask(
482 FROM_HERE, NewRunnableMethod(this, &PrinterJobHandler::DoPrint, 460 FROM_HERE, NewRunnableMethod(this, &PrinterJobHandler::DoPrint,
483 job_details_, 461 job_details_,
484 printer_info_.printer_name)); 462 printer_info_.printer_name));
485 } 463 }
486 } 464 }
(...skipping 25 matching lines...) Expand all
512 // Calling Stop() will cause the OnJobCompleted to be called which will 490 // Calling Stop() will cause the OnJobCompleted to be called which will
513 // remove the updater object from the list. 491 // remove the updater object from the list.
514 job_status_updater_list_.front()->Stop(); 492 job_status_updater_list_.front()->Stop();
515 } 493 }
516 if (delegate_) { 494 if (delegate_) {
517 delegate_->OnPrinterJobHandlerShutdown(this, 495 delegate_->OnPrinterJobHandlerShutdown(this,
518 printer_info_cloud_.printer_id); 496 printer_info_cloud_.printer_id);
519 } 497 }
520 } 498 }
521 499
522 void PrinterJobHandler::HandleServerError(const GURL& url) {
523 VLOG(1) << "CP_PROXY: Handle server error, printer id: "
524 << printer_info_cloud_.printer_id << ", url: " << url;
525 Task* task_to_retry = NewRunnableMethod(this,
526 &PrinterJobHandler::FetchURL, url);
527 Task* task_on_give_up = NewRunnableMethod(this, next_failure_handler_);
528 CloudPrintHelpers::HandleServerError(&server_error_count_, kMaxRetryCount,
529 -1, kBaseRetryInterval, task_to_retry,
530 task_on_give_up);
531 }
532
533 void PrinterJobHandler::UpdateJobStatus(cloud_print::PrintJobStatus status, 500 void PrinterJobHandler::UpdateJobStatus(cloud_print::PrintJobStatus status,
534 PrintJobError error) { 501 PrintJobError error) {
535 VLOG(1) << "CP_PROXY: Update job status, id: " 502 VLOG(1) << "CP_PROXY: Update job status, id: "
536 << printer_info_cloud_.printer_id; 503 << printer_info_cloud_.printer_id;
537 if (!shutting_down_) { 504 if (!shutting_down_) {
538 if (!job_details_.job_id_.empty()) { 505 if (!job_details_.job_id_.empty()) {
539 VLOG(1) << "CP_PROXY: Updating status, job id: " << job_details_.job_id_ 506 VLOG(1) << "CP_PROXY: Updating status, job id: " << job_details_.job_id_
540 << ", status: " << status; 507 << ", status: " << status;
541
542 ResponseHandler response_handler = NULL;
543 if (error == SUCCESS) { 508 if (error == SUCCESS) {
544 response_handler = 509 SetNextJSONHandler(
545 &PrinterJobHandler::HandleSuccessStatusUpdateResponse; 510 &PrinterJobHandler::HandleSuccessStatusUpdateResponse);
546 } else { 511 } else {
547 response_handler = 512 SetNextJSONHandler(
548 &PrinterJobHandler::HandleFailureStatusUpdateResponse; 513 &PrinterJobHandler::HandleFailureStatusUpdateResponse);
549 } 514 }
550 MakeServerRequest( 515 request_ = new CloudPrintURLFetcher;
516 request_->StartGetRequest(
551 CloudPrintHelpers::GetUrlForJobStatusUpdate(cloud_print_server_url_, 517 CloudPrintHelpers::GetUrlForJobStatusUpdate(cloud_print_server_url_,
552 job_details_.job_id_, 518 job_details_.job_id_,
553 status), 519 status),
554 response_handler, 520 this,
555 &PrinterJobHandler::Stop); 521 auth_token_,
522 kCloudPrintAPIRetryPolicy);
556 } 523 }
557 } 524 }
558 } 525 }
559 526
560 bool PrinterJobHandler::HandleSuccessStatusUpdateResponse( 527 void PrinterJobHandler::SetNextJSONHandler(JSONDataHandler handler) {
561 const URLFetcher* source, 528 next_json_data_handler_ = handler;
562 const GURL& url, 529 next_data_handler_ = NULL;
563 const URLRequestStatus& status,
564 int response_code,
565 const ResponseCookies& cookies,
566 const std::string& data) {
567 VLOG(1) << "CP_PROXY: Handle success status update response, id: "
568 << printer_info_cloud_.printer_id;
569 // If there was a network error or a non-200 response (which, for our purposes
570 // is the same as a network error), we want to retry.
571 if (!status.is_success() || (response_code != 200)) {
572 return false;
573 }
574 // The print job has been spooled locally. We now need to create an object
575 // that monitors the status of the job and updates the server.
576 scoped_refptr<JobStatusUpdater> job_status_updater =
577 new JobStatusUpdater(printer_info_.printer_name, job_details_.job_id_,
578 local_job_id_, auth_token_, cloud_print_server_url_,
579 print_system_.get(), this);
580 job_status_updater_list_.push_back(job_status_updater);
581 MessageLoop::current()->PostTask(
582 FROM_HERE, NewRunnableMethod(job_status_updater.get(),
583 &JobStatusUpdater::UpdateStatus));
584 bool succeeded = false;
585 CloudPrintHelpers::ParseResponseJSON(data, &succeeded, NULL);
586 if (succeeded) {
587 // Since we just printed successfully, we want to look for more jobs.
588 server_job_available_ = true;
589 }
590 MessageLoop::current()->PostTask(
591 FROM_HERE, NewRunnableMethod(this, &PrinterJobHandler::Stop));
592 return true;
593 } 530 }
594 531
595 bool PrinterJobHandler::HandleFailureStatusUpdateResponse( 532 void PrinterJobHandler::SetNextDataHandler(DataHandler handler) {
596 const URLFetcher* source, 533 next_data_handler_ = handler;
597 const GURL& url, 534 next_json_data_handler_ = NULL;
598 const URLRequestStatus& status,
599 int response_code,
600 const ResponseCookies& cookies,
601 const std::string& data) {
602 VLOG(1) << "CP_PROXY: Handle failure status update response, id: "
603 << printer_info_cloud_.printer_id;
604 // If there was a network error or a non-200 response (which, for our purposes
605 // is the same as a network error), we want to retry.
606 if (!status.is_success() || (response_code != 200)) {
607 return false;
608 }
609 MessageLoop::current()->PostTask(
610 FROM_HERE, NewRunnableMethod(this, &PrinterJobHandler::Stop));
611 return true;
612 }
613
614 void PrinterJobHandler::MakeServerRequest(const GURL& url,
615 ResponseHandler response_handler,
616 FailureHandler failure_handler) {
617 VLOG(1) << "CP_PROXY: Printer job handle, make server request, id: "
618 << printer_info_cloud_.printer_id << ", url: " << url;
619 if (!shutting_down_) {
620 server_error_count_ = 0;
621 // Set up the next response handler
622 next_response_handler_ = response_handler;
623 next_failure_handler_ = failure_handler;
624 FetchURL(url);
625 }
626 }
627
628 void PrinterJobHandler::FetchURL(const GURL& url) {
629 VLOG(1) << "CP_PROXY: PrinterJobHandler::FetchURL, url: " << url;
630 request_.reset(new URLFetcher(url, URLFetcher::GET, this));
631 CloudPrintHelpers::PrepCloudPrintRequest(request_.get(), auth_token_);
632 request_->Start();
633 } 535 }
634 536
635 bool PrinterJobHandler::HavePendingTasks() { 537 bool PrinterJobHandler::HavePendingTasks() {
636 return server_job_available_ || printer_update_pending_ || 538 return server_job_available_ || printer_update_pending_ ||
637 printer_delete_pending_; 539 printer_delete_pending_;
638 } 540 }
639 541
640 void PrinterJobHandler::FailedFetchingJobData() { 542 void PrinterJobHandler::FailedFetchingJobData() {
641 if (!shutting_down_) { 543 if (!shutting_down_) {
642 LOG(ERROR) << "CP_PROXY: Failed fetching job data for printer: " << 544 LOG(ERROR) << "CP_PROXY: Failed fetching job data for printer: " <<
(...skipping 30 matching lines...) Expand all
673 } 575 }
674 576
675 void PrinterJobHandler::OnJobSpoolFailed() { 577 void PrinterJobHandler::OnJobSpoolFailed() {
676 DCHECK(MessageLoop::current() == print_thread_.message_loop()); 578 DCHECK(MessageLoop::current() == print_thread_.message_loop());
677 job_spooler_ = NULL; 579 job_spooler_ = NULL;
678 job_handler_message_loop_proxy_->PostTask(FROM_HERE, 580 job_handler_message_loop_proxy_->PostTask(FROM_HERE,
679 NewRunnableMethod(this, 581 NewRunnableMethod(this,
680 &PrinterJobHandler::JobFailed, 582 &PrinterJobHandler::JobFailed,
681 PRINT_FAILED)); 583 PRINT_FAILED));
682 } 584 }
OLDNEW
« no previous file with comments | « chrome/service/cloud_print/printer_job_handler.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698