Parallel Download: Fix missing request in an edge case.

Previously we always send a request after the last received slice, this
may lead to an out of range request, and we fix this issue in
https://chromium.googlesource.com/chromium/src/+/cb75f08beac18e6a237bf605fc612362b346d6fc

However, when the orginal request is completed before creating parallel
requests, we may not send parallel requests correctly due to the
assumption of always sending a request after last slice.

This CL fixes this issue and adds test coverage for this edge case.


Bug: 822340
Change-Id: Ibe459a642dc2f743075a5c9744ec1d9710446b05
Reviewed-on: https://chromium-review.googlesource.com/964992
Reviewed-by: Min Qin <qinmin@chromium.org>
Commit-Queue: Xing Liu <xingliu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#544165}
diff --git a/content/browser/download/parallel_download_job.cc b/content/browser/download/parallel_download_job.cc
index 97d2087..37c82bd 100644
--- a/content/browser/download/parallel_download_job.cc
+++ b/content/browser/download/parallel_download_job.cc
@@ -214,9 +214,6 @@
 
 void ParallelDownloadJob::ForkSubRequests(
     const download::DownloadItem::ReceivedSlices& slices_to_download) {
-  if (slices_to_download.size() < 2)
-    return;
-
   // If the initial request is working on the first hole, don't create parallel
   // request for this hole.
   bool skip_first_slice = true;
diff --git a/content/browser/download/parallel_download_job_unittest.cc b/content/browser/download/parallel_download_job_unittest.cc
index 244bbd0..43a64a9 100644
--- a/content/browser/download/parallel_download_job_unittest.cc
+++ b/content/browser/download/parallel_download_job_unittest.cc
@@ -389,6 +389,23 @@
   EXPECT_EQ(1u, job_->workers().size());
   VerifyWorker(75, 0);
   DestroyParallelJob();
+
+  // Three received slices with two hole in the middle and the last slice is
+  // finished.
+  slices = {download::DownloadItem::ReceivedSlice(0, 25),
+            download::DownloadItem::ReceivedSlice(50, 25),
+            download::DownloadItem::ReceivedSlice(100, 25, true)};
+  CreateParallelJob(25, 125, slices, 3, 1, 10);
+
+  // If the first hole is filled by the original request after the job is
+  // initialized but before parallel request is created, the second hole should
+  // be filled, and no out of range request will be created.
+  slices[0].received_bytes = 50;
+  set_received_slices(slices);
+  BuildParallelRequests();
+  EXPECT_EQ(1u, job_->workers().size());
+  VerifyWorker(75, 0);
+  DestroyParallelJob();
 }
 
 // Pause, cancel, resume can be called before or after the worker establish