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