Home | History | Annotate | Download | only in printing
      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;
    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