| // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CHROME_SERVICE_CLOUD_PRINT_PRINTER_JOB_HANDLER_H_ |
| #define CHROME_SERVICE_CLOUD_PRINT_PRINTER_JOB_HANDLER_H_ |
| #pragma once |
| |
| #include <list> |
| #include <string> |
| #include <vector> |
| |
| #include "base/file_path.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/message_loop_proxy.h" |
| #include "base/threading/thread.h" |
| #include "base/time.h" |
| #include "chrome/service/cloud_print/cloud_print_url_fetcher.h" |
| #include "chrome/service/cloud_print/job_status_updater.h" |
| #include "googleurl/src/gurl.h" |
| #include "net/url_request/url_request_status.h" |
| #include "printing/backend/print_backend.h" |
| |
| class URLFetcher; |
| // A class that handles cloud print jobs for a particular printer. This class |
| // imlements a state machine that transitions from Start to various states. The |
| // various states are shown in the below diagram. |
| // the status on the server. |
| |
| // Start --> No pending tasks --> Done |
| // | |
| // | |
| // | Have Pending tasks |
| // | |
| // | |
| // <----Delete Pending -- | ---Update Pending-----> |
| // | | | |
| // | | | |
| // | | | |
| // Delete Printer from server | Update Printer info on server |
| // Shutdown | Go to Stop |
| // | |
| // | Job Available |
| // | |
| // | |
| // Fetch Next Job Metadata |
| // Fetch Print Ticket |
| // Fetch Print Data |
| // Spool Print Job |
| // Create Job StatusUpdater for job |
| // Mark job as "in progress" on server |
| // (On any unrecoverable error in any of the above steps go to Stop) |
| // Go to Stop |
| // | |
| // | |
| // | |
| // | |
| // | |
| // | |
| // | |
| // Stop |
| // (If there are pending tasks go back to Start) |
| |
| class PrinterJobHandler : public base::RefCountedThreadSafe<PrinterJobHandler>, |
| public CloudPrintURLFetcherDelegate, |
| public JobStatusUpdaterDelegate, |
| public cloud_print::PrinterWatcherDelegate, |
| public cloud_print::JobSpoolerDelegate { |
| enum PrintJobError { |
| SUCCESS, |
| JOB_DOWNLOAD_FAILED, |
| INVALID_JOB_DATA, |
| PRINT_FAILED, |
| }; |
| struct JobDetails { |
| JobDetails(); |
| ~JobDetails(); |
| void Clear(); |
| |
| std::string job_id_; |
| std::string job_title_; |
| std::string print_ticket_; |
| FilePath print_data_file_path_; |
| std::string print_data_mime_type_; |
| std::vector<std::string> tags_; |
| }; |
| |
| public: |
| class Delegate { |
| public: |
| virtual void OnPrinterJobHandlerShutdown( |
| PrinterJobHandler* job_handler, const std::string& printer_id) = 0; |
| virtual void OnAuthError() = 0; |
| // Called when the PrinterJobHandler cannot find the printer locally. The |
| // delegate returns |delete_from_server| to true if the printer should be |
| // deleted from the server,false otherwise. |
| virtual void OnPrinterNotFound(const std::string& printer_name, |
| bool* delete_from_server) = 0; |
| |
| protected: |
| virtual ~Delegate() {} |
| }; |
| |
| struct PrinterInfoFromCloud { |
| std::string printer_id; |
| std::string caps_hash; |
| std::string tags_hash; |
| }; |
| |
| // Begin public interface |
| PrinterJobHandler(const printing::PrinterBasicInfo& printer_info, |
| const PrinterInfoFromCloud& printer_info_from_server, |
| const GURL& cloud_print_server_url, |
| cloud_print::PrintSystem* print_system, |
| Delegate* delegate); |
| virtual ~PrinterJobHandler(); |
| bool Initialize(); |
| // Requests a job check. |reason| is the reason for fetching the job. Used |
| // for logging and diagnostc purposes. |
| void CheckForJobs(const std::string& reason); |
| // Shutdown everything (the process is exiting). |
| void Shutdown(); |
| base::TimeTicks last_job_fetch_time() const { return last_job_fetch_time_; } |
| // End public interface |
| |
| // Begin Delegate implementations |
| |
| // CloudPrintURLFetcher::Delegate implementation. |
| virtual CloudPrintURLFetcher::ResponseAction HandleRawResponse( |
| const content::URLFetcher* source, |
| const GURL& url, |
| const net::URLRequestStatus& status, |
| int response_code, |
| const net::ResponseCookies& cookies, |
| const std::string& data); |
| virtual CloudPrintURLFetcher::ResponseAction HandleRawData( |
| const content::URLFetcher* source, |
| const GURL& url, |
| const std::string& data); |
| virtual CloudPrintURLFetcher::ResponseAction HandleJSONData( |
| const content::URLFetcher* source, |
| const GURL& url, |
| base::DictionaryValue* json_data, |
| bool succeeded); |
| virtual void OnRequestGiveUp(); |
| virtual void OnRequestAuthError(); |
| |
| // JobStatusUpdater::Delegate implementation |
| virtual bool OnJobCompleted(JobStatusUpdater* updater); |
| virtual void OnAuthError(); |
| |
| // cloud_print::PrinterWatcherDelegate implementation |
| virtual void OnPrinterDeleted(); |
| virtual void OnPrinterChanged(); |
| virtual void OnJobChanged(); |
| |
| // cloud_print::JobSpoolerDelegate implementation. |
| // Called on print_thread_. |
| virtual void OnJobSpoolSucceeded(const cloud_print::PlatformJobId& job_id); |
| virtual void OnJobSpoolFailed(); |
| |
| // End Delegate implementations |
| |
| private: |
| // Prototype for a JSON data handler. |
| typedef CloudPrintURLFetcher::ResponseAction |
| (PrinterJobHandler::*JSONDataHandler)(const content::URLFetcher* source, |
| const GURL& url, |
| base::DictionaryValue* json_data, |
| bool succeeded); |
| // Prototype for a data handler. |
| typedef CloudPrintURLFetcher::ResponseAction |
| (PrinterJobHandler::*DataHandler)(const content::URLFetcher* source, |
| const GURL& url, |
| const std::string& data); |
| // Begin request handlers for each state in the state machine |
| CloudPrintURLFetcher::ResponseAction HandlePrinterUpdateResponse( |
| const content::URLFetcher* source, |
| const GURL& url, |
| base::DictionaryValue* json_data, |
| bool succeeded); |
| |
| CloudPrintURLFetcher::ResponseAction HandlePrinterDeleteResponse( |
| const content::URLFetcher* source, |
| const GURL& url, |
| base::DictionaryValue* json_data, |
| bool succeeded); |
| |
| CloudPrintURLFetcher::ResponseAction HandleJobMetadataResponse( |
| const content::URLFetcher* source, |
| const GURL& url, |
| base::DictionaryValue* json_data, |
| bool succeeded); |
| |
| CloudPrintURLFetcher::ResponseAction HandlePrintTicketResponse( |
| const content::URLFetcher* source, |
| const GURL& url, |
| const std::string& data); |
| |
| CloudPrintURLFetcher::ResponseAction HandlePrintDataResponse( |
| const content::URLFetcher* source, |
| const GURL& url, |
| const std::string& data); |
| |
| CloudPrintURLFetcher::ResponseAction HandleSuccessStatusUpdateResponse( |
| const content::URLFetcher* source, |
| const GURL& url, |
| base::DictionaryValue* json_data, |
| bool succeeded); |
| |
| CloudPrintURLFetcher::ResponseAction HandleFailureStatusUpdateResponse( |
| const content::URLFetcher* source, |
| const GURL& url, |
| base::DictionaryValue* json_data, |
| bool succeeded); |
| // End request handlers for each state in the state machine |
| |
| // Start the state machine. Based on the flags set this could mean updating |
| // printer information, deleting the printer from the server or looking for |
| // new print jobs |
| void Start(); |
| |
| // End the state machine. If there are pending tasks, we will post a Start |
| // again. |
| void Stop(); |
| |
| void StartPrinting(); |
| void HandleServerError(const GURL& url); |
| void Reset(); |
| void UpdateJobStatus(cloud_print::PrintJobStatus status, PrintJobError error); |
| |
| // Sets the next response handler to the specifed JSON data handler. |
| void SetNextJSONHandler(JSONDataHandler handler); |
| // Sets the next response handler to the specifed data handler. |
| void SetNextDataHandler(DataHandler handler); |
| |
| void JobFailed(PrintJobError error); |
| void JobSpooled(cloud_print::PlatformJobId local_job_id); |
| // Returns false if printer info is up to date and no updating is needed. |
| bool UpdatePrinterInfo(); |
| bool HavePendingTasks(); |
| void FailedFetchingJobData(); |
| |
| // Callback that asynchronously receives printer caps and defaults. |
| void OnReceivePrinterCaps( |
| bool succeeded, |
| const std::string& printer_name, |
| const printing::PrinterCapsAndDefaults& caps_and_defaults); |
| |
| // Called on print_thread_. |
| void DoPrint(const JobDetails& job_details, |
| const std::string& printer_name); |
| |
| scoped_refptr<CloudPrintURLFetcher> request_; |
| scoped_refptr<cloud_print::PrintSystem> print_system_; |
| printing::PrinterBasicInfo printer_info_; |
| PrinterInfoFromCloud printer_info_cloud_; |
| GURL cloud_print_server_url_; |
| std::string print_data_url_; |
| JobDetails job_details_; |
| Delegate* delegate_; |
| // Once the job has been spooled to the local spooler, this specifies the |
| // job id of the job on the local spooler. |
| cloud_print::PlatformJobId local_job_id_; |
| |
| // The next response handler can either be a JSONDataHandler or a |
| // DataHandler (depending on the current request being made). |
| JSONDataHandler next_json_data_handler_; |
| DataHandler next_data_handler_; |
| // The number of consecutive times that connecting to the server failed. |
| int server_error_count_; |
| // The thread on which the actual print operation happens |
| base::Thread print_thread_; |
| // The Job spooler object. This is only non-NULL during a print operation. |
| // It lives and dies on |print_thread_| |
| scoped_refptr<cloud_print::PrintSystem::JobSpooler> job_spooler_; |
| // The message loop proxy representing the thread on which this object |
| // was created. Used by the print thread. |
| scoped_refptr<base::MessageLoopProxy> job_handler_message_loop_proxy_; |
| |
| // There may be pending tasks in the message queue when Shutdown is called. |
| // We set this flag so as to do nothing in those tasks. |
| bool shutting_down_; |
| |
| // A string indicating the reason we are fetching jobs from the server |
| // (used to specify the reason in the fetch URL). |
| std::string job_fetch_reason_; |
| // Flags that specify various pending server updates |
| bool job_check_pending_; |
| bool printer_update_pending_; |
| bool printer_delete_pending_; |
| |
| // Some task in the state machine is in progress. |
| bool task_in_progress_; |
| scoped_refptr<cloud_print::PrintSystem::PrinterWatcher> printer_watcher_; |
| typedef std::list< scoped_refptr<JobStatusUpdater> > JobStatusUpdaterList; |
| JobStatusUpdaterList job_status_updater_list_; |
| |
| base::TimeTicks last_job_fetch_time_; |
| |
| DISALLOW_COPY_AND_ASSIGN(PrinterJobHandler); |
| }; |
| |
| // This typedef is to workaround the issue with certain versions of |
| // Visual Studio where it gets confused between multiple Delegate |
| // classes and gives a C2500 error. (I saw this error on the try bots - |
| // the workaround was not needed for my machine). |
| typedef PrinterJobHandler::Delegate PrinterJobHandlerDelegate; |
| |
| #endif // CHROME_SERVICE_CLOUD_PRINT_PRINTER_JOB_HANDLER_H_ |