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