Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 /* -*- Mode: C++; tab-width: 4; 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 #ifndef downloadmanager___h___
7 #define downloadmanager___h___
9 #if defined(XP_WIN)
10 #define DOWNLOAD_SCANNER
11 #endif
13 #include "nsIDownload.h"
14 #include "nsIDownloadManager.h"
15 #include "nsIDownloadProgressListener.h"
16 #include "nsIFile.h"
17 #include "nsIMIMEInfo.h"
18 #include "nsINavHistoryService.h"
19 #include "nsIObserver.h"
20 #include "nsIObserverService.h"
21 #include "nsIStringBundle.h"
22 #include "nsISupportsPrimitives.h"
23 #include "nsWeakReference.h"
24 #include "nsITimer.h"
25 #include "nsString.h"
27 #include "mozStorageHelper.h"
28 #include "nsAutoPtr.h"
29 #include "nsCOMArray.h"
31 typedef int16_t DownloadState;
32 typedef int16_t DownloadType;
34 class nsIArray;
35 class nsDownload;
37 #ifdef DOWNLOAD_SCANNER
38 #include "nsDownloadScanner.h"
39 #endif
41 class nsDownloadManager : public nsIDownloadManager,
42 public nsINavHistoryObserver,
43 public nsIObserver,
44 public nsSupportsWeakReference
45 {
46 public:
47 NS_DECL_ISUPPORTS
48 NS_DECL_NSIDOWNLOADMANAGER
49 NS_DECL_NSINAVHISTORYOBSERVER
50 NS_DECL_NSIOBSERVER
52 nsresult Init();
54 static nsDownloadManager *GetSingleton();
56 virtual ~nsDownloadManager();
57 nsDownloadManager()
58 #ifdef DOWNLOAD_SCANNER
59 : mScanner(nullptr)
60 #endif
61 {
62 }
64 protected:
65 nsresult InitDB();
66 nsresult InitFileDB();
67 void CloseAllDBs();
68 void CloseDB(mozIStorageConnection* aDBConn,
69 mozIStorageStatement* aUpdateStmt,
70 mozIStorageStatement* aGetIdsStmt);
71 nsresult InitPrivateDB();
72 already_AddRefed<mozIStorageConnection> GetFileDBConnection(nsIFile *dbFile) const;
73 already_AddRefed<mozIStorageConnection> GetPrivateDBConnection() const;
74 nsresult CreateTable(mozIStorageConnection* aDBConn);
76 /**
77 * Fix up the database after a crash such as dealing with previously-active
78 * downloads. Call this before RestoreActiveDownloads to get the downloads
79 * fixed here to be auto-resumed.
80 */
81 nsresult RestoreDatabaseState();
83 /**
84 * Paused downloads that survive across sessions are considered active, so
85 * rebuild the list of these downloads.
86 */
87 nsresult RestoreActiveDownloads();
89 nsresult GetDownloadFromDB(const nsACString& aGUID, nsDownload **retVal);
90 nsresult GetDownloadFromDB(uint32_t aID, nsDownload **retVal);
91 nsresult GetDownloadFromDB(mozIStorageConnection* aDBConn,
92 mozIStorageStatement* stmt,
93 nsDownload **retVal);
95 /**
96 * Specially track the active downloads so that we don't need to check
97 * every download to see if they're in progress.
98 */
99 nsresult AddToCurrentDownloads(nsDownload *aDl);
101 void SendEvent(nsDownload *aDownload, const char *aTopic);
103 /**
104 * Adds a download with the specified information to the DB.
105 *
106 * @return The id of the download, or 0 if there was an error.
107 */
108 int64_t AddDownloadToDB(const nsAString &aName,
109 const nsACString &aSource,
110 const nsACString &aTarget,
111 const nsAString &aTempPath,
112 int64_t aStartTime,
113 int64_t aEndTime,
114 const nsACString &aMimeType,
115 const nsACString &aPreferredApp,
116 nsHandlerInfoAction aPreferredAction,
117 bool aPrivate,
118 nsACString &aNewGUID);
120 void NotifyListenersOnDownloadStateChange(int16_t aOldState,
121 nsDownload *aDownload);
122 void NotifyListenersOnProgressChange(nsIWebProgress *aProgress,
123 nsIRequest *aRequest,
124 int64_t aCurSelfProgress,
125 int64_t aMaxSelfProgress,
126 int64_t aCurTotalProgress,
127 int64_t aMaxTotalProgress,
128 nsDownload *aDownload);
129 void NotifyListenersOnStateChange(nsIWebProgress *aProgress,
130 nsIRequest *aRequest,
131 uint32_t aStateFlags,
132 nsresult aStatus,
133 nsDownload *aDownload);
135 nsDownload *FindDownload(const nsACString& aGUID);
136 nsDownload *FindDownload(uint32_t aID);
138 /**
139 * First try to resume the download, and if that fails, retry it.
140 *
141 * @param aDl The download to resume and/or retry.
142 */
143 nsresult ResumeRetry(nsDownload *aDl);
145 /**
146 * Pause all active downloads and remember if they should try to auto-resume
147 * when the download manager starts again.
148 *
149 * @param aSetResume Indicate if the downloads that get paused should be set
150 * as auto-resume.
151 */
152 nsresult PauseAllDownloads(bool aSetResume);
154 /**
155 * Resume all paused downloads unless we're only supposed to do the automatic
156 * ones; in that case, try to retry them as well if resuming doesn't work.
157 *
158 * @param aResumeAll If true, all downloads will be resumed; otherwise, only
159 * those that are marked as auto-resume will resume.
160 */
161 nsresult ResumeAllDownloads(bool aResumeAll);
163 /**
164 * Stop tracking the active downloads. Only use this when we're about to quit
165 * the download manager because we destroy our list of active downloads to
166 * break the dlmgr<->dl cycle. Active downloads that aren't real-paused will
167 * be canceled.
168 */
169 nsresult RemoveAllDownloads();
171 /**
172 * Find all downloads from a source URI and delete them.
173 *
174 * @param aURI
175 * The source URI to remove downloads
176 */
177 nsresult RemoveDownloadsForURI(nsIURI *aURI);
179 /**
180 * Callback used for resuming downloads after getting a wake notification.
181 *
182 * @param aTimer
183 * Timer object fired after some delay after a wake notification
184 * @param aClosure
185 * nsDownloadManager object used to resume downloads
186 */
187 static void ResumeOnWakeCallback(nsITimer *aTimer, void *aClosure);
188 nsCOMPtr<nsITimer> mResumeOnWakeTimer;
190 void ConfirmCancelDownloads(int32_t aCount,
191 nsISupportsPRBool *aCancelDownloads,
192 const char16_t *aTitle,
193 const char16_t *aCancelMessageMultiple,
194 const char16_t *aCancelMessageSingle,
195 const char16_t *aDontCancelButton);
197 int32_t GetRetentionBehavior();
199 /**
200 * Type to indicate possible behaviors for active downloads across sessions.
201 *
202 * Possible values are:
203 * QUIT_AND_RESUME - downloads should be auto-resumed
204 * QUIT_AND_PAUSE - downloads should be paused
205 * QUIT_AND_CANCEL - downloads should be cancelled
206 */
207 enum QuitBehavior {
208 QUIT_AND_RESUME = 0,
209 QUIT_AND_PAUSE = 1,
210 QUIT_AND_CANCEL = 2
211 };
213 /**
214 * Indicates user-set behavior for active downloads across sessions,
215 *
216 * @return value of user-set pref for active download behavior
217 */
218 enum QuitBehavior GetQuitBehavior();
220 void OnEnterPrivateBrowsingMode();
221 void OnLeavePrivateBrowsingMode();
223 nsresult RetryDownload(const nsACString& aGUID);
224 nsresult RetryDownload(nsDownload* dl);
226 nsresult RemoveDownload(const nsACString& aGUID);
228 nsresult NotifyDownloadRemoval(nsDownload* aRemoved);
230 // Virus scanner for windows
231 #ifdef DOWNLOAD_SCANNER
232 private:
233 nsDownloadScanner* mScanner;
234 #endif
236 private:
237 nsresult CleanUp(mozIStorageConnection* aDBConn);
238 nsresult InitStatements(mozIStorageConnection* aDBConn,
239 mozIStorageStatement** aUpdateStatement,
240 mozIStorageStatement** aGetIdsStatement);
241 nsresult RemoveAllDownloads(nsCOMArray<nsDownload>& aDownloads);
242 nsresult PauseAllDownloads(nsCOMArray<nsDownload>& aDownloads, bool aSetResume);
243 nsresult ResumeAllDownloads(nsCOMArray<nsDownload>& aDownloads, bool aResumeAll);
244 nsresult RemoveDownloadsForURI(mozIStorageStatement* aStatement, nsIURI *aURI);
246 bool mUseJSTransfer;
247 nsCOMArray<nsIDownloadProgressListener> mListeners;
248 nsCOMArray<nsIDownloadProgressListener> mPrivacyAwareListeners;
249 nsCOMPtr<nsIStringBundle> mBundle;
250 nsCOMPtr<mozIStorageConnection> mDBConn;
251 nsCOMPtr<mozIStorageConnection> mPrivateDBConn;
252 nsCOMArray<nsDownload> mCurrentDownloads;
253 nsCOMArray<nsDownload> mCurrentPrivateDownloads;
254 nsCOMPtr<nsIObserverService> mObserverService;
255 nsCOMPtr<mozIStorageStatement> mUpdateDownloadStatement;
256 nsCOMPtr<mozIStorageStatement> mUpdatePrivateDownloadStatement;
257 nsCOMPtr<mozIStorageStatement> mGetIdsForURIStatement;
258 nsCOMPtr<mozIStorageStatement> mGetPrivateIdsForURIStatement;
259 nsAutoPtr<mozStorageTransaction> mHistoryTransaction;
261 static nsDownloadManager *gDownloadManagerService;
263 friend class nsDownload;
264 };
266 class nsDownload : public nsIDownload
267 {
268 public:
269 NS_DECL_NSIWEBPROGRESSLISTENER
270 NS_DECL_NSIWEBPROGRESSLISTENER2
271 NS_DECL_NSITRANSFER
272 NS_DECL_NSIDOWNLOAD
273 NS_DECL_ISUPPORTS
275 nsDownload();
276 virtual ~nsDownload();
278 /**
279 * This method MUST be called when changing states on a download. It will
280 * notify the download listener when a change happens. This also updates the
281 * database, by calling UpdateDB().
282 */
283 nsresult SetState(DownloadState aState);
285 protected:
286 /**
287 * Finish up the download by breaking reference cycles and clearing unneeded
288 * data. Additionally, the download removes itself from the download
289 * manager's list of current downloads.
290 *
291 * NOTE: This method removes the cycle created when starting the download, so
292 * make sure to use kungFuDeathGrip if you want to access member variables.
293 */
294 void Finalize();
296 /**
297 * For finished resumed downloads that came in from exthandler, perform the
298 * action that would have been done if the download wasn't resumed.
299 */
300 nsresult ExecuteDesiredAction();
302 /**
303 * Move the temporary file to the final destination by removing the existing
304 * dummy target and renaming the temporary.
305 */
306 nsresult MoveTempToTarget();
308 /**
309 * Update the start time which also implies the last update time is the same.
310 */
311 void SetStartTime(int64_t aStartTime);
313 /**
314 * Update the amount of bytes transferred and max bytes; and recalculate the
315 * download percent.
316 */
317 void SetProgressBytes(int64_t aCurrBytes, int64_t aMaxBytes);
319 /**
320 * All this does is cancel the connection that the download is using. It does
321 * not remove it from the download manager.
322 */
323 nsresult CancelTransfer();
325 /**
326 * Download is not transferring?
327 */
328 bool IsPaused();
330 /**
331 * Download can continue from the middle of a transfer?
332 */
333 bool IsResumable();
335 /**
336 * Download was resumed?
337 */
338 bool WasResumed();
340 /**
341 * Indicates if the download should try to automatically resume or not.
342 */
343 bool ShouldAutoResume();
345 /**
346 * Download is in a state to stop and complete the download?
347 */
348 bool IsFinishable();
350 /**
351 * Download is totally done transferring and all?
352 */
353 bool IsFinished();
355 /**
356 * Update the DB with the current state of the download including time,
357 * download state and other values not known when first creating the
358 * download DB entry.
359 */
360 nsresult UpdateDB();
362 /**
363 * Fail a download because of a failure status and prompt the provided
364 * message or use a generic download failure message if nullptr.
365 */
366 nsresult FailDownload(nsresult aStatus, const char16_t *aMessage);
368 /**
369 * Opens the downloaded file with the appropriate application, which is
370 * either the OS default, MIME type default, or the one selected by the user.
371 *
372 * This also adds the temporary file to the "To be deleted on Exit" list, if
373 * the corresponding user preference is set (except on OS X).
374 *
375 * This function was adopted from nsExternalAppHandler::OpenWithApplication
376 * (uriloader/exthandler/nsExternalHelperAppService.cpp).
377 */
378 nsresult OpenWithApplication();
380 nsDownloadManager *mDownloadManager;
381 nsCOMPtr<nsIURI> mTarget;
383 private:
384 nsString mDisplayName;
385 nsCString mEntityID;
386 nsCString mGUID;
388 nsCOMPtr<nsIURI> mSource;
389 nsCOMPtr<nsIURI> mReferrer;
390 nsCOMPtr<nsICancelable> mCancelable;
391 nsCOMPtr<nsIRequest> mRequest;
392 nsCOMPtr<nsIFile> mTempFile;
393 nsCOMPtr<nsIMIMEInfo> mMIMEInfo;
395 DownloadState mDownloadState;
397 uint32_t mID;
398 int32_t mPercentComplete;
400 /**
401 * These bytes are based on the position of where the request started, so 0
402 * doesn't necessarily mean we have nothing. Use GetAmountTransferred and
403 * GetSize for the real transferred amount and size.
404 */
405 int64_t mCurrBytes;
406 int64_t mMaxBytes;
408 PRTime mStartTime;
409 PRTime mLastUpdate;
410 int64_t mResumedAt;
411 double mSpeed;
413 bool mHasMultipleFiles;
414 bool mPrivate;
416 /**
417 * Track various states of the download trying to auto-resume when starting
418 * the download manager or restoring from a crash.
419 *
420 * DONT_RESUME: Don't automatically resume the download
421 * AUTO_RESUME: Automaically resume the download
422 */
423 enum AutoResume { DONT_RESUME, AUTO_RESUME };
424 AutoResume mAutoResume;
426 /**
427 * Stores the SHA-256 hash associated with the downloaded file.
428 */
429 nsAutoCString mHash;
431 /**
432 * Stores the certificate chains in an nsIArray of nsIX509CertList of
433 * nsIX509Cert, if this binary is signed.
434 */
435 nsCOMPtr<nsIArray> mSignatureInfo;
437 friend class nsDownloadManager;
438 };
440 #endif