Bug 1858509 add thread-safety annotations around MediaSourceDemuxer::mMonitor r=alwu
[gecko.git] / layout / printing / nsPagePrintTimer.cpp
blob88f4deb3e51faab921656e66ac318e2fe499f050
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,
18 nsITimerCallback)
20 nsPagePrintTimer::nsPagePrintTimer(nsPrintJob* aPrintJob,
21 nsIDocumentViewerPrint* aDocViewerPrint,
22 mozilla::dom::Document* aDocument,
23 uint32_t aDelay)
24 : Runnable("nsPagePrintTimer"),
25 mPrintJob(aPrintJob),
26 mDocViewerPrint(aDocViewerPrint),
27 mDocument(aDocument),
28 mDelay(aDelay),
29 mFiringCount(0),
30 mPrintObj(nullptr),
31 mWatchDogCount(0),
32 mDone(false) {
33 MOZ_ASSERT(aDocViewerPrint && aDocument);
34 mDocViewerPrint->IncrementDestroyBlockedCount();
37 nsPagePrintTimer::~nsPagePrintTimer() { Disconnect(); }
39 void nsPagePrintTimer::Disconnect() {
40 mPrintJob = nullptr;
41 mPrintObj = nullptr;
42 if (mDocViewerPrint) {
43 // This matches the IncrementDestroyBlockedCount call in the constructor.
44 mDocViewerPrint->DecrementDestroyBlockedCount();
45 mDocViewerPrint = nullptr;
49 nsresult nsPagePrintTimer::StartTimer(bool aUseDelay) {
50 uint32_t delay = 0;
51 if (aUseDelay) {
52 if (mFiringCount < 10) {
53 // Longer delay for the few first pages.
54 delay = mDelay + ((10 - mFiringCount) * 100);
55 } else {
56 delay = mDelay;
59 return NS_NewTimerWithCallback(getter_AddRefs(mTimer), this, delay,
60 nsITimer::TYPE_ONE_SHOT,
61 GetMainThreadSerialEventTarget());
64 nsresult nsPagePrintTimer::StartWatchDogTimer() {
65 if (mWatchDogTimer) {
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() {
76 if (mWatchDogTimer) {
77 mWatchDogTimer->Cancel();
78 mWatchDogTimer = nullptr;
82 // nsRunnable
83 NS_IMETHODIMP
84 nsPagePrintTimer::Run() {
85 bool initNewTimer = true;
86 bool donePrinting;
88 // donePrinting will be true if it completed successfully or
89 // if the printing was cancelled
90 donePrinting = !mPrintJob || mPrintJob->PrintSheet(mPrintObj);
91 if (donePrinting) {
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))) {
96 initNewTimer = false;
97 mDone = true;
101 // Note that the Stop() destroys this after the print job finishes
102 // (The nsPrintJob stops holding a reference when DonePrintingSheets
103 // returns true.)
104 Stop();
105 if (initNewTimer) {
106 ++mFiringCount;
107 nsresult result = StartTimer(/*aUseDelay*/ true);
108 if (NS_FAILED(result)) {
109 mDone = true; // had a failure.. we are finished..
110 if (mPrintJob) {
111 mPrintJob->SetIsPrinting(false);
115 return NS_OK;
118 // nsITimerCallback
119 NS_IMETHODIMP
120 nsPagePrintTimer::Notify(nsITimer* timer) {
121 // When finished there may be still pending notifications, which we can just
122 // ignore.
123 if (mDone) {
124 return NS_OK;
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)
132 if (!timer) {
133 // Reset the counter since a mozPrintCallback has finished.
134 mWatchDogCount = 0;
135 } else if (timer == mTimer) {
136 // Reset the watchdog timer before the start of every sheet.
137 mWatchDogCount = 0;
138 mTimer = nullptr;
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.
144 if (mTimer) {
145 return NS_OK;
147 } else if (timer == mWatchDogTimer) {
148 mWatchDogCount++;
149 PROFILER_MARKER_TEXT(
150 "nsPagePrintTimer::Notify", LAYOUT_Printing, {},
151 nsPrintfCString("Watchdog Timer Count %d", mWatchDogCount));
153 if (mWatchDogCount > WATCH_DOG_MAX_COUNT) {
154 Fail();
155 return NS_OK;
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) {
166 StopWatchDogTimer();
167 // Pass nullptr here since name already was set in constructor.
168 mDocument->Dispatch(do_AddRef(this));
169 } else {
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();
175 return NS_OK;
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) {
187 return;
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) {
201 mPrintObj = aPO;
202 mDone = false;
203 return StartTimer(false);
206 void nsPagePrintTimer::Stop() {
207 if (mTimer) {
208 mTimer->Cancel();
209 mTimer = nullptr;
211 StopWatchDogTimer();
214 void nsPagePrintTimer::Fail() {
215 NS_WARNING("nsPagePrintTimer::Fail called");
216 PROFILER_MARKER_TEXT("nsPagePrintTimer", LAYOUT_Printing, {},
217 "nsPagePrintTimer::Fail aborting print operation"_ns);
219 mDone = true;
220 Stop();
221 if (mPrintJob) {
222 mPrintJob->CleanupOnFailure(NS_OK, false);