diff options
Diffstat (limited to 'layout/printing/nsPrintJob.h')
-rw-r--r-- | layout/printing/nsPrintJob.h | 311 |
1 files changed, 311 insertions, 0 deletions
diff --git a/layout/printing/nsPrintJob.h b/layout/printing/nsPrintJob.h new file mode 100644 index 0000000000..d2ab0854ba --- /dev/null +++ b/layout/printing/nsPrintJob.h @@ -0,0 +1,311 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef nsPrintJob_h +#define nsPrintJob_h + +#include "mozilla/Attributes.h" +#include "mozilla/layout/RemotePrintJobChild.h" +#include "mozilla/Maybe.h" +#include "mozilla/UniquePtr.h" + +#include "nsCOMPtr.h" + +#include "nsHashKeys.h" +#include "nsIFrame.h" // For WeakFrame +#include "nsSize.h" +#include "nsTArray.h" +#include "nsTHashtable.h" +#include "nsWeakReference.h" + +// Interfaces +#include "nsIWebProgress.h" +#include "nsIWebProgressListener.h" + +// Classes +class nsIFrame; +class nsIPrintSettings; +class nsPrintData; +class nsPagePrintTimer; +class nsIDocShell; +class nsIDocumentViewerPrint; +class nsIFrame; +class nsPrintObject; +class nsIDocShell; +class nsPageSequenceFrame; +class nsPIDOMWindowOuter; +class nsView; + +namespace mozilla { +class PresShell; +namespace dom { +class Document; +class PrintPreviewResultInfo; +} // namespace dom +} // namespace mozilla + +/** + * A print job may be instantiated either for printing to an actual physical + * printer, or for creating a print preview. + */ +class nsPrintJob final : public nsIWebProgressListener, + public nsSupportsWeakReference { + using Document = mozilla::dom::Document; + using PrintPreviewResolver = + std::function<void(const mozilla::dom::PrintPreviewResultInfo&)>; + using RemotePrintJobChild = mozilla::layout::RemotePrintJobChild; + + public: + // nsISupports interface... + NS_DECL_ISUPPORTS + + NS_DECL_NSIWEBPROGRESSLISTENER + + /** + * Construct & initialize for printing, or for creating a print preview + * document. + * + * aDocViewerPrint owns us. + * + * When called in preparation for printing, aOriginalDoc is aDocViewerPrint's + * document. The document/viewer may be for a sub-document (an iframe). + * + * When called in preparation for print preview, aOriginalDoc belongs to a + * different docViewer, in a different docShell, in a different TabGroup. + * In this case our aDocViewerPrint is the docViewer for the about:blank + * document in a new tab that the Firefox frontend code has created in + * preparation for PrintPreview to generate a print preview document in it. + * + * NOTE: In the case we're called for print preview, aOriginalDoc actually + * may not be the original document that the user selected to print. It + * is not the actual original document in the case when the user chooses to + * display a simplified version of a print preview document. In that + * instance the Firefox frontend code creates a second print preview tab, + * with a new docViewer and nsPrintJob, and passes the previous print preview + * document as aOriginalDoc (it doesn't want to pass the actual original + * document since it may have mutated)! + * TODO(dholbert): This^ note is probably somewhat out of date, in part + * because frontend code doesn't create "print preview tabs" anymore, + * now that we have a tab-modal print/print-preview dialog... + */ + nsPrintJob(nsIDocumentViewerPrint& aDocViewerPrint, nsIDocShell& aDocShell, + Document& aOriginalDoc, float aScreenDPI); + + // Our nsIWebBrowserPrint implementation (nsDocumentViewer) defers to the + // following methods. + + /** + * May be called immediately after initialization, or after one or more + * PrintPreview calls. + */ + MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult + Print(Document& aSourceDoc, nsIPrintSettings* aPrintSettings, + RemotePrintJobChild* aRemotePrintJob, + nsIWebProgressListener* aWebProgressListener); + + /** + * Generates a new print preview document and replaces our docViewer's + * document with it. (Note that this breaks the normal invariant that a + * Document and its nsDocumentViewer have an unchanging 1:1 relationship.) + * + * This may be called multiple times on the same instance in order to + * recreate the print preview document to take account of settings that the + * user has changed in the print preview interface. In this case aSourceDoc + * is actually our docViewer's current document! + */ + MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult + PrintPreview(Document& aSourceDoc, nsIPrintSettings* aPrintSettings, + nsIWebProgressListener* aWebProgressListener, + PrintPreviewResolver&& aCallback); + + bool IsDoingPrint() const { return mIsDoingPrinting; } + bool CreatedForPrintPreview() const { return mCreatedForPrintPreview; } + /// If the returned value is not greater than zero, an error occurred. + int32_t GetRawNumPages() const; + // Returns whether the preview is empty due to page range exclusion. + bool GetIsEmpty() const; + + // Returns the total number of PrintedSheetFrames (i.e. faces of a sheet of + // paper) for this print job. (This may be less than the raw number of pages, + // due to pages having been skipped in a page range or combined into a single + // sheet via pages-per-sheet.) + int32_t GetPrintPreviewNumSheets() const; + + // The setters here also update the DocViewer + void SetIsPrinting(bool aIsPrinting); + bool GetIsPrinting() const { return mIsDoingPrinting; } + void SetIsPrintPreview(bool aIsPrintPreview); + bool GetIsCreatingPrintPreview() const { return mIsCreatingPrintPreview; } + + std::tuple<nsPageSequenceFrame*, int32_t> GetSeqFrameAndCountSheets() const; + + bool PrePrintSheet(); + bool PrintSheet(nsPrintObject* aPOect, bool& aInRange); + bool DonePrintingSheets(nsPrintObject* aPO, nsresult aResult); + + nsresult CleanupOnFailure(nsresult aResult, bool aIsPrinting); + // If FinishPrintPreview() fails, caller may need to reset the state of the + // object, for example by calling CleanupOnFailure(). + MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult FinishPrintPreview(); + MOZ_CAN_RUN_SCRIPT_BOUNDARY void FirePrintingErrorEvent(nsresult aPrintError); + + bool CheckBeforeDestroy() const; + nsresult Cancel(); + void Destroy(); + void DestroyPrintingData(); + + private: + nsPrintJob& operator=(const nsPrintJob& aOther) = delete; + + ~nsPrintJob(); + + MOZ_CAN_RUN_SCRIPT nsresult DocumentReadyForPrinting(); + MOZ_CAN_RUN_SCRIPT nsresult SetupToPrintContent(); + nsresult EnablePOsForPrinting(); + + void BuildNestedPrintObjects( + const mozilla::UniquePtr<nsPrintObject>& aParentPO); + + bool PrintDocContent(const mozilla::UniquePtr<nsPrintObject>& aPO, + nsresult& aStatus); + nsresult DoPrint(const mozilla::UniquePtr<nsPrintObject>& aPO); + + nsresult ReflowDocList(const mozilla::UniquePtr<nsPrintObject>& aPO); + + MOZ_CAN_RUN_SCRIPT_BOUNDARY + nsresult ReflowPrintObject(const mozilla::UniquePtr<nsPrintObject>& aPO); + + void CalcNumPrintablePages(int32_t& aNumPages); + + nsresult StartPagePrintTimer(const mozilla::UniquePtr<nsPrintObject>& aPO); + + /// Customizes the behaviour of GetDisplayTitleAndURL. + enum class DocTitleDefault : uint32_t { eDocURLElseFallback, eFallback }; + + /** + * Gets the title and URL of the document for display in save-to-PDF dialogs, + * print spooler lists and page headers/footers. This will get the title/URL + * from the PrintSettings, if set, otherwise it will get them from the + * document. + * + * For the title specifically, if a value is not provided by the settings + * object or the document then, if eDocURLElseFallback is passed, the document + * URL will be returned as the title if it's non-empty (which should always be + * the case). Otherwise a non-empty fallback title will be returned. + */ + static void GetDisplayTitleAndURL(Document& aDoc, nsIPrintSettings* aSettings, + DocTitleDefault aTitleDefault, + nsAString& aTitle, nsAString& aURLStr); + + MOZ_CAN_RUN_SCRIPT nsresult CommonPrint( + bool aIsPrintPreview, nsIPrintSettings* aPrintSettings, + nsIWebProgressListener* aWebProgressListener, Document& aSourceDoc); + + MOZ_CAN_RUN_SCRIPT nsresult DoCommonPrint( + bool aIsPrintPreview, nsIPrintSettings* aPrintSettings, + nsIWebProgressListener* aWebProgressListener, Document& aSourceDoc); + + void FirePrintCompletionEvent(); + + void DisconnectPagePrintTimer(); + + /** + * This method is called to resume printing after all outstanding resources + * referenced by the static clone have finished loading. (It is possibly + * called synchronously if there are no resources to load.) While a static + * clone will generally just be able to reference the (already loaded) + * resources that the original document references, the static clone may + * reference additional resources that have not previously been loaded + * (if it has a 'print' style sheet, for example). + */ + MOZ_CAN_RUN_SCRIPT nsresult + MaybeResumePrintAfterResourcesLoaded(bool aCleanupOnError); + + bool ShouldResumePrint() const; + + nsresult SetRootView(nsPrintObject* aPO, bool& aDoReturn, + bool& aDocumentIsTopLevel, nsSize& aAdjSize); + nsView* GetParentViewForRoot(); + void UpdateZoomRatio(nsPrintObject* aPO); + MOZ_CAN_RUN_SCRIPT nsresult ReconstructAndReflow(); + MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult UpdateSelectionAndShrinkPrintObject( + nsPrintObject* aPO, bool aDocumentIsTopLevel); + MOZ_CAN_RUN_SCRIPT nsresult InitPrintDocConstruction(bool aHandleError); + void FirePrintPreviewUpdateEvent(); + + void PageDone(nsresult aResult); + + nsCOMPtr<nsIPrintSettings> mPrintSettings; + + // The docViewer that owns us, and its docShell. + nsCOMPtr<nsIDocumentViewerPrint> mDocViewerPrint; + nsWeakPtr mDocShell; + + WeakFrame mPageSeqFrame; + + // We are the primary owner of our nsPrintData member vars. These vars + // are refcounted so that functions (e.g. nsPrintData methods) can create + // temporary owning references when they need to fire a callback that + // could conceivably destroy this nsPrintJob owner object and all its + // member-data. + RefPtr<nsPrintData> mPrt; + + RefPtr<nsPagePrintTimer> mPagePrintTimer; + + // Only set if this nsPrintJob was created for a real print. + RefPtr<RemotePrintJobChild> mRemotePrintJob; + + // The root print object. + mozilla::UniquePtr<nsPrintObject> mPrintObject; + + // If there is a focused iframe, mSelectionRoot is set to its nsPrintObject. + // Otherwise, if there is a selection, it is set to the root nsPrintObject. + // Otherwise, it is unset. + nsPrintObject* mSelectionRoot = nullptr; + + // Array of non-owning pointers to all the nsPrintObjects owned by this + // nsPrintJob. This includes mPrintObject, as well as all of its mKids (and + // their mKids, etc.) + nsTArray<nsPrintObject*> mPrintDocList; + + // If the code that initiates a print preview passes a PrintPreviewResolver + // (a std::function) to be notified of the final sheet/page counts (once + // we've sufficiently laid out the document to know what those are), that + // callback is stored here. + PrintPreviewResolver mPrintPreviewCallback; + + // The scale factor that would need to be applied to all pages to make the + // widest page fit without overflowing/clipping. + float mShrinkToFitFactor = 1.0f; + + float mScreenDPI = 115.0f; + + int32_t mNumPrintablePages = 0; + + // Indicates if the page has a specific orientation from @page { size }. + // Stores true if this is landscape, false if this is portrait, or nothing + // if there is no page-size-orientation. + mozilla::Maybe<bool> mMaybeCSSPageLandscape; + + // Indicates if the page has a specific size from @page { size }. + // Stores the page size if one was found. + mozilla::Maybe<nsSize> mMaybeCSSPageSize; + + // If true, indicates that we have started Printing but have not gone to the + // timer to start printing the pages. It gets turned off right before we go + // to the timer. + bool mPreparingForPrint = false; + + bool mCreatedForPrintPreview = false; + bool mIsCreatingPrintPreview = false; + bool mIsDoingPrinting = false; + bool mDidLoadDataForPrinting = false; + bool mShrinkToFit = false; + bool mDoingInitialReflow = false; + bool mIsDestroying = false; + bool mDisallowSelectionPrint = false; +}; + +#endif // nsPrintJob_h |