Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
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/. */
6 #include "nsPagePrintTimer.h"
7 #include "nsIContentViewer.h"
8 #include "nsIServiceManager.h"
9 #include "nsPrintEngine.h"
11 NS_IMPL_ISUPPORTS_INHERITED(nsPagePrintTimer, nsRunnable, nsITimerCallback)
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 }
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 }
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 }
66 void
67 nsPagePrintTimer::StopWatchDogTimer()
68 {
69 if (mWatchDogTimer) {
70 mWatchDogTimer->Cancel();
71 mWatchDogTimer = nullptr;
72 }
73 }
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;
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 }
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 }
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 }
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 }
136 if (mDocViewerPrint) {
137 bool donePrePrint = mPrintEngine->PrePrintPage();
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 }
148 }
149 return NS_OK;
150 }
152 nsresult
153 nsPagePrintTimer::Start(nsPrintObject* aPO)
154 {
155 mPrintObj = aPO;
156 mWatchDogCount = 0;
157 mDone = false;
158 return StartTimer(false);
159 }
162 void
163 nsPagePrintTimer::Stop()
164 {
165 if (mTimer) {
166 mTimer->Cancel();
167 mTimer = nullptr;
168 }
169 StopWatchDogTimer();
170 }
172 void
173 nsPagePrintTimer::Fail()
174 {
175 mDone = true;
176 Stop();
177 if (mPrintEngine) {
178 mPrintEngine->CleanupOnFailure(NS_OK, false);
179 }
180 }