Bug 798005 - Resume interrupted downloads in the stub installer, instead of starting over. r?agashlin draft
authorMatt Howell <mhowell@mozilla.com>
Fri, 08 Sep 2017 11:03:48 -0700
changeset 676228 52ae7a5e77f46735c2cfd6c47b0b6135bac9320c
parent 675508 53bbdaaa2b8c1819061be26101b075c081b23260
child 734884 2499e7dacd6040f50124a863caf443555db860b2
push id83435
push usermhowell@mozilla.com
push dateFri, 06 Oct 2017 20:52:06 +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,47 @@ 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"
+    ${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,17 +500,17 @@ 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);
         ec = ERROR_BROKEN_PIPE;
       }
       break;
     }
 
@@ -516,16 +531,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 +550,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..54dc6f4f32c279b4a0d42a6a8ee564a0f462f157
GIT binary patch
literal 33792
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
Vo_{_6dj9qN>-pF7ujhaG`Cn^k?U?`o