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 PrinterWatcherDelegate,
     71                           public JobSpoolerDelegate {
     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   };
     89 
     90   // Begin public interface
     91   PrinterJobHandler(const printing::PrinterBasicInfo& printer_info,
     92                     const PrinterInfoFromCloud& printer_info_from_server,
     93                     const GURL& cloud_print_server_url,
     94                     PrintSystem* print_system,
     95                     Delegate* delegate);
     96 
     97   bool Initialize();
     98 
     99   std::string GetPrinterName() const;
    100 
    101   // Requests a job check. |reason| is the reason for fetching the job. Used
    102   // for logging and diagnostc purposes.
    103   void CheckForJobs(const std::string& reason);
    104 
    105   // Shutdown everything (the process is exiting).
    106   void Shutdown();
    107 
    108   base::TimeTicks last_job_fetch_time() const { return last_job_fetch_time_; }
    109   // End public interface
    110 
    111   // Begin Delegate implementations
    112 
    113   // CloudPrintURLFetcher::Delegate implementation.
    114   virtual CloudPrintURLFetcher::ResponseAction HandleRawResponse(
    115       const net::URLFetcher* source,
    116       const GURL& url,
    117       const net::URLRequestStatus& status,
    118       int response_code,
    119       const net::ResponseCookies& cookies,
    120       const std::string& data) OVERRIDE;
    121   virtual CloudPrintURLFetcher::ResponseAction HandleRawData(
    122       const net::URLFetcher* source,
    123       const GURL& url,
    124       const std::string& data) OVERRIDE;
    125   virtual CloudPrintURLFetcher::ResponseAction HandleJSONData(
    126       const net::URLFetcher* source,
    127       const GURL& url,
    128       base::DictionaryValue* json_data,
    129       bool succeeded) OVERRIDE;
    130   virtual void OnRequestGiveUp() OVERRIDE;
    131   virtual CloudPrintURLFetcher::ResponseAction OnRequestAuthError() OVERRIDE;
    132   virtual std::string GetAuthHeader() OVERRIDE;
    133 
    134   // JobStatusUpdater::Delegate implementation
    135   virtual bool OnJobCompleted(JobStatusUpdater* updater) OVERRIDE;
    136   virtual void OnAuthError() OVERRIDE;
    137 
    138   // PrinterWatcherDelegate implementation
    139   virtual void OnPrinterDeleted() OVERRIDE;
    140   virtual void OnPrinterChanged() OVERRIDE;
    141   virtual void OnJobChanged() OVERRIDE;
    142 
    143   // JobSpoolerDelegate implementation.
    144   // Called on print_thread_.
    145   virtual void OnJobSpoolSucceeded(const PlatformJobId& job_id) OVERRIDE;
    146   virtual void OnJobSpoolFailed() OVERRIDE;
    147 
    148   // End Delegate implementations
    149 
    150  private:
    151   friend class base::RefCountedThreadSafe<PrinterJobHandler>;
    152 
    153   enum PrintJobError {
    154     SUCCESS,
    155     JOB_DOWNLOAD_FAILED,
    156     INVALID_JOB_DATA,
    157     PRINT_FAILED,
    158   };
    159 
    160   // Prototype for a JSON data handler.
    161   typedef CloudPrintURLFetcher::ResponseAction
    162       (PrinterJobHandler::*JSONDataHandler)(const net::URLFetcher* source,
    163                                             const GURL& url,
    164                                             base::DictionaryValue* json_data,
    165                                             bool succeeded);
    166   // Prototype for a data handler.
    167   typedef CloudPrintURLFetcher::ResponseAction
    168       (PrinterJobHandler::*DataHandler)(const net::URLFetcher* source,
    169                                         const GURL& url,
    170                                         const std::string& data);
    171 
    172   virtual ~PrinterJobHandler();
    173 
    174   // Begin request handlers for each state in the state machine
    175   CloudPrintURLFetcher::ResponseAction HandlePrinterUpdateResponse(
    176       const net::URLFetcher* source,
    177       const GURL& url,
    178       base::DictionaryValue* json_data,
    179       bool succeeded);
    180 
    181   CloudPrintURLFetcher::ResponseAction HandleJobMetadataResponse(
    182       const net::URLFetcher* source,
    183       const GURL& url,
    184       base::DictionaryValue* json_data,
    185       bool succeeded);
    186 
    187   CloudPrintURLFetcher::ResponseAction HandlePrintTicketResponse(
    188       const net::URLFetcher* source,
    189       const GURL& url,
    190       const std::string& data);
    191 
    192   CloudPrintURLFetcher::ResponseAction HandlePrintDataResponse(
    193       const net::URLFetcher* source,
    194       const GURL& url,
    195       const std::string& data);
    196 
    197   CloudPrintURLFetcher::ResponseAction HandleInProgressStatusUpdateResponse(
    198       const net::URLFetcher* source,
    199       const GURL& url,
    200       base::DictionaryValue* json_data,
    201       bool succeeded);
    202 
    203   CloudPrintURLFetcher::ResponseAction HandleFailureStatusUpdateResponse(
    204       const net::URLFetcher* source,
    205       const GURL& url,
    206       base::DictionaryValue* json_data,
    207       bool succeeded);
    208   // End request handlers for each state in the state machine
    209 
    210   // Start the state machine. Based on the flags set this could mean updating
    211   // printer information, deleting the printer from the server or looking for
    212   // new print jobs
    213   void Start();
    214 
    215   // End the state machine. If there are pending tasks, we will post a Start
    216   // again.
    217   void Stop();
    218 
    219   void StartPrinting();
    220   void Reset();
    221   void UpdateJobStatus(PrintJobStatus status, PrintJobError error);
    222 
    223   // Run a job check as the result of a scheduled check
    224   void RunScheduledJobCheck();
    225 
    226   // Sets the next response handler to the specifed JSON data handler.
    227   void SetNextJSONHandler(JSONDataHandler handler);
    228   // Sets the next response handler to the specifed data handler.
    229   void SetNextDataHandler(DataHandler handler);
    230 
    231   void JobFailed(PrintJobError error);
    232   void JobSpooled(PlatformJobId local_job_id);
    233   // Returns false if printer info is up to date and no updating is needed.
    234   bool UpdatePrinterInfo();
    235   bool HavePendingTasks();
    236   void FailedFetchingJobData();
    237 
    238   // Callback that asynchronously receives printer caps and defaults.
    239   void OnReceivePrinterCaps(
    240     bool succeeded,
    241     const std::string& printer_name,
    242     const printing::PrinterCapsAndDefaults& caps_and_defaults);
    243 
    244   // Called on print_thread_.
    245   void DoPrint(const JobDetails& job_details,
    246                const std::string& printer_name);
    247 
    248   scoped_refptr<CloudPrintURLFetcher> request_;
    249   scoped_refptr<PrintSystem> print_system_;
    250   printing::PrinterBasicInfo printer_info_;
    251   PrinterInfoFromCloud printer_info_cloud_;
    252   GURL cloud_print_server_url_;
    253   std::string print_data_url_;
    254   JobDetails job_details_;
    255   Delegate* delegate_;
    256   // Once the job has been spooled to the local spooler, this specifies the
    257   // job id of the job on the local spooler.
    258   PlatformJobId local_job_id_;
    259 
    260   // The next response handler can either be a JSONDataHandler or a
    261   // DataHandler (depending on the current request being made).
    262   JSONDataHandler next_json_data_handler_;
    263   DataHandler next_data_handler_;
    264   // The number of consecutive times that connecting to the server failed.
    265   int server_error_count_;
    266   // The thread on which the actual print operation happens
    267   base::Thread print_thread_;
    268   // The Job spooler object. This is only non-NULL during a print operation.
    269   // It lives and dies on |print_thread_|
    270   scoped_refptr<PrintSystem::JobSpooler> job_spooler_;
    271   // The message loop proxy representing the thread on which this object
    272   // was created. Used by the print thread.
    273   scoped_refptr<base::MessageLoopProxy> job_handler_message_loop_proxy_;
    274 
    275   // There may be pending tasks in the message queue when Shutdown is called.
    276   // We set this flag so as to do nothing in those tasks.
    277   bool shutting_down_;
    278 
    279   // A string indicating the reason we are fetching jobs from the server
    280   // (used to specify the reason in the fetch URL).
    281   std::string job_fetch_reason_;
    282   // Flags that specify various pending server updates
    283   bool job_check_pending_;
    284   bool printer_update_pending_;
    285 
    286   // Some task in the state machine is in progress.
    287   bool task_in_progress_;
    288   scoped_refptr<PrintSystem::PrinterWatcher> printer_watcher_;
    289   typedef std::list< scoped_refptr<JobStatusUpdater> > JobStatusUpdaterList;
    290   JobStatusUpdaterList job_status_updater_list_;
    291 
    292   // Manages parsing the job queue
    293   PrinterJobQueueHandler job_queue_handler_;
    294 
    295   base::TimeTicks last_job_fetch_time_;
    296   base::WeakPtrFactory<PrinterJobHandler> weak_ptr_factory_;
    297 
    298   DISALLOW_COPY_AND_ASSIGN(PrinterJobHandler);
    299 };
    300 
    301 // This typedef is to workaround the issue with certain versions of
    302 // Visual Studio where it gets confused between multiple Delegate
    303 // classes and gives a C2500 error. (I saw this error on the try bots -
    304 // the workaround was not needed for my machine).
    305 typedef PrinterJobHandler::Delegate PrinterJobHandlerDelegate;
    306 
    307 }  // namespace cloud_print
    308 
    309 #endif  // CHROME_SERVICE_CLOUD_PRINT_PRINTER_JOB_HANDLER_H_
    310