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