Add a flag to allow parallel downloading without accept-ranges header in response.
If a download response doesn't have accept-ranges header, we don't fork
parallel requests today. A majority server doesn't send accept-ranges
header even though they support it.
This CL adds a flag to enable parallel downloading even accept-ranges
header are not present.
BUG=971366
Change-Id: I11fc2e7c131a7407d7ee5f269ee5e6b3ff2ce789
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1648797
Reviewed-by: Xing Liu <xingliu@chromium.org>
Reviewed-by: Steven Holte <holte@chromium.org>
Commit-Queue: Min Qin <qinmin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#668062}
diff --git a/components/download/internal/common/download_job_factory.cc b/components/download/internal/common/download_job_factory.cc
index 7d62075..87da385 100644
--- a/components/download/internal/common/download_job_factory.cc
+++ b/components/download/internal/common/download_job_factory.cc
@@ -10,6 +10,7 @@
#include "components/download/internal/common/parallel_download_job.h"
#include "components/download/internal/common/parallel_download_utils.h"
#include "components/download/internal/common/save_package_download_job.h"
+#include "components/download/public/common/download_features.h"
#include "components/download/public/common/download_item.h"
#include "components/download/public/common/download_stats.h"
#include "components/download/public/common/download_url_loader_factory_getter.h"
@@ -47,11 +48,15 @@
create_info.method == "GET" && create_info.url().SchemeIsHTTPOrHTTPS();
bool partial_response_success =
download_item->GetReceivedSlices().empty() || create_info.offset != 0;
- bool is_parallelizable =
- has_strong_validator &&
- create_info.accept_range == RangeRequestSupportType::kSupport &&
- has_content_length && satisfy_min_file_size && satisfy_connection_type &&
- http_get_method && partial_response_success;
+ bool range_support_allowed =
+ create_info.accept_range == RangeRequestSupportType::kSupport ||
+ (base::FeatureList::IsEnabled(
+ features::kUseParallelRequestsForUnknwonRangeSupport) &&
+ create_info.accept_range == RangeRequestSupportType::kUnknown);
+ bool is_parallelizable = has_strong_validator && range_support_allowed &&
+ has_content_length && satisfy_min_file_size &&
+ satisfy_connection_type && http_get_method &&
+ partial_response_success;
if (!IsParallelDownloadEnabled())
return is_parallelizable;
@@ -65,9 +70,13 @@
RecordParallelDownloadCreationEvent(
ParallelDownloadCreationEvent::FALLBACK_REASON_STRONG_VALIDATORS);
}
- if (create_info.accept_range != RangeRequestSupportType::kSupport) {
+ if (!range_support_allowed) {
RecordParallelDownloadCreationEvent(
ParallelDownloadCreationEvent::FALLBACK_REASON_ACCEPT_RANGE_HEADER);
+ if (create_info.accept_range == RangeRequestSupportType::kUnknown) {
+ RecordParallelDownloadCreationEvent(
+ ParallelDownloadCreationEvent::FALLBACK_REASON_UNKNOWN_RANGE_SUPPORT);
+ }
}
if (!has_content_length) {
RecordParallelDownloadCreationEvent(
diff --git a/components/download/internal/common/download_stats.cc b/components/download/internal/common/download_stats.cc
index 1a91d9e..1fe8b19 100644
--- a/components/download/internal/common/download_stats.cc
+++ b/components/download/internal/common/download_stats.cc
@@ -1054,8 +1054,16 @@
request_count, 1, 10, 11);
}
-void RecordParallelDownloadAddStreamSuccess(bool success) {
- UMA_HISTOGRAM_BOOLEAN("Download.ParallelDownloadAddStreamSuccess", success);
+void RecordParallelDownloadAddStreamSuccess(bool success,
+ bool support_range_request) {
+ if (support_range_request) {
+ base::UmaHistogramBoolean("Download.ParallelDownloadAddStreamSuccess",
+ success);
+ } else {
+ base::UmaHistogramBoolean(
+ "Download.ParallelDownloadAddStreamSuccess.NoAcceptRangesHeader",
+ success);
+ }
}
void RecordParallelizableContentLength(int64_t content_length) {
diff --git a/components/download/internal/common/parallel_download_job.cc b/components/download/internal/common/parallel_download_job.cc
index 1ac7dbbb..763116b 100644
--- a/components/download/internal/common/parallel_download_job.cc
+++ b/components/download/internal/common/parallel_download_job.cc
@@ -35,6 +35,7 @@
content_length_(create_info.total_bytes),
requests_sent_(false),
is_canceled_(false),
+ range_support_(create_info.accept_range),
url_loader_factory_getter_(std::move(url_loader_factory_getter)),
url_request_context_getter_(url_request_context_getter),
connector_(connector) {}
@@ -134,7 +135,9 @@
success = DownloadJob::AddInputStream(std::move(input_stream),
worker->offset(), worker->length());
}
- RecordParallelDownloadAddStreamSuccess(success);
+
+ RecordParallelDownloadAddStreamSuccess(
+ success, range_support_ == RangeRequestSupportType::kSupport);
// Destroy the request if the sink is gone.
if (!success) {
diff --git a/components/download/internal/common/parallel_download_job.h b/components/download/internal/common/parallel_download_job.h
index 71c45c86..ca41083 100644
--- a/components/download/internal/common/parallel_download_job.h
+++ b/components/download/internal/common/parallel_download_job.h
@@ -14,6 +14,7 @@
#include "base/timer/timer.h"
#include "components/download/internal/common/download_job_impl.h"
#include "components/download/internal/common/download_worker.h"
+#include "components/download/public/common/download_create_info.h"
#include "components/download/public/common/download_export.h"
#include "components/download/public/common/parallel_download_configs.h"
@@ -119,6 +120,9 @@
// If the download progress is canceled.
bool is_canceled_;
+ // Whether the server accepts range requests.
+ RangeRequestSupportType range_support_;
+
// URLLoaderFactory getter to issue network requests with network service
scoped_refptr<download::DownloadURLLoaderFactoryGetter>
url_loader_factory_getter_;
diff --git a/components/download/public/common/download_features.cc b/components/download/public/common/download_features.cc
index 7e945dd..4692f756 100644
--- a/components/download/public/common/download_features.cc
+++ b/components/download/public/common/download_features.cc
@@ -48,6 +48,11 @@
const base::Feature kAllowDownloadResumptionWithoutStrongValidators{
"AllowDownloadResumptionWithoutStrongValidators",
base::FEATURE_DISABLED_BY_DEFAULT};
+
+const base::Feature kUseParallelRequestsForUnknwonRangeSupport{
+ "UseParallelRequestForUnknwonRangeSupport",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
} // namespace features
} // namespace download
diff --git a/components/download/public/common/download_features.h b/components/download/public/common/download_features.h
index a3d7fda7..5dcfc4f 100644
--- a/components/download/public/common/download_features.h
+++ b/components/download/public/common/download_features.h
@@ -45,7 +45,12 @@
// Whether download resumption is allowed when there are no strong validators.
COMPONENTS_DOWNLOAD_EXPORT extern const base::Feature
kAllowDownloadResumptionWithoutStrongValidators;
+
+// Whether download resumption is allowed when there are no strong validators.
+COMPONENTS_DOWNLOAD_EXPORT extern const base::Feature
+ kUseParallelRequestsForUnknwonRangeSupport;
} // namespace features
+
} // namespace download
#endif // COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_FEATURES_H_
diff --git a/components/download/public/common/download_stats.h b/components/download/public/common/download_stats.h
index b1b3947412..447e8fd 100644
--- a/components/download/public/common/download_stats.h
+++ b/components/download/public/common/download_stats.h
@@ -216,6 +216,9 @@
// The http method or url scheme does not meet the requirement.
FALLBACK_REASON_HTTP_METHOD,
+ // Range support is unknown from the response.
+ FALLBACK_REASON_UNKNOWN_RANGE_SUPPORT,
+
// Last entry of the enum.
COUNT,
};
@@ -323,8 +326,11 @@
int request_count);
// Records if each byte stream is successfully added to download sink.
+// |support_range_request| indicates whether the server strongly supports range
+// requests.
COMPONENTS_DOWNLOAD_EXPORT void RecordParallelDownloadAddStreamSuccess(
- bool success);
+ bool success,
+ bool support_range_request);
// Records the bandwidth for parallelizable download and estimates the saved
// time at the file end. Does not count in any hash computation or file
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index c7d93e5..acaf08b 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -44358,6 +44358,7 @@
label="Remaining download time does not meet the requirement."/>
<int value="8"
label="HTTP method or url scheme does not meet the requirement."/>
+ <int value="9" label="Unknown range support from the response header."/>
</enum>
<enum name="ParentFrameKnown">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index d476eeb..a15089e 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -155523,6 +155523,12 @@
<affected-histogram name="Tabs.StateTransfer.Time_Inactive"/>
</histogram_suffixes>
+<histogram_suffixes name="NoAcceptRangesHeader" separator=".">
+ <suffix name="NoAcceptRangesHeader"
+ label="For parallel requests created without accept-ranges header."/>
+ <affected-histogram name="Download.ParallelDownloadAddStreamSuccess"/>
+</histogram_suffixes>
+
<histogram_suffixes name="NotificationDisplayExperiment" separator="_">
<obsolete>
Deprecated October 2017 (feature enabled by default).