servo: Merge #13677 - Use the fetch stack for HTMLMediaElement (from servo:media-fetch); r=Manishearth
authorMs2ger <Ms2ger@gmail.com>
Tue, 11 Oct 2016 11:10:39 -0500
changeset 339885 947ebc8b43fc8b3c435e02f41042894e040fafc9
parent 339884 1fbb397120eb5a59693f454216c3f915bc93aa36
child 339886 752a824583bf9b280c2f301c96cbd08b16818343
push id31307
push usergszorc@mozilla.com
push dateSat, 04 Feb 2017 00:59:06 +0000
treeherdermozilla-central@94079d43835f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersManishearth
servo: Merge #13677 - Use the fetch stack for HTMLMediaElement (from servo:media-fetch); r=Manishearth Source-Repo: https://github.com/servo/servo Source-Revision: 51bcf516c831f60a6fc05d970df5fad99730558e
servo/components/script/dom/htmlmediaelement.rs
--- a/servo/components/script/dom/htmlmediaelement.rs
+++ b/servo/components/script/dom/htmlmediaelement.rs
@@ -10,28 +10,32 @@ use dom::bindings::codegen::Bindings::At
 use dom::bindings::codegen::Bindings::HTMLMediaElementBinding::CanPlayTypeResult;
 use dom::bindings::codegen::Bindings::HTMLMediaElementBinding::HTMLMediaElementConstants::*;
 use dom::bindings::codegen::Bindings::HTMLMediaElementBinding::HTMLMediaElementMethods;
 use dom::bindings::codegen::Bindings::MediaErrorBinding::MediaErrorConstants::*;
 use dom::bindings::codegen::Bindings::MediaErrorBinding::MediaErrorMethods;
 use dom::bindings::inheritance::Castable;
 use dom::bindings::js::{Root, MutNullableHeap, JS};
 use dom::bindings::refcounted::Trusted;
+use dom::bindings::reflector::Reflectable;
 use dom::bindings::str::DOMString;
 use dom::document::Document;
 use dom::element::{Element, AttributeMutation};
 use dom::event::{Event, EventBubbles, EventCancelable};
+use dom::htmlaudioelement::HTMLAudioElement;
 use dom::htmlelement::HTMLElement;
 use dom::htmlsourceelement::HTMLSourceElement;
+use dom::htmlvideoelement::HTMLVideoElement;
 use dom::mediaerror::MediaError;
 use dom::node::{window_from_node, document_from_node, Node, UnbindContext};
 use dom::virtualmethods::VirtualMethods;
 use ipc_channel::ipc;
 use ipc_channel::router::ROUTER;
-use net_traits::{AsyncResponseListener, AsyncResponseTarget, Metadata, NetworkError};
+use net_traits::{FetchResponseListener, FetchMetadata, Metadata, NetworkError};
+use net_traits::request::{CredentialsMode, Destination, RequestInit, Type as RequestType};
 use network_listener::{NetworkListener, PreInvoke};
 use script_thread::{Runnable, ScriptThread};
 use std::cell::Cell;
 use std::sync::{Arc, Mutex};
 use string_cache::Atom;
 use task_source::TaskSource;
 use time::{self, Timespec, Duration};
 use url::Url;
@@ -50,37 +54,46 @@ struct HTMLMediaElementContext {
     /// Url of resource requested.
     url: Url,
     /// Whether the media metadata has been completely received.
     have_metadata: bool,
     /// True if this response is invalid and should be ignored.
     ignore_response: bool,
 }
 
