Skip to content

Commit

Permalink
Implement srcObject logic for Blob media providers
Browse files Browse the repository at this point in the history
  • Loading branch information
ferjm committed Mar 26, 2019
1 parent 40d599e commit bc69210
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 14 deletions.
76 changes: 63 additions & 13 deletions components/script/dom/htmlmediaelement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@ use crate::dom::bindings::codegen::Bindings::MediaErrorBinding::MediaErrorMethod
use crate::dom::bindings::codegen::Bindings::TextTrackBinding::{TextTrackKind, TextTrackMode};
use crate::dom::bindings::codegen::InheritTypes::{ElementTypeId, HTMLElementTypeId};
use crate::dom::bindings::codegen::InheritTypes::{HTMLMediaElementTypeId, NodeTypeId};
use crate::dom::bindings::codegen::UnionTypes::VideoTrackOrAudioTrackOrTextTrack;
use crate::dom::bindings::codegen::UnionTypes::{
MediaStreamOrBlob, VideoTrackOrAudioTrackOrTextTrack,
};
use crate::dom::bindings::error::{Error, ErrorResult, Fallible};
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::num::Finite;
use crate::dom::bindings::refcounted::Trusted;
use crate::dom::bindings::reflector::DomObject;
use crate::dom::bindings::root::{DomRoot, LayoutDom, MutNullableDom};
use crate::dom::bindings::root::{Dom, DomRoot, LayoutDom, MutNullableDom};
use crate::dom::bindings::str::{DOMString, USVString};
use crate::dom::blob::Blob;
use crate::dom::document::Document;
Expand All @@ -35,13 +37,15 @@ use crate::dom::htmlelement::HTMLElement;
use crate::dom::htmlsourceelement::HTMLSourceElement;
use crate::dom::htmlvideoelement::HTMLVideoElement;
use crate::dom::mediaerror::MediaError;
use crate::dom::mediastream::MediaStream;
use crate::dom::node::{document_from_node, window_from_node, Node, NodeDamage, UnbindContext};
use crate::dom::performanceresourcetiming::InitiatorType;
use crate::dom::promise::Promise;
use crate::dom::texttrack::TextTrack;
use crate::dom::texttracklist::TextTrackList;
use crate::dom::timeranges::{TimeRanges, TimeRangesContainer};
use crate::dom::trackevent::TrackEvent;
use crate::dom::url::URL;
use crate::dom::videotrack::VideoTrack;
use crate::dom::videotracklist::VideoTrackList;
use crate::dom::virtualmethods::VirtualMethods;
Expand Down Expand Up @@ -155,6 +159,25 @@ impl FrameRenderer for MediaFrameRenderer {
}
}

#[must_root]
#[derive(JSTraceable, MallocSizeOf)]
enum SrcObject {
MediaStream(Dom<MediaStream>),
Blob(Dom<Blob>),
}

impl From<MediaStreamOrBlob> for SrcObject {
#[allow(unrooted_must_root)]
fn from(src_object: MediaStreamOrBlob) -> SrcObject {
match src_object {
MediaStreamOrBlob::Blob(blob) => SrcObject::Blob(Dom::from_ref(&*blob)),
MediaStreamOrBlob::MediaStream(stream) => {
SrcObject::MediaStream(Dom::from_ref(&*stream))
},
}
}
}

