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 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 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 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
|