summaryrefslogtreecommitdiffstats
path: root/chrome/service/cloud_print/printer_job_handler.h
blob: 510136d1b0b4d4241e0accdb815e65d6f8d4abbc (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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
// 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.

#ifndef CHROME_SERVICE_CLOUD_PRINT_PRINTER_JOB_HANDLER_H_
#define CHROME_SERVICE_CLOUD_PRINT_PRINTER_JOB_HANDLER_H_

#include <list>
#include <string>
#include <vector>

#include "base/file_path.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop_proxy.h"
#include "base/threading/thread.h"
#include "base/time.h"
#include "chrome/service/cloud_print/cloud_print_url_fetcher.h"
#include "chrome/service/cloud_print/job_status_updater.h"
#include "chrome/service/cloud_print/printer_job_queue_handler.h"
#include "googleurl/src/gurl.h"
#include "net/url_request/url_request_status.h"
#include "printing/backend/print_backend.h"

class URLFetcher;
// A class that handles cloud print jobs for a particular printer. This class
// imlements a state machine that transitions from Start to various states. The
// various states are shown in the below diagram.
// the status on the server.

//                            Start --> No pending tasks --> Done
//                              |
//                              |
//                              | Have Pending tasks
//                              |
//                              |
//                              | ---Update Pending----->
//                              |                       |
//                              |                       |
//                              |                       |
//                              |                 Update Printer info on server
//                              |                      Go to Stop
//                              |
//                              | Job Available
//                              |
//                              |
//                        Fetch Next Job Metadata
//                        Fetch Print Ticket
//                        Fetch Print Data
//                        Spool Print Job
//                        Create Job StatusUpdater for job
//                        Mark job as "in progress" on server
//     (On any unrecoverable error in any of the above steps go to Stop)
//                        Go to Stop
//                              |
//                              |
//                              |
//                              |
//                              |
//                              |
//                              |
//                             Stop
//               (If there are pending tasks go back to Start)

namespace cloud_print {

class PrinterJobHandler : public base::RefCountedThreadSafe<PrinterJobHandler>,
                          public CloudPrintURLFetcherDelegate,
                          public JobStatusUpdaterDelegate,
                          public PrinterWatcherDelegate,
                          public JobSpoolerDelegate {
 public:
  class Delegate {
   public:
     // Notify delegate about authentication error.
     virtual void OnAuthError() = 0;
     // Notify delegate that printer has been deleted.
     virtual void OnPrinterDeleted(const std::string& printer_name) = 0;

   protected:
     virtual ~Delegate() {}
  };

  struct PrinterInfoFromCloud {
    std::string printer_id;
    std::string caps_hash;
    std::string tags_hash;
  };

  // Begin public interface
  PrinterJobHandler(const printing::PrinterBasicInfo& printer_info,
                    const PrinterInfoFromCloud& printer_info_from_server,
                    const GURL& cloud_print_server_url,
                    PrintSystem* print_system,
                    Delegate* delegate);

  bool Initialize();

  std::string GetPrinterName() const;

  // Requests a job check. |reason| is the reason for fetching the job. Used
  // for logging and diagnostc purposes.
  void CheckForJobs(const std::string& reason);

  // Shutdown everything (the process is exiting).
  void Shutdown();

  base::TimeTicks last_job_fetch_time() const { return last_job_fetch_time_; }
  // End public interface

  // Begin Delegate implementations

  // CloudPrintURLFetcher::Delegate implementation.
  virtual CloudPrintURLFetcher::ResponseAction HandleRawResponse(
      const net::URLFetcher* source,
      const GURL& url,
      const net::URLRequestStatus& status,
      int response_code,
      const net::ResponseCookies& cookies,
      const std::string& data) OVERRIDE;
  virtual CloudPrintURLFetcher::ResponseAction HandleRawData(
      const net::URLFetcher* source,
      const GURL& url,
      const std::string& data) OVERRIDE;
  virtual CloudPrintURLFetcher::ResponseAction HandleJSONData(
      const net::URLFetcher* source,
      const GURL& url,
      base::DictionaryValue* json_data,
      bool succeeded) OVERRIDE;
  virtual void OnRequestGiveUp() OVERRIDE;
  virtual CloudPrintURLFetcher::ResponseAction OnRequestAuthError() OVERRIDE;
  virtual std::string GetAuthHeader() OVERRIDE;

  // JobStatusUpdater::Delegate implementation
  virtual bool OnJobCompleted(JobStatusUpdater* updater) OVERRIDE;
  virtual void OnAuthError() OVERRIDE;

  // PrinterWatcherDelegate implementation
  virtual void OnPrinterDeleted() OVERRIDE;
  virtual void OnPrinterChanged() OVERRIDE;
  virtual void OnJobChanged() OVERRIDE;

  // JobSpoolerDelegate implementation.
  // Called on print_thread_.
  virtual void OnJobSpoolSucceeded(const PlatformJobId& job_id) OVERRIDE;
  virtual void OnJobSpoolFailed() OVERRIDE;

  // End Delegate implementations

 private:
  friend class base::RefCountedThreadSafe<PrinterJobHandler>;

  enum PrintJobError {
    SUCCESS,
    JOB_DOWNLOAD_FAILED,
    INVALID_JOB_DATA,
    PRINT_FAILED,
  };

  // Prototype for a JSON data handler.
  typedef CloudPrintURLFetcher::ResponseAction
      (PrinterJobHandler::*JSONDataHandler)(const net::URLFetcher* source,
                                            const GURL& url,
                                            base::DictionaryValue* json_data,
                                            bool succeeded);
  // Prototype for a data handler.
  typedef CloudPrintURLFetcher::ResponseAction
      (PrinterJobHandler::*DataHandler)(const net::URLFetcher* source,
                                        const GURL& url,
                                        const std::string& data);

  virtual ~PrinterJobHandler();

  // Begin request handlers for each state in the state machine
  CloudPrintURLFetcher::ResponseAction HandlePrinterUpdateResponse(
      const net::URLFetcher* source,
      const GURL& url,
      base::DictionaryValue* json_data,
      bool succeeded);

  CloudPrintURLFetcher::ResponseAction HandleJobMetadataResponse(
      const net::URLFetcher* source,
      const GURL& url,
      base::DictionaryValue* json_data,
      bool succeeded);

  CloudPrintURLFetcher::ResponseAction HandlePrintTicketResponse(
      const net::URLFetcher* source,
      const GURL& url,
      const std::string& data);

  CloudPrintURLFetcher::ResponseAction HandlePrintDataResponse(
      const net::URLFetcher* source,
      const GURL& url,
      const std::string& data);

  CloudPrintURLFetcher::ResponseAction HandleSuccessStatusUpdateResponse(
      const net::URLFetcher* source,
      const GURL& url,
      base::DictionaryValue* json_data,
      bool succeeded);

  CloudPrintURLFetcher::ResponseAction HandleFailureStatusUpdateResponse(
      const net::URLFetcher* source,
      const GURL& url,
      base::DictionaryValue* json_data,
      bool succeeded);
  // End request handlers for each state in the state machine

  // Start the state machine. Based on the flags set this could mean updating
  // printer information, deleting the printer from the server or looking for
  // new print jobs
  void Start();

  // End the state machine. If there are pending tasks, we will post a Start
  // again.
  void Stop();

  void StartPrinting();
  void Reset();
  void UpdateJobStatus(PrintJobStatus status, PrintJobError error);

  // Sets the next response handler to the specifed JSON data handler.
  void SetNextJSONHandler(JSONDataHandler handler);
  // Sets the next response handler to the specifed data handler.
  void SetNextDataHandler(DataHandler handler);

  void JobFailed(PrintJobError error);
  void JobSpooled(PlatformJobId local_job_id);
  // Returns false if printer info is up to date and no updating is needed.
  bool UpdatePrinterInfo();
  bool HavePendingTasks();
  void FailedFetchingJobData();

  // Callback that asynchronously receives printer caps and defaults.
  void OnReceivePrinterCaps(
    bool succeeded,
    const std::string& printer_name,
    const printing::PrinterCapsAndDefaults& caps_and_defaults);

  // Called on print_thread_.
  void DoPrint(const JobDetails& job_details,
               const std::string& printer_name);

  scoped_refptr<CloudPrintURLFetcher> request_;
  scoped_refptr<PrintSystem> print_system_;
  printing::PrinterBasicInfo printer_info_;
  PrinterInfoFromCloud printer_info_cloud_;
  GURL cloud_print_server_url_;
  std::string print_data_url_;
  JobDetails job_details_;
  Delegate* delegate_;
  // Once the job has been spooled to the local spooler, this specifies the
  // job id of the job on the local spooler.
  PlatformJobId local_job_id_;

  // The next response handler can either be a JSONDataHandler or a
  // DataHandler (depending on the current request being made).
  JSONDataHandler next_json_data_handler_;
  DataHandler next_data_handler_;
  // The number of consecutive times that connecting to the server failed.
  int server_error_count_;
  // The thread on which the actual print operation happens
  base::Thread print_thread_;
  // The Job spooler object. This is only non-NULL during a print operation.
  // It lives and dies on |print_thread_|
  scoped_refptr<PrintSystem::JobSpooler> job_spooler_;
  // The message loop proxy representing the thread on which this object
  // was created. Used by the print thread.
  scoped_refptr<base::MessageLoopProxy> job_handler_message_loop_proxy_;

  // There may be pending tasks in the message queue when Shutdown is called.
  // We set this flag so as to do nothing in those tasks.
  bool shutting_down_;

  // A string indicating the reason we are fetching jobs from the server
  // (used to specify the reason in the fetch URL).
  std::string job_fetch_reason_;
  // Flags that specify various pending server updates
  bool job_check_pending_;
  bool printer_update_pending_;

  // Some task in the state machine is in progress.
  bool task_in_progress_;
  scoped_refptr<PrintSystem::PrinterWatcher> printer_watcher_;
  typedef std::list< scoped_refptr<JobStatusUpdater> > JobStatusUpdaterList;
  JobStatusUpdaterList job_status_updater_list_;

  // Manages parsing the job queue
  PrinterJobQueueHandler job_queue_handler_;

  base::TimeTicks last_job_fetch_time_;
  base::WeakPtrFactory<PrinterJobHandler> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN(PrinterJobHandler);
};

// This typedef is to workaround the issue with certain versions of
// Visual Studio where it gets confused between multiple Delegate
// classes and gives a C2500 error. (I saw this error on the try bots -
// the workaround was not needed for my machine).
typedef PrinterJobHandler::Delegate PrinterJobHandlerDelegate;

}  // namespace cloud_print

#endif  // CHROME_SERVICE_CLOUD_PRINT_PRINTER_JOB_HANDLER_H_