servo: Merge #10203 - Avoid script execution when not found (from Shiroy:script-not-found-executed); r=Ms2ger
authorShiroy <awacheux.utc@gmail.com>
Sat, 09 Apr 2016 15:27:27 +0500
changeset 476633 cd86da741612933fa7f41e5e102f94b1039a5e3a
parent 476632 a614fe2d45a878029c95e618929458ee754bdba8
child 476634 d07ee1178d980f2d5ff8a86d6c429eb0d3e9a82b
push id44079
push userbmo:gps@mozilla.com
push dateSat, 04 Feb 2017 00:14:49 +0000
reviewersMs2ger
servo: Merge #10203 - Avoid script execution when not found (from Shiroy:script-not-found-executed); r=Ms2ger Fix #8391 If the status code is an error or has not been received, we discard data and prevent the script from being executed. Source-Repo: https://github.com/servo/servo Source-Revision: 4720992ffcf23a166b3ae08d8090cff5a993a0b6
servo/components/script/dom/htmlscriptelement.rs
--- a/servo/components/script/dom/htmlscriptelement.rs
+++ b/servo/components/script/dom/htmlscriptelement.rs
@@ -23,16 +23,17 @@ use dom::eventtarget::EventTarget;
 use dom::htmlelement::HTMLElement;
 use dom::node::{ChildrenMutation, CloneChildrenFlag, Node};
 use dom::node::{document_from_node, window_from_node};
 use dom::virtualmethods::VirtualMethods;
 use dom::window::ScriptHelpers;
 use encoding::label::encoding_from_whatwg_label;
 use encoding::types::{DecoderTrap, Encoding, EncodingRef};
 use html5ever::tree_builder::NextParserState;
+use hyper::http::RawStatus;
 use ipc_channel::ipc;
 use ipc_channel::router::ROUTER;
 use js::jsapi::RootedValue;
 use js::jsval::UndefinedValue;
 use net_traits::{AsyncResponseListener, AsyncResponseTarget, Metadata};
 use network_listener::{NetworkListener, PreInvoke};
 use script_runtime::ScriptChan;
 use script_thread::MainThreadScriptChan;
@@ -131,30 +132,45 @@ struct ScriptContext {
     /// The element that initiated the request.
     elem: Trusted<HTMLScriptElement>,
     /// The response body received to date.
     data: Vec<u8>,
     /// The response metadata received to date.
     metadata: Option<Metadata>,
     /// The initial URL requested.
     url: Url,
+    /// Indicates whether the request failed, and why
+    status: Result<(), String>
 }
 
 impl AsyncResponseListener for ScriptContext {
     fn headers_available(&mut self, metadata: Metadata) {
+        let status_code = match metadata.status {
+            Some(RawStatus(c, _)) => c,
+            _ => 0
+        };
+
+        self.status = match status_code {
+            0 => Err("No http status code received".to_owned()),
+            200...299 => Ok(()), // HTTP ok status codes
+            _ => Err(format!("HTTP error code {}", status_code))
+        };
+
         self.metadata = Some(metadata);
     }
 
     fn data_available(&mut self, payload: Vec<u8>) {
-        let mut payload = payload;
-        self.data.append(&mut payload);
+        if self.status.is_ok() {
+            let mut payload = payload;
+            self.data.append(&mut payload);
+        }
     }
 
     fn response_complete(&mut self, status: Result<(), String>) {
-        let load = status.map(|_| {
+        let load = status.and(self.status.clone()).map(|_| {
             let data = mem::replace(&mut self.data, vec!());
             let metadata = self.metadata.take().unwrap();
             (metadata, data)
         });
         let elem = self.elem.root();
         // TODO: maybe set this to None again after script execution to save memory.
         *elem.load.borrow_mut() = Some(ScriptOrigin::External(load));
         elem.ready_to_be_parser_executed.set(true);
@@ -287,16 +303,17 @@ impl HTMLScriptElement {
                 let script_chan = window.networking_task_source();
                 let elem = Trusted::new(self, script_chan.clone());
 
                 let context = Arc::new(Mutex::new(ScriptContext {
                     elem: elem,
                     data: vec!(),
                     metadata: None,
                     url: url.clone(),
+                    status: Ok(())
                 }));
 
                 let (action_sender, action_receiver) = ipc::channel().unwrap();
                 let listener = NetworkListener {
                     context: context,
                     script_chan: script_chan,
                 };
                 let response_target = AsyncResponseTarget {