| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |