tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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