1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
9 #include "mozilla/Attributes.h"
10 #include "mozilla/layout/RemotePrintJobChild.h"
11 #include "mozilla/Maybe.h"
12 #include "mozilla/UniquePtr.h"
16 #include "nsHashKeys.h"
17 #include "nsIFrame.h" // For WeakFrame
20 #include "nsTHashtable.h"
21 #include "nsWeakReference.h"
24 #include "nsIWebProgress.h"
25 #include "nsIWebProgressListener.h"
29 class nsIPrintSettings
;
31 class nsPagePrintTimer
;
33 class nsIDocumentViewerPrint
;
37 class nsPageSequenceFrame
;
38 class nsPIDOMWindowOuter
;
45 class PrintPreviewResultInfo
;
47 } // namespace mozilla
50 * A print job may be instantiated either for printing to an actual physical
51 * printer, or for creating a print preview.
53 class nsPrintJob final
: public nsIWebProgressListener
,
54 public nsSupportsWeakReference
{
55 using Document
= mozilla::dom::Document
;
56 using PrintPreviewResolver
=
57 std::function
<void(const mozilla::dom::PrintPreviewResultInfo
&)>;
58 using RemotePrintJobChild
= mozilla::layout::RemotePrintJobChild
;
61 // nsISupports interface...
64 NS_DECL_NSIWEBPROGRESSLISTENER
67 * Construct & initialize for printing, or for creating a print preview
70 * aDocViewerPrint owns us.
72 * When called in preparation for printing, aOriginalDoc is aDocViewerPrint's
73 * document. The document/viewer may be for a sub-document (an iframe).
75 * When called in preparation for print preview, aOriginalDoc belongs to a
76 * different docViewer, in a different docShell, in a different TabGroup.
77 * In this case our aDocViewerPrint is the docViewer for the about:blank
78 * document in a new tab that the Firefox frontend code has created in
79 * preparation for PrintPreview to generate a print preview document in it.
81 * NOTE: In the case we're called for print preview, aOriginalDoc actually
82 * may not be the original document that the user selected to print. It
83 * is not the actual original document in the case when the user chooses to
84 * display a simplified version of a print preview document. In that
85 * instance the Firefox frontend code creates a second print preview tab,
86 * with a new docViewer and nsPrintJob, and passes the previous print preview
87 * document as aOriginalDoc (it doesn't want to pass the actual original
88 * document since it may have mutated)!
89 * TODO(dholbert): This^ note is probably somewhat out of date, in part
90 * because frontend code doesn't create "print preview tabs" anymore,
91 * now that we have a tab-modal print/print-preview dialog...
93 nsPrintJob(nsIDocumentViewerPrint
& aDocViewerPrint
, nsIDocShell
& aDocShell
,
94 Document
& aOriginalDoc
, float aScreenDPI
);
96 // Our nsIWebBrowserPrint implementation (nsDocumentViewer) defers to the
100 * May be called immediately after initialization, or after one or more
101 * PrintPreview calls.
103 MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult
104 Print(Document
& aSourceDoc
, nsIPrintSettings
* aPrintSettings
,
105 RemotePrintJobChild
* aRemotePrintJob
,
106 nsIWebProgressListener
* aWebProgressListener
);
109 * Generates a new print preview document and replaces our docViewer's
110 * document with it. (Note that this breaks the normal invariant that a
111 * Document and its nsDocumentViewer have an unchanging 1:1 relationship.)
113 * This may be called multiple times on the same instance in order to
114 * recreate the print preview document to take account of settings that the
115 * user has changed in the print preview interface. In this case aSourceDoc
116 * is actually our docViewer's current document!
118 MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult
119 PrintPreview(Document
& aSourceDoc
, nsIPrintSettings
* aPrintSettings
,
120 nsIWebProgressListener
* aWebProgressListener
,
121 PrintPreviewResolver
&& aCallback
);
123 bool IsDoingPrint() const { return mIsDoingPrinting
; }
124 bool CreatedForPrintPreview() const { return mCreatedForPrintPreview
; }
125 /// If the returned value is not greater than zero, an error occurred.
126 int32_t GetRawNumPages() const;
127 // Returns whether the preview is empty due to page range exclusion.
128 bool GetIsEmpty() const;
130 // Returns the total number of PrintedSheetFrames (i.e. faces of a sheet of
131 // paper) for this print job. (This may be less than the raw number of pages,
132 // due to pages having been skipped in a page range or combined into a single
133 // sheet via pages-per-sheet.)
134 int32_t GetPrintPreviewNumSheets() const;
136 // The setters here also update the DocViewer
137 void SetIsPrinting(bool aIsPrinting
);
138 bool GetIsPrinting() const { return mIsDoingPrinting
; }
139 void SetIsPrintPreview(bool aIsPrintPreview
);
140 bool GetIsCreatingPrintPreview() const { return mIsCreatingPrintPreview
; }
142 std::tuple
<nsPageSequenceFrame
*, int32_t> GetSeqFrameAndCountSheets() const;
144 bool PrePrintSheet();
145 bool PrintSheet(nsPrintObject
* aPOect
);
146 bool DonePrintingSheets(nsPrintObject
* aPO
, nsresult aResult
);
148 nsresult
CleanupOnFailure(nsresult aResult
, bool aIsPrinting
);
149 // If FinishPrintPreview() fails, caller may need to reset the state of the
150 // object, for example by calling CleanupOnFailure().
151 MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult
FinishPrintPreview();
152 MOZ_CAN_RUN_SCRIPT_BOUNDARY
void FirePrintingErrorEvent(nsresult aPrintError
);
154 bool CheckBeforeDestroy() const;
157 void DestroyPrintingData();
160 nsPrintJob
& operator=(const nsPrintJob
& aOther
) = delete;
164 MOZ_CAN_RUN_SCRIPT nsresult
DocumentReadyForPrinting();
165 MOZ_CAN_RUN_SCRIPT nsresult
SetupToPrintContent();
166 nsresult
EnablePOsForPrinting();
168 void BuildNestedPrintObjects(
169 const mozilla::UniquePtr
<nsPrintObject
>& aParentPO
);
171 bool PrintDocContent(const mozilla::UniquePtr
<nsPrintObject
>& aPO
,
173 nsresult
DoPrint(const mozilla::UniquePtr
<nsPrintObject
>& aPO
);
175 nsresult
ReflowDocList(const mozilla::UniquePtr
<nsPrintObject
>& aPO
);
177 MOZ_CAN_RUN_SCRIPT_BOUNDARY
178 nsresult
ReflowPrintObject(const mozilla::UniquePtr
<nsPrintObject
>& aPO
);
180 void CalcNumPrintablePages(int32_t& aNumPages
);
182 nsresult
StartPagePrintTimer(const mozilla::UniquePtr
<nsPrintObject
>& aPO
);
184 /// Customizes the behaviour of GetDisplayTitleAndURL.
185 enum class DocTitleDefault
: uint32_t { eDocURLElseFallback
, eFallback
};
188 * Gets the title and URL of the document for display in save-to-PDF dialogs,
189 * print spooler lists and page headers/footers. This will get the title/URL
190 * from the PrintSettings, if set, otherwise it will get them from the
193 * For the title specifically, if a value is not provided by the settings
194 * object or the document then, if eDocURLElseFallback is passed, the document
195 * URL will be returned as the title if it's non-empty (which should always be
196 * the case). Otherwise a non-empty fallback title will be returned.
198 static void GetDisplayTitleAndURL(Document
& aDoc
, nsIPrintSettings
* aSettings
,
199 DocTitleDefault aTitleDefault
,
200 nsAString
& aTitle
, nsAString
& aURLStr
);
202 MOZ_CAN_RUN_SCRIPT nsresult
CommonPrint(
203 bool aIsPrintPreview
, nsIPrintSettings
* aPrintSettings
,
204 nsIWebProgressListener
* aWebProgressListener
, Document
& aSourceDoc
);
206 MOZ_CAN_RUN_SCRIPT nsresult
DoCommonPrint(
207 bool aIsPrintPreview
, nsIPrintSettings
* aPrintSettings
,
208 nsIWebProgressListener
* aWebProgressListener
, Document
& aSourceDoc
);
210 void FirePrintCompletionEvent();
212 void DisconnectPagePrintTimer();
215 * This method is called to resume printing after all outstanding resources
216 * referenced by the static clone have finished loading. (It is possibly
217 * called synchronously if there are no resources to load.) While a static
218 * clone will generally just be able to reference the (already loaded)
219 * resources that the original document references, the static clone may
220 * reference additional resources that have not previously been loaded
221 * (if it has a 'print' style sheet, for example).
223 MOZ_CAN_RUN_SCRIPT nsresult
224 MaybeResumePrintAfterResourcesLoaded(bool aCleanupOnError
);
226 bool ShouldResumePrint() const;
228 nsresult
SetRootView(nsPrintObject
* aPO
, bool& aDoReturn
,
229 bool& aDocumentIsTopLevel
, nsSize
& aAdjSize
);
230 nsView
* GetParentViewForRoot();
231 void UpdateZoomRatio(nsPrintObject
* aPO
);
232 MOZ_CAN_RUN_SCRIPT nsresult
ReconstructAndReflow();
233 MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult
UpdateSelectionAndShrinkPrintObject(
234 nsPrintObject
* aPO
, bool aDocumentIsTopLevel
);
235 MOZ_CAN_RUN_SCRIPT nsresult
InitPrintDocConstruction(bool aHandleError
);
236 void FirePrintPreviewUpdateEvent();
238 void PageDone(nsresult aResult
);
240 nsCOMPtr
<nsIPrintSettings
> mPrintSettings
;
242 // The docViewer that owns us, and its docShell.
243 nsCOMPtr
<nsIDocumentViewerPrint
> mDocViewerPrint
;
246 WeakFrame mPageSeqFrame
;
248 // We are the primary owner of our nsPrintData member vars. These vars
249 // are refcounted so that functions (e.g. nsPrintData methods) can create
250 // temporary owning references when they need to fire a callback that
251 // could conceivably destroy this nsPrintJob owner object and all its
253 RefPtr
<nsPrintData
> mPrt
;
255 RefPtr
<nsPagePrintTimer
> mPagePrintTimer
;
257 // Only set if this nsPrintJob was created for a real print.
258 RefPtr
<RemotePrintJobChild
> mRemotePrintJob
;
260 // The root print object.
261 mozilla::UniquePtr
<nsPrintObject
> mPrintObject
;
263 // If there is a focused iframe, mSelectionRoot is set to its nsPrintObject.
264 // Otherwise, if there is a selection, it is set to the root nsPrintObject.
265 // Otherwise, it is unset.
266 nsPrintObject
* mSelectionRoot
= nullptr;
268 // Array of non-owning pointers to all the nsPrintObjects owned by this
269 // nsPrintJob. This includes mPrintObject, as well as all of its mKids (and
270 // their mKids, etc.)
271 nsTArray
<nsPrintObject
*> mPrintDocList
;
273 // If the code that initiates a print preview passes a PrintPreviewResolver
274 // (a std::function) to be notified of the final sheet/page counts (once
275 // we've sufficiently laid out the document to know what those are), that
276 // callback is stored here.
277 PrintPreviewResolver mPrintPreviewCallback
;
279 // The scale factor that would need to be applied to all pages to make the
280 // widest page fit without overflowing/clipping.
281 float mShrinkToFitFactor
= 1.0f
;
283 float mScreenDPI
= 115.0f
;
285 int32_t mNumPrintablePages
= 0;
287 // Indicates if the page has a specific orientation from @page { size }.
288 // Stores true if this is landscape, false if this is portrait, or nothing
289 // if there is no page-size-orientation.
290 mozilla::Maybe
<bool> mMaybeCSSPageLandscape
;
292 // Indicates if the page has a specific size from @page { size }.
293 // Stores the page size if one was found.
294 mozilla::Maybe
<nsSize
> mMaybeCSSPageSize
;
296 // If true, indicates that we have started Printing but have not gone to the
297 // timer to start printing the pages. It gets turned off right before we go
299 bool mPreparingForPrint
= false;
301 bool mCreatedForPrintPreview
= false;
302 bool mIsCreatingPrintPreview
= false;
303 bool mIsDoingPrinting
= false;
304 bool mDidLoadDataForPrinting
= false;
305 bool mShrinkToFit
= false;
306 bool mDoingInitialReflow
= false;
307 bool mIsDestroying
= false;
308 bool mDisallowSelectionPrint
= false;
311 #endif // nsPrintJob_h