diff options
author | Manish Goregaokar <manishsmail@gmail.com> | 2016-06-01 17:18:11 +0530 |
---|---|---|
committer | Manish Goregaokar <manishsmail@gmail.com> | 2016-06-10 20:53:23 +0530 |
commit | 5e49873af7bfe7190afa98a8d6bee08582213fb1 (patch) | |
tree | 9a2b2e8da9dbf650baa62aa16a647cadc11c08f8 /components/script/dom | |
parent | d4f428ad9559f7d5f338e565e7f5d5efab70f67f (diff) | |
download | servo-5e49873af7bfe7190afa98a8d6bee08582213fb1.tar.gz servo-5e49873af7bfe7190afa98a8d6bee08582213fb1.zip |
Hook XHR up to fetch
Diffstat (limited to 'components/script/dom')
-rw-r--r-- | components/script/dom/xmlhttprequest.rs | 189 |
1 files changed, 42 insertions, 147 deletions
diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs index 3cb74ec282c..400549dc714 100644 --- a/components/script/dom/xmlhttprequest.rs +++ b/components/script/dom/xmlhttprequest.rs @@ -2,8 +2,6 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use cors::CORSResponse; -use cors::{AsyncCORSResponseListener, CORSRequest, RequestMode, allow_cross_origin_request}; use document_loader::DocumentLoader; use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::BlobBinding::BlobMethods; @@ -45,17 +43,17 @@ use js::jsapi::JS_ClearPendingException; use js::jsapi::{JSContext, JS_ParseJSON, RootedValue}; use js::jsval::{JSVal, NullValue, UndefinedValue}; use msg::constellation_msg::{PipelineId, ReferrerPolicy}; -use net_traits::CoreResourceMsg::Load; +use net_traits::CoreResourceMsg::Fetch; use net_traits::trim_http_whitespace; -use net_traits::{AsyncResponseListener, AsyncResponseTarget, Metadata, NetworkError, RequestSource}; -use net_traits::{LoadConsumer, LoadContext, LoadData, ResourceCORSData, CoreResourceThread, LoadOrigin}; +use net_traits::{FetchResponseListener, Metadata, NetworkError, RequestSource}; +use net_traits::{LoadContext, LoadData, CoreResourceThread, LoadOrigin}; use network_listener::{NetworkListener, PreInvoke}; use parse::html::{ParseContext, parse_html}; use parse::xml::{self, parse_xml}; use script_runtime::ScriptChan; use std::ascii::AsciiExt; use std::borrow::ToOwned; -use std::cell::{Cell, RefCell}; +use std::cell::Cell; use std::default::Default; use std::str; use std::sync::{Arc, Mutex}; @@ -63,7 +61,6 @@ use string_cache::Atom; use time; use timers::{OneshotTimerCallback, OneshotTimerHandle}; use url::{Url, Position}; -use util::prefs::mozbrowser_enabled; #[derive(JSTraceable, PartialEq, Copy, Clone, HeapSizeOf)] enum XMLHttpRequestState { @@ -82,7 +79,6 @@ pub struct GenerationId(u32); struct XHRContext { xhr: TrustedXHRAddress, gen_id: GenerationId, - cors_request: Option<CORSRequest>, buf: DOMRefCell<Vec<u8>>, sync_status: DOMRefCell<Option<ErrorResult>>, } @@ -216,75 +212,42 @@ impl XMLHttpRequest { } } - fn check_cors(context: Arc<Mutex<XHRContext>>, - load_data: LoadData, - req: CORSRequest, - script_chan: Box<ScriptChan + Send>, - core_resource_thread: CoreResourceThread) { - struct CORSContext { - xhr: Arc<Mutex<XHRContext>>, - load_data: RefCell<Option<LoadData>>, - req: CORSRequest, - script_chan: Box<ScriptChan + Send>, - core_resource_thread: CoreResourceThread, - } - - impl AsyncCORSResponseListener for CORSContext { - fn response_available(&self, response: CORSResponse) { - if response.network_error { - let mut context = self.xhr.lock().unwrap(); - let xhr = context.xhr.root(); - xhr.process_partial_response(XHRProgress::Errored(context.gen_id, Error::Network)); - *context.sync_status.borrow_mut() = Some(Err(Error::Network)); - return; - } - - let mut load_data = self.load_data.borrow_mut().take().unwrap(); - load_data.cors = Some(ResourceCORSData { - preflight: self.req.preflight_flag, - origin: self.req.origin.clone() - }); - - XMLHttpRequest::initiate_async_xhr(self.xhr.clone(), self.script_chan.clone(), - self.core_resource_thread.clone(), load_data); - } - } - - let cors_context = CORSContext { - xhr: context, - load_data: RefCell::new(Some(load_data)), - req: req.clone(), - script_chan: script_chan.clone(), - core_resource_thread: core_resource_thread, - }; - - req.http_fetch_async(box cors_context, script_chan); - } - fn initiate_async_xhr(context: Arc<Mutex<XHRContext>>, script_chan: Box<ScriptChan + Send>, core_resource_thread: CoreResourceThread, load_data: LoadData) { - impl AsyncResponseListener for XHRContext { - fn headers_available(&mut self, metadata: Result<Metadata, NetworkError>) { - let xhr = self.xhr.root(); - let rv = xhr.process_headers_available(self.cors_request.clone(), - self.gen_id, - metadata); - if rv.is_err() { - *self.sync_status.borrow_mut() = Some(rv); + 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_eof(&mut self, response: Result<Vec<u8>, NetworkError>) { + match response { + Ok(buf) => { + *self.buf.borrow_mut() = buf; + // todo move to a process_chunk + self.xhr.root().process_data_available(self.gen_id, self.buf.borrow().clone()); + let rv = self.xhr.root().process_response_complete(self.gen_id, Ok(())); + *self.sync_status.borrow_mut() = Some(rv); + } + Err(e) => { + let rv = self.xhr.root().process_response_complete(self.gen_id, Err(e)); + *self.sync_status.borrow_mut() = Some(rv); + } + } + + } - } - - fn data_available(&mut self, payload: Vec<u8>) { - self.buf.borrow_mut().extend_from_slice(&payload); - self.xhr.root().process_data_available(self.gen_id, self.buf.borrow().clone()); - } - - fn response_complete(&mut self, status: Result<(), NetworkError>) { - let rv = self.xhr.root().process_response_complete(self.gen_id, status); - *self.sync_status.borrow_mut() = Some(rv); - } } impl PreInvoke for XHRContext { @@ -298,13 +261,10 @@ impl XMLHttpRequest { context: context, script_chan: script_chan, }; - 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()); }); - core_resource_thread.send(Load(load_data, LoadConsumer::Listener(response_target), None)).unwrap(); + core_resource_thread.send(Fetch(load_data, action_sender)).unwrap(); } } @@ -637,34 +597,13 @@ impl XMLHttpRequestMethods for XMLHttpRequest { // CORS stuff let global = self.global(); - let referer_url = self.global().r().get_url(); - let mode = if self.upload_events.get() { - RequestMode::ForcedPreflight - } else { - RequestMode::CORS - }; let mut combined_headers = load_data.headers.clone(); combined_headers.extend(load_data.preserved_headers.iter()); - let cors_request = CORSRequest::maybe_new(referer_url.clone(), - load_data.url.clone(), - mode, - load_data.method.clone(), - combined_headers, - true); - match cors_request { - Ok(None) => { - let bytes = referer_url[..Position::AfterPath].as_bytes().to_vec(); - self.request_headers.borrow_mut().set_raw("Referer".to_owned(), vec![bytes]); - }, - Ok(Some(ref req)) => self.insert_trusted_header("origin".to_owned(), - req.origin.to_string()), - _ => {} - } debug!("request_headers = {:?}", *self.request_headers.borrow()); self.fetch_time.set(time::now().to_timespec().sec); - let rv = self.fetch(load_data, cors_request, global.r()); + let rv = self.fetch(load_data, global.r()); // Step 10 if self.sync.get() { return rv; @@ -879,7 +818,7 @@ impl XMLHttpRequest { event.fire(self.upcast()); } - fn process_headers_available(&self, cors_request: Option<CORSRequest>, + fn process_headers_available(&self, gen_id: GenerationId, metadata: Result<Metadata, NetworkError>) -> Result<(), Error> { let metadata = match metadata { @@ -890,34 +829,7 @@ impl XMLHttpRequest { }, }; - let bypass_cross_origin_check = { - // We want to be able to do cross-origin requests in browser.html. - // If the XHR happens in a top level window and the mozbrowser - // preference is enabled, we allow bypassing the CORS check. - // This is a temporary measure until we figure out Servo privilege - // story. See https://github.com/servo/servo/issues/9582 - if let GlobalRoot::Window(win) = self.global() { - let is_root_pipeline = win.parent_info().is_none(); - let is_mozbrowser_enabled = mozbrowser_enabled(); - is_root_pipeline && is_mozbrowser_enabled - } else { - false - } - }; - - if !bypass_cross_origin_check { - if let Some(ref req) = cors_request { - match metadata.headers { - Some(ref h) if allow_cross_origin_request(req, h) => {}, - _ => { - self.process_partial_response(XHRProgress::Errored(gen_id, Error::Network)); - return Err(Error::Network); - } - } - } - } else { - debug!("Bypassing cross origin check"); - } + // todo allow cors in mozbrowser *self.response_url.borrow_mut() = metadata.final_url[..Position::AfterQuery].to_owned(); @@ -1319,24 +1231,12 @@ impl XMLHttpRequest { fn fetch(&self, load_data: LoadData, - cors_request: Result<Option<CORSRequest>, ()>, global: GlobalRef) -> ErrorResult { - let cors_request = match cors_request { - Err(_) => { - // Happens in case of unsupported cross-origin URI schemes. - // Supported schemes are http, https, data, and about. - self.process_partial_response(XHRProgress::Errored( - self.generation_id.get(), Error::Network)); - return Err(Error::Network); - } - Ok(req) => req, - }; let xhr = Trusted::new(self); let context = Arc::new(Mutex::new(XHRContext { xhr: xhr, - cors_request: cors_request.clone(), gen_id: self.generation_id.get(), buf: DOMRefCell::new(vec!()), sync_status: DOMRefCell::new(None), @@ -1350,13 +1250,8 @@ impl XMLHttpRequest { }; let core_resource_thread = global.core_resource_thread(); - if let Some(req) = cors_request { - XMLHttpRequest::check_cors(context.clone(), load_data, req.clone(), - script_chan.clone(), core_resource_thread); - } else { - XMLHttpRequest::initiate_async_xhr(context.clone(), script_chan, - core_resource_thread, load_data); - } + XMLHttpRequest::initiate_async_xhr(context.clone(), script_chan, + core_resource_thread, load_data); if let Some(script_port) = script_port { loop { |