Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #include "nsPagePrintTimer.h"
7 :
8 : #include "mozilla/Unused.h"
9 : #include "nsIContentViewer.h"
10 : #include "nsIServiceManager.h"
11 : #include "nsPrintEngine.h"
12 :
13 : using namespace mozilla;
14 :
15 0 : NS_IMPL_ISUPPORTS_INHERITED(nsPagePrintTimer, mozilla::Runnable, nsITimerCallback)
16 :
17 0 : nsPagePrintTimer::~nsPagePrintTimer()
18 : {
19 : // "Destroy" the document viewer; this normally doesn't actually
20 : // destroy it because of the IncrementDestroyRefCount call below
21 : // XXX This is messy; the document viewer should use a single approach
22 : // to keep itself alive during printing
23 0 : nsCOMPtr<nsIContentViewer> cv(do_QueryInterface(mDocViewerPrint));
24 0 : if (cv) {
25 0 : cv->Destroy();
26 : }
27 0 : }
28 :
29 : nsresult
30 0 : nsPagePrintTimer::StartTimer(bool aUseDelay)
31 : {
32 : nsresult result;
33 0 : mTimer = do_CreateInstance("@mozilla.org/timer;1", &result);
34 0 : if (NS_FAILED(result)) {
35 0 : NS_WARNING("unable to start the timer");
36 : } else {
37 0 : uint32_t delay = 0;
38 0 : if (aUseDelay) {
39 0 : if (mFiringCount < 10) {
40 : // Longer delay for the few first pages.
41 0 : delay = mDelay + ((10 - mFiringCount) * 100);
42 : } else {
43 0 : delay = mDelay;
44 : }
45 : }
46 0 : mTimer->SetTarget(mDocument->EventTargetFor(TaskCategory::Other));
47 0 : mTimer->InitWithCallback(this, delay, nsITimer::TYPE_ONE_SHOT);
48 : }
49 0 : return result;
50 : }
51 :
52 : nsresult
53 0 : nsPagePrintTimer::StartWatchDogTimer()
54 : {
55 : nsresult result;
56 0 : if (mWatchDogTimer) {
57 0 : mWatchDogTimer->Cancel();
58 : }
59 0 : mWatchDogTimer = do_CreateInstance("@mozilla.org/timer;1", &result);
60 0 : if (NS_FAILED(result)) {
61 0 : NS_WARNING("unable to start the timer");
62 : } else {
63 : // Instead of just doing one timer for a long period do multiple so we
64 : // can check if the user cancelled the printing.
65 0 : mWatchDogTimer->SetTarget(mDocument->EventTargetFor(TaskCategory::Other));
66 0 : mWatchDogTimer->InitWithCallback(this, WATCH_DOG_INTERVAL,
67 0 : nsITimer::TYPE_ONE_SHOT);
68 : }
69 0 : return result;
70 : }
71 :
72 : void
73 0 : nsPagePrintTimer::StopWatchDogTimer()
74 : {
75 0 : if (mWatchDogTimer) {
76 0 : mWatchDogTimer->Cancel();
77 0 : mWatchDogTimer = nullptr;
78 : }
79 0 : }
80 :
81 : //nsRunnable
82 : NS_IMETHODIMP
83 0 : nsPagePrintTimer::Run()
84 : {
85 0 : bool initNewTimer = true;
86 : // Check to see if we are done
87 : // inRange will be true if a page is actually printed
88 : bool inRange;
89 : bool donePrinting;
90 :
91 : // donePrinting will be true if it completed successfully or
92 : // if the printing was cancelled
93 0 : donePrinting = !mPrintEngine || mPrintEngine->PrintPage(mPrintObj, inRange);
94 0 : if (donePrinting) {
95 : // now clean up print or print the next webshell
96 0 : if (!mPrintEngine || mPrintEngine->DonePrintingPages(mPrintObj, NS_OK)) {
97 0 : initNewTimer = false;
98 0 : mDone = true;
99 : }
100 : }
101 :
102 : // Note that the Stop() destroys this after the print job finishes
103 : // (The PrintEngine stops holding a reference when DonePrintingPages
104 : // returns true.)
105 0 : Stop();
106 0 : if (initNewTimer) {
107 0 : ++mFiringCount;
108 0 : nsresult result = StartTimer(inRange);
109 0 : if (NS_FAILED(result)) {
110 0 : mDone = true; // had a failure.. we are finished..
111 0 : if (mPrintEngine) {
112 0 : mPrintEngine->SetIsPrinting(false);
113 : }
114 : }
115 : }
116 0 : return NS_OK;
117 : }
118 :
119 : // nsITimerCallback
120 : NS_IMETHODIMP
121 0 : nsPagePrintTimer::Notify(nsITimer *timer)
122 : {
123 : // When finished there may be still pending notifications, which we can just
124 : // ignore.
125 0 : if (mDone) {
126 0 : return NS_OK;
127 : }
128 :
129 : // There are four things that call Notify with different values for timer:
130 : // 1) the delay between pages (timer == mTimer)
131 : // 2) canvasPrintState done (timer == null)
132 : // 3) the watch dog timer (timer == mWatchDogTimer)
133 : // 4) the waiting for remote print "timer" (timer == mWaitingForRemotePrint)
134 0 : if (!timer) {
135 : // Reset the counter since a mozPrintCallback has finished.
136 0 : mWatchDogCount = 0;
137 0 : } else if (timer == mTimer) {
138 : // Reset the watchdog timer before the start of every page.
139 0 : mWatchDogCount = 0;
140 0 : mTimer = nullptr;
141 0 : } else if (timer == mWaitingForRemotePrint) {
142 0 : mWaitingForRemotePrint = nullptr;
143 :
144 : // If we are still waiting for the page delay timer, don't let the
145 : // notification from the remote print job trigger the next page.
146 0 : if (mTimer) {
147 0 : return NS_OK;
148 : }
149 0 : } else if (timer == mWatchDogTimer) {
150 0 : mWatchDogCount++;
151 0 : if (mWatchDogCount > WATCH_DOG_MAX_COUNT) {
152 0 : Fail();
153 0 : return NS_OK;
154 : }
155 : }
156 :
157 0 : if (mDocViewerPrint) {
158 0 : bool donePrePrint = true;
159 0 : if (mPrintEngine) {
160 0 : donePrePrint = mPrintEngine->PrePrintPage();
161 : }
162 :
163 0 : if (donePrePrint && !mWaitingForRemotePrint) {
164 0 : StopWatchDogTimer();
165 : // Pass nullptr here since name already was set in constructor.
166 0 : mDocument->Dispatch(nullptr, TaskCategory::Other, do_AddRef(this));
167 : } else {
168 : // Start the watch dog if we're waiting for preprint to ensure that if any
169 : // mozPrintCallbacks take to long we error out.
170 0 : StartWatchDogTimer();
171 : }
172 :
173 : }
174 0 : return NS_OK;
175 : }
176 :
177 :
178 : void
179 0 : nsPagePrintTimer::WaitForRemotePrint()
180 : {
181 : nsresult result;
182 0 : mWaitingForRemotePrint = do_CreateInstance("@mozilla.org/timer;1", &result);
183 0 : if (NS_FAILED(result)) {
184 0 : NS_WARNING("Failed to wait for remote print, we might time-out.");
185 0 : mWaitingForRemotePrint = nullptr;
186 : }
187 0 : }
188 :
189 : void
190 0 : nsPagePrintTimer::RemotePrintFinished()
191 : {
192 0 : if (!mWaitingForRemotePrint) {
193 0 : return;
194 : }
195 :
196 0 : mWaitingForRemotePrint->SetTarget(
197 0 : mDocument->EventTargetFor(mozilla::TaskCategory::Other));
198 : mozilla::Unused <<
199 0 : mWaitingForRemotePrint->InitWithCallback(this, 0, nsITimer::TYPE_ONE_SHOT);
200 : }
201 :
202 : nsresult
203 0 : nsPagePrintTimer::Start(nsPrintObject* aPO)
204 : {
205 0 : mPrintObj = aPO;
206 0 : mDone = false;
207 0 : return StartTimer(false);
208 : }
209 :
210 :
211 : void
212 0 : nsPagePrintTimer::Stop()
213 : {
214 0 : if (mTimer) {
215 0 : mTimer->Cancel();
216 0 : mTimer = nullptr;
217 : }
218 0 : StopWatchDogTimer();
219 0 : }
220 :
221 : void
222 0 : nsPagePrintTimer::Fail()
223 : {
224 0 : NS_WARNING("nsPagePrintTimer::Fail called");
225 :
226 0 : mDone = true;
227 0 : Stop();
228 0 : if (mPrintEngine) {
229 0 : mPrintEngine->CleanupOnFailure(NS_OK, false);
230 : }
231 0 : }
|