aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/net/filemanager_thread.rs49
-rw-r--r--components/shared/net/filemanager_thread.rs10
-rw-r--r--tests/wpt/meta/fetch/range/blob.any.js.ini24
-rw-r--r--tests/wpt/meta/xhr/blob-range.any.js.ini20
-rw-r--r--tests/wpt/mozilla/meta/MANIFEST.json7
-rw-r--r--tests/wpt/mozilla/tests/mozilla/range_request_blob_url.html60
6 files changed, 75 insertions, 95 deletions
diff --git a/components/net/filemanager_thread.rs b/components/net/filemanager_thread.rs
index b501d845c9b..e72290b2694 100644
--- a/components/net/filemanager_thread.rs
+++ b/components/net/filemanager_thread.rs
@@ -11,7 +11,7 @@ use std::sync::atomic::{self, AtomicBool, AtomicUsize, Ordering};
use std::sync::{Arc, Mutex, RwLock, Weak};
use embedder_traits::{EmbedderMsg, EmbedderProxy, FilterPattern};
-use headers::{ContentLength, ContentType, HeaderMap, HeaderMapExt, Range};
+use headers::{ContentLength, ContentRange, ContentType, HeaderMap, HeaderMapExt, Range};
use http::header::{self, HeaderValue};
use ipc_channel::ipc::{self, IpcSender};
use log::warn;
@@ -290,24 +290,39 @@ impl FileManager {
response: &mut Response,
) -> Result<(), BlobURLStoreError> {
let file_impl = self.store.get_impl(id, file_token, origin_in)?;
+ /*
+ Only Fetch Blob Range Request would have unresolved range, and only in that case we care about range header.
+ */
+ let mut is_range_requested = false;
match file_impl {
FileImpl::Memory(buf) => {
let bounds = match bounds {
- BlobBounds::Unresolved(range) => get_range_request_bounds(range, buf.size),
+ BlobBounds::Unresolved(range) => {
+ if range.is_some() {
+ is_range_requested = true;
+ }
+ get_range_request_bounds(range, buf.size)
+ },
BlobBounds::Resolved(bounds) => bounds,
};
let range = bounds
.get_final(Some(buf.size))
.map_err(|_| BlobURLStoreError::InvalidRange)?;
- let range = range.to_abs_range(buf.size as usize);
+ let range = range.to_abs_blob_range(buf.size as usize);
let len = range.len() as u64;
+ let content_range = if is_range_requested {
+ ContentRange::bytes(range.start as u64..range.end as u64, buf.size).ok()
+ } else {
+ None
+ };
set_headers(
&mut response.headers,
len,
buf.type_string.parse().unwrap_or(mime::TEXT_PLAIN),
/* filename */ None,
+ content_range,
);
let mut bytes = vec![];
@@ -327,9 +342,14 @@ impl FileManager {
let file = File::open(&metadata.path)
.map_err(|e| BlobURLStoreError::External(e.to_string()))?;
-
+ let mut is_range_requested = false;
let bounds = match bounds {
- BlobBounds::Unresolved(range) => get_range_request_bounds(range, metadata.size),
+ BlobBounds::Unresolved(range) => {
+ if range.is_some() {
+ is_range_requested = true;
+ }
+ get_range_request_bounds(range, metadata.size)
+ },
BlobBounds::Resolved(bounds) => bounds,
};
let range = bounds
@@ -349,6 +369,13 @@ impl FileManager {
.and_then(|osstr| osstr.to_str())
.map(|s| s.to_string());
+ let content_range = if is_range_requested {
+ let abs_range = range.to_abs_blob_range(metadata.size as usize);
+ ContentRange::bytes(abs_range.start as u64..abs_range.end as u64, metadata.size)
+ .ok()
+ } else {
+ None
+ };
set_headers(
&mut response.headers,
metadata.size,
@@ -356,6 +383,7 @@ impl FileManager {
.first()
.unwrap_or(mime::TEXT_PLAIN),
filename,
+ content_range,
);
self.fetch_file_in_chunks(
@@ -939,8 +967,17 @@ fn read_file_in_chunks(
}
}
-fn set_headers(headers: &mut HeaderMap, content_length: u64, mime: Mime, filename: Option<String>) {
+fn set_headers(
+ headers: &mut HeaderMap,
+ content_length: u64,
+ mime: Mime,
+ filename: Option<String>,
+ content_range: Option<ContentRange>,
+) {
headers.typed_insert(ContentLength(content_length));
+ if let Some(content_range) = content_range {
+ headers.typed_insert(content_range);
+ }
headers.typed_insert(ContentType::from(mime.clone()));
let name = match filename {
Some(name) => name,
diff --git a/components/shared/net/filemanager_thread.rs b/components/shared/net/filemanager_thread.rs
index c6d0dde7ecb..5167ab1b4de 100644
--- a/components/shared/net/filemanager_thread.rs
+++ b/components/shared/net/filemanager_thread.rs
@@ -109,6 +109,16 @@ impl RelativePos {
end: (start + span).to_usize().unwrap(),
}
}
+
+ // Per <https://fetch.spec.whatwg.org/#concept-scheme-fetch> step 3.blob.14.8:
+ // "A range header denotes an inclusive byte range, while the slice blob algorithm input range does not.
+ // To use the slice blob algorithm, we have to increment rangeEnd."
+ pub fn to_abs_blob_range(&self, size: usize) -> Range<usize> {
+ let orig_range = self.to_abs_range(size);
+ let start = orig_range.start;
+ let end = usize::min(orig_range.end + 1, size);
+ Range { start, end }
+ }
}
/// Response to file selection request
diff --git a/tests/wpt/meta/fetch/range/blob.any.js.ini b/tests/wpt/meta/fetch/range/blob.any.js.ini
index b20ec230d9d..9dd565dc64f 100644
--- a/tests/wpt/meta/fetch/range/blob.any.js.ini
+++ b/tests/wpt/meta/fetch/range/blob.any.js.ini
@@ -1,18 +1,18 @@
[blob.any.html]
[A simple blob range request.]
- expected: FAIL
+ expected: PASS
[A blob range request with no end.]
- expected: FAIL
+ expected: PASS
[A blob range request with no start.]
- expected: FAIL
+ expected: PASS
[A simple blob range request with whitespace.]
- expected: FAIL
+ expected: PASS
[Blob content with short content and a large range end]
- expected: FAIL
+ expected: PASS
[Blob range with whitespace before and after hyphen]
expected: FAIL
@@ -60,7 +60,7 @@
expected: FAIL
[Blob content with short content and a range end matching content length]
- expected: FAIL
+ expected: PASS
[Blob range with no value]
expected: FAIL
@@ -83,19 +83,19 @@
[blob.any.worker.html]
[A simple blob range request.]
- expected: FAIL
+ expected: PASS
[A blob range request with no end.]
- expected: FAIL
+ expected: PASS
[A blob range request with no start.]
- expected: FAIL
+ expected: PASS
[A simple blob range request with whitespace.]
- expected: FAIL
+ expected: PASS
[Blob content with short content and a large range end]
- expected: FAIL
+ expected: PASS
[Blob range with whitespace before and after hyphen]
expected: FAIL
@@ -143,7 +143,7 @@
expected: FAIL
[Blob content with short content and a range end matching content length]
- expected: FAIL
+ expected: PASS
[Blob range with no value]
expected: FAIL
diff --git a/tests/wpt/meta/xhr/blob-range.any.js.ini b/tests/wpt/meta/xhr/blob-range.any.js.ini
index e743d94658e..158301c7929 100644
--- a/tests/wpt/meta/xhr/blob-range.any.js.ini
+++ b/tests/wpt/meta/xhr/blob-range.any.js.ini
@@ -1,24 +1,24 @@
[blob-range.any.worker.html]
[A simple blob range request.]
- expected: FAIL
+ expected: PASS
[A blob range request with no type.]
expected: FAIL
[A blob range request with no end.]
- expected: FAIL
+ expected: PASS
[A blob range request with no start.]
- expected: FAIL
+ expected: PASS
[A simple blob range request with whitespace.]
expected: FAIL
[Blob content with short content and a large range end]
- expected: FAIL
+ expected: PASS
[Blob content with short content and a range end matching content length]
- expected: FAIL
+ expected: PASS
[Blob range with whitespace before and after hyphen]
expected: FAIL
@@ -83,25 +83,25 @@
[blob-range.any.html]
[A simple blob range request.]
- expected: FAIL
+ expected: PASS
[A blob range request with no type.]
expected: FAIL
[A blob range request with no end.]
- expected: FAIL
+ expected: PASS
[A blob range request with no start.]
- expected: FAIL
+ expected: PASS
[A simple blob range request with whitespace.]
expected: FAIL
[Blob content with short content and a large range end]
- expected: FAIL
+ expected: PASS
[Blob content with short content and a range end matching content length]
- expected: FAIL
+ expected: PASS
[Blob range with whitespace before and after hyphen]
expected: FAIL
diff --git a/tests/wpt/mozilla/meta/MANIFEST.json b/tests/wpt/mozilla/meta/MANIFEST.json
index 0e36ca7dca4..2577bfabe3e 100644
--- a/tests/wpt/mozilla/meta/MANIFEST.json
+++ b/tests/wpt/mozilla/meta/MANIFEST.json
@@ -13905,13 +13905,6 @@
{}
]
],
- "range_request_blob_url.html": [
- "075397620e989dafc814c0ed2bca46bd476bccf6",
- [
- null,
- {}
- ]
- ],
"range_request_file_url.html": [
"4fd4ddc8b1a9959e90b243795267c220d6a05f5e",
[
diff --git a/tests/wpt/mozilla/tests/mozilla/range_request_blob_url.html b/tests/wpt/mozilla/tests/mozilla/range_request_blob_url.html
deleted file mode 100644
index 075397620e9..00000000000
--- a/tests/wpt/mozilla/tests/mozilla/range_request_blob_url.html
+++ /dev/null
@@ -1,60 +0,0 @@
-<html>
-<head>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script>
-[{
- range: "bytes=0-",
- status: 206,
- expected: "abcdefghijklmnopqrstuvwxyz"
-}, {
- range: "bytes=0-9",
- status: 206,
- expected: "abcdefghi"
-}, {
- range: "bytes=1-9",
- status: 206,
- expected: "bcdefghi"
-}, {
- range: "bytes=-10",
- status: 206,
- expected: "qrstuvwxyz"
-}, {
- range: "bytes=0-100",
- status: 206,
- expected: "abcdefghijklmnopqrstuvwxyz"
-}, {
- range: "bytes=100-",
- status: 416,
- expected: ""
-}, {
- range: "bytes=-100",
- status: 206,
- expected: "abcdefghijklmnopqrstuvwxyz"
-}].forEach(test => {
- promise_test(function() {
- const abc = "abcdefghijklmnopqrstuvwxyz";
- const blob = new Blob([abc], { "type": "text/plain" });
- return fetch(URL.createObjectURL(blob), {
- headers: {
- "Range": test.range
- }
- })
- .then(response => {
- assert_equals(response.status, test.status);
- if (response.status != 206) {
- return "";
- }
- return response.text();
- })
- .then(response => {
- assert_equals(response, test.expected);
- });
- });
-});
-
-</script>
-</head>
-</body>
-</html>
-