|
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 #include "nsIContentViewer.h" |
|
8 #include "nsIServiceManager.h" |
|
9 #include "nsPrintEngine.h" |
|
10 |
|
11 NS_IMPL_ISUPPORTS_INHERITED(nsPagePrintTimer, nsRunnable, nsITimerCallback) |
|
12 |
|
13 nsPagePrintTimer::~nsPagePrintTimer() |
|
14 { |
|
15 // "Destroy" the document viewer; this normally doesn't actually |
|
16 // destroy it because of the IncrementDestroyRefCount call below |
|
17 // XXX This is messy; the document viewer should use a single approach |
|
18 // to keep itself alive during printing |
|
19 nsCOMPtr<nsIContentViewer> cv(do_QueryInterface(mDocViewerPrint)); |
|
20 if (cv) { |
|
21 cv->Destroy(); |
|
22 } |
|
23 } |
|
24 |
|
25 nsresult |
|
26 nsPagePrintTimer::StartTimer(bool aUseDelay) |
|
27 { |
|
28 nsresult result; |
|
29 mTimer = do_CreateInstance("@mozilla.org/timer;1", &result); |
|
30 if (NS_FAILED(result)) { |
|
31 NS_WARNING("unable to start the timer"); |
|
32 } else { |
|
33 uint32_t delay = 0; |
|
34 if (aUseDelay) { |
|
35 if (mFiringCount < 10) { |
|
36 // Longer delay for the few first pages. |
|
37 delay = mDelay + ((10 - mFiringCount) * 100); |
|
38 } else { |
|
39 delay = mDelay; |
|
40 } |
|
41 } |
|
42 mTimer->InitWithCallback(this, delay, nsITimer::TYPE_ONE_SHOT); |
|
43 } |
|
44 return result; |
|
45 } |
|
46 |
|
47 nsresult |
|
48 nsPagePrintTimer::StartWatchDogTimer() |
|
49 { |
|
50 nsresult result; |
|
51 if (mWatchDogTimer) { |
|
52 mWatchDogTimer->Cancel(); |
|
53 } |
|
54 mWatchDogTimer = do_CreateInstance("@mozilla.org/timer;1", &result); |
|
55 if (NS_FAILED(result)) { |
|
56 NS_WARNING("unable to start the timer"); |
|
57 } else { |
|
58 // Instead of just doing one timer for a long period do multiple so we |
|
59 // can check if the user cancelled the printing. |
|
60 mWatchDogTimer->InitWithCallback(this, WATCH_DOG_INTERVAL, |
|
61 nsITimer::TYPE_ONE_SHOT); |
|
62 } |
|
63 return result; |
|
64 } |
|
65 |
|
66 void |
|
67 nsPagePrintTimer::StopWatchDogTimer() |
|
68 { |
|
69 if (mWatchDogTimer) { |
|
70 mWatchDogTimer->Cancel(); |
|
71 mWatchDogTimer = nullptr; |
|
72 } |
|
73 } |
|
74 |
|
75 //nsRunnable |
|
76 NS_IMETHODIMP |
|
77 nsPagePrintTimer::Run() |
|
78 { |
|
79 bool initNewTimer = true; |
|
80 // Check to see if we are done |
|
81 // inRange will be true if a page is actually printed |
|
82 bool inRange; |
|
83 bool donePrinting; |
|
84 |
|
85 // donePrinting will be true if it completed successfully or |
|
86 // if the printing was cancelled |
|
87 donePrinting = mPrintEngine->PrintPage(mPrintObj, inRange); |
|
88 if (donePrinting) { |
|
89 // now clean up print or print the next webshell |
|
90 if (mPrintEngine->DonePrintingPages(mPrintObj, NS_OK)) { |
|
91 initNewTimer = false; |
|
92 mDone = true; |
|
93 } |
|
94 } |
|
95 |
|
96 // Note that the Stop() destroys this after the print job finishes |
|
97 // (The PrintEngine stops holding a reference when DonePrintingPages |
|
98 // returns true.) |
|
99 Stop(); |
|
100 if (initNewTimer) { |
|
101 ++mFiringCount; |
|
102 nsresult result = StartTimer(inRange); |
|
103 if (NS_FAILED(result)) { |
|
104 mDone = true; // had a failure.. we are finished.. |
|
105 mPrintEngine->SetIsPrinting(false); |
|
106 } |
|
107 } |
|
108 return NS_OK; |
|
109 } |
|
110 |
|
111 // nsITimerCallback |
|
112 NS_IMETHODIMP |
|
113 nsPagePrintTimer::Notify(nsITimer *timer) |
|
114 { |
|
115 // When finished there may be still pending notifications, which we can just |
|
116 // ignore. |
|
117 if (mDone) { |
|
118 return NS_OK; |
|
119 } |
|
120 |
|
121 // There are three things that call Notify with different values for timer: |
|
122 // 1) the delay between pages (timer == mTimer) |
|
123 // 2) canvasPrintState done (timer == null) |
|
124 // 3) the watch dog timer (timer == mWatchDogTimer) |
|
125 if (timer && timer == mWatchDogTimer) { |
|
126 mWatchDogCount++; |
|
127 if (mWatchDogCount > WATCH_DOG_MAX_COUNT) { |
|
128 Fail(); |
|
129 return NS_OK; |
|
130 } |
|
131 } else if(!timer) { |
|
132 // Reset the counter since a mozPrintCallback has finished. |
|
133 mWatchDogCount = 0; |
|
134 } |
|
135 |
|
136 if (mDocViewerPrint) { |
|
137 bool donePrePrint = mPrintEngine->PrePrintPage(); |
|
138 |
|
139 if (donePrePrint) { |
|
140 StopWatchDogTimer(); |
|
141 NS_DispatchToMainThread(this); |
|
142 } else { |
|
143 // Start the watch dog if we're waiting for preprint to ensure that if any |
|
144 // mozPrintCallbacks take to long we error out. |
|
145 StartWatchDogTimer(); |
|
146 } |
|
147 |
|
148 } |
|
149 return NS_OK; |
|
150 } |
|
151 |
|
152 nsresult |
|
153 nsPagePrintTimer::Start(nsPrintObject* aPO) |
|
154 { |
|
155 mPrintObj = aPO; |
|
156 mWatchDogCount = 0; |
|
157 mDone = false; |
|
158 return StartTimer(false); |
|
159 } |
|
160 |
|
161 |
|
162 void |
|
163 nsPagePrintTimer::Stop() |
|
164 { |
|
165 if (mTimer) { |
|
166 mTimer->Cancel(); |
|
167 mTimer = nullptr; |
|
168 } |
|
169 StopWatchDogTimer(); |
|
170 } |
|
171 |
|
172 void |
|
173 nsPagePrintTimer::Fail() |
|
174 { |
|
175 mDone = true; |
|
176 Stop(); |
|
177 if (mPrintEngine) { |
|
178 mPrintEngine->CleanupOnFailure(NS_OK, false); |
|
179 } |
|
180 } |