Home | History | Annotate | Download | only in cloud_print
      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:
     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 
    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