|
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/. */ |
|
5 |
|
6 #ifndef downloadmanager___h___ |
|
7 #define downloadmanager___h___ |
|
8 |
|
9 #if defined(XP_WIN) |
|
10 #define DOWNLOAD_SCANNER |
|
11 #endif |
|
12 |
|
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" |
|
26 |
|
27 #include "mozStorageHelper.h" |
|
28 #include "nsAutoPtr.h" |
|
29 #include "nsCOMArray.h" |
|
30 |
|
31 typedef int16_t DownloadState; |
|
32 typedef int16_t DownloadType; |
|
33 |
|
34 class nsIArray; |
|
35 class nsDownload; |
|
36 |
|
37 #ifdef DOWNLOAD_SCANNER |
|
38 #include "nsDownloadScanner.h" |
|
39 #endif |
|
40 |
|
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 |
|
51 |
|
52 nsresult Init(); |
|
53 |
|
54 static nsDownloadManager *GetSingleton(); |
|
55 |
|
56 virtual ~nsDownloadManager(); |
|
57 nsDownloadManager() |
|
58 #ifdef DOWNLOAD_SCANNER |
|
59 : mScanner(nullptr) |
|
60 #endif |
|
61 { |
|
62 } |
|
63 |
|
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); |
|
75 |
|
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(); |
|
82 |
|
83 /** |
|
84 * Paused downloads that survive across sessions are considered active, so |
|
85 * rebuild the list of these downloads. |
|
86 */ |
|
87 nsresult RestoreActiveDownloads(); |
|
88 |
|
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); |
|
94 |
|
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); |
|
100 |
|
101 void SendEvent(nsDownload *aDownload, const char *aTopic); |
|
102 |
|
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); |
|
119 |
|
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); |
|
134 |
|
135 nsDownload *FindDownload(const nsACString& aGUID); |
|
136 nsDownload *FindDownload(uint32_t aID); |
|
137 |
|
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); |
|
144 |
|
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); |
|
153 |
|
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); |
|
162 |
|
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(); |
|
170 |
|
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); |
|
178 |
|
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; |
|
189 |
|
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); |
|
196 |
|
197 int32_t GetRetentionBehavior(); |
|
198 |
|
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 }; |
|
212 |
|
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(); |
|
219 |
|
220 void OnEnterPrivateBrowsingMode(); |
|
221 void OnLeavePrivateBrowsingMode(); |
|
222 |
|
223 nsresult RetryDownload(const nsACString& aGUID); |
|
224 nsresult RetryDownload(nsDownload* dl); |
|
225 |
|
226 nsresult RemoveDownload(const nsACString& aGUID); |
|
227 |
|
228 nsresult NotifyDownloadRemoval(nsDownload* aRemoved); |
|
229 |
|
230 // Virus scanner for windows |
|
231 #ifdef DOWNLOAD_SCANNER |
|
232 private: |
|
233 nsDownloadScanner* mScanner; |
|
234 #endif |
|
235 |
|
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); |
|
245 |
|
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; |
|
260 |
|
261 static nsDownloadManager *gDownloadManagerService; |
|
262 |
|
263 friend class nsDownload; |
|
264 }; |
|
265 |
|
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 |
|
274 |
|
275 nsDownload(); |
|
276 virtual ~nsDownload(); |
|
277 |
|
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); |
|
284 |
|
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(); |
|
295 |
|
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(); |
|
301 |
|
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(); |
|
307 |
|
308 /** |
|
309 * Update the start time which also implies the last update time is the same. |
|
310 */ |
|
311 void SetStartTime(int64_t aStartTime); |
|
312 |
|
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); |
|
318 |
|
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(); |
|
324 |
|
325 /** |
|
326 * Download is not transferring? |
|
327 */ |
|
328 bool IsPaused(); |
|
329 |
|
330 /** |
|
331 * Download can continue from the middle of a transfer? |
|
332 */ |
|
333 bool IsResumable(); |
|
334 |
|
335 /** |
|
336 * Download was resumed? |
|
337 */ |
|
338 bool WasResumed(); |
|
339 |
|
340 /** |
|
341 * Indicates if the download should try to automatically resume or not. |
|
342 */ |
|
343 bool ShouldAutoResume(); |
|
344 |
|
345 /** |
|
346 * Download is in a state to stop and complete the download? |
|
347 */ |
|
348 bool IsFinishable(); |
|
349 |
|
350 /** |
|
351 * Download is totally done transferring and all? |
|
352 */ |
|
353 bool IsFinished(); |
|
354 |
|
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(); |
|
361 |
|
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); |
|
367 |
|
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(); |
|
379 |
|
380 nsDownloadManager *mDownloadManager; |
|
381 nsCOMPtr<nsIURI> mTarget; |
|
382 |
|
383 private: |
|
384 nsString mDisplayName; |
|
385 nsCString mEntityID; |
|
386 nsCString mGUID; |
|
387 |
|
388 nsCOMPtr<nsIURI> mSource; |
|
389 nsCOMPtr<nsIURI> mReferrer; |
|
390 nsCOMPtr<nsICancelable> mCancelable; |
|
391 nsCOMPtr<nsIRequest> mRequest; |
|
392 nsCOMPtr<nsIFile> mTempFile; |
|
393 nsCOMPtr<nsIMIMEInfo> mMIMEInfo; |
|
394 |
|
395 DownloadState mDownloadState; |
|
396 |
|
397 uint32_t mID; |
|
398 int32_t mPercentComplete; |
|
399 |
|
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; |
|
407 |
|
408 PRTime mStartTime; |
|
409 PRTime mLastUpdate; |
|
410 int64_t mResumedAt; |
|
411 double mSpeed; |
|
412 |
|
413 bool mHasMultipleFiles; |
|
414 bool mPrivate; |
|
415 |
|
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; |
|
425 |
|
426 /** |
|
427 * Stores the SHA-256 hash associated with the downloaded file. |
|
428 */ |
|
429 nsAutoCString mHash; |
|
430 |
|
431 /** |
|
432 * Stores the certificate chains in an nsIArray of nsIX509CertList of |
|
433 * nsIX509Cert, if this binary is signed. |
|
434 */ |
|
435 nsCOMPtr<nsIArray> mSignatureInfo; |
|
436 |
|
437 friend class nsDownloadManager; |
|
438 }; |
|
439 |
|
440 #endif |