15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/service/cloud_print/job_status_updater.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_reader.h" 90f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "base/metrics/histogram.h" 10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/cloud_print/cloud_print_constants.h" 14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/service/cloud_print/cloud_print_service_helpers.h" 157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace cloud_print { 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace { 20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool IsTerminalJobState(PrintJobStatus status) { 22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return status == PRINT_JOB_STATUS_ERROR || 23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) status == PRINT_JOB_STATUS_COMPLETED; 24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} // namespace 27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)JobStatusUpdater::JobStatusUpdater(const std::string& printer_name, 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& job_id, 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PlatformJobId& local_job_id, 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& cloud_print_server_url, 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PrintSystem* print_system, 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Delegate* delegate) 340f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) : start_time_(base::Time::Now()), 350f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) printer_name_(printer_name), 360f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) job_id_(job_id), 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) local_job_id_(local_job_id), 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cloud_print_server_url_(cloud_print_server_url), 390f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) print_system_(print_system), 400f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) delegate_(delegate), 410f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) stopped_(false) { 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(delegate_); 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Start checking the status of the local print job. 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JobStatusUpdater::UpdateStatus() { 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It does not matter if we had already sent out an update and are waiting for 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a response. This is a new update and we will simply cancel the old request 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and send a new one. 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!stopped_) { 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool need_update = false; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the job has already been completed, we just need to update the server 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with that status. The *only* reason we would come back here in that case 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is if our last server update attempt failed. 55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (IsTerminalJobState(last_job_details_.status)) { 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) need_update = true; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PrintJobDetails details; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (print_system_->GetJobDetails(printer_name_, local_job_id_, 600f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) &details)) { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (details != last_job_details_) { 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_job_details_ = details; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) need_update = true; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If GetJobDetails failed, the most likely case is that the job no 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // longer exists in the OS queue. We are going to assume it is done in 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this case. 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_job_details_.Clear(); 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_job_details_.status = PRINT_JOB_STATUS_COMPLETED; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) need_update = true; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 730f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("CloudPrint.NativeJobStatus", 740f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) last_job_details_.status, PRINT_JOB_STATUS_MAX); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (need_update) { 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request_ = CloudPrintURLFetcher::Create(); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_->StartGetRequest( 790f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) CloudPrintURLFetcher::REQUEST_UPDATE_JOB, 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetUrlForJobStatusUpdate( 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cloud_print_server_url_, job_id_, last_job_details_), 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kCloudPrintAPIMaxRetryCount, 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string()); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JobStatusUpdater::Stop() { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_ = NULL; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(delegate_); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stopped_ = true; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->OnJobCompleted(this); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CloudPrintURLFetcher::Delegate implementation. 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CloudPrintURLFetcher::ResponseAction JobStatusUpdater::HandleJSONData( 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLFetcher* source, 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue* json_data, 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool succeeded) { 102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (IsTerminalJobState(last_job_details_.status)) { 103a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::MessageLoop::current()->PostTask( 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, base::Bind(&JobStatusUpdater::Stop, this)); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return CloudPrintURLFetcher::STOP_PROCESSING; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CloudPrintURLFetcher::ResponseAction JobStatusUpdater::OnRequestAuthError() { 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We got an Auth error and have no idea how long it will take to refresh 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // auth information (may take forever). We'll drop current request and 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // propagate this error to the upper level. After auth issues will be 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // resolved, GCP connector will restart. 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (delegate_) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->OnAuthError(); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return CloudPrintURLFetcher::STOP_PROCESSING; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string JobStatusUpdater::GetAuthHeader() { 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return GetCloudPrintAuthHeaderFromStore(); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)JobStatusUpdater::~JobStatusUpdater() {} 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace cloud_print 126