• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 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 #ifndef CHROME_SERVICE_CLOUD_PRINT_PRINTER_JOB_HANDLER_H_
6 #define CHROME_SERVICE_CLOUD_PRINT_PRINTER_JOB_HANDLER_H_
7 
8 #include <list>
9 #include <string>
10 #include <vector>
11 
12 #include "base/files/file_path.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/memory/weak_ptr.h"
15 #include "base/message_loop/message_loop_proxy.h"
16 #include "base/threading/thread.h"
17 #include "base/time/time.h"
18 #include "chrome/service/cloud_print/cloud_print_url_fetcher.h"
19 #include "chrome/service/cloud_print/job_status_updater.h"
20 #include "chrome/service/cloud_print/printer_job_queue_handler.h"
21 #include "net/url_request/url_request_status.h"
22 #include "printing/backend/print_backend.h"
23 #include "url/gurl.h"
24 
25 class URLFetcher;
26 // A class that handles cloud print jobs for a particular printer. This class
27 // imlements a state machine that transitions from Start to various states. The
28 // various states are shown in the below diagram.
29 // the status on the server.
30 
31 //                            Start --> No pending tasks --> Done
32 //                              |
33 //                              |
34 //                              | Have Pending tasks
35 //                              |
36 //                              |
37 //                              | ---Update Pending----->
38 //                              |                       |
39 //                              |                       |
40 //                              |                       |
41 //                              |                 Update Printer info on server
42 //                              |                      Go to Stop
43 //                              |
44 //                              | Job Available
45 //                              |
46 //                              |
47 //                        Fetch Next Job Metadata
48 //                        Fetch Print Ticket
49 //                        Fetch Print Data
50 //                        Spool Print Job
51 //                        Create Job StatusUpdater for job
52 //                        Mark job as "in progress" on server
53 //     (On any unrecoverable error in any of the above steps go to Stop)
54 //                        Go to Stop
55 //                              |
56 //                              |
57 //                              |
58 //                              |
59 //                              |
60 //                              |
61 //                              |
62 //                             Stop
63 //               (If there are pending tasks go back to Start)
64 
65 namespace cloud_print {
66 
67 class PrinterJobHandler : public base::RefCountedThreadSafe<PrinterJobHandler>,
68                           public CloudPrintURLFetcherDelegate,
69                           public JobStatusUpdaterDelegate,
70                           public PrintSystem::PrinterWatcher::Delegate,
71                           public PrintSystem::JobSpooler::Delegate {
72  public:
73   class Delegate {
74    public:
75      // Notify delegate about authentication error.
76      virtual void OnAuthError() = 0;
77      // Notify delegate that printer has been deleted.
78      virtual void OnPrinterDeleted(const std::string& printer_name) = 0;
79 
80    protected:
~Delegate()81      virtual ~Delegate() {}
82   };
83 
84   struct PrinterInfoFromCloud {
85     std::string printer_id;
86     std::string caps_hash;
87     std::string tags_hash;
88     int current_xmpp_timeout;
89     int pending_xmpp_timeout;
90 
91     PrinterInfoFromCloud();
92   };
93 
94   // Begin public interface
95   PrinterJobHandler(const printing::PrinterBasicInfo& printer_info,
96                     const PrinterInfoFromCloud& printer_info_from_server,
97                     const GURL& cloud_print_server_url,
98                     PrintSystem* print_system,
99                     Delegate* delegate);
100 
101   bool Initialize();
102 
103   std::string GetPrinterName() const;
104 
105   // Requests a job check. |reason| is the reason for fetching the job. Used
106   // for logging and diagnostc purposes.
107   void CheckForJobs(const std::string& reason);
108 
109   // Shutdown everything (the process is exiting).
110   void Shutdown();
111 
last_job_fetch_time()112   base::TimeTicks last_job_fetch_time() const { return last_job_fetch_time_; }
113   // End public interface
114 
115   // Begin Delegate implementations
116 
117   // CloudPrintURLFetcher::Delegate implementation.
118   virtual CloudPrintURLFetcher::ResponseAction HandleRawResponse(
119       const net::URLFetcher* source,
120       const GURL& url,
121       const net::URLRequestStatus& status,
122       int response_code,
123       const net::ResponseCookies& cookies,
124       const std::string& data) OVERRIDE;
125   virtual CloudPrintURLFetcher::ResponseAction HandleRawData(
126       const net::URLFetcher* source,
127       const GURL& url,
128       const std::string& data) OVERRIDE;
129   virtual CloudPrintURLFetcher::ResponseAction HandleJSONData(
130       const net::URLFetcher* source,
131       const GURL& url,
132       base::DictionaryValue* json_data,
133       bool succeeded) OVERRIDE;
134   virtual void OnRequestGiveUp() OVERRIDE;
135   virtual CloudPrintURLFetcher::ResponseAction OnRequestAuthError() OVERRIDE;
136   virtual std::string GetAuthHeader() OVERRIDE;
137 
138   // JobStatusUpdater::Delegate implementation
139   virtual bool OnJobCompleted(JobStatusUpdater* updater) OVERRIDE;
140   virtual void OnAuthError() OVERRIDE;
141 
142   // PrinterWatcherDelegate implementation
143   virtual void OnPrinterDeleted() OVERRIDE;
144   virtual void OnPrinterChanged() OVERRIDE;
145   virtual void OnJobChanged() OVERRIDE;
146 
147   // JobSpoolerDelegate implementation.
148   // Called on print_thread_.
149   virtual void OnJobSpoolSucceeded(const PlatformJobId& job_id) OVERRIDE;
150   virtual void OnJobSpoolFailed() OVERRIDE;
151 
152   // End Delegate implementations
153 
154   static void ReportsStats();
155 
156  private:
157   friend class base::RefCountedThreadSafe<PrinterJobHandler>;
158 
159   enum PrintJobError {
160     JOB_SUCCESS,
161     JOB_DOWNLOAD_FAILED,
162     JOB_VALIDATE_TICKET_FAILED,
163     JOB_FAILED,
164     JOB_MAX,
165   };
166 
167   // Prototype for a JSON data handler.
168   typedef CloudPrintURLFetcher::ResponseAction
169       (PrinterJobHandler::*JSONDataHandler)(const net::URLFetcher* source,
170                                             const GURL& url,
171                                             base::DictionaryValue* json_data,
172                                             bool succeeded);
173   // Prototype for a data handler.
174   typedef CloudPrintURLFetcher::ResponseAction
175       (PrinterJobHandler::*DataHandler)(const net::URLFetcher* source,
176                                         const GURL& url,
177                                         const std::string& data);
178 
179   virtual ~PrinterJobHandler();
180 
181   // Begin request handlers for each state in the state machine
182   CloudPrintURLFetcher::ResponseAction HandlePrinterUpdateResponse(
183       const net::URLFetcher* source,
184       const GURL& url,
185       base::DictionaryValue* json_data,
186       bool succeeded);
187 
188   CloudPrintURLFetcher::ResponseAction HandleJobMetadataResponse(
189       const net::URLFetcher* source,
190       const GURL& url,
191       base::DictionaryValue* json_data,
192       bool succeeded);
193 
194   CloudPrintURLFetcher::ResponseAction HandlePrintTicketResponse(
195       const net::URLFetcher* source,
196       const GURL& url,
197       const std::string& data);
198 
199   CloudPrintURLFetcher::ResponseAction HandlePrintDataResponse(
200       const net::URLFetcher* source,
201       const GURL& url,
202       const std::string& data);
203 
204   CloudPrintURLFetcher::ResponseAction HandleInProgressStatusUpdateResponse(
205       const net::URLFetcher* source,
206       const GURL& url,
207       base::DictionaryValue* json_data,
208       bool succeeded);
209 
210   CloudPrintURLFetcher::ResponseAction HandleFailureStatusUpdateResponse(
211       const net::URLFetcher* source,
212       const GURL& url,
213       base::DictionaryValue* json_data,
214       bool succeeded);
215   // End request handlers for each state in the state machine
216 
217   // Start the state machine. Based on the flags set this could mean updating
218   // printer information, deleting the printer from the server or looking for
219   // new print jobs
220   void Start();
221 
222   // End the state machine. If there are pending tasks, we will post a Start
223   // again.
224   void Stop();
225 
226   void StartPrinting();
227   void Reset();
228   void UpdateJobStatus(PrintJobStatus status, PrintJobError error);
229 
230   // Run a job check as the result of a scheduled check
231   void RunScheduledJobCheck();
232 
233   // Sets the next response handler to the specified JSON data handler.
234   void SetNextJSONHandler(JSONDataHandler handler);
235   // Sets the next response handler to the specified data handler.
236   void SetNextDataHandler(DataHandler handler);
237 
238   void JobFailed(PrintJobError error);
239   void JobSpooled(PlatformJobId local_job_id);
240   // Returns false if printer info is up to date and no updating is needed.
241   bool UpdatePrinterInfo();
242   bool HavePendingTasks();
243   void ValidatePrintTicketFailed();
244 
245   // Callback that asynchronously receives printer caps and defaults.
246   void OnReceivePrinterCaps(
247     bool succeeded,
248     const std::string& printer_name,
249     const printing::PrinterCapsAndDefaults& caps_and_defaults);
250 
251   // Called on print_thread_.
252   void DoPrint(const JobDetails& job_details,
253                const std::string& printer_name);
254 
255   scoped_refptr<CloudPrintURLFetcher> request_;
256   scoped_refptr<PrintSystem> print_system_;
257   printing::PrinterBasicInfo printer_info_;
258   PrinterInfoFromCloud printer_info_cloud_;
259   GURL cloud_print_server_url_;
260   std::string print_data_url_;
261   JobDetails job_details_;
262   Delegate* delegate_;
263   // Once the job has been spooled to the local spooler, this specifies the
264   // job id of the job on the local spooler.
265   PlatformJobId local_job_id_;
266 
267   // The next response handler can either be a JSONDataHandler or a
268   // DataHandler (depending on the current request being made).
269   JSONDataHandler next_json_data_handler_;
270   DataHandler next_data_handler_;
271   // The number of consecutive times that connecting to the server failed.
272   int server_error_count_;
273   // The thread on which the actual print operation happens
274   base::Thread print_thread_;
275   // The Job spooler object. This is only non-NULL during a print operation.
276   // It lives and dies on |print_thread_|
277   scoped_refptr<PrintSystem::JobSpooler> job_spooler_;
278   // The message loop proxy representing the thread on which this object
279   // was created. Used by the print thread.
280   scoped_refptr<base::MessageLoopProxy> job_handler_message_loop_proxy_;
281 
282   // There may be pending tasks in the message queue when Shutdown is called.
283   // We set this flag so as to do nothing in those tasks.
284   bool shutting_down_;
285 
286   // A string indicating the reason we are fetching jobs from the server
287   // (used to specify the reason in the fetch URL).
288   std::string job_fetch_reason_;
289   // Flags that specify various pending server updates
290   bool job_check_pending_;
291   bool printer_update_pending_;
292 
293   // Number of seconds between XMPP pings (for server registration)
294   int xmpp_ping_interval_;
295 
296   // Some task in the state machine is in progress.
297   bool task_in_progress_;
298   scoped_refptr<PrintSystem::PrinterWatcher> printer_watcher_;
299   typedef std::list< scoped_refptr<JobStatusUpdater> > JobStatusUpdaterList;
300   JobStatusUpdaterList job_status_updater_list_;
301 
302   // Manages parsing the job queue
303   PrinterJobQueueHandler job_queue_handler_;
304 
305   base::TimeTicks last_job_fetch_time_;
306   base::WeakPtrFactory<PrinterJobHandler> weak_ptr_factory_;
307 
308   base::Time job_start_time_;
309   base::Time spooling_start_time_;
310   base::Time last_caps_update_time_;
311 
312   DISALLOW_COPY_AND_ASSIGN(PrinterJobHandler);
313 };
314 
315 // This typedef is to workaround the issue with certain versions of
316 // Visual Studio where it gets confused between multiple Delegate
317 // classes and gives a C2500 error. (I saw this error on the try bots -
318 // the workaround was not needed for my machine).
319 typedef PrinterJobHandler::Delegate PrinterJobHandlerDelegate;
320 
321 }  // namespace cloud_print
322 
323 #endif  // CHROME_SERVICE_CLOUD_PRINT_PRINTER_JOB_HANDLER_H_
324