diff options
Diffstat (limited to 'components/script/dom/htmlscriptelement.rs')
-rw-r--r-- | components/script/dom/htmlscriptelement.rs | 106 |
1 files changed, 88 insertions, 18 deletions
diff --git a/components/script/dom/htmlscriptelement.rs b/components/script/dom/htmlscriptelement.rs index 11f4451ad50..566b69967d4 100644 --- a/components/script/dom/htmlscriptelement.rs +++ b/components/script/dom/htmlscriptelement.rs @@ -5,6 +5,7 @@ use document_loader::LoadType; use dom::attr::Attr; use dom::bindings::cell::DOMRefCell; +use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods; use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods; use dom::bindings::codegen::Bindings::HTMLScriptElementBinding; use dom::bindings::codegen::Bindings::HTMLScriptElementBinding::HTMLScriptElementMethods; @@ -14,6 +15,7 @@ use dom::bindings::inheritance::Castable; use dom::bindings::js::{JS, Root}; use dom::bindings::js::RootedReference; use dom::bindings::refcounted::Trusted; +use dom::bindings::reflector::Reflectable; use dom::bindings::str::DOMString; use dom::document::Document; use dom::element::{AttributeMutation, Element, ElementCreator}; @@ -29,7 +31,8 @@ use html5ever::tree_builder::NextParserState; use ipc_channel::ipc; use ipc_channel::router::ROUTER; use js::jsval::UndefinedValue; -use net_traits::{AsyncResponseListener, AsyncResponseTarget, Metadata, NetworkError}; +use net_traits::{FetchMetadata, FetchResponseListener, Metadata, NetworkError}; +use net_traits::request::{CORSSettings, CredentialsMode, Destination, RequestInit, RequestMode, Type as RequestType}; use network_listener::{NetworkListener, PreInvoke}; use std::ascii::AsciiExt; use std::cell::Cell; @@ -151,9 +154,17 @@ struct ScriptContext { status: Result<(), NetworkError> } -impl AsyncResponseListener for ScriptContext { - fn headers_available(&mut self, metadata: Result<Metadata, NetworkError>) { - self.metadata = metadata.ok(); +impl FetchResponseListener for ScriptContext { + fn process_request_body(&mut self) {} // TODO(KiChjang): Perhaps add custom steps to perform fetch here? + + fn process_request_eof(&mut self) {} // TODO(KiChjang): Perhaps add custom steps to perform fetch here? + + fn process_response(&mut self, + metadata: Result<FetchMetadata, NetworkError>) { + self.metadata = metadata.ok().map(|meta| match meta { + FetchMetadata::Unfiltered(m) => m, + FetchMetadata::Filtered { unsafe_, .. } => unsafe_ + }); let status_code = self.metadata.as_ref().and_then(|m| { match m.status { @@ -169,18 +180,17 @@ impl AsyncResponseListener for ScriptContext { }; } - fn data_available(&mut self, payload: Vec<u8>) { + fn process_response_chunk(&mut self, mut chunk: Vec<u8>) { if self.status.is_ok() { - let mut payload = payload; - self.data.append(&mut payload); + self.data.append(&mut chunk); } } /// https://html.spec.whatwg.org/multipage/#fetch-a-classic-script /// step 4-9 - fn response_complete(&mut self, status: Result<(), NetworkError>) { + fn process_response_eof(&mut self, response: Result<(), NetworkError>) { // Step 5. - let load = status.and(self.status.clone()).map(|_| { + let load = response.and(self.status.clone()).map(|_| { let metadata = self.metadata.take().unwrap(); // Step 6. @@ -210,8 +220,38 @@ impl PreInvoke for ScriptContext {} /// https://html.spec.whatwg.org/multipage/#fetch-a-classic-script fn fetch_a_classic_script(script: &HTMLScriptElement, url: Url, + cors_setting: Option<CORSSettings>, character_encoding: EncodingRef) { - // TODO(#9186): use the fetch infrastructure. + let doc = document_from_node(script); + + // Step 1, 2. + let request = RequestInit { + url: url.clone(), + type_: RequestType::Script, + destination: Destination::Script, + // https://html.spec.whatwg.org/multipage/#create-a-potential-cors-request + // Step 1 + mode: match cors_setting { + Some(_) => RequestMode::CORSMode, + None => RequestMode::NoCORS, + }, + // https://html.spec.whatwg.org/multipage/#create-a-potential-cors-request + // Step 3-4 + credentials_mode: match cors_setting { + Some(CORSSettings::Anonymous) => CredentialsMode::CredentialsSameOrigin, + _ => CredentialsMode::Include, + }, + origin: doc.url().clone(), + pipeline_id: Some(script.global().r().pipeline_id()), + // FIXME: Set to true for now, discussion in https://github.com/whatwg/fetch/issues/381 + same_origin_data: true, + referrer_url: Some(doc.url().clone()), + referrer_policy: doc.get_referrer_policy(), + .. RequestInit::default() + }; + + // TODO: Step 3, Add custom steps to perform fetch + let context = Arc::new(Mutex::new(ScriptContext { elem: Trusted::new(script), character_encoding: character_encoding, @@ -229,14 +269,11 @@ fn fetch_a_classic_script(script: &HTMLScriptElement, script_chan: doc.window().networking_task_source(), wrapper: Some(doc.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()); }); - - doc.load_async(LoadType::Script(url), response_target, None); + doc.fetch_async(LoadType::Script(url), request, action_sender, None); } impl HTMLScriptElement { @@ -322,7 +359,13 @@ impl HTMLScriptElement { .and_then(|charset| encoding_from_whatwg_label(&charset.value())) .unwrap_or_else(|| doc.encoding()); - // TODO: Step 14: CORS. + // Step 14. + let cors_setting = match self.GetCrossOrigin() { + Some(ref s) if *s == "anonymous" => Some(CORSSettings::Anonymous), + Some(ref s) if *s == "use-credentials" => Some(CORSSettings::UseCredentials), + None => None, + _ => unreachable!() + }; // TODO: Step 15: Nonce. @@ -354,10 +397,11 @@ impl HTMLScriptElement { }; // Step 18.6. - fetch_a_classic_script(self, url, encoding); + fetch_a_classic_script(self, url, cors_setting, encoding); true }, + // TODO: Step 19. None => false, }; @@ -652,6 +696,32 @@ impl HTMLScriptElementMethods for HTMLScriptElement { // https://html.spec.whatwg.org/multipage/#dom-script-htmlfor make_setter!(SetHtmlFor, "for"); + // https://html.spec.whatwg.org/multipage/#dom-script-crossorigin + fn GetCrossOrigin(&self) -> Option<DOMString> { + let element = self.upcast::<Element>(); + let attr = element.get_attribute(&ns!(), &atom!("crossorigin")); + + if let Some(mut val) = attr.map(|v| v.Value()) { + val.make_ascii_lowercase(); + if val == "anonymous" || val == "use-credentials" { + return Some(val); + } + return Some(DOMString::from("anonymous")); + } + None + } + + // https://html.spec.whatwg.org/multipage/#dom-script-crossorigin + fn SetCrossOrigin(&self, value: Option<DOMString>) { + let element = self.upcast::<Element>(); + match value { + Some(val) => element.set_string_attribute(&atom!("crossorigin"), val), + None => { + element.remove_attribute(&ns!(), &atom!("crossorigin")); + } + } + } + // https://html.spec.whatwg.org/multipage/#dom-script-text fn Text(&self) -> DOMString { Node::collect_text_contents(self.upcast::<Node>().children()) |