Bug 798005 - Resume interrupted downloads in the stub installer, instead of starting over. r=agashlin
authorMatt Howell <mhowell@mozilla.com>
Fri, 08 Sep 2017 11:03:48 -0700
changeset 428058 f5fcec1a1c2d0ef7aea81ea2f8fcdfb09d2ff3dc
parent 428057 7af19bab721c6081171964adc48bbc201e78f4c8
child 428059 ebd2ef6abc6a7034a0a41f5954aec6ea3793b53f
push id97
push userfmarier@mozilla.com
push dateSat, 14 Oct 2017 01:12:59 +0000
reviewersagashlin
bugs798005
milestone58.0a1
Bug 798005 - Resume interrupted downloads in the stub installer, instead of starting over. r=agashlin MozReview-Commit-ID: GxEqsrDBdIm
browser/installer/windows/nsis/stub.nsi
other-licenses/nsis/Contrib/InetBgDL/InetBgDL.cpp
other-licenses/nsis/Plugins/InetBgDL.dll
--- a/browser/installer/windows/nsis/stub.nsi
+++ b/browser/installer/windows/nsis/stub.nsi
@@ -853,17 +853,21 @@ Function createInstall
     StrCpy $InstallTotalSteps ${InstallPaveOverTotalSteps}
   ${Else}
     StrCpy $InstallTotalSteps ${InstallCleanTotalSteps}
   ${EndIf}
 
   ${ITBL3Create}
   ${ITBL3SetProgressState} "${TBPF_INDETERMINATE}"
 
+  ; Make sure the file we're about to try to download to doesn't already exist,
+  ; so we don't end up trying to "resume" on top of the wrong file.
+  Delete "$PLUGINSDIR\download.exe"
   ${NSD_CreateTimer} StartDownload ${DownloadIntervalMS}
+
   ${NSD_CreateTimer} ClearBlurb ${BlurbDisplayMS}
 
   LockWindow off
   nsDialogs::Show
 
   ${NSD_FreeImage} $BgBitmapImage
 FunctionEnd
 
@@ -926,40 +930,48 @@ FunctionEnd
 
 Function OnDownload
   InetBgDL::GetStats
   # $0 = HTTP status code, 0=Completed
   # $1 = Completed files
   # $2 = Remaining files
   # $3 = Number of downloaded bytes for the current file
   # $4 = Size of current file (Empty string if the size is unknown)
-  # /RESET must be used if status $0 > 299 (e.g. failure)
+  # /RESET must be used if status $0 > 299 (e.g. failure), even if resuming
   # When status is $0 =< 299 it is handled by InetBgDL
   StrCpy $DownloadServerIP "$5"
   ${If} $0 > 299
     ${NSD_KillTimer} OnDownload
     IntOp $DownloadRetryCount $DownloadRetryCount + 1
-    ${If} "$DownloadReset" != "true"
-      StrCpy $DownloadedBytes "0"
-      ${NSD_AddStyle} $Progressbar ${PBS_MARQUEE}
-      SendMessage $Progressbar ${PBM_SETMARQUEE} 1 \
-                  $ProgressbarMarqueeIntervalMS ; start=1|stop=0 interval(ms)=+N
-      ${ITBL3SetProgressState} "${TBPF_INDETERMINATE}"
-    ${EndIf}
-    InetBgDL::Get /RESET /END
-    StrCpy $DownloadSizeBytes ""
-    StrCpy $DownloadReset "true"
-
     ${If} $DownloadRetryCount >= ${DownloadMaxRetries}
       StrCpy $ExitCode "${ERR_DOWNLOAD_TOO_MANY_RETRIES}"
       ; Use a timer so the UI has a chance to update
       ${NSD_CreateTimer} DisplayDownloadError ${InstallIntervalMS}
-    ${Else}
-      ${NSD_CreateTimer} StartDownload ${DownloadRetryIntervalMS}
+      Return
     ${EndIf}