#[dom_struct]
pub struct HTMLMediaElement {
htmlelement: HTMLElement,
Expand All @@ -163,7 +186,7 @@ pub struct HTMLMediaElement {
/// <https://html.spec.whatwg.org/multipage/#dom-media-readystate>
ready_state: Cell<ReadyState>,
/// <https://html.spec.whatwg.org/multipage/#dom-media-srcobject>
src_object: MutNullableDom<Blob>,
src_object: DomRefCell<Option<SrcObject>>,
/// <https://html.spec.whatwg.org/multipage/#dom-media-currentsrc>
current_src: DomRefCell<String>,
/// Incremented whenever tasks associated with this element are cancelled.
Expand Down Expand Up @@ -210,6 +233,9 @@ pub struct HTMLMediaElement {
muted: Cell<bool>,
/// URL of the media resource, if any.
resource_url: DomRefCell<Option<ServoUrl>>,
/// URL of the media resource, if the resource is set through the src_object attribute and it
/// is a blob.
blob_url: DomRefCell<Option<ServoUrl>>,
/// https://html.spec.whatwg.org/multipage/#dom-media-played
#[ignore_malloc_size_of = "Rc"]
played: DomRefCell<TimeRangesContainer>,
Expand Down Expand Up @@ -278,6 +304,7 @@ impl HTMLMediaElement {
volume: Cell::new(1.0),
seeking: Cell::new(false),
resource_url: DomRefCell::new(None),
blob_url: DomRefCell::new(None),
played: DomRefCell::new(TimeRangesContainer::new()),
audio_tracks_list: Default::default(),
video_tracks_list: Default::default(),
Expand Down Expand Up @@ -555,7 +582,7 @@ impl HTMLMediaElement {
Children(DomRoot<HTMLSourceElement>),
}
fn mode(media: &HTMLMediaElement) -> Option<Mode> {
if media.src_object.get().is_some() {
if media.src_object.borrow().is_some() {
return Some(Mode::Object);
}
if let Some(attr) = media
Expand Down Expand Up @@ -659,7 +686,7 @@ impl HTMLMediaElement {
}

fn fetch_request(&self, offset: Option<u64>) {
if self.resource_url.borrow().is_none() {
if self.resource_url.borrow().is_none() && self.blob_url.borrow().is_none() {
eprintln!("Missing request url");
self.queue_dedicated_media_source_failure_steps();
return;
Expand All @@ -677,8 +704,12 @@ impl HTMLMediaElement {
header::RANGE,
HeaderValue::from_str(&format!("bytes={}-", offset.unwrap_or(0))).unwrap(),
);
let url = match self.resource_url.borrow().as_ref() {
Some(url) => url.clone(),
None => self.blob_url.borrow().as_ref().unwrap().clone(),
};
let request = RequestInit {
url: self.resource_url.borrow().as_ref().unwrap().clone(),
url: url.clone(),
headers,
destination,
credentials_mode: CredentialsMode::Include,
Expand All @@ -698,7 +729,7 @@ impl HTMLMediaElement {
*current_fetch_context = Some(fetch_context);
let fetch_listener = Arc::new(Mutex::new(HTMLMediaElementFetchListener::new(
self,
self.resource_url.borrow().as_ref().unwrap().clone(),
url.clone(),
offset.unwrap_or(0),
)));
let (action_sender, action_receiver) = ipc::channel().unwrap();
Expand Down Expand Up @@ -786,8 +817,19 @@ impl HTMLMediaElement {
self.fetch_request(None);
},
Resource::Object => {
// FIXME(nox): Actually do something with the object.
self.queue_dedicated_media_source_failure_steps();
if let Some(ref src_object) = *self.src_object.borrow() {
match src_object {
SrcObject::Blob(blob) => {
let blob_url = URL::CreateObjectURL(&self.global(), &*blob);
*self.blob_url.borrow_mut() =
Some(ServoUrl::parse(&blob_url).expect("infallible"));
self.fetch_request(None);
},
SrcObject::MediaStream(_) => {
self.queue_dedicated_media_source_failure_steps();
},
}
}
},
}
}
Expand Down Expand Up @@ -1539,13 +1581,21 @@ impl HTMLMediaElementMethods for HTMLMediaElement {
}

// https://html.spec.whatwg.org/multipage/#dom-media-srcobject
fn GetSrcObject(&self) -> Option<DomRoot<Blob>> {
self.src_object.get()
fn GetSrcObject(&self) -> Option<MediaStreamOrBlob> {
match *self.src_object.borrow() {
Some(ref src_object) => Some(match src_object {
SrcObject::Blob(blob) => MediaStreamOrBlob::Blob(DomRoot::from_ref(&*blob)),
SrcObject::MediaStream(stream) => {
MediaStreamOrBlob::MediaStream(DomRoot::from_ref(&*stream))
},
}),
None => None,
}
}

// https://html.spec.whatwg.org/multipage/#dom-media-srcobject
fn SetSrcObject(&self, value: Option<&Blob>) {
self.src_object.set(value);
fn SetSrcObject(&self, value: Option<MediaStreamOrBlob>) {
*self.src_object.borrow_mut() = value.map(|value| value.into());
self.media_element_load_algorithm();
}

Expand Down
2 changes: 1 addition & 1 deletion components/script/dom/webidls/HTMLMediaElement.webidl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// https://html.spec.whatwg.org/multipage/#htmlmediaelement

enum CanPlayTypeResult { "" /* empty string */, "maybe", "probably" };
typedef /* (MediaStream or MediaSource or */ Blob /* ) */ MediaProvider;
typedef (MediaStream /*or MediaSource */ or Blob) MediaProvider;

[Abstract]
interface HTMLMediaElement : HTMLElement {
Expand Down
20 changes: 20 additions & 0 deletions tests/wpt/metadata/MANIFEST.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
{
"items": {
"conformancechecker": {
"html/semantics/embedded-content/media-elements/src_object_blob.html": []
},
"manual": {
"2dcontext/conformance-requirements/2d.coordinatespace-manual.html": [
[
Expand Down Expand Up @@ -12775,6 +12778,7 @@
{}
]
],
"html/semantics/embedded-content/media-elements/src_object_blob.html": [],
"html/semantics/embedded-content/media-elements/video_controls_present-manual.html": [
[
"html/semantics/embedded-content/media-elements/video_controls_present-manual.html",
Expand Down Expand Up @@ -194571,6 +194575,7 @@
{}
]
],
"html/semantics/embedded-content/media-elements/src_object_blob.html": [],
"html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-after-controls-added.html": [
[
"html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-after-controls-added.html",
Expand Down Expand Up @@ -201711,6 +201716,7 @@
{}
]
],
"html/semantics/embedded-content/media-elements/src_object_blob.html": [],
"infrastructure/assumptions/ahem-ref.html": [
[
"infrastructure/assumptions/ahem-ref.html",
Expand Down Expand Up @@ -201809,6 +201815,7 @@
]
},
"stub": {
"html/semantics/embedded-content/media-elements/src_object_blob.html": [],
"service-workers/stub-3.1-service-worker-obj.html": [
[
"service-workers/stub-3.1-service-worker-obj.html",
Expand Down Expand Up @@ -300426,6 +300433,7 @@
{}
]
],
"html/semantics/embedded-content/media-elements/src_object_blob.html": [],
"html/semantics/embedded-content/media-elements/track/track-element/cors/support/common.js": [
[
{}
Expand Down Expand Up @@ -388893,6 +388901,12 @@
{}
]
],
"html/semantics/embedded-content/media-elements/src_object_blob.html": [
[
"html/semantics/embedded-content/media-elements/src_object_blob.html",
{}
]
],
"html/semantics/embedded-content/media-elements/src_reflects_attribute_not_source_elements.html": [
[
"html/semantics/embedded-content/media-elements/src_reflects_attribute_not_source_elements.html",
Expand Down Expand Up @@ -474312,6 +474326,7 @@
{}
]
],
"html/semantics/embedded-content/media-elements/src_object_blob.html": [],
"svg/text/visualtests/text-inline-size-001-visual.svg": [
[
"svg/text/visualtests/text-inline-size-001-visual.svg",
Expand Down Expand Up @@ -474362,6 +474377,7 @@
]
},
"wdspec": {
"html/semantics/embedded-content/media-elements/src_object_blob.html": [],
"infrastructure/webdriver/tests/test_load_file.py": [
[
"infrastructure/webdriver/tests/test_load_file.py",
Expand Down Expand Up @@ -660109,6 +660125,10 @@
"56a99028deb273359f32fc14b53b9317a4b9c76d",
"testharness"
],
"html/semantics/embedded-content/media-elements/src_object_blob.html": [
"3ab7477cca523df6a724d0cdb2d479048bfa00f7",
"testharness"
],
"html/semantics/embedded-content/media-elements/src_reflects_attribute_not_source_elements.html": [
"3dd43cc3f5524a32b7438e33481552653076cbe8",
"testharness"
Expand Down
9 changes: 9 additions & 0 deletions tests/wpt/mozilla/meta/MANIFEST.json
Original file line number Diff line number Diff line change
Expand Up @@ -10839,6 +10839,11 @@
{}
]
],
"mozilla/movie_5.mp4": [
[
{}
]
],
"mozilla/nested_asap_script.js": [
[
{}
Expand Down Expand Up @@ -20321,6 +20326,10 @@
"3d8a4d170595ee7bd8926581eefd179a20d131a8",
"testharness"
],
"mozilla/movie_5.mp4": [
"fb5dbca23808bee44003692cb0e139dd6a22e874",
"support"
],
"mozilla/mql_borrow.html": [
"17ee0dc48a30933429cb901760ef1b074ed56b6e",
"testharness"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<!doctype html>
<meta charset="utf-8">
<title>HTMLMediaElement.srcObject blob</title>
<script src='/common/media.js'></script>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<video></video>
<script>
async_test(function(t) {
t.step(function() {
fetch(getVideoURI('/media/movie_5'))
.then(function(response) {
return response.blob();
})
.then(function(blob) {
let video = document.querySelector("video");
video.srcObject = blob;
video.addEventListener('ended', function() {
t.done();
});
video.play().catch(function(error) {
assert(false, error);
});
})
.catch(function(error) {
assert(false, error);
});
});
});
</script>

0 comments on commit bc69210

Please sign in to comment.