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