+
+    ; 1000 is a special code meaning InetBgDL lost the connection before it got
+    ; all the bytes it was expecting. We'll try to resume the transfer in that
+    ; case (assuming we aren't out of retries), so don't treat it as a reset
+    ; or clear the progress bar.
+    ${If} $0 != 1000
+      ${If} "$DownloadReset" != "true"
+        StrCpy $DownloadedBytes "0"
+        ${NSD_AddStyle} $Progressbar ${PBS_MARQUEE}
+        SendMessage $Progressbar ${PBM_SETMARQUEE} 1 \
+                    $ProgressbarMarqueeIntervalMS ; start=1|stop=0 interval(ms)=+N
+        ${ITBL3SetProgressState} "${TBPF_INDETERMINATE}"
+      ${EndIf}
+      StrCpy $DownloadSizeBytes ""
+      StrCpy $DownloadReset "true"
+      Delete "$PLUGINSDIR\download.exe"
+    ${EndIf}
+
+    InetBgDL::Get /RESET /END
+    ${NSD_CreateTimer} StartDownload ${DownloadRetryIntervalMS}
     Return
   ${EndIf}
 
   ${If} "$DownloadReset" == "true"
     System::Call "kernel32::GetTickCount()l .s"
     Pop $StartLastDownloadTickCount
     StrCpy $DownloadReset "false"
     ; The seconds elapsed from the start of the download phase until the first
--- a/other-licenses/nsis/Contrib/InetBgDL/InetBgDL.cpp
+++ b/other-licenses/nsis/Contrib/InetBgDL/InetBgDL.cpp
@@ -8,16 +8,17 @@
 
 #define STATUS_COMPLETEDALL 0
 #define STATUS_INITIAL 202
 #define STATUS_CONNECTING STATUS_INITIAL //102
 #define STATUS_DOWNLOADING STATUS_INITIAL
 #define STATUS_ERR_GETLASTERROR 418 //HTTP: I'm a teapot: Win32 error code in $3
 #define STATUS_ERR_LOCALFILEWRITEERROR 450 //HTTP: MS parental control extension
 #define STATUS_ERR_CANCELLED 499
+#define STATUS_ERR_CONNECTION_LOST 1000
 
 typedef DWORD FILESIZE_T; // Limit to 4GB for now...
 #define FILESIZE_UNKNOWN (-1)
 
 #define MAX_STRLEN 1024
 
 HINSTANCE g_hInst;
 NSIS::stack_t*g_pLocations = NULL;
@@ -261,16 +262,17 @@ void __stdcall InetStatusCallback(HINTER
 #endif
 }
 
 DWORD CALLBACK TaskThreadProc(LPVOID ThreadParam)
 {
   NSIS::stack_t *pURL,*pFile;
   HINTERNET hInetSes = NULL, hInetFile = NULL;
   DWORD cbio = sizeof(DWORD);
+  DWORD previouslyWritten = 0, writtenThisSession = 0;
   HANDLE hLocalFile;
   bool completedFile = false;
 startnexttask:
   hLocalFile = INVALID_HANDLE_VALUE;
   pFile = NULL;
   TaskLock_AcquireExclusive();
   // Now that we've acquired the lock, we can set the event to indicate this.
   // SetEvent will likely never fail, but if it does we should set it to NULL
@@ -315,16 +317,17 @@ startnexttask:
   {
     if (0)
     {
 diegle:
       DWORD gle = GetLastError();
       //TODO? if (ERROR_INTERNET_EXTENDED_ERROR==gle) InternetGetLastResponseInfo(...)
       g_Status = STATUS_ERR_GETLASTERROR;
     }
+die:
     if (hInetSes)
     {
       InternetCloseHandle(hInetSes);
     }
     if (INVALID_HANDLE_VALUE != hLocalFile)
     {
       CloseHandle(hLocalFile);
     }
@@ -367,22 +370,30 @@ diegle:
     if (g_ReceiveTimeout)
     {
       InternetSetOption(hInetSes, INTERNET_OPTION_RECEIVE_TIMEOUT,
                         &g_ReceiveTimeout, sizeof(DWORD));
     }
   }
 
   DWORD ec = ERROR_SUCCESS;
-  hLocalFile = CreateFile(pFile->text, GENERIC_WRITE,FILE_SHARE_READ | FILE_SHARE_DELETE,NULL,CREATE_ALWAYS, 0, NULL);
+  hLocalFile = CreateFile(pFile->text, GENERIC_READ | GENERIC_WRITE,
+                          FILE_SHARE_READ | FILE_SHARE_DELETE,
+                          NULL, OPEN_ALWAYS, 0, NULL);
   if (INVALID_HANDLE_VALUE == hLocalFile)
   {
     TRACE(_T("InetBgDl: CreateFile file handle invalid\n"));
     goto diegle;
   }
+  if (GetLastError() == ERROR_ALREADY_EXISTS) {
+    // Resuming a download that was started earlier and then aborted.
+    previouslyWritten = GetFileSize(hLocalFile, NULL);
+    g_cbCurrXF = previouslyWritten;
+    SetFilePointer(hLocalFile, previouslyWritten, NULL, FILE_BEGIN);
+  }
 
   const DWORD IOURedirFlags = INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP |
                               INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS;
   const DWORD IOUCacheFlags = INTERNET_FLAG_RESYNCHRONIZE |
                               INTERNET_FLAG_NO_CACHE_WRITE |
                               INTERNET_FLAG_PRAGMA_NOCACHE |
                               INTERNET_FLAG_RELOAD;
   const DWORD IOUCookieFlags = INTERNET_FLAG_NO_COOKIES;
@@ -412,19 +423,23 @@ diegle:
   // Only http and https are supported
   if (uc.nScheme != INTERNET_SCHEME_HTTP &&
       uc.nScheme != INTERNET_SCHEME_HTTPS)
   {
     TRACE(_T("InetBgDl: only http and https is supported, aborting...\n"));
     goto diegle;
   }
 
+  // Tell the server to pick up wherever we left off.
+  TCHAR headers[32] = _T("");
+  _snwprintf(headers, 32, _T("Range: bytes=%d-\r\n"), previouslyWritten);
+
   TRACE(_T("InetBgDl: calling InternetOpenUrl with url=%s\n"), pURL->text);
   hInetFile = InternetOpenUrl(hInetSes, pURL->text,
-                              NULL, 0, IOUFlags |
+                              headers, -1, IOUFlags |
                               (uc.nScheme == INTERNET_SCHEME_HTTPS ?
                                INTERNET_FLAG_SECURE : 0), 1);
   if (!hInetFile)
   {
     TRACE(_T("InetBgDl: InternetOpenUrl failed with gle=%u\n"),
           GetLastError());
     goto diegle;
   }
@@ -485,20 +500,21 @@ diegle:
       // EOF or broken connection?
       // TODO: Can InternetQueryDataAvailable detect this?
 
       TRACE(_T("InetBgDl: InternetReadFile true with 0 cbio, cbThisFile=%d, gle=%u\n"),
             cbThisFile, GetLastError());
       // If we haven't transferred all of the file, and we know how big the file
       // is, and we have no more data to read from the HTTP request, then set a
       // broken pipe error. Reading without StatsLock is ok in this thread.
-      if (FILESIZE_UNKNOWN != cbThisFile && g_cbCurrXF != cbThisFile)
+      if (FILESIZE_UNKNOWN != cbThisFile && writtenThisSession != cbThisFile)
       {
-        TRACE(_T("InetBgDl: downloaded file size of %d bytes doesn't equal ") \
-              _T("expected file size of %d bytes\n"), g_cbCurrXF, cbThisFile);
+        TRACE(_T("InetBgDl: expected Content-Length of %d bytes, ")
+              _T("but transferred %d bytes\n"),
+              cbThisFile, writtenThisSession);
         ec = ERROR_BROKEN_PIPE;
       }
       break;
     }
 
     // Check if we canceled the download
     if (0 == g_FilesTotal)
     {
@@ -516,16 +532,17 @@ diegle:
         ec = GetLastError();
         break;
       }
 
       StatsLock_AcquireExclusive();
       if (FILESIZE_UNKNOWN != cbThisFile) {
         g_cbCurrTot = cbThisFile;
       }
+      writtenThisSession += cbXF;
       g_cbCurrXF += cbXF;
       StatsLock_ReleaseExclusive();
     }
   }
 
   TRACE(_T("InetBgDl: TaskThreadProc completed %s, ec=%u\n"), pURL->text, ec);
   InternetCloseHandle(hInetFile);
   if (ERROR_SUCCESS == ec)
@@ -534,16 +551,21 @@ diegle:
     {
       CloseHandle(hLocalFile);
       hLocalFile = INVALID_HANDLE_VALUE;
     }
     StackFreeItem(pURL);
     StackFreeItem(pFile);
     ++completedFile;
   }
+  else if (ERROR_BROKEN_PIPE == ec)
+  {
+    g_Status = STATUS_ERR_CONNECTION_LOST;
+    goto die;
+  }
   else
   {
     TRACE(_T("InetBgDl: failed with ec=%u\n"), ec);
     SetLastError(ec);
     goto diegle;
   }
   goto startnexttask;
 }
index 976fc0c1482250b5f2b015f4cf897f27194dde77..1d12b16b20d02e471c2e0f7cb7e6d850fecf1ddb
GIT binary patch
literal 33792
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
R`+WO+`+WO+`}|Ko{}*Z&(OLii