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 25class 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 65namespace cloud_print { 66 67class 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 307 base::Time job_start_time_; 308 base::Time spooling_start_time_; 309 base::Time last_caps_update_time_; 310 311 base::WeakPtrFactory<PrinterJobHandler> weak_ptr_factory_; 312 313 DISALLOW_COPY_AND_ASSIGN(PrinterJobHandler); 314}; 315 316// This typedef is to workaround the issue with certain versions of 317// Visual Studio where it gets confused between multiple Delegate 318// classes and gives a C2500 error. (I saw this error on the try bots - 319// the workaround was not needed for my machine). 320typedef PrinterJobHandler::Delegate PrinterJobHandlerDelegate; 321 322} // namespace cloud_print 323 324#endif // CHROME_SERVICE_CLOUD_PRINT_PRINTER_JOB_HANDLER_H_ 325