Coverage Report

Created: 2018-09-25 14:53

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