mirror of
https://github.com/servo/servo.git
synced 2025-07-23 15:23:42 +01:00
Implement the constructor for EventSource
This commit is contained in:
parent
75d35241db
commit
d99d26cf1f
4 changed files with 105 additions and 25 deletions
|
@ -70,7 +70,7 @@ pub enum CredentialsMode {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// [Cache mode](https://fetch.spec.whatwg.org/#concept-request-cache-mode)
|
/// [Cache mode](https://fetch.spec.whatwg.org/#concept-request-cache-mode)
|
||||||
#[derive(Copy, Clone, PartialEq, HeapSizeOf)]
|
#[derive(Copy, Clone, PartialEq, Serialize, Deserialize, HeapSizeOf)]
|
||||||
pub enum CacheMode {
|
pub enum CacheMode {
|
||||||
Default,
|
Default,
|
||||||
NoStore,
|
NoStore,
|
||||||
|
@ -111,14 +111,16 @@ pub enum CorsSettings {
|
||||||
UseCredentials
|
UseCredentials
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone)]
|
#[derive(Serialize, Deserialize, Clone, HeapSizeOf)]
|
||||||
pub struct RequestInit {
|
pub struct RequestInit {
|
||||||
#[serde(deserialize_with = "::hyper_serde::deserialize",
|
#[serde(deserialize_with = "::hyper_serde::deserialize",
|
||||||
serialize_with = "::hyper_serde::serialize")]
|
serialize_with = "::hyper_serde::serialize")]
|
||||||
|
#[ignore_heap_size_of = "Defined in hyper"]
|
||||||
pub method: Method,
|
pub method: Method,
|
||||||
pub url: Url,
|
pub url: Url,
|
||||||
#[serde(deserialize_with = "::hyper_serde::deserialize",
|
#[serde(deserialize_with = "::hyper_serde::deserialize",
|
||||||
serialize_with = "::hyper_serde::serialize")]
|
serialize_with = "::hyper_serde::serialize")]
|
||||||
|
#[ignore_heap_size_of = "Defined in hyper"]
|
||||||
pub headers: Headers,
|
pub headers: Headers,
|
||||||
pub unsafe_request: bool,
|
pub unsafe_request: bool,
|
||||||
pub body: Option<Vec<u8>>,
|
pub body: Option<Vec<u8>>,
|
||||||
|
@ -127,6 +129,7 @@ pub struct RequestInit {
|
||||||
pub destination: Destination,
|
pub destination: Destination,
|
||||||
pub synchronous: bool,
|
pub synchronous: bool,
|
||||||
pub mode: RequestMode,
|
pub mode: RequestMode,
|
||||||
|
pub cache_mode: CacheMode,
|
||||||
pub use_cors_preflight: bool,
|
pub use_cors_preflight: bool,
|
||||||
pub credentials_mode: CredentialsMode,
|
pub credentials_mode: CredentialsMode,
|
||||||
pub use_url_credentials: bool,
|
pub use_url_credentials: bool,
|
||||||
|
@ -152,6 +155,7 @@ impl Default for RequestInit {
|
||||||
destination: Destination::None,
|
destination: Destination::None,
|
||||||
synchronous: false,
|
synchronous: false,
|
||||||
mode: RequestMode::NoCors,
|
mode: RequestMode::NoCors,
|
||||||
|
cache_mode: CacheMode::Default,
|
||||||
use_cors_preflight: false,
|
use_cors_preflight: false,
|
||||||
credentials_mode: CredentialsMode::Omit,
|
credentials_mode: CredentialsMode::Omit,
|
||||||
use_url_credentials: false,
|
use_url_credentials: false,
|
||||||
|
@ -261,6 +265,7 @@ impl Request {
|
||||||
req.use_cors_preflight = init.use_cors_preflight;
|
req.use_cors_preflight = init.use_cors_preflight;
|
||||||
req.credentials_mode = init.credentials_mode;
|
req.credentials_mode = init.credentials_mode;
|
||||||
req.use_url_credentials = init.use_url_credentials;
|
req.use_url_credentials = init.use_url_credentials;
|
||||||
|
req.cache_mode.set(init.cache_mode);
|
||||||
*req.referrer.borrow_mut() = if let Some(url) = init.referrer_url {
|
*req.referrer.borrow_mut() = if let Some(url) = init.referrer_url {
|
||||||
Referrer::ReferrerUrl(url)
|
Referrer::ReferrerUrl(url)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -63,7 +63,7 @@ use net_traits::{Metadata, NetworkError, ReferrerPolicy, ResourceThreads};
|
||||||
use net_traits::filemanager_thread::RelativePos;
|
use net_traits::filemanager_thread::RelativePos;
|
||||||
use net_traits::image::base::{Image, ImageMetadata};
|
use net_traits::image::base::{Image, ImageMetadata};
|
||||||
use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheThread};
|
use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheThread};
|
||||||
use net_traits::request::Request;
|
use net_traits::request::{Request, RequestInit};
|
||||||
use net_traits::response::{Response, ResponseBody};
|
use net_traits::response::{Response, ResponseBody};
|
||||||
use net_traits::response::HttpsState;
|
use net_traits::response::HttpsState;
|
||||||
use net_traits::storage_thread::StorageType;
|
use net_traits::storage_thread::StorageType;
|
||||||
|
@ -349,6 +349,7 @@ no_jsmanaged_fields!(AttrValue);
|
||||||
no_jsmanaged_fields!(Snapshot);
|
no_jsmanaged_fields!(Snapshot);
|
||||||
no_jsmanaged_fields!(HttpsState);
|
no_jsmanaged_fields!(HttpsState);
|
||||||
no_jsmanaged_fields!(Request);
|
no_jsmanaged_fields!(Request);
|
||||||
|
no_jsmanaged_fields!(RequestInit);
|
||||||
no_jsmanaged_fields!(SharedRt);
|
no_jsmanaged_fields!(SharedRt);
|
||||||
no_jsmanaged_fields!(TouchpadPressurePhase);
|
no_jsmanaged_fields!(TouchpadPressurePhase);
|
||||||
no_jsmanaged_fields!(USVString);
|
no_jsmanaged_fields!(USVString);
|
||||||
|
|
|
@ -11,11 +11,20 @@ use dom::bindings::reflector::reflect_dom_object;
|
||||||
use dom::bindings::str::DOMString;
|
use dom::bindings::str::DOMString;
|
||||||
use dom::eventtarget::EventTarget;
|
use dom::eventtarget::EventTarget;
|
||||||
use dom::globalscope::GlobalScope;
|
use dom::globalscope::GlobalScope;
|
||||||
|
use hyper::header::{Accept, qitem};
|
||||||
|
use ipc_channel::ipc;
|
||||||
|
use ipc_channel::router::ROUTER;
|
||||||
|
use net_traits::{CoreResourceMsg, FetchMetadata, FetchResponseListener, NetworkError};
|
||||||
|
use net_traits::request::{CacheMode, CorsSettings, CredentialsMode};
|
||||||
|
use net_traits::request::{RequestInit, RequestMode};
|
||||||
|
use network_listener::{NetworkListener, PreInvoke};
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
#[derive(JSTraceable, PartialEq, Copy, Clone, Debug, HeapSizeOf)]
|
#[derive(JSTraceable, PartialEq, Copy, Clone, Debug, HeapSizeOf)]
|
||||||
enum EventSourceReadyState {
|
/// https://html.spec.whatwg.org/multipage/#dom-eventsource-readystate
|
||||||
|
enum ReadyState {
|
||||||
Connecting = 0,
|
Connecting = 0,
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
Open = 1,
|
Open = 1,
|
||||||
|
@ -25,50 +34,114 @@ enum EventSourceReadyState {
|
||||||
#[dom_struct]
|
#[dom_struct]
|
||||||
pub struct EventSource {
|
pub struct EventSource {
|
||||||
eventtarget: EventTarget,
|
eventtarget: EventTarget,
|
||||||
url: Url,
|
url: DOMRefCell<Option<Url>>,
|
||||||
|
request: DOMRefCell<Option<RequestInit>>,
|
||||||
ready_state: Cell<EventSourceReadyState>,
|
ready_state: Cell<EventSourceReadyState>,
|
||||||
with_credentials: bool,
|
with_credentials: bool,
|
||||||
last_event_id: DOMRefCell<DOMString>
|
last_event_id: DOMRefCell<DOMString>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct EventSourceContext;
|
||||||
|
|
||||||
|
impl FetchResponseListener for EventSourceContext {
|
||||||
|
fn process_request_body(&mut self) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_request_eof(&mut self) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_response(&mut self, _metadata: Result<FetchMetadata, NetworkError>) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_response_chunk(&mut self, mut _chunk: Vec<u8>) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_response_eof(&mut self, _response: Result<(), NetworkError>) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PreInvoke for EventSourceContext {}
|
||||||
|
|
||||||
impl EventSource {
|
impl EventSource {
|
||||||
fn new_inherited(url: Url, with_credentials: bool) -> EventSource {
|
fn new_inherited(with_credentials: bool) -> EventSource {
|
||||||
EventSource {
|
EventSource {
|
||||||
eventtarget: EventTarget::new_inherited(),
|
eventtarget: EventTarget::new_inherited(),
|
||||||
url: url,
|
url: DOMRefCell::new(None),
|
||||||
ready_state: Cell::new(EventSourceReadyState::Connecting),
|
request: DOMRefCell::new(None),
|
||||||
|
ready_state: Cell::new(ReadyState::Connecting),
|
||||||
with_credentials: with_credentials,
|
with_credentials: with_credentials,
|
||||||
last_event_id: DOMRefCell::new(DOMString::from(""))
|
last_event_id: DOMRefCell::new(DOMString::from(""))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new(global: &GlobalScope, url: Url, with_credentials: bool) -> Root<EventSource> {
|
fn new(global: &GlobalScope, with_credentials: bool) -> Root<EventSource> {
|
||||||
reflect_dom_object(box EventSource::new_inherited(url, with_credentials),
|
reflect_dom_object(box EventSource::new_inherited(with_credentials),
|
||||||
global,
|
global,
|
||||||
Wrap)
|
Wrap)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn Constructor(global: &GlobalScope,
|
pub fn Constructor(global: &GlobalScope,
|
||||||
url_str: DOMString,
|
url: DOMString,
|
||||||
event_source_init: &EventSourceInit) -> Fallible<Root<EventSource>> {
|
event_source_init: &EventSourceInit) -> Fallible<Root<EventSource>> {
|
||||||
// Steps 1-2
|
// Step 1
|
||||||
let base_url = global.get_url();
|
let ev = EventSource::new(global, event_source_init.withCredentials);
|
||||||
let url = match base_url.join(&*url_str) {
|
// TODO: Step 2 relevant settings object
|
||||||
|
// Step 3
|
||||||
|
let base_url = global.api_base_url();
|
||||||
|
let url_record = match base_url.join(&*url) {
|
||||||
Ok(u) => u,
|
Ok(u) => u,
|
||||||
|
// Step 4
|
||||||
Err(_) => return Err(Error::Syntax)
|
Err(_) => return Err(Error::Syntax)
|
||||||
};
|
};
|
||||||
// Step 3
|
|
||||||
let event_source = EventSource::new(global, url, event_source_init.withCredentials);
|
|
||||||
// Step 4
|
|
||||||
// Step 5
|
// Step 5
|
||||||
// Step 6
|
*ev.url.borrow_mut() = Some(url_record.clone());
|
||||||
// Step 7
|
// Steps 6-7
|
||||||
|
let cors_attribute_state = if event_source_init.withCredentials {
|
||||||
|
CorsSettings::UseCredentials
|
||||||
|
} else {
|
||||||
|
CorsSettings::Anonymous
|
||||||
|
};
|
||||||
// Step 8
|
// Step 8
|
||||||
// Step 9
|
// TODO: Step 9 set request's client settings
|
||||||
|
let mut request = RequestInit {
|
||||||
|
url: url_record,
|
||||||
|
origin: global.get_url(),
|
||||||
|
pipeline_id: Some(global.pipeline_id()),
|
||||||
|
// https://html.spec.whatwg.org/multipage/#create-a-potential-cors-request
|
||||||
|
use_url_credentials: true,
|
||||||
|
mode: RequestMode::CorsMode,
|
||||||
|
credentials_mode: if cors_attribute_state == CorsSettings::Anonymous {
|
||||||
|
CredentialsMode::CredentialsSameOrigin
|
||||||
|
} else {
|
||||||
|
CredentialsMode::Include
|
||||||
|
},
|
||||||
|
..RequestInit::default()
|
||||||
|
};
|
||||||
// Step 10
|
// Step 10
|
||||||
|
request.headers.set(Accept(vec![qitem(mime!(Text / EventStream))]));
|
||||||
// Step 11
|
// Step 11
|
||||||
Ok(event_source)
|
request.cache_mode = CacheMode::NoStore;
|
||||||
// Step 12
|
// Step 12
|
||||||
|
*ev.request.borrow_mut() = Some(request.clone());
|
||||||
|
// Step 14
|
||||||
|
let context = EventSourceContext;
|
||||||
|
let listener = NetworkListener {
|
||||||
|
context: Arc::new(Mutex::new(context)),
|
||||||
|
script_chan: global.script_chan(),
|
||||||
|
wrapper: None
|
||||||
|
};
|
||||||
|
let (action_sender, action_receiver) = ipc::channel().unwrap();
|
||||||
|
ROUTER.add_route(action_receiver.to_opaque(), box move |message| {
|
||||||
|
listener.notify_fetch(message.to().unwrap());
|
||||||
|
});
|
||||||
|
global.core_resource_thread().send(CoreResourceMsg::Fetch(request, action_sender)).unwrap();
|
||||||
|
// Step 13
|
||||||
|
Ok(ev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +157,7 @@ impl EventSourceMethods for EventSource {
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-eventsource-url
|
// https://html.spec.whatwg.org/multipage/#dom-eventsource-url
|
||||||
fn Url(&self) -> DOMString {
|
fn Url(&self) -> DOMString {
|
||||||
DOMString::from(self.url.as_str())
|
DOMString::from(self.url.borrow().clone().map_or("".to_owned(), Url::into_string))
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-eventsource-withcredentials
|
// https://html.spec.whatwg.org/multipage/#dom-eventsource-withcredentials
|
||||||
|
@ -99,7 +172,7 @@ impl EventSourceMethods for EventSource {
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-eventsource-close
|
// https://html.spec.whatwg.org/multipage/#dom-eventsource-close
|
||||||
fn Close(&self) {
|
fn Close(&self) {
|
||||||
self.ready_state.set(EventSourceReadyState::Closed);
|
self.ready_state.set(ReadyState::Closed);
|
||||||
// TODO: Terminate ongoing fetch
|
// TODO: Terminate ongoing fetch
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use dom::bindings::codegen::Bindings::RequestBinding::RequestInfo;
|
||||||
use dom::bindings::codegen::Bindings::RequestBinding::RequestInit;
|
use dom::bindings::codegen::Bindings::RequestBinding::RequestInit;
|
||||||
use dom::bindings::codegen::Bindings::ResponseBinding::ResponseBinding::ResponseMethods;
|
use dom::bindings::codegen::Bindings::ResponseBinding::ResponseBinding::ResponseMethods;
|
||||||
use dom::bindings::codegen::Bindings::ResponseBinding::ResponseType as DOMResponseType;
|
use dom::bindings::codegen::Bindings::ResponseBinding::ResponseType as DOMResponseType;
|
||||||
use dom::bindings::codegen::UnionTypes::RequestOrUSVString;
|
|
||||||
use dom::bindings::error::Error;
|
use dom::bindings::error::Error;
|
||||||
use dom::bindings::js::Root;
|
use dom::bindings::js::Root;
|
||||||
use dom::bindings::refcounted::{Trusted, TrustedPromise};
|
use dom::bindings::refcounted::{Trusted, TrustedPromise};
|
||||||
|
@ -62,12 +62,13 @@ fn request_init_from_request(request: NetTraitsRequest) -> NetTraitsRequestInit
|
||||||
referrer_policy: request.referrer_policy.get(),
|
referrer_policy: request.referrer_policy.get(),
|
||||||
pipeline_id: request.pipeline_id.get(),
|
pipeline_id: request.pipeline_id.get(),
|
||||||
redirect_mode: request.redirect_mode.get(),
|
redirect_mode: request.redirect_mode.get(),
|
||||||
|
..NetTraitsRequestInit::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://fetch.spec.whatwg.org/#fetch-method
|
// https://fetch.spec.whatwg.org/#fetch-method
|
||||||
#[allow(unrooted_must_root)]
|
#[allow(unrooted_must_root)]
|
||||||
pub fn Fetch(global: &GlobalScope, input: RequestOrUSVString, init: &RequestInit) -> Rc<Promise> {
|
pub fn Fetch(global: &GlobalScope, input: RequestInfo, init: &RequestInit) -> Rc<Promise> {
|
||||||
let core_resource_thread = global.core_resource_thread();
|
let core_resource_thread = global.core_resource_thread();
|
||||||
|
|
||||||
// Step 1
|
// Step 1
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue