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/. */
7 #include "nsPagePrintTimer.h"
9 #include "mozilla/dom/Document.h"
10 #include "mozilla/ProfilerMarkers.h"
11 #include "mozilla/Unused.h"
12 #include "nsPrintJob.h"
13 #include "nsPrintObject.h"
15 using namespace mozilla
;
17 NS_IMPL_ISUPPORTS_INHERITED(nsPagePrintTimer
, mozilla::Runnable
,
20 nsPagePrintTimer::nsPagePrintTimer(nsPrintJob
* aPrintJob
,
21 nsIDocumentViewerPrint
* aDocViewerPrint
,
22 mozilla::dom::Document
* aDocument
,
24 : Runnable("nsPagePrintTimer"),
26 mDocViewerPrint(aDocViewerPrint
),
33 MOZ_ASSERT(aDocViewerPrint
&& aDocument
);
34 mDocViewerPrint
->IncrementDestroyBlockedCount();
37 nsPagePrintTimer::~nsPagePrintTimer() { Disconnect(); }
39 void nsPagePrintTimer::Disconnect() {
42 if (mDocViewerPrint
) {
43 // This matches the IncrementDestroyBlockedCount call in the constructor.
44 mDocViewerPrint
->DecrementDestroyBlockedCount();
45 mDocViewerPrint
= nullptr;
49 nsresult
nsPagePrintTimer::StartTimer(bool aUseDelay
) {
52 if (mFiringCount
< 10) {
53 // Longer delay for the few first pages.
54 delay
= mDelay
+ ((10 - mFiringCount
) * 100);
59 return NS_NewTimerWithCallback(getter_AddRefs(mTimer
), this, delay
,
60 nsITimer::TYPE_ONE_SHOT
,
61 GetMainThreadSerialEventTarget());
64 nsresult
nsPagePrintTimer::StartWatchDogTimer() {
66 mWatchDogTimer
->Cancel();
68 // Instead of just doing one timer for a long period do multiple so we
69 // can check if the user cancelled the printing.
70 return NS_NewTimerWithCallback(getter_AddRefs(mWatchDogTimer
), this,
71 WATCH_DOG_INTERVAL
, nsITimer::TYPE_ONE_SHOT
,
72 GetMainThreadSerialEventTarget());
75 void nsPagePrintTimer::StopWatchDogTimer() {
77 mWatchDogTimer
->Cancel();
78 mWatchDogTimer
= nullptr;
84 nsPagePrintTimer::Run() {
85 bool initNewTimer
= true;
88 // donePrinting will be true if it completed successfully or
89 // if the printing was cancelled
90 donePrinting
= !mPrintJob
|| mPrintJob
->PrintSheet(mPrintObj
);
92 if (mWaitingForRemotePrint
||
93 // If we are not waiting for the remote printing, it is the time to
94 // end printing task by calling DonePrintingSheets.
95 (!mPrintJob
|| mPrintJob
->DonePrintingSheets(mPrintObj
, NS_OK
))) {
101 // Note that the Stop() destroys this after the print job finishes
102 // (The nsPrintJob stops holding a reference when DonePrintingSheets
107 nsresult result
= StartTimer(/*aUseDelay*/ true);
108 if (NS_FAILED(result
)) {
109 mDone
= true; // had a failure.. we are finished..
111 mPrintJob
->SetIsPrinting(false);
120 nsPagePrintTimer::Notify(nsITimer
* timer
) {
121 // When finished there may be still pending notifications, which we can just
127 // There are four things that call Notify with different values for timer:
128 // 1) the delay between sheets (timer == mTimer)
129 // 2) canvasPrintState done (timer == null)
130 // 3) the watch dog timer (timer == mWatchDogTimer)
131 // 4) the waiting for remote print "timer" (timer == mWaitingForRemotePrint)
133 // Reset the counter since a mozPrintCallback has finished.
135 } else if (timer
== mTimer
) {
136 // Reset the watchdog timer before the start of every sheet.
139 } else if (timer
== mWaitingForRemotePrint
) {
140 mWaitingForRemotePrint
= nullptr;
142 // If we are still waiting for the sheet delay timer, don't let the
143 // notification from the remote print job trigger the next sheet.
147 } else if (timer
== mWatchDogTimer
) {
149 PROFILER_MARKER_TEXT(
150 "nsPagePrintTimer::Notify", LAYOUT_Printing
, {},
151 nsPrintfCString("Watchdog Timer Count %d", mWatchDogCount
));
153 if (mWatchDogCount
> WATCH_DOG_MAX_COUNT
) {
159 bool donePrePrint
= true;
160 // Don't start to pre-print if we're waiting on the parent still.
161 if (mPrintJob
&& !mWaitingForRemotePrint
) {
162 donePrePrint
= mPrintJob
->PrePrintSheet();
165 if (donePrePrint
&& !mWaitingForRemotePrint
) {
167 // Pass nullptr here since name already was set in constructor.
168 mDocument
->Dispatch(do_AddRef(this));
170 // Start the watch dog if we're waiting for preprint to ensure that if any
171 // mozPrintCallbacks take to long we error out.
172 StartWatchDogTimer();
178 void nsPagePrintTimer::WaitForRemotePrint() {
179 mWaitingForRemotePrint
= NS_NewTimer();
180 if (!mWaitingForRemotePrint
) {
181 NS_WARNING("Failed to wait for remote print, we might time-out.");
185 void nsPagePrintTimer::RemotePrintFinished() {
186 if (!mWaitingForRemotePrint
) {
190 // now clean up print or print the next webshell
191 if (mDone
&& mPrintJob
) {
192 mDone
= mPrintJob
->DonePrintingSheets(mPrintObj
, NS_OK
);
195 mWaitingForRemotePrint
->SetTarget(GetMainThreadSerialEventTarget());
196 mozilla::Unused
<< mWaitingForRemotePrint
->InitWithCallback(
197 this, 0, nsITimer::TYPE_ONE_SHOT
);
200 nsresult
nsPagePrintTimer::Start(nsPrintObject
* aPO
) {
203 return StartTimer(false);
206 void nsPagePrintTimer::Stop() {
214 void nsPagePrintTimer::Fail() {
215 NS_WARNING("nsPagePrintTimer::Fail called");
216 PROFILER_MARKER_TEXT("nsPagePrintTimer", LAYOUT_Printing
, {},
217 "nsPagePrintTimer::Fail aborting print operation"_ns
);
222 mPrintJob
->CleanupOnFailure(NS_OK
, false);