aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/net/fetch/methods.rs12
-rw-r--r--components/net_traits/lib.rs26
-rw-r--r--components/net_traits/request.rs81
-rw-r--r--components/net_traits/response.rs48
-rw-r--r--components/script/document_loader.rs17
-rw-r--r--components/script/dom/document.rs13
-rw-r--r--components/script/dom/htmlscriptelement.rs106
-rw-r--r--components/script/dom/webidls/HTMLScriptElement.webidl2
-rw-r--r--components/script/dom/xmlhttprequest.rs75
-rw-r--r--tests/wpt/metadata/MANIFEST.json12
-rw-r--r--tests/wpt/metadata/html/dom/interfaces.html.ini6
-rw-r--r--tests/wpt/metadata/html/dom/reflection-misc.html.ini219
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/resources/cross-origin.py10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-crossorigin-network.html49
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-crossorigin.html39
15 files changed, 363 insertions, 352 deletions
diff --git a/components/net/fetch/methods.rs b/components/net/fetch/methods.rs
index dd35ce06656..1f3eb0e5a24 100644
--- a/components/net/fetch/methods.rs
+++ b/components/net/fetch/methods.rs
@@ -22,7 +22,7 @@ use hyper::status::StatusCode;
use hyper_serde::Serde;
use mime_guess::guess_mime_type;
use msg::constellation_msg::ReferrerPolicy;
-use net_traits::FetchTaskTarget;
+use net_traits::{FetchTaskTarget, FetchMetadata};
use net_traits::request::{CacheMode, CredentialsMode, Destination};
use net_traits::request::{RedirectMode, Referrer, Request, RequestMode, ResponseTainting};
use net_traits::request::{Type, Origin, Window};
@@ -361,13 +361,14 @@ fn main_fetch(request: Rc<Request>, cache: &mut CORSCache, cors_flag: bool,
}
}
} else if let Some(ref mut target) = *target {
- if let ResponseBody::Done(ref vec) = *response.body.lock().unwrap() {
+ let body = response.body.lock().unwrap();
+ if let ResponseBody::Done(ref vec) = *body {
// in case there was no channel to wait for, the body was
// obtained synchronously via basic_fetch for data/file/about/etc
// We should still send the body across as a chunk
target.process_response_chunk(vec.clone());
} else {
- assert!(*response.body.lock().unwrap() == ResponseBody::Empty)
+ assert!(*body == ResponseBody::Empty)
}
}
@@ -981,7 +982,10 @@ fn http_network_fetch(request: Rc<Request>,
// We're about to spawn a thread to be waited on here
*done_chan = Some(channel());
- let meta = response.metadata().expect("Response metadata should exist at this stage");
+ let meta = match response.metadata().expect("Response metadata should exist at this stage") {
+ FetchMetadata::Unfiltered(m) => m,
+ FetchMetadata::Filtered { unsafe_, .. } => unsafe_
+ };
let done_sender = done_chan.as_ref().map(|ch| ch.0.clone());
let devtools_sender = devtools_chan.clone();
let meta_status = meta.status.clone();
diff --git a/components/net_traits/lib.rs b/components/net_traits/lib.rs
index 036fb54d940..2cbc198e0f7 100644
--- a/components/net_traits/lib.rs
+++ b/components/net_traits/lib.rs
@@ -170,7 +170,7 @@ pub enum FetchResponseMsg {
ProcessRequestBody,
ProcessRequestEOF,
// todo: send more info about the response (or perhaps the entire Response)
- ProcessResponse(Result<Metadata, NetworkError>),
+ ProcessResponse(Result<FetchMetadata, NetworkError>),
ProcessResponseChunk(Vec<u8>),
ProcessResponseEOF(Result<(), NetworkError>),
}
@@ -200,10 +200,25 @@ pub trait FetchTaskTarget {
fn process_response_eof(&mut self, response: &Response);
}
+#[derive(Serialize, Deserialize)]
+pub enum FilteredMetadata {
+ Opaque,
+ Transparent(Metadata)
+}
+
+#[derive(Serialize, Deserialize)]
+pub enum FetchMetadata {
+ Unfiltered(Metadata),
+ Filtered {
+ filtered: FilteredMetadata,
+ unsafe_: Metadata
+ }
+}
+
pub trait FetchResponseListener {
fn process_request_body(&mut self);
fn process_request_eof(&mut self);
- fn process_response(&mut self, metadata: Result<Metadata, NetworkError>);
+ fn process_response(&mut self, metadata: Result<FetchMetadata, NetworkError>);
fn process_response_chunk(&mut self, chunk: Vec<u8>);
fn process_response_eof(&mut self, response: Result<(), NetworkError>);
}
@@ -520,6 +535,13 @@ impl PendingAsyncLoad {
let consumer = LoadConsumer::Listener(listener);
self.core_resource_thread.send(CoreResourceMsg::Load(load_data, consumer, None)).unwrap();
}
+
+ /// Initiate the fetch associated with this pending load.
+ pub fn fetch_async(mut self, request: RequestInit, fetch_target: IpcSender<FetchResponseMsg>) {
+ self.guard.neuter();
+
+ self.core_resource_thread.send(CoreResourceMsg::Fetch(request, fetch_target)).unwrap();
+ }
}
/// Message sent in response to `Load`. Contains metadata, and a port
diff --git a/components/net_traits/request.rs b/components/net_traits/request.rs
index 1ed8950bf2d..c31f821680d 100644
--- a/components/net_traits/request.rs
+++ b/components/net_traits/request.rs
@@ -6,6 +6,7 @@ use hyper::header::Headers;
use hyper::method::Method;
use msg::constellation_msg::{PipelineId, ReferrerPolicy};
use std::cell::{Cell, RefCell};
+use std::default::Default;
use std::mem::swap;
use url::{Origin as UrlOrigin, Url};
@@ -20,7 +21,7 @@ pub enum Initiator {
}
/// A request [type](https://fetch.spec.whatwg.org/#concept-request-type)
-#[derive(Copy, Clone, PartialEq, HeapSizeOf)]
+#[derive(Copy, Clone, PartialEq, Serialize, Deserialize, HeapSizeOf)]
pub enum Type {
None, Audio, Font, Image,
Script, Style, Track, Video
@@ -103,7 +104,7 @@ pub enum Window {
}
/// [CORS settings attribute](https://html.spec.whatwg.org/multipage/#attr-crossorigin-anonymous)
-#[derive(Copy, Clone, PartialEq)]
+#[derive(Copy, Clone, PartialEq, Serialize, Deserialize)]
pub enum CORSSettings {
Anonymous,
UseCredentials
@@ -122,6 +123,7 @@ pub struct RequestInit {
pub same_origin_data: bool,
pub body: Option<Vec<u8>>,
// TODO: client object
+ pub type_: Type,
pub destination: Destination,
pub synchronous: bool,
pub mode: RequestMode,
@@ -137,6 +139,30 @@ pub struct RequestInit {
pub pipeline_id: Option<PipelineId>,
}
+impl Default for RequestInit {
+ fn default() -> RequestInit {
+ RequestInit {
+ method: Method::Get,
+ url: Url::parse("about:blank").unwrap(),
+ headers: Headers::new(),
+ unsafe_request: false,
+ same_origin_data: false,
+ body: None,
+ type_: Type::None,
+ destination: Destination::None,
+ synchronous: false,
+ mode: RequestMode::NoCORS,
+ use_cors_preflight: false,
+ credentials_mode: CredentialsMode::Omit,
+ use_url_credentials: false,
+ origin: Url::parse("about:blank").unwrap(),
+ referrer_url: None,
+ referrer_policy: None,
+ pipeline_id: None,
+ }
+ }
+}
+
/// A [Request](https://fetch.spec.whatwg.org/#requests) as defined by the Fetch spec
#[derive(Clone, HeapSizeOf)]
pub struct Request {
@@ -232,6 +258,7 @@ impl Request {
req.unsafe_request = init.unsafe_request;
req.same_origin_data.set(init.same_origin_data);
*req.body.borrow_mut() = init.body;
+ req.type_ = init.type_;
req.destination = init.destination;
req.synchronous = init.synchronous;
req.mode = init.mode;
@@ -248,56 +275,6 @@ impl Request {
req
}
- /// https://html.spec.whatwg.org/multipage/#create-a-potential-cors-request
- pub fn potential_cors_request(url: Url,
- cors_attribute_state: Option<CORSSettings>,
- is_service_worker_global_scope: bool,
- same_origin_fallback: bool,
- pipeline_id: Option<PipelineId>) -> Request {
- Request {
- method: RefCell::new(Method::Get),
- local_urls_only: false,
- sandboxed_storage_area_urls: false,
- headers: RefCell::new(Headers::new()),
- unsafe_request: false,
- body: RefCell::new(None),
- is_service_worker_global_scope: is_service_worker_global_scope,
- window: Cell::new(Window::Client),
- keep_alive: Cell::new(false),
- skip_service_worker: Cell::new(false),
- initiator: Initiator::None,
- type_: Type::None,
- destination: Destination::None,
- origin: RefCell::new(Origin::Client),
- omit_origin_header: Cell::new(false),
- same_origin_data: Cell::new(false),
- referrer: RefCell::new(Referrer::Client),
- referrer_policy: Cell::new(None),
- synchronous: false,
- // Step 1-2
- mode: match cors_attribute_state {
- Some(_) => RequestMode::CORSMode,
- None if same_origin_fallback => RequestMode::SameOrigin,
- None => RequestMode::NoCORS
- },
- use_cors_preflight: false,
- // Step 3-4
- credentials_mode: match cors_attribute_state {
- Some(CORSSettings::Anonymous) => CredentialsMode::CredentialsSameOrigin,
- _ => CredentialsMode::Include,
- },
- use_url_credentials: true,
- cache_mode: Cell::new(CacheMode::Default),
- redirect_mode: Cell::new(RedirectMode::Follow),
- integrity_metadata: RefCell::new(String::new()),
- url_list: RefCell::new(vec![url]),
- redirect_count: Cell::new(0),
- response_tainting: Cell::new(ResponseTainting::Basic),
- pipeline_id: Cell::new(pipeline_id),
- done: Cell::new(false)
- }
- }
-
pub fn url(&self) -> Url {
self.url_list.borrow().first().unwrap().clone()
}
diff --git a/components/net_traits/response.rs b/components/net_traits/response.rs
index 823c56c7002..c4b4a3fe8e3 100644
--- a/components/net_traits/response.rs
+++ b/components/net_traits/response.rs
@@ -4,7 +4,7 @@
//! The [Response](https://fetch.spec.whatwg.org/#responses) object
//! resulting from a [fetch operation](https://fetch.spec.whatwg.org/#concept-fetch)
-use {Metadata, NetworkError};
+use {FetchMetadata, FilteredMetadata, Metadata, NetworkError};
use hyper::header::{AccessControlExposeHeaders, ContentType, Headers};
use hyper::status::StatusCode;
use hyper_serde::Serde;
@@ -225,24 +225,42 @@ impl Response {
response
}
- pub fn metadata(&self) -> Result<Metadata, NetworkError> {
- let mut metadata = if let Some(ref url) = self.url {
- Metadata::default(url.clone())
- } else {
- return Err(NetworkError::Internal("No url found in response".to_string()));
+ pub fn metadata(&self) -> Result<FetchMetadata, NetworkError> {
+ fn init_metadata(response: &Response, url: &Url) -> Metadata {
+ let mut metadata = Metadata::default(url.clone());
+ metadata.set_content_type(match response.headers.get() {
+ Some(&ContentType(ref mime)) => Some(mime),
+ None => None
+ });
+ metadata.headers = Some(Serde(response.headers.clone()));
+ metadata.status = response.raw_status.clone();
+ metadata.https_state = response.https_state;
+ metadata
};
if self.is_network_error() {
- return Err(NetworkError::Internal("Cannot extract metadata from network error".to_string()));
+ return Err(NetworkError::Internal("Cannot extract metadata from network error".to_owned()));
}
- metadata.set_content_type(match self.headers.get() {
- Some(&ContentType(ref mime)) => Some(mime),
- None => None
- });
- metadata.headers = Some(Serde(self.headers.clone()));
- metadata.status = self.raw_status.clone();
- metadata.https_state = self.https_state;
- return Ok(metadata);
+ let metadata = self.url.as_ref().map(|url| init_metadata(self, url));
+
+ if let Some(ref response) = self.internal_response {
+ match response.url {
+ Some(ref url) => {
+ let unsafe_metadata = init_metadata(response, url);
+
+ Ok(FetchMetadata::Filtered {
+ filtered: match metadata {
+ Some(m) => FilteredMetadata::Transparent(m),
+ None => FilteredMetadata::Opaque
+ },
+ unsafe_: unsafe_metadata
+ })
+ }
+ None => Err(NetworkError::Internal("No url found in unsafe response".to_owned()))
+ }
+ } else {
+ Ok(FetchMetadata::Unfiltered(metadata.unwrap()))
+ }
}
}
diff --git a/components/script/document_loader.rs b/components/script/document_loader.rs
index 0fc1e5e06c5..5209b68b9ac 100644
--- a/components/script/document_loader.rs
+++ b/components/script/document_loader.rs
@@ -7,9 +7,11 @@
use dom::bindings::js::JS;
use dom::document::Document;
+use ipc_channel::ipc::IpcSender;
use msg::constellation_msg::{PipelineId, ReferrerPolicy};
-use net_traits::{PendingAsyncLoad, AsyncResponseTarget, LoadContext};
-use net_traits::{ResourceThreads, IpcSend};
+use net_traits::{AsyncResponseTarget, PendingAsyncLoad, LoadContext};
+use net_traits::{FetchResponseMsg, ResourceThreads, IpcSend};
+use net_traits::request::RequestInit;
use std::thread;
use url::Url;
@@ -148,6 +150,17 @@ impl DocumentLoader {
pending.load_async(listener)
}
+ /// Initiate a new fetch.
+ pub fn fetch_async(&mut self,
+ load: LoadType,
+ request: RequestInit,
+ fetch_target: IpcSender<FetchResponseMsg>,
+ referrer: &Document,
+ referrer_policy: Option<ReferrerPolicy>) {
+ let pending = self.prepare_async_load(load, referrer, referrer_policy);
+ pending.fetch_async(request, fetch_target);
+ }
+
/// Mark an in-progress network request complete.
pub fn finish_load(&mut self, load: &LoadType) {
let idx = self.blocking_loads.iter().position(|unfinished| *unfinished == *load);
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index 15cb50aa466..2cca84a625a 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -95,9 +95,10 @@ use js::jsapi::JS_GetRuntime;
use msg::constellation_msg::{ALT, CONTROL, SHIFT, SUPER};
use msg::constellation_msg::{Key, KeyModifiers, KeyState};
use msg::constellation_msg::{PipelineId, ReferrerPolicy};
-use net_traits::{AsyncResponseTarget, IpcSend, PendingAsyncLoad};
+use net_traits::{AsyncResponseTarget, FetchResponseMsg, IpcSend, PendingAsyncLoad};
use net_traits::CookieSource::NonHTTP;
use net_traits::CoreResourceMsg::{GetCookiesForUrl, SetCookiesForUrl};
+use net_traits::request::RequestInit;
use net_traits::response::HttpsState;
use num_traits::ToPrimitive;
use origin::Origin;
@@ -1433,6 +1434,14 @@ impl Document {
loader.load_async(load, listener, self, referrer_policy);
}
+ pub fn fetch_async(&self, load: LoadType,
+ request: RequestInit,
+ fetch_target: IpcSender<FetchResponseMsg>,
+ referrer_policy: Option<ReferrerPolicy>) {
+ let mut loader = self.loader.borrow_mut();
+ loader.fetch_async(load, request, fetch_target, self, referrer_policy);
+ }
+
pub fn finish_load(&self, load: LoadType) {
debug!("Document got finish_load: {:?}", load);
// The parser might need the loader, so restrict the lifetime of the borrow.
@@ -1520,7 +1529,7 @@ impl Document {
}
/// https://html.spec.whatwg.org/multipage/#the-end step 5 and the latter parts of
- /// https://html.spec.whatwg.org/multipage/#prepare-a-script 15.d and 15.e.
+ /// https://html.spec.whatwg.org/multipage/#prepare-a-script 20.d and 20.e.
pub fn process_asap_scripts(&self) {
// Execute the first in-order asap-executed script if it's ready, repeat as required.
// Re-borrowing the list for each step because it can also be borrowed under execute.
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())
diff --git a/components/script/dom/webidls/HTMLScriptElement.webidl b/components/script/dom/webidls/HTMLScriptElement.webidl
index 17df2e7e08b..1636df7a12b 100644
--- a/components/script/dom/webidls/HTMLScriptElement.webidl
+++ b/components/script/dom/webidls/HTMLScriptElement.webidl
@@ -10,7 +10,7 @@ interface HTMLScriptElement : HTMLElement {
attribute DOMString charset;
// attribute boolean async;
attribute boolean defer;
- // attribute DOMString crossOrigin;
+ attribute DOMString? crossOrigin;
[Pure]
attribute DOMString text;
diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs
index d034b60aebd..24ee2c28d36 100644
--- a/components/script/dom/xmlhttprequest.rs
+++ b/components/script/dom/xmlhttprequest.rs
@@ -45,8 +45,8 @@ use js::jsapi::{JSContext, JS_ParseJSON};
use js::jsapi::JS_ClearPendingException;
use js::jsval::{JSVal, NullValue, UndefinedValue};
use msg::constellation_msg::{PipelineId, ReferrerPolicy};
-use net_traits::{CoreResourceThread, LoadOrigin};
-use net_traits::{FetchResponseListener, Metadata, NetworkError};
+use net_traits::{CoreResourceThread, FetchMetadata, FilteredMetadata};
+use net_traits::{FetchResponseListener, LoadOrigin, NetworkError};
use net_traits::CoreResourceMsg::Fetch;
use net_traits::request::{CredentialsMode, Destination, RequestInit, RequestMode};
use net_traits::trim_http_whitespace;
@@ -219,35 +219,39 @@ impl XMLHttpRequest {
core_resource_thread: CoreResourceThread,
init: RequestInit) {
impl FetchResponseListener for XHRContext {
- fn process_request_body(&mut self) {
- // todo
- }
- fn process_request_eof(&mut self) {
- // todo
- }
- fn process_response(&mut self, metadata: Result<Metadata, NetworkError>) {
- let xhr = self.xhr.root();
- let rv = xhr.process_headers_available(self.gen_id,
- metadata);
- if rv.is_err() {
- *self.sync_status.borrow_mut() = Some(rv);
- }
- }
- fn process_response_chunk(&mut self, mut chunk: Vec<u8>) {
- self.buf.borrow_mut().append(&mut chunk);
- self.xhr.root().process_data_available(self.gen_id, self.buf.borrow().clone());
- }
- fn process_response_eof(&mut self, response: Result<(), NetworkError>) {
- let rv = match response {
- Ok(()) => {
- self.xhr.root().process_response_complete(self.gen_id, Ok(()))
- }
- Err(e) => {
- self.xhr.root().process_response_complete(self.gen_id, Err(e))
- }
- };
+ fn process_request_body(&mut self) {
+ // todo
+ }
+
+ fn process_request_eof(&mut self) {
+ // todo
+ }
+
+ fn process_response(&mut self,
+ metadata: Result<FetchMetadata, NetworkError>) {
+ let xhr = self.xhr.root();
+ let rv = xhr.process_headers_available(self.gen_id, metadata);
+ if rv.is_err() {
*self.sync_status.borrow_mut() = Some(rv);
}
+ }
+
+ fn process_response_chunk(&mut self, mut chunk: Vec<u8>) {
+ self.buf.borrow_mut().append(&mut chunk);
+ self.xhr.root().process_data_available(self.gen_id, self.buf.borrow().clone());
+ }
+
+ fn process_response_eof(&mut self, response: Result<(), NetworkError>) {
+ let rv = match response {
+ Ok(()) => {
+ self.xhr.root().process_response_complete(self.gen_id, Ok(()))
+ }
+ Err(e) => {
+ self.xhr.root().process_response_complete(self.gen_id, Err(e))
+ }
+ };
+ *self.sync_status.borrow_mut() = Some(rv);
+ }
}
impl PreInvoke for XHRContext {
@@ -273,9 +277,11 @@ impl LoadOrigin for XMLHttpRequest {
fn referrer_url(&self) -> Option<Url> {
return self.referrer_url.clone();
}
+
fn referrer_policy(&self) -> Option<ReferrerPolicy> {
return self.referrer_policy;
}
+
fn pipeline_id(&self) -> Option<PipelineId> {
let global = self.global();
Some(global.r().pipeline_id())
@@ -596,6 +602,7 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
referrer_url: self.referrer_url.clone(),
referrer_policy: self.referrer_policy.clone(),
pipeline_id: self.pipeline_id(),
+ .. RequestInit::default()
};
if bypass_cross_origin_check {
@@ -862,10 +869,16 @@ impl XMLHttpRequest {
}
fn process_headers_available(&self,
- gen_id: GenerationId, metadata: Result<Metadata, NetworkError>)
+ gen_id: GenerationId, metadata: Result<FetchMetadata, NetworkError>)
-> Result<(), Error> {
let metadata = match metadata {
- Ok(meta) => meta,
+ Ok(meta) => match meta {
+ FetchMetadata::Unfiltered(m) => m,
+ FetchMetadata::Filtered { filtered, .. } => match filtered {
+ FilteredMetadata::Opaque => return Err(Error::Network),
+ FilteredMetadata::Transparent(m) => m
+ }
+ },
Err(_) => {
self.process_partial_response(XHRProgress::Errored(gen_id, Error::Network));
return Err(Error::Network);
diff --git a/tests/wpt/metadata/MANIFEST.json b/tests/wpt/metadata/MANIFEST.json
index ad6f50c06f5..93cdc730d5e 100644
--- a/tests/wpt/metadata/MANIFEST.json
+++ b/tests/wpt/metadata/MANIFEST.json
@@ -37505,6 +37505,18 @@
"path": "html/semantics/forms/the-input-element/minlength.html",
"url": "/html/semantics/forms/the-input-element/minlength.html"
}
+ ],
+ "html/semantics/scripting-1/the-script-element/script-crossorigin-network.html": [
+ {
+ "path": "html/semantics/scripting-1/the-script-element/script-crossorigin-network.html",
+ "url": "/html/semantics/scripting-1/the-script-element/script-crossorigin-network.html"
+ }
+ ],
+ "html/semantics/scripting-1/the-script-element/script-crossorigin.html": [
+ {
+ "path": "html/semantics/scripting-1/the-script-element/script-crossorigin.html",
+ "url": "/html/semantics/scripting-1/the-script-element/script-crossorigin.html"
+ }
]
}
},
diff --git a/tests/wpt/metadata/html/dom/interfaces.html.ini b/tests/wpt/metadata/html/dom/interfaces.html.ini
index 240d96a350b..6600612366f 100644
--- a/tests/wpt/metadata/html/dom/interfaces.html.ini
+++ b/tests/wpt/metadata/html/dom/interfaces.html.ini
@@ -4359,15 +4359,9 @@
[HTMLScriptElement interface: attribute async]
expected: FAIL
- [HTMLScriptElement interface: attribute crossOrigin]
- expected: FAIL
-
[HTMLScriptElement interface: document.createElement("script") must inherit property "async" with the proper type (3)]
expected: FAIL
- [HTMLScriptElement interface: document.createElement("script") must inherit property "crossOrigin" with the proper type (5)]
- expected: FAIL
-
[HTMLCanvasElement interface: operation probablySupportsContext(DOMString,any)]
expected: FAIL
diff --git a/tests/wpt/metadata/html/dom/reflection-misc.html.ini b/tests/wpt/metadata/html/dom/reflection-misc.html.ini
index 953d81ccd68..bfe086b35fd 100644
--- a/tests/wpt/metadata/html/dom/reflection-misc.html.ini
+++ b/tests/wpt/metadata/html/dom/reflection-misc.html.ini
@@ -1317,222 +1317,6 @@
[script.tabIndex: IDL set to -2147483648 followed by getAttribute()]
expected: FAIL
- [script.crossOrigin: typeof IDL attribute]
- expected: FAIL
-
- [script.crossOrigin: IDL get with DOM attribute unset]
- expected: FAIL
-
- [script.crossOrigin: setAttribute() to "" followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: setAttribute() to " \\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07 \\b\\t\\n\\v\\f\\r\\x0e\\x0f \\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17 \\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f foo " followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: setAttribute() to undefined followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: setAttribute() to 7 followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: setAttribute() to 1.5 followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: setAttribute() to true followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: setAttribute() to false followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: setAttribute() to object "[object Object\]" followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: setAttribute() to NaN followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: setAttribute() to Infinity followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: setAttribute() to -Infinity followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: setAttribute() to "\\0" followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: setAttribute() to null followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: setAttribute() to object "test-toString" followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: setAttribute() to object "test-valueOf" followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: setAttribute() to "anonymous" followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: setAttribute() to "xanonymous" followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: setAttribute() to "anonymous\\0" followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: setAttribute() to "nonymous" followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: setAttribute() to "ANONYMOUS" followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: setAttribute() to "use-credentials" followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: setAttribute() to "xuse-credentials" followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: setAttribute() to "use-credentials\\0" followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: setAttribute() to "se-credentials" followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: setAttribute() to "USE-CREDENTIALS" followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: IDL set to "" followed by getAttribute()]
- expected: FAIL
-
- [script.crossOrigin: IDL set to "" followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: IDL set to " \\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07 \\b\\t\\n\\v\\f\\r\\x0e\\x0f \\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17 \\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f foo " followed by getAttribute()]
- expected: FAIL
-
- [script.crossOrigin: IDL set to " \\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07 \\b\\t\\n\\v\\f\\r\\x0e\\x0f \\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17 \\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f foo " followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: IDL set to undefined followed by getAttribute()]
- expected: FAIL
-
- [script.crossOrigin: IDL set to undefined followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: IDL set to 7 followed by getAttribute()]
- expected: FAIL
-
- [script.crossOrigin: IDL set to 7 followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: IDL set to 1.5 followed by getAttribute()]
- expected: FAIL
-
- [script.crossOrigin: IDL set to 1.5 followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: IDL set to true followed by getAttribute()]
- expected: FAIL
-
- [script.crossOrigin: IDL set to true followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: IDL set to false followed by getAttribute()]
- expected: FAIL
-
- [script.crossOrigin: IDL set to false followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: IDL set to object "[object Object\]" followed by getAttribute()]
- expected: FAIL
-
- [script.crossOrigin: IDL set to object "[object Object\]" followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: IDL set to NaN followed by getAttribute()]
- expected: FAIL
-
- [script.crossOrigin: IDL set to NaN followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: IDL set to Infinity followed by getAttribute()]
- expected: FAIL
-
- [script.crossOrigin: IDL set to Infinity followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: IDL set to -Infinity followed by getAttribute()]
- expected: FAIL
-
- [script.crossOrigin: IDL set to -Infinity followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: IDL set to "\\0" followed by getAttribute()]
- expected: FAIL
-
- [script.crossOrigin: IDL set to "\\0" followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: IDL set to object "test-toString" followed by getAttribute()]
- expected: FAIL
-
- [script.crossOrigin: IDL set to object "test-toString" followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: IDL set to object "test-valueOf" followed by getAttribute()]
- expected: FAIL
-
- [script.crossOrigin: IDL set to object "test-valueOf" followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: IDL set to "anonymous" followed by getAttribute()]
- expected: FAIL
-
- [script.crossOrigin: IDL set to "xanonymous" followed by getAttribute()]
- expected: FAIL
-
- [script.crossOrigin: IDL set to "xanonymous" followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: IDL set to "anonymous\\0" followed by getAttribute()]
- expected: FAIL
-
- [script.crossOrigin: IDL set to "anonymous\\0" followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: IDL set to "nonymous" followed by getAttribute()]
- expected: FAIL
-
- [script.crossOrigin: IDL set to "nonymous" followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: IDL set to "ANONYMOUS" followed by getAttribute()]
- expected: FAIL
-
- [script.crossOrigin: IDL set to "ANONYMOUS" followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: IDL set to "use-credentials" followed by getAttribute()]
- expected: FAIL
-
- [script.crossOrigin: IDL set to "xuse-credentials" followed by getAttribute()]
- expected: FAIL
-
- [script.crossOrigin: IDL set to "xuse-credentials" followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: IDL set to "use-credentials\\0" followed by getAttribute()]
- expected: FAIL
-
- [script.crossOrigin: IDL set to "use-credentials\\0" followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: IDL set to "se-credentials" followed by getAttribute()]
- expected: FAIL
-
- [script.crossOrigin: IDL set to "se-credentials" followed by IDL get]
- expected: FAIL
-
- [script.crossOrigin: IDL set to "USE-CREDENTIALS" followed by IDL get]
- expected: FAIL
-
[script.itemScope: typeof IDL attribute]
expected: FAIL
@@ -12447,6 +12231,3 @@
[dialog.itemId: IDL set to object "test-valueOf" followed by IDL get]
expected: FAIL
- [script.crossOrigin: IDL set to null followed by getAttribute()]
- expected: FAIL
-
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/resources/cross-origin.py b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/resources/cross-origin.py
new file mode 100644
index 00000000000..f8e05d96627
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/resources/cross-origin.py
@@ -0,0 +1,10 @@
+def main(request, response):
+ headers = [("Content-Type", "text/javascript")]
+ milk = request.cookies.first("milk", None)
+
+ if milk is None:
+ return headers, "var included = false;"
+ elif milk.value == "yes":
+ return headers, "var included = true;"
+
+ return headers, "var included = false;"
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-crossorigin-network.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-crossorigin-network.html
new file mode 100644
index 00000000000..488dd4488a4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-crossorigin-network.html
@@ -0,0 +1,49 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>HTMLScriptElement: crossorigin attribute network test</title>
+<link rel="author" title="KiChjang" href="mailto:kungfukeith11@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#cors-settings-attribute">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<body>
+ <script type="text/javascript">
+ var test1 = async_test(document.title + "1");
+ var test2 = async_test(document.title + "2");
+ var test3 = async_test(document.title + "3");
+
+ var script1 = document.createElement("script");
+ script1.src = "resources/cross-origin.py";
+ script1.crossOrigin = "use-credentials";
+ var script2 = document.createElement("script");
+ script2.src = "resources/cross-origin.py";
+ script2.crossOrigin = "gibberish";
+ var script3 = document.createElement("script");
+ script3.src = "resources/cross-origin.py";
+
+ document.cookie = "milk=yes";
+ document.body.appendChild(script1);
+ script1.onload = function() {
+ test1.step(function() {
+ assert_true(included, "credentials should be included in script request");
+ test1.done();
+ });
+ };
+
+ document.body.appendChild(script2);
+ script2.onload = function() {
+ test2.step(function() {
+ assert_true(included, "invalid values should default to include credentials due to response tainting");
+ test2.done();
+ });
+ };
+
+ document.body.appendChild(script3);
+ script3.onload = function() {
+ test3.step(function() {
+ assert_true(included, "missing value should default to include credentials");
+ test3.done();
+ });
+ };
+ </script>
+</body>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-crossorigin.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-crossorigin.html
new file mode 100644
index 00000000000..52857a08ea0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-crossorigin.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>HTMLScriptElement: crossOrigin IDL attribute</title>
+<link rel="author" title="KiChjang" href="mailto:kungfukeith11@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#cors-settings-attribute">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script id="script1"></script>
+<script id="script2" crossorigin=""></script>
+<script id="script3" crossorigin="foo"></script>
+<script id="script4" crossorigin="anonymous"></script>
+<script id="script5" crossorigin="use-credentials"></script>
+<script>
+test(function() {
+ var script1 = document.getElementById("script1");
+ var script2 = document.getElementById("script2");
+ var script3 = document.getElementById("script3");
+ var script4 = document.getElementById("script4");
+ var script5 = document.getElementById("script5");
+
+ assert_equals(script1.crossOrigin, null, "Missing value default should be null");
+ assert_equals(script2.crossOrigin, "anonymous", "Empty string should map to anonymous");
+ assert_equals(script3.crossOrigin, "anonymous", "Invalid value default should be anonymous");
+ assert_equals(script4.crossOrigin, "anonymous", "anonymous should be parsed correctly");
+ assert_equals(script5.crossOrigin, "use-credentials", "use-credentials should be parsed correctly");
+
+ script1.crossOrigin = "bar";
+ assert_equals(script1.crossOrigin, "anonymous", "Setting to invalid value would default to anonymous");
+
+ script2.crossOrigin = null;
+ assert_equals(script2.crossOrigin, null, "Resetting to null should work");
+
+ script4.crossOrigin = "use-credentials";
+ assert_equals(script4.crossOrigin, "use-credentials", "Switching from anonymous to use-credentials should work");
+
+ script5.crossOrigin = "anonymous";
+ assert_equals(script5.crossOrigin, "anonymous", "Switching from use-credentials to anonymous should work");
+}, document.title);
+</script>