-impl AsyncResponseListener for HTMLMediaElementContext {
+impl FetchResponseListener for HTMLMediaElementContext {
+    fn process_request_body(&mut self) {}
+
+    fn process_request_eof(&mut self) {}
+
     // https://html.spec.whatwg.org/multipage/#media-data-processing-steps-list
-    fn headers_available(&mut self, metadata: Result<Metadata, NetworkError>) {
-        self.metadata = metadata.ok();
+    fn process_response(&mut self, metadata: Result<FetchMetadata, NetworkError>) {
+        self.metadata = metadata.ok().map(|m| {
+            match m {
+                FetchMetadata::Unfiltered(m) => m,
+                FetchMetadata::Filtered { unsafe_, .. } => unsafe_
+            }
+        });
 
         // => "If the media data cannot be fetched at all..."
         let is_failure = self.metadata
                              .as_ref()
                              .and_then(|m| m.status
                                             .as_ref()
                                             .map(|&(s, _)| s < 200 || s >= 300))
                              .unwrap_or(false);
         if is_failure {
             // Ensure that the element doesn't receive any further notifications
             // of the aborted fetch. The dedicated failure steps will be executed
             // when response_complete runs.
             self.ignore_response = true;
         }
     }
 
-    fn data_available(&mut self, mut payload: Vec<u8>) {
+    fn process_response_chunk(&mut self, mut payload: Vec<u8>) {
         if self.ignore_response {
             return;
         }
 
         self.data.append(&mut payload);
 
         let elem = self.elem.root();
 
@@ -96,17 +109,17 @@ impl AsyncResponseListener for HTMLMedia
         // => "If mode is remote" step 2
         if time::get_time() > self.next_progress_event {
             elem.queue_fire_simple_event("progress");
             self.next_progress_event = time::get_time() + Duration::milliseconds(350);
         }
     }
 
     // https://html.spec.whatwg.org/multipage/#media-data-processing-steps-list
-    fn response_complete(&mut self, status: Result<(), NetworkError>) {
+    fn process_response_eof(&mut self, status: Result<(), NetworkError>) {
         let elem = self.elem.root();
 
         // => "If the media data can be fetched but is found by inspection to be in an unsupported
         //     format, or can otherwise not be rendered at all"
         if !self.have_metadata {
             elem.queue_dedicated_media_source_failure_steps();
         }
         // => "Once the entire media resource has been fetched..."
@@ -503,32 +516,51 @@ impl HTMLMediaElement {
                 return;
             }
 
             // 4.2
             let context = Arc::new(Mutex::new(HTMLMediaElementContext::new(self, url.clone())));
             let (action_sender, action_receiver) = ipc::channel().unwrap();
             let window = window_from_node(self);
             let script_chan = window.networking_task_source();
-            let listener = box NetworkListener {
+            let listener = NetworkListener {
                 context: context,
                 script_chan: script_chan,
                 wrapper: Some(window.get_runnable_wrapper()),
             };
 
-            let response_target = AsyncResponseTarget {
-                sender: action_sender,
-            };
             ROUTER.add_route(action_receiver.to_opaque(), box move |message| {
-                listener.notify_action(message.to().unwrap());
+                listener.notify_fetch(message.to().unwrap());
             });
 
             // FIXME: we're supposed to block the load event much earlier than now
-            let doc = document_from_node(self);
-            doc.load_async(LoadType::Media(url), response_target, None);
+            let document = document_from_node(self);
+
+            let ty = if self.is::<HTMLAudioElement>() {
+                RequestType::Audio
+            } else if self.is::<HTMLVideoElement>() {
+                RequestType::Video
+            } else {
+                unreachable!("Unexpected HTMLMediaElement")
+            };
+
+            let request = RequestInit {
+                url: url.clone(),
+                type_: ty,
+                destination: Destination::Media,
+                credentials_mode: CredentialsMode::Include,
+                use_url_credentials: true,
+                origin: document.url().clone(),
+                pipeline_id: Some(self.global().pipeline_id()),
+                referrer_url: Some(document.url().clone()),
+                referrer_policy: document.get_referrer_policy(),
+                .. RequestInit::default()
+            };
+
+            document.fetch_async(LoadType::Media(url), request, action_sender);
         } else {
             // TODO local resource fetch
             self.queue_dedicated_media_source_failure_steps();
         }
     }
 
     fn queue_dedicated_media_source_failure_steps(&self) {
         let window = window_from_node(self);