summaryrefslogtreecommitdiffstats
path: root/chrome/service/cloud_print/job_status_updater.cc
blob: dcdca08f71edc2176b2de6e903f363949b07b45f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/service/cloud_print/job_status_updater.h"

#include "base/bind.h"
#include "base/json/json_reader.h"
#include "base/metrics/histogram.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/common/cloud_print/cloud_print_constants.h"
#include "chrome/service/cloud_print/cloud_print_service_helpers.h"
#include "url/gurl.h"

namespace cloud_print {

namespace {

bool IsTerminalJobState(PrintJobStatus status) {
  return status == PRINT_JOB_STATUS_ERROR ||
         status == PRINT_JOB_STATUS_COMPLETED;
}

}  // namespace

JobStatusUpdater::JobStatusUpdater(const std::string& printer_name,
                                   const std::string& job_id,
                                   PlatformJobId& local_job_id,
                                   const GURL& cloud_print_server_url,
                                   PrintSystem* print_system,
                                   Delegate* delegate)
    : start_time_(base::Time::Now()),
      printer_name_(printer_name),
      job_id_(job_id),
      local_job_id_(local_job_id),
      cloud_print_server_url_(cloud_print_server_url),
      print_system_(print_system),
      delegate_(delegate),
      stopped_(false) {
  DCHECK(delegate_);
}

// Start checking the status of the local print job.
void JobStatusUpdater::UpdateStatus() {
  // It does not matter if we had already sent out an update and are waiting for
  // a response. This is a new update and we will simply cancel the old request
  // and send a new one.
  if (!stopped_) {
    bool need_update = false;
    // If the job has already been completed, we just need to update the server
    // with that status. The *only* reason we would come back here in that case
    // is if our last server update attempt failed.
    if (IsTerminalJobState(last_job_details_.status)) {
      need_update = true;
    } else {
      PrintJobDetails details;
      if (print_system_->GetJobDetails(printer_name_, local_job_id_,
                                       &details)) {
        if (details != last_job_details_) {
          last_job_details_ = details;
          need_update = true;
        }
      } else {
        // If GetJobDetails failed, the most likely case is that the job no
        // longer exists in the OS queue. We are going to assume it is done in
        // this case.
        last_job_details_.Clear();
        last_job_details_.status = PRINT_JOB_STATUS_COMPLETED;
        need_update = true;
      }
      UMA_HISTOGRAM_ENUMERATION("CloudPrint.NativeJobStatus",
                                last_job_details_.status, PRINT_JOB_STATUS_MAX);
    }
    if (need_update) {
      request_ = CloudPrintURLFetcher::Create();
      request_->StartGetRequest(
          CloudPrintURLFetcher::REQUEST_UPDATE_JOB,
          GetUrlForJobStatusUpdate(
              cloud_print_server_url_, job_id_, last_job_details_),
          this,
          kCloudPrintAPIMaxRetryCount,
          std::string());
    }
  }
}

void JobStatusUpdater::Stop() {
  request_ = NULL;
  DCHECK(delegate_);
  stopped_ = true;
  delegate_->OnJobCompleted(this);
}

// CloudPrintURLFetcher::Delegate implementation.
CloudPrintURLFetcher::ResponseAction JobStatusUpdater::HandleJSONData(
      const net::URLFetcher* source,
      const GURL& url,
      base::DictionaryValue* json_data,
      bool succeeded) {
  if (IsTerminalJobState(last_job_details_.status)) {
    base::MessageLoop::current()->PostTask(
        FROM_HERE, base::Bind(&JobStatusUpdater::Stop, this));
  }
  return CloudPrintURLFetcher::STOP_PROCESSING;
}

CloudPrintURLFetcher::ResponseAction JobStatusUpdater::OnRequestAuthError() {
  // We got an Auth error and have no idea how long it will take to refresh
  // auth information (may take forever). We'll drop current request and
  // propagate this error to the upper level. After auth issues will be
  // resolved, GCP connector will restart.
  if (delegate_)
    delegate_->OnAuthError();
  return CloudPrintURLFetcher::STOP_PROCESSING;
}

std::string JobStatusUpdater::GetAuthHeader() {
  return GetCloudPrintAuthHeaderFromStore();
}

JobStatusUpdater::~JobStatusUpdater() {}

}  // namespace cloud_print