Bug 789507 - Add watchdog for mozPrintCallbacks. r=smaug

This commit is contained in:
Brendan Dahl 2012-10-02 10:42:21 -07:00
parent fadf9023d4
commit 45e10cee30
3 changed files with 81 additions and 1 deletions

View File

@ -112,6 +112,7 @@ nsSimplePageSequenceFrame::nsSimplePageSequenceFrame(nsStyleContext* aContext) :
nsSimplePageSequenceFrame::~nsSimplePageSequenceFrame()
{
delete mPageData;
ResetPrintCanvasList();
}
NS_QUERYFRAME_HEAD(nsSimplePageSequenceFrame)

View File

@ -44,6 +44,34 @@ nsPagePrintTimer::StartTimer(bool aUseDelay)
return result;
}
nsresult
nsPagePrintTimer::StartWatchDogTimer()
{
nsresult result;
if (mWatchDogTimer) {
mWatchDogTimer->Cancel();
}
mWatchDogTimer = do_CreateInstance("@mozilla.org/timer;1", &result);
if (NS_FAILED(result)) {
NS_WARNING("unable to start the timer");
} else {
// Instead of just doing one timer for a long period do multiple so we
// can check if the user cancelled the printing.
mWatchDogTimer->InitWithCallback(this, WATCH_DOG_INTERVAL,
nsITimer::TYPE_ONE_SHOT);
}
return result;
}
void
nsPagePrintTimer::StopWatchDogTimer()
{
if (mWatchDogTimer) {
mWatchDogTimer->Cancel();
mWatchDogTimer = nullptr;
}
}
//nsRunnable
NS_IMETHODIMP
nsPagePrintTimer::Run()
@ -61,6 +89,7 @@ nsPagePrintTimer::Run()
// now clean up print or print the next webshell
if (mPrintEngine->DonePrintingPages(mPrintObj, NS_OK)) {
initNewTimer = false;
mDone = true;
}
}
@ -72,7 +101,7 @@ nsPagePrintTimer::Run()
++mFiringCount;
nsresult result = StartTimer(inRange);
if (NS_FAILED(result)) {
donePrinting = true; // had a failure.. we are finished..
mDone = true; // had a failure.. we are finished..
mPrintEngine->SetIsPrinting(false);
}
}
@ -83,11 +112,37 @@ nsPagePrintTimer::Run()
NS_IMETHODIMP
nsPagePrintTimer::Notify(nsITimer *timer)
{
// When finished there may be still pending notifications, which we can just
// ignore.
if (mDone) {
return NS_OK;
}
// There are three things that call Notify with different values for timer:
// 1) the delay between pages (timer == mTimer)
// 2) canvasPrintState done (timer == null)
// 3) the watch dog timer (timer == mWatchDogTimer)
if (timer && timer == mWatchDogTimer) {
mWatchDogCount++;
if (mWatchDogCount > WATCH_DOG_MAX_COUNT) {
Fail();
return NS_OK;
}
} else if(!timer) {
// Reset the counter since a mozPrintCallback has finished.
mWatchDogCount = 0;
}
if (mDocViewerPrint) {
bool donePrePrint = mPrintEngine->PrePrintPage();
if (donePrePrint) {
StopWatchDogTimer();
NS_DispatchToMainThread(this);
} else {
// Start the watch dog if we're waiting for preprint to ensure that if any
// mozPrintCallbacks take to long we error out.
StartWatchDogTimer();
}
}
@ -98,6 +153,8 @@ nsresult
nsPagePrintTimer::Start(nsPrintObject* aPO)
{
mPrintObj = aPO;
mWatchDogCount = 0;
mDone = false;
return StartTimer(false);
}
@ -109,4 +166,15 @@ nsPagePrintTimer::Stop()
mTimer->Cancel();
mTimer = nullptr;
}
StopWatchDogTimer();
}
void
nsPagePrintTimer::Fail()
{
mDone = true;
Stop();
if (mPrintEngine) {
mPrintEngine->CleanupOnFailure(NS_OK, false);
}
}

View File

@ -33,6 +33,8 @@ public:
, mDelay(aDelay)
, mFiringCount(0)
, mPrintObj(nullptr)
, mWatchDogCount(0)
, mDone(false)
{
mDocViewerPrint->IncrementDestroyRefCount();
}
@ -48,13 +50,22 @@ public:
private:
nsresult StartTimer(bool aUseDelay);
nsresult StartWatchDogTimer();
void StopWatchDogTimer();
void Fail();
nsPrintEngine* mPrintEngine;
nsCOMPtr<nsIDocumentViewerPrint> mDocViewerPrint;
nsCOMPtr<nsITimer> mTimer;
nsCOMPtr<nsITimer> mWatchDogTimer;
uint32_t mDelay;
uint32_t mFiringCount;
nsPrintObject * mPrintObj;
uint32_t mWatchDogCount;
bool mDone;
static const uint32_t WATCH_DOG_INTERVAL = 1000;
static const uint32_t WATCH_DOG_MAX_COUNT = 10;
};