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 |