OLD | NEW |
(Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "chrome/browser/printing/cloud_print/printer_job_handler.h" |
| 6 |
| 7 #include "base/file_util.h" |
| 8 #include "base/json/json_reader.h" |
| 9 #include "base/md5.h" |
| 10 #include "base/string_util.h" |
| 11 #include "base/utf_string_conversions.h" |
| 12 #include "base/values.h" |
| 13 #include "chrome/browser/printing/cloud_print/cloud_print_consts.h" |
| 14 #include "chrome/browser/printing/cloud_print/cloud_print_helpers.h" |
| 15 #include "chrome/browser/printing/cloud_print/job_status_updater.h" |
| 16 #include "googleurl/src/gurl.h" |
| 17 #include "net/http/http_response_headers.h" |
| 18 |
| 19 PrinterJobHandler::PrinterJobHandler( |
| 20 const cloud_print::PrinterBasicInfo& printer_info, |
| 21 const std::string& printer_id, |
| 22 const std::string& caps_hash, |
| 23 const std::string& auth_token, |
| 24 Delegate* delegate) |
| 25 : printer_info_(printer_info), |
| 26 printer_id_(printer_id), |
| 27 auth_token_(auth_token), |
| 28 last_caps_hash_(caps_hash), |
| 29 delegate_(delegate), |
| 30 local_job_id_(-1), |
| 31 next_response_handler_(NULL), |
| 32 server_error_count_(0), |
| 33 print_thread_("Chrome_CloudPrintJobPrintThread"), |
| 34 shutting_down_(false), |
| 35 server_job_available_(false), |
| 36 printer_update_pending_(true), |
| 37 printer_delete_pending_(false), |
| 38 task_in_progress_(false) { |
| 39 } |
| 40 |
| 41 bool PrinterJobHandler::Initialize() { |
| 42 if (cloud_print::IsValidPrinter(printer_info_.printer_name)) { |
| 43 printer_change_notifier_.StartWatching(printer_info_.printer_name, this); |
| 44 NotifyJobAvailable(); |
| 45 } else { |
| 46 // This printer does not exist any more. Delete it from the server. |
| 47 OnPrinterDeleted(); |
| 48 } |
| 49 return true; |
| 50 } |
| 51 |
| 52 PrinterJobHandler::~PrinterJobHandler() { |
| 53 printer_change_notifier_.StopWatching(); |
| 54 } |
| 55 |
| 56 void PrinterJobHandler::Reset() { |
| 57 print_data_url_.clear(); |
| 58 job_details_.Clear(); |
| 59 request_.reset(); |
| 60 print_thread_.Stop(); |
| 61 } |
| 62 |
| 63 void PrinterJobHandler::Start() { |
| 64 if (task_in_progress_) { |
| 65 // Multiple Starts can get posted because of multiple notifications |
| 66 // We want to ignore the other ones that happen when a task is in progress. |
| 67 return; |
| 68 } |
| 69 Reset(); |
| 70 if (!shutting_down_) { |
| 71 // Check if we have work to do. |
| 72 if (HavePendingTasks()) { |
| 73 if (printer_delete_pending_) { |
| 74 printer_delete_pending_ = false; |
| 75 task_in_progress_ = true; |
| 76 MakeServerRequest( |
| 77 CloudPrintHelpers::GetUrlForPrinterDelete(printer_id_), |
| 78 &PrinterJobHandler::HandlePrinterDeleteResponse); |
| 79 } |
| 80 if (!task_in_progress_ && printer_update_pending_) { |
| 81 printer_update_pending_ = false; |
| 82 task_in_progress_ = UpdatePrinterInfo(); |
| 83 } |
| 84 if (!task_in_progress_ && server_job_available_) { |
| 85 task_in_progress_ = true; |
| 86 server_job_available_ = false; |
| 87 // We need to fetch any pending jobs for this printer |
| 88 MakeServerRequest(CloudPrintHelpers::GetUrlForJobFetch(printer_id_), |
| 89 &PrinterJobHandler::HandleJobMetadataResponse); |
| 90 } |
| 91 } |
| 92 } |
| 93 } |
| 94 |
| 95 void PrinterJobHandler::Stop() { |
| 96 task_in_progress_ = false; |
| 97 Reset(); |
| 98 if (HavePendingTasks()) { |
| 99 MessageLoop::current()->PostTask( |
| 100 FROM_HERE, NewRunnableMethod(this, &PrinterJobHandler::Start)); |
| 101 } |
| 102 } |
| 103 |
| 104 void PrinterJobHandler::NotifyJobAvailable() { |
| 105 server_job_available_ = true; |
| 106 if (!task_in_progress_) { |
| 107 MessageLoop::current()->PostTask( |
| 108 FROM_HERE, NewRunnableMethod(this, &PrinterJobHandler::Start)); |
| 109 } |
| 110 } |
| 111 |
| 112 bool PrinterJobHandler::UpdatePrinterInfo() { |
| 113 // We need to update the parts of the printer info that have changed |
| 114 // (could be printer name, description, status or capabilities). |
| 115 cloud_print::PrinterBasicInfo printer_info; |
| 116 printer_change_notifier_.GetCurrentPrinterInfo(&printer_info); |
| 117 cloud_print::PrinterCapsAndDefaults printer_caps; |
| 118 std::string post_data; |
| 119 std::string mime_boundary; |
| 120 if (cloud_print::GetPrinterCapsAndDefaults(printer_info.printer_name, |
| 121 &printer_caps)) { |
| 122 std::string caps_hash = MD5String(printer_caps.printer_capabilities); |
| 123 CloudPrintHelpers::CreateMimeBoundaryForUpload(&mime_boundary); |
| 124 if (caps_hash != last_caps_hash_) { |
| 125 // Hashes don't match, we need to upload new capabilities (the defaults |
| 126 // go for free along with the capabilities) |
| 127 last_caps_hash_ = caps_hash; |
| 128 CloudPrintHelpers::AddMultipartValueForUpload( |
| 129 kPrinterCapsValue, printer_caps.printer_capabilities, |
| 130 mime_boundary, printer_caps.caps_mime_type, &post_data); |
| 131 CloudPrintHelpers::AddMultipartValueForUpload( |
| 132 kPrinterDefaultsValue, printer_caps.printer_defaults, |
| 133 mime_boundary, printer_caps.defaults_mime_type, |
| 134 &post_data); |
| 135 CloudPrintHelpers::AddMultipartValueForUpload( |
| 136 WideToUTF8(kPrinterCapsHashValue).c_str(), caps_hash, mime_boundary, |
| 137 std::string(), &post_data); |
| 138 } |
| 139 } |
| 140 if (printer_info.printer_name != printer_info_.printer_name) { |
| 141 CloudPrintHelpers::AddMultipartValueForUpload(kPrinterNameValue, |
| 142 printer_info.printer_name, |
| 143 mime_boundary, |
| 144 std::string(), &post_data); |
| 145 } |
| 146 if (printer_info.printer_description != printer_info_.printer_description) { |
| 147 CloudPrintHelpers::AddMultipartValueForUpload( |
| 148 kPrinterDescValue, printer_info.printer_description, mime_boundary, |
| 149 std::string() , &post_data); |
| 150 } |
| 151 if (printer_info.printer_status != printer_info_.printer_status) { |
| 152 CloudPrintHelpers::AddMultipartValueForUpload( |
| 153 kPrinterStatusValue, StringPrintf("%d", printer_info.printer_status), |
| 154 mime_boundary, std::string(), &post_data); |
| 155 } |
| 156 printer_info_ = printer_info; |
| 157 bool ret = false; |
| 158 if (!post_data.empty()) { |
| 159 // Terminate the request body |
| 160 post_data.append("--" + mime_boundary + "--\r\n"); |
| 161 std::string mime_type("multipart/form-data; boundary="); |
| 162 mime_type += mime_boundary; |
| 163 request_.reset( |
| 164 new URLFetcher(CloudPrintHelpers::GetUrlForPrinterUpdate(printer_id_), |
| 165 URLFetcher::POST, this)); |
| 166 CloudPrintHelpers::PrepCloudPrintRequest(request_.get(), auth_token_); |
| 167 request_->set_upload_data(mime_type, post_data); |
| 168 next_response_handler_ = &PrinterJobHandler::HandlePrinterUpdateResponse; |
| 169 request_->Start(); |
| 170 ret = true; |
| 171 } |
| 172 return ret; |
| 173 } |
| 174 |
| 175 // URLFetcher::Delegate implementation. |
| 176 void PrinterJobHandler::OnURLFetchComplete( |
| 177 const URLFetcher* source, const GURL& url, const URLRequestStatus& status, |
| 178 int response_code, const ResponseCookies& cookies, |
| 179 const std::string& data) { |
| 180 if (!shutting_down_) { |
| 181 DCHECK(source == request_.get()); |
| 182 // We need a next response handler because we are strictly a sequential |
| 183 // state machine. We need each response handler to tell us which state to |
| 184 // advance to next. |
| 185 DCHECK(next_response_handler_); |
| 186 if (!(this->*next_response_handler_)(source, url, status, |
| 187 response_code, cookies, data)) { |
| 188 // By contract, if the response handler returns false, it wants us to |
| 189 // retry the request (upto the usual limit after which we give up and |
| 190 // send the state machine to the Stop state); |
| 191 HandleServerError(url); |
| 192 } |
| 193 } |
| 194 } |
| 195 |
| 196 // JobStatusUpdater::Delegate implementation |
| 197 bool PrinterJobHandler::OnJobCompleted(JobStatusUpdater* updater) { |
| 198 bool ret = false; |
| 199 for (JobStatusUpdaterList::iterator index = job_status_updater_list_.begin(); |
| 200 index != job_status_updater_list_.end(); index++) { |
| 201 if (index->get() == updater) { |
| 202 job_status_updater_list_.erase(index); |
| 203 ret = true; |
| 204 break; |
| 205 } |
| 206 } |
| 207 return ret; |
| 208 } |
| 209 |
| 210 // cloud_print::PrinterChangeNotifier::Delegate implementation |
| 211 void PrinterJobHandler::OnPrinterAdded() { |
| 212 // Should never get this notification for a printer |
| 213 NOTREACHED(); |
| 214 } |
| 215 |
| 216 void PrinterJobHandler::OnPrinterDeleted() { |
| 217 printer_delete_pending_ = true; |
| 218 if (!task_in_progress_) { |
| 219 MessageLoop::current()->PostTask( |
| 220 FROM_HERE, NewRunnableMethod(this, &PrinterJobHandler::Start)); |
| 221 } |
| 222 } |
| 223 |
| 224 void PrinterJobHandler::OnPrinterChanged() { |
| 225 printer_update_pending_ = true; |
| 226 if (!task_in_progress_) { |
| 227 MessageLoop::current()->PostTask( |
| 228 FROM_HERE, NewRunnableMethod(this, &PrinterJobHandler::Start)); |
| 229 } |
| 230 } |
| 231 |
| 232 void PrinterJobHandler::OnJobChanged() { |
| 233 // Some job on the printer changed. Loop through all our JobStatusUpdaters |
| 234 // and have them check for updates. |
| 235 for (JobStatusUpdaterList::iterator index = job_status_updater_list_.begin(); |
| 236 index != job_status_updater_list_.end(); index++) { |
| 237 MessageLoop::current()->PostTask( |
| 238 FROM_HERE, NewRunnableMethod(index->get(), |
| 239 &JobStatusUpdater::UpdateStatus)); |
| 240 } |
| 241 } |
| 242 |
| 243 bool PrinterJobHandler::HandlePrinterUpdateResponse( |
| 244 const URLFetcher* source, const GURL& url, const URLRequestStatus& status, |
| 245 int response_code, const ResponseCookies& cookies, |
| 246 const std::string& data) { |
| 247 bool ret = false; |
| 248 // If there was a network error or a non-200 response (which, for our purposes |
| 249 // is the same as a network error), we want to retry. |
| 250 if (status.is_success() && (response_code == 200)) { |
| 251 bool succeeded = false; |
| 252 DictionaryValue* response_dict = NULL; |
| 253 CloudPrintHelpers::ParseResponseJSON(data, &succeeded, &response_dict); |
| 254 // If we get valid JSON back, we are done. |
| 255 if (NULL != response_dict) { |
| 256 ret = true; |
| 257 } |
| 258 } |
| 259 if (ret) { |
| 260 // We are done here. Go to the Stop state |
| 261 MessageLoop::current()->PostTask( |
| 262 FROM_HERE, NewRunnableMethod(this, &PrinterJobHandler::Stop)); |
| 263 } else { |
| 264 // Since we failed to update the server, set the flag again. |
| 265 printer_update_pending_ = true; |
| 266 } |
| 267 return ret; |
| 268 } |
| 269 |
| 270 bool PrinterJobHandler::HandlePrinterDeleteResponse( |
| 271 const URLFetcher* source, const GURL& url, const URLRequestStatus& status, |
| 272 int response_code, const ResponseCookies& cookies, |
| 273 const std::string& data) { |
| 274 bool ret = false; |
| 275 // If there was a network error or a non-200 response (which, for our purposes |
| 276 // is the same as a network error), we want to retry. |
| 277 if (status.is_success() && (response_code == 200)) { |
| 278 bool succeeded = false; |
| 279 DictionaryValue* response_dict = NULL; |
| 280 CloudPrintHelpers::ParseResponseJSON(data, &succeeded, &response_dict); |
| 281 // If we get valid JSON back, we are done. |
| 282 if (NULL != response_dict) { |
| 283 ret = true; |
| 284 } |
| 285 } |
| 286 if (ret) { |
| 287 // The printer has been deleted. Shutdown the handler class. |
| 288 MessageLoop::current()->PostTask( |
| 289 FROM_HERE, NewRunnableMethod(this, &PrinterJobHandler::Shutdown)); |
| 290 } else { |
| 291 // Since we failed to update the server, set the flag again. |
| 292 printer_delete_pending_ = true; |
| 293 } |
| 294 return ret; |
| 295 } |
| 296 |
| 297 bool PrinterJobHandler::HandleJobMetadataResponse( |
| 298 const URLFetcher* source, const GURL& url, const URLRequestStatus& status, |
| 299 int response_code, const ResponseCookies& cookies, |
| 300 const std::string& data) { |
| 301 // If there was a network error or a non-200 response (which, for our purposes |
| 302 // is the same as a network error), we want to retry. |
| 303 if (!status.is_success() || (response_code != 200)) { |
| 304 return false; |
| 305 } |
| 306 bool succeeded = false; |
| 307 DictionaryValue* response_dict = NULL; |
| 308 CloudPrintHelpers::ParseResponseJSON(data, &succeeded, &response_dict); |
| 309 if (NULL == response_dict) { |
| 310 // If we did not get a valid JSON response, we need to retry. |
| 311 return false; |
| 312 } |
| 313 Task* next_task = NULL; |
| 314 if (succeeded) { |
| 315 ListValue* job_list = NULL; |
| 316 response_dict->GetList(kJobListValue, &job_list); |
| 317 if (job_list) { |
| 318 // Even though it is a job list, for now we are only interested in the |
| 319 // first job |
| 320 DictionaryValue* job_data = NULL; |
| 321 if (job_list->GetDictionary(0, &job_data)) { |
| 322 job_data->GetString(kIdValue, &job_details_.job_id_); |
| 323 job_data->GetString(kTitleValue, &job_details_.job_title_); |
| 324 std::string print_ticket_url; |
| 325 job_data->GetString(kTicketUrlValue, &print_ticket_url); |
| 326 job_data->GetString(kFileUrlValue, &print_data_url_); |
| 327 next_task = NewRunnableMethod( |
| 328 this, &PrinterJobHandler::MakeServerRequest, |
| 329 GURL(print_ticket_url.c_str()), |
| 330 &PrinterJobHandler::HandlePrintTicketResponse); |
| 331 } |
| 332 } |
| 333 } |
| 334 if (!next_task) { |
| 335 // If we got a valid JSON but there were no jobs, we are done |
| 336 next_task = NewRunnableMethod(this, &PrinterJobHandler::Stop); |
| 337 } |
| 338 delete response_dict; |
| 339 DCHECK(next_task); |
| 340 MessageLoop::current()->PostTask(FROM_HERE, next_task); |
| 341 return true; |
| 342 } |
| 343 |
| 344 bool PrinterJobHandler::HandlePrintTicketResponse( |
| 345 const URLFetcher* source, const GURL& url, const URLRequestStatus& status, |
| 346 int response_code, const ResponseCookies& cookies, |
| 347 const std::string& data) { |
| 348 // If there was a network error or a non-200 response (which, for our purposes |
| 349 // is the same as a network error), we want to retry. |
| 350 if (!status.is_success() || (response_code != 200)) { |
| 351 return false; |
| 352 } |
| 353 if (cloud_print::ValidatePrintTicket(printer_info_.printer_name, data)) { |
| 354 job_details_.print_ticket_ = data; |
| 355 MessageLoop::current()->PostTask( |
| 356 FROM_HERE, |
| 357 NewRunnableMethod(this, |
| 358 &PrinterJobHandler::MakeServerRequest, |
| 359 GURL(print_data_url_.c_str()), |
| 360 &PrinterJobHandler::HandlePrintDataResponse)); |
| 361 } else { |
| 362 // The print ticket was not valid. We are done here. |
| 363 MessageLoop::current()->PostTask( |
| 364 FROM_HERE, NewRunnableMethod(this, &PrinterJobHandler::JobFailed, |
| 365 INVALID_JOB_DATA)); |
| 366 } |
| 367 return true; |
| 368 } |
| 369 |
| 370 bool PrinterJobHandler::HandlePrintDataResponse(const URLFetcher* source, |
| 371 const GURL& url, |
| 372 const URLRequestStatus& status, |
| 373 int response_code, |
| 374 const ResponseCookies& cookies, |
| 375 const std::string& data) { |
| 376 // If there was a network error or a non-200 response (which, for our purposes |
| 377 // is the same as a network error), we want to retry. |
| 378 if (!status.is_success() || (response_code != 200)) { |
| 379 return false; |
| 380 } |
| 381 Task* next_task = NULL; |
| 382 if (file_util::CreateTemporaryFile(&job_details_.print_data_file_path_)) { |
| 383 int ret = file_util::WriteFile(job_details_.print_data_file_path_, |
| 384 data.c_str(), |
| 385 data.length()); |
| 386 source->response_headers()->GetMimeType( |
| 387 &job_details_.print_data_mime_type_); |
| 388 DCHECK(ret == static_cast<int>(data.length())); |
| 389 if (ret == static_cast<int>(data.length())) { |
| 390 next_task = NewRunnableMethod(this, &PrinterJobHandler::StartPrinting); |
| 391 } |
| 392 } |
| 393 // If there was no task allocated above, then there was an error in |
| 394 // saving the print data, bail out here. |
| 395 if (!next_task) { |
| 396 next_task = NewRunnableMethod(this, &PrinterJobHandler::JobFailed, |
| 397 JOB_DOWNLOAD_FAILED); |
| 398 } |
| 399 MessageLoop::current()->PostTask(FROM_HERE, next_task); |
| 400 return true; |
| 401 } |
| 402 |
| 403 void PrinterJobHandler::StartPrinting() { |
| 404 // We are done with the request object for now. |
| 405 request_.reset(); |
| 406 if (!shutting_down_) { |
| 407 if (!print_thread_.Start()) { |
| 408 JobFailed(PRINT_FAILED); |
| 409 } else { |
| 410 print_thread_.message_loop()->PostTask( |
| 411 FROM_HERE, NewRunnableFunction(&PrinterJobHandler::DoPrint, |
| 412 job_details_, |
| 413 printer_info_.printer_name, this, |
| 414 MessageLoop::current())); |
| 415 } |
| 416 } |
| 417 } |
| 418 |
| 419 void PrinterJobHandler::JobFailed(PrintJobError error) { |
| 420 if (!shutting_down_) { |
| 421 UpdateJobStatus(cloud_print::PRINT_JOB_STATUS_ERROR, error); |
| 422 } |
| 423 } |
| 424 |
| 425 void PrinterJobHandler::JobSpooled(cloud_print::PlatformJobId local_job_id) { |
| 426 if (!shutting_down_) { |
| 427 local_job_id_ = local_job_id; |
| 428 UpdateJobStatus(cloud_print::PRINT_JOB_STATUS_IN_PROGRESS, SUCCESS); |
| 429 print_thread_.Stop(); |
| 430 } |
| 431 } |
| 432 |
| 433 void PrinterJobHandler::Shutdown() { |
| 434 Reset(); |
| 435 shutting_down_ = true; |
| 436 while (!job_status_updater_list_.empty()) { |
| 437 // Calling Stop() will cause the OnJobCompleted to be called which will |
| 438 // remove the updater object from the list. |
| 439 job_status_updater_list_.front()->Stop(); |
| 440 } |
| 441 if (delegate_) { |
| 442 delegate_->OnPrinterJobHandlerShutdown(this, printer_id_); |
| 443 } |
| 444 } |
| 445 |
| 446 void PrinterJobHandler::HandleServerError(const GURL& url) { |
| 447 Task* task_to_retry = NewRunnableMethod(this, |
| 448 &PrinterJobHandler::MakeServerRequest, |
| 449 url, next_response_handler_); |
| 450 Task* task_on_give_up = NewRunnableMethod(this, &PrinterJobHandler::Stop); |
| 451 CloudPrintHelpers::HandleServerError(&server_error_count_, kMaxRetryCount, |
| 452 -1, kBaseRetryInterval, task_to_retry, |
| 453 task_on_give_up); |
| 454 } |
| 455 |
| 456 void PrinterJobHandler::UpdateJobStatus(cloud_print::PrintJobStatus status, |
| 457 PrintJobError error) { |
| 458 if (!shutting_down_) { |
| 459 if (!job_details_.job_id_.empty()) { |
| 460 ResponseHandler response_handler = NULL; |
| 461 if (error == SUCCESS) { |
| 462 response_handler = |
| 463 &PrinterJobHandler::HandleSuccessStatusUpdateResponse; |
| 464 } else { |
| 465 response_handler = |
| 466 &PrinterJobHandler::HandleFailureStatusUpdateResponse; |
| 467 } |
| 468 MakeServerRequest( |
| 469 CloudPrintHelpers::GetUrlForJobStatusUpdate(job_details_.job_id_, |
| 470 status), |
| 471 response_handler); |
| 472 } |
| 473 } |
| 474 } |
| 475 |
| 476 bool PrinterJobHandler::HandleSuccessStatusUpdateResponse( |
| 477 const URLFetcher* source, const GURL& url, const URLRequestStatus& status, |
| 478 int response_code, const ResponseCookies& cookies, |
| 479 const std::string& data) { |
| 480 // If there was a network error or a non-200 response (which, for our purposes |
| 481 // is the same as a network error), we want to retry. |
| 482 if (!status.is_success() || (response_code != 200)) { |
| 483 return false; |
| 484 } |
| 485 // The print job has been spooled locally. We now need to create an object |
| 486 // that monitors the status of the job and updates the server. |
| 487 scoped_refptr<JobStatusUpdater> job_status_updater = |
| 488 new JobStatusUpdater(printer_info_.printer_name, job_details_.job_id_, |
| 489 local_job_id_, auth_token_, this); |
| 490 job_status_updater_list_.push_back(job_status_updater); |
| 491 MessageLoop::current()->PostTask( |
| 492 FROM_HERE, NewRunnableMethod(job_status_updater.get(), |
| 493 &JobStatusUpdater::UpdateStatus)); |
| 494 bool succeeded = false; |
| 495 CloudPrintHelpers::ParseResponseJSON(data, &succeeded, NULL); |
| 496 if (succeeded) { |
| 497 // Since we just printed successfully, we want to look for more jobs. |
| 498 server_job_available_ = true; |
| 499 } |
| 500 MessageLoop::current()->PostTask( |
| 501 FROM_HERE, NewRunnableMethod(this, &PrinterJobHandler::Stop)); |
| 502 return true; |
| 503 } |
| 504 |
| 505 bool PrinterJobHandler::HandleFailureStatusUpdateResponse( |
| 506 const URLFetcher* source, const GURL& url, const URLRequestStatus& status, |
| 507 int response_code, const ResponseCookies& cookies, |
| 508 const std::string& data) { |
| 509 // If there was a network error or a non-200 response (which, for our purposes |
| 510 // is the same as a network error), we want to retry. |
| 511 if (!status.is_success() || (response_code != 200)) { |
| 512 return false; |
| 513 } |
| 514 MessageLoop::current()->PostTask( |
| 515 FROM_HERE, NewRunnableMethod(this, &PrinterJobHandler::Stop)); |
| 516 return true; |
| 517 } |
| 518 |
| 519 void PrinterJobHandler::MakeServerRequest(const GURL& url, |
| 520 ResponseHandler response_handler) { |
| 521 if (!shutting_down_) { |
| 522 request_.reset(new URLFetcher(url, URLFetcher::GET, this)); |
| 523 server_error_count_ = 0; |
| 524 CloudPrintHelpers::PrepCloudPrintRequest(request_.get(), auth_token_); |
| 525 // Set up the next response handler |
| 526 next_response_handler_ = response_handler; |
| 527 request_->Start(); |
| 528 } |
| 529 } |
| 530 |
| 531 bool PrinterJobHandler::HavePendingTasks() { |
| 532 return server_job_available_ || printer_update_pending_ || |
| 533 printer_delete_pending_; |
| 534 } |
| 535 |
| 536 |
| 537 void PrinterJobHandler::DoPrint(const JobDetails& job_details, |
| 538 const std::string& printer_name, |
| 539 PrinterJobHandler* job_handler, |
| 540 MessageLoop* job_message_loop) { |
| 541 DCHECK(job_handler); |
| 542 DCHECK(job_message_loop); |
| 543 cloud_print::PlatformJobId job_id = -1; |
| 544 if (cloud_print::SpoolPrintJob(job_details.print_ticket_, |
| 545 job_details.print_data_file_path_, |
| 546 job_details.print_data_mime_type_, |
| 547 printer_name, |
| 548 job_details.job_title_, &job_id)) { |
| 549 job_message_loop->PostTask(FROM_HERE, |
| 550 NewRunnableMethod(job_handler, |
| 551 &PrinterJobHandler::JobSpooled, |
| 552 job_id)); |
| 553 } else { |
| 554 job_message_loop->PostTask(FROM_HERE, |
| 555 NewRunnableMethod(job_handler, |
| 556 &PrinterJobHandler::JobFailed, |
| 557 PRINT_FAILED)); |
| 558 } |
| 559 } |
| 560 |
OLD | NEW |