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_BROWSER_PRINTING_PRINT_JOB_H_ 6 #define CHROME_BROWSER_PRINTING_PRINT_JOB_H_ 7 8 #include "base/basictypes.h" 9 #include "base/memory/scoped_ptr.h" 10 #include "base/memory/weak_ptr.h" 11 #include "base/message_loop/message_loop.h" 12 #include "chrome/browser/printing/print_job_worker_owner.h" 13 #include "content/public/browser/notification_observer.h" 14 #include "content/public/browser/notification_registrar.h" 15 16 class Thread; 17 18 namespace base { 19 class RefCountedMemory; 20 } 21 22 namespace printing { 23 24 class JobEventDetails; 25 class MetafilePlayer; 26 class PdfToEmfConverter; 27 class PrintJobWorker; 28 class PrintedDocument; 29 class PrintedPage; 30 class PrintedPagesSource; 31 class PrinterQuery; 32 33 // Manages the print work for a specific document. Talks to the printer through 34 // PrintingContext through PrintJobWorker. Hides access to PrintingContext in a 35 // worker thread so the caller never blocks. PrintJob will send notifications on 36 // any state change. While printing, the PrintJobManager instance keeps a 37 // reference to the job to be sure it is kept alive. All the code in this class 38 // runs in the UI thread. 39 class PrintJob : public PrintJobWorkerOwner, 40 public content::NotificationObserver { 41 public: 42 // Create a empty PrintJob. When initializing with this constructor, 43 // post-constructor initialization must be done with Initialize(). 44 PrintJob(); 45 46 // Grabs the ownership of the PrintJobWorker from another job, which is 47 // usually a PrinterQuery. Set the expected page count of the print job. 48 void Initialize(PrintJobWorkerOwner* job, PrintedPagesSource* source, 49 int page_count); 50 51 // content::NotificationObserver implementation. 52 virtual void Observe(int type, 53 const content::NotificationSource& source, 54 const content::NotificationDetails& details) OVERRIDE; 55 56 // PrintJobWorkerOwner implementation. 57 virtual void GetSettingsDone(const PrintSettings& new_settings, 58 PrintingContext::Result result) OVERRIDE; 59 virtual PrintJobWorker* DetachWorker(PrintJobWorkerOwner* new_owner) OVERRIDE; 60 virtual const PrintSettings& settings() const OVERRIDE; 61 virtual int cookie() const OVERRIDE; 62 63 // Starts the actual printing. Signals the worker that it should begin to 64 // spool as soon as data is available. 65 void StartPrinting(); 66 67 // Asks for the worker thread to finish its queued tasks and disconnects the 68 // delegate object. The PrintJobManager will remove its reference. This may 69 // have the side-effect of destroying the object if the caller doesn't have a 70 // handle to the object. Use PrintJob::is_stopped() to check whether the 71 // worker thread has actually stopped. 72 void Stop(); 73 74 // Cancels printing job and stops the worker thread. Takes effect immediately. 75 void Cancel(); 76 77 // Synchronously wait for the job to finish. It is mainly useful when the 78 // process is about to be shut down and we're waiting for the spooler to eat 79 // our data. 80 bool FlushJob(base::TimeDelta timeout); 81 82 // Disconnects the PrintedPage source (PrintedPagesSource). It is done when 83 // the source is being destroyed. 84 void DisconnectSource(); 85 86 // Returns true if the print job is pending, i.e. between a StartPrinting() 87 // and the end of the spooling. 88 bool is_job_pending() const; 89 90 // Access the current printed document. Warning: may be NULL. 91 PrintedDocument* document() const; 92 93 #if defined(OS_WIN) 94 void StartPdfToEmfConversion( 95 const scoped_refptr<base::RefCountedMemory>& bytes, 96 const gfx::Size& page_size, 97 const gfx::Rect& content_area); 98 #endif // OS_WIN 99 100 protected: 101 virtual ~PrintJob(); 102 103 private: 104 // Updates document_ to a new instance. 105 void UpdatePrintedDocument(PrintedDocument* new_document); 106 107 // Processes a NOTIFY_PRINT_JOB_EVENT notification. 108 void OnNotifyPrintJobEvent(const JobEventDetails& event_details); 109 110 // Releases the worker thread by calling Stop(), then broadcasts a JOB_DONE 111 // notification. 112 void OnDocumentDone(); 113 114 // Terminates the worker thread in a very controlled way, to work around any 115 // eventual deadlock. 116 void ControlledWorkerShutdown(); 117 118 // Called at shutdown when running a nested message loop. 119 void Quit(); 120 121 void HoldUntilStopIsCalled(); 122 123 #if defined(OS_WIN) 124 void OnPdfToEmfStarted(int page_count); 125 void OnPdfToEmfPageConverted(int page_number, 126 double scale_factor, 127 scoped_ptr<MetafilePlayer> emf); 128 #endif // OS_WIN 129 130 content::NotificationRegistrar registrar_; 131 132 // Source that generates the PrintedPage's (i.e. a WebContents). It will be 133 // set back to NULL if the source is deleted before this object. 134 PrintedPagesSource* source_; 135 136 // All the UI is done in a worker thread because many Win32 print functions 137 // are blocking and enters a message loop without your consent. There is one 138 // worker thread per print job. 139 scoped_ptr<PrintJobWorker> worker_; 140 141 // Cache of the print context settings for access in the UI thread. 142 PrintSettings settings_; 143 144 // The printed document. 145 scoped_refptr<PrintedDocument> document_; 146 147 // Is the worker thread printing. 148 bool is_job_pending_; 149 150 // Is Canceling? If so, try to not cause recursion if on FAILED notification, 151 // the notified calls Cancel() again. 152 bool is_canceling_; 153 154 #if defined(OS_WIN) 155 class PdfToEmfState; 156 scoped_ptr<PdfToEmfState> ptd_to_emf_state_; 157 #endif // OS_WIN 158 159 // Used at shutdown so that we can quit a nested message loop. 160 base::WeakPtrFactory<PrintJob> quit_factory_; 161 162 DISALLOW_COPY_AND_ASSIGN(PrintJob); 163 }; 164 165 // Details for a NOTIFY_PRINT_JOB_EVENT notification. The members may be NULL. 166 class JobEventDetails : public base::RefCountedThreadSafe<JobEventDetails> { 167 public: 168 // Event type. 169 enum Type { 170 // Print... dialog box has been closed with OK button. 171 USER_INIT_DONE, 172 173 // Print... dialog box has been closed with CANCEL button. 174 USER_INIT_CANCELED, 175 176 // An automated initialization has been done, e.g. Init(false, NULL). 177 DEFAULT_INIT_DONE, 178 179 // A new document started printing. 180 NEW_DOC, 181 182 // A new page started printing. 183 NEW_PAGE, 184 185 // A page is done printing. 186 PAGE_DONE, 187 188 // A document is done printing. The worker thread is still alive. Warning: 189 // not a good moment to release the handle to PrintJob. 190 DOC_DONE, 191 192 // The worker thread is finished. A good moment to release the handle to 193 // PrintJob. 194 JOB_DONE, 195 196 // All missing pages have been requested. 197 ALL_PAGES_REQUESTED, 198 199 // An error occured. Printing is canceled. 200 FAILED, 201 }; 202 203 JobEventDetails(Type type, PrintedDocument* document, PrintedPage* page); 204 205 // Getters. 206 PrintedDocument* document() const; 207 PrintedPage* page() const; type()208 Type type() const { 209 return type_; 210 } 211 212 private: 213 friend class base::RefCountedThreadSafe<JobEventDetails>; 214 215 ~JobEventDetails(); 216 217 scoped_refptr<PrintedDocument> document_; 218 scoped_refptr<PrintedPage> page_; 219 const Type type_; 220 221 DISALLOW_COPY_AND_ASSIGN(JobEventDetails); 222 }; 223 224 } // namespace printing 225 226 #endif // CHROME_BROWSER_PRINTING_PRINT_JOB_H_ 227