aboutsummaryrefslogtreecommitdiffstats
path: root/components/script
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2016-09-21 18:49:33 -0500
committerGitHub <noreply@github.com>2016-09-21 18:49:33 -0500
commitf357afc94ac437c4323bcc4d46c2767ccef73b73 (patch)
tree2a5b7952f3b1c3ac3a5cd7facba026440815a8ba /components/script
parentecb44e748b090655bea9d519448c02d290b9e957 (diff)
parent6fbd2aa5b7628bd47971806ddf438cd350a60bee (diff)
downloadservo-f357afc94ac437c4323bcc4d46c2767ccef73b73.tar.gz
servo-f357afc94ac437c4323bcc4d46c2767ccef73b73.zip
Auto merge of #12472 - KiChjang:use-fetch-in-script, r=jdm
Use fetch infrastructure to load external scripts Fixes #9186. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/12472) <!-- Reviewable:end -->
Diffstat (limited to 'components/script')
-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
5 files changed, 159 insertions, 54 deletions
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);