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 385372 f5fcec1a1c2d0ef7aea81ea2f8fcdfb09d2ff3dc
parent 385371 7af19bab721c6081171964adc48bbc201e78f4c8
child 385373 ebd2ef6abc6a7034a0a41f5954aec6ea3793b53f
push id52999
push usermhowell@mozilla.com
push dateTue, 10 Oct 2017 19:24:58 +0000
treeherderautoland@f5fcec1a1c2d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersagashlin
bugs798005
milestone58.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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