diff --git a/toolkit/components/downloads/src/nsDownloadManager.cpp b/toolkit/components/downloads/src/nsDownloadManager.cpp index b749bbdfe30..7e463d6ea11 100644 --- a/toolkit/components/downloads/src/nsDownloadManager.cpp +++ b/toolkit/components/downloads/src/nsDownloadManager.cpp @@ -131,6 +131,28 @@ nsDownloadManager::~nsDownloadManager() gDownloadManagerService = nsnull; } +nsresult +nsDownloadManager::ResumeRetry(nsDownload *aDl) +{ + // Keep a reference in case we need to cancel the download + nsRefPtr dl = aDl; + + // Try to resume the active download + nsresult rv = dl->Resume(); + + // If not, try to retry the download + if (NS_FAILED(rv)) { + // First cancel the download so it's no longer active + rv = CancelDownload(dl->mID); + + // Then retry it + if (NS_SUCCEEDED(rv)) + rv = RetryDownload(dl->mID); + } + + return rv; +} + nsresult nsDownloadManager::PauseAllDownloads(PRBool aSetResume) { @@ -154,6 +176,32 @@ nsDownloadManager::PauseAllDownloads(PRBool aSetResume) return retVal; } +nsresult +nsDownloadManager::ResumeAllDownloads(PRBool aResumeAll) +{ + nsresult retVal = NS_OK; + for (PRInt32 i = mCurrentDownloads.Count() - 1; i >= 0; --i) { + nsRefPtr dl = mCurrentDownloads[i]; + + // If aResumeAll is true, then resume everything; otherwise, check if the + // download should auto-resume + if (aResumeAll || dl->ShouldAutoResume()) { + // Reset auto-resume before retrying so that it gets into the DB through + // ResumeRetry's eventual call to SetState. We clear the value now so we + // don't accidentally query completed downloads that were previously + // auto-resumed (and try to resume them). + dl->mAutoResume = nsDownload::DONT_RESUME; + + // Try to resume/retry the download but don't bail now if we fail + nsresult rv = ResumeRetry(dl); + if (NS_FAILED(rv)) + retVal = rv; + } + } + + return retVal; +} + nsresult nsDownloadManager::RemoveAllDownloads() { @@ -678,13 +726,16 @@ nsDownloadManager::RestoreActiveDownloads() nsresult rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING( "SELECT id " "FROM moz_downloads " - "WHERE state = ?1 " - "AND LENGTH(entityID) > 0"), getter_AddRefs(stmt)); + "WHERE (state = ?1 AND LENGTH(entityID) > 0) " + "OR autoResume != ?2"), getter_AddRefs(stmt)); NS_ENSURE_SUCCESS(rv, rv); rv = stmt->BindInt32Parameter(0, nsIDownloadManager::DOWNLOAD_PAUSED); NS_ENSURE_SUCCESS(rv, rv); + rv = stmt->BindInt32Parameter(1, nsDownload::DONT_RESUME); + NS_ENSURE_SUCCESS(rv, rv); + nsresult retVal = NS_OK; PRBool hasResults; while (NS_SUCCEEDED(stmt->ExecuteStep(&hasResults)) && hasResults) { nsRefPtr dl; @@ -693,9 +744,14 @@ nsDownloadManager::RestoreActiveDownloads() // database because we're iterating over a live statement. if (NS_FAILED(GetDownloadFromDB(stmt->AsInt32(0), getter_AddRefs(dl))) || NS_FAILED(AddToCurrentDownloads(dl))) - rv = NS_ERROR_FAILURE; + retVal = NS_ERROR_FAILURE; } - return rv; + + // Try to resume only the downloads that should auto-resume + rv = ResumeAllDownloads(PR_FALSE); + NS_ENSURE_SUCCESS(rv, rv); + + return retVal; } PRInt64 diff --git a/toolkit/components/downloads/src/nsDownloadManager.h b/toolkit/components/downloads/src/nsDownloadManager.h index 3b0d3909818..cb7e665429e 100644 --- a/toolkit/components/downloads/src/nsDownloadManager.h +++ b/toolkit/components/downloads/src/nsDownloadManager.h @@ -155,6 +155,13 @@ protected: nsDownload *FindDownload(PRUint32 aID); + /** + * First try to resume the download, and if that fails, retry it. + * + * @param aDl The download to resume and/or retry. + */ + nsresult ResumeRetry(nsDownload *aDl); + /** * Pause all active downloads and remember if they should try to auto-resume * when the download manager starts again. @@ -164,6 +171,15 @@ protected: */ nsresult PauseAllDownloads(PRBool aSetResume); + /** + * Resume all paused downloads unless we're only supposed to do the automatic + * ones; in that case, try to retry them as well if resuming doesn't work. + * + * @param aResumeAll If true, all downloads will be resumed; otherwise, only + * those that are marked as auto-resume will resume. + */ + nsresult ResumeAllDownloads(PRBool aResumeAll); + /** * Stop tracking the active downloads. Only use this when we're about to quit * the download manager because we destroy our list of active downloads to