diff options
author | bors-servo <metajack+bors@gmail.com> | 2015-02-04 11:57:54 -0700 |
---|---|---|
committer | bors-servo <metajack+bors@gmail.com> | 2015-02-04 11:57:54 -0700 |
commit | 7e3f504d94ffb77ec6148166d2ab73978e1c71c8 (patch) | |
tree | c3d04d3b52e8f83197819565c867b52df167b2a5 /components/script/dom | |
parent | 58a3cdcbef30e04199d33dc83cea0ace3e2cfcf1 (diff) | |
parent | 0557f8592cb965658be471d8807a2404483c0806 (diff) | |
download | servo-7e3f504d94ffb77ec6148166d2ab73978e1c71c8.tar.gz servo-7e3f504d94ffb77ec6148166d2ab73978e1c71c8.zip |
auto merge of #4519 : jdm/servo/cookies, r=Ms2ger
As specified in http://tools.ietf.org/html/rfc6265. Requires https://github.com/servo/cookie-rs/pull/1. Tested against http://www.joshmatthews.net/cookie.php, http://www.html-kit.com/tools/cookietester/, https://github.com/login, and https://mobile.twitter.com/session/new .
Diffstat (limited to 'components/script/dom')
-rw-r--r-- | components/script/dom/document.rs | 43 | ||||
-rw-r--r-- | components/script/dom/element.rs | 4 | ||||
-rw-r--r-- | components/script/dom/htmlformelement.rs | 13 | ||||
-rw-r--r-- | components/script/dom/node.rs | 2 | ||||
-rw-r--r-- | components/script/dom/webidls/Document.webidl | 2 | ||||
-rw-r--r-- | components/script/dom/xmlhttprequest.rs | 62 |
6 files changed, 83 insertions, 43 deletions
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index b6a5659a88a..3734527bc09 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -19,7 +19,7 @@ use dom::bindings::codegen::InheritTypes::{HTMLAreaElementDerived, HTMLEmbedElem use dom::bindings::codegen::InheritTypes::{HTMLFormElementDerived, HTMLImageElementDerived}; use dom::bindings::codegen::InheritTypes::{HTMLScriptElementDerived}; use dom::bindings::error::{ErrorResult, Fallible}; -use dom::bindings::error::Error::{NotSupported, InvalidCharacter}; +use dom::bindings::error::Error::{NotSupported, InvalidCharacter, Security}; use dom::bindings::error::Error::{HierarchyRequest, NamespaceError}; use dom::bindings::global::GlobalRef; use dom::bindings::js::{MutNullableJS, JS, JSRef, LayoutJS, Temporary, TemporaryPushable}; @@ -54,6 +54,8 @@ use dom::range::Range; use dom::treewalker::TreeWalker; use dom::uievent::UIEvent; use dom::window::{Window, WindowHelpers}; +use net::resource_task::ControlMsg::{SetCookiesForUrl, GetCookiesForUrl}; +use net::cookie_storage::CookieSource::NonHTTP; use util::namespace; use util::str::{DOMString, split_html_space_chars}; @@ -68,6 +70,7 @@ use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::ascii::AsciiExt; use std::cell::{Cell, Ref}; use std::default::Default; +use std::sync::mpsc::channel; use time; #[derive(PartialEq)] @@ -170,7 +173,7 @@ pub trait DocumentHelpers<'a> { fn window(self) -> Temporary<Window>; fn encoding_name(self) -> Ref<'a, DOMString>; fn is_html_document(self) -> bool; - fn url(self) -> &'a Url; + fn url(self) -> Url; fn quirks_mode(self) -> QuirksMode; fn set_quirks_mode(self, mode: QuirksMode); fn set_last_modified(self, value: DOMString); @@ -206,8 +209,9 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> { self.is_html_document } - fn url(self) -> &'a Url { - &self.extended_deref().url + // http://dom.spec.whatwg.org/#dom-document-url + fn url(self) -> Url { + self.url.clone() } fn quirks_mode(self) -> QuirksMode { @@ -1003,7 +1007,38 @@ impl<'a> DocumentMethods for JSRef<'a, Document> { Temporary::new(self.window) } + // https://html.spec.whatwg.org/multipage/dom.html#dom-document-cookie + fn GetCookie(self) -> Fallible<DOMString> { + //TODO: return empty string for cookie-averse Document + let url = self.url(); + if !is_scheme_host_port_tuple(&url) { + return Err(Security); + } + let window = self.window.root(); + let page = window.page(); + let (tx, rx) = channel(); + let _ = page.resource_task.send(GetCookiesForUrl(url, tx, NonHTTP)); + let cookies = rx.recv().unwrap(); + Ok(cookies.unwrap_or("".to_owned())) + } + + // https://html.spec.whatwg.org/multipage/dom.html#dom-document-cookie + fn SetCookie(self, cookie: DOMString) -> ErrorResult { + //TODO: ignore for cookie-averse Document + let url = self.url(); + if !is_scheme_host_port_tuple(&url) { + return Err(Security); + } + let window = self.window.root(); + let page = window.page(); + let _ = page.resource_task.send(SetCookiesForUrl(url, cookie, NonHTTP)); + Ok(()) + } + global_event_handlers!(); event_handler!(readystatechange, GetOnreadystatechange, SetOnreadystatechange); } +fn is_scheme_host_port_tuple(url: &Url) -> bool { + url.host().is_some() && url.port_or_default().is_some() +} diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index b1b458bad40..69eb3f2ee23 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -777,7 +777,7 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> { let base = doc.r().url(); // https://html.spec.whatwg.org/multipage/infrastructure.html#reflect // XXXManishearth this doesn't handle `javascript:` urls properly - match UrlParser::new().base_url(base).parse(url.as_slice()) { + match UrlParser::new().base_url(&base).parse(url.as_slice()) { Ok(parsed) => parsed.serialize(), Err(_) => "".to_owned() } @@ -1174,7 +1174,7 @@ impl<'a> VirtualMethods for JSRef<'a, Element> { // Modifying the `style` attribute might change style. let node: JSRef<Node> = NodeCast::from_ref(*self); let doc = document_from_node(*self).root(); - let base_url = doc.r().url().clone(); + let base_url = doc.r().url(); let value = attr.value(); let style = Some(parse_style_attribute(value.as_slice(), &base_url)); *self.style_attribute.borrow_mut() = style; diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs index 5f0ec3f212a..74f789ab491 100644 --- a/components/script/dom/htmlformelement.rs +++ b/components/script/dom/htmlformelement.rs @@ -23,6 +23,8 @@ use dom::htmlbuttonelement::{HTMLButtonElement}; use dom::htmltextareaelement::{HTMLTextAreaElement, HTMLTextAreaElementHelpers}; use dom::node::{Node, NodeHelpers, NodeTypeId, document_from_node, window_from_node}; use hyper::method::Method; +use hyper::header::common::ContentType; +use hyper::mime; use servo_msg::constellation_msg::LoadData; use util::str::DOMString; use script_task::{ScriptChan, ScriptMsg}; @@ -178,7 +180,7 @@ impl<'a> HTMLFormElementHelpers for JSRef<'a, HTMLFormElement> { } // TODO: Resolve the url relative to the submitter element // Step 10-15 - let action_components = UrlParser::new().base_url(base).parse(action.as_slice()).unwrap_or(base.clone()); + let action_components = UrlParser::new().base_url(&base).parse(action.as_slice()).unwrap_or(base); let _action = action_components.serialize(); let scheme = action_components.scheme.clone(); let enctype = submitter.enctype(); @@ -186,12 +188,17 @@ impl<'a> HTMLFormElementHelpers for JSRef<'a, HTMLFormElement> { let _target = submitter.target(); // TODO: Handle browsing contexts, partially loaded documents (step 16-17) + let mut load_data = LoadData::new(action_components); + let parsed_data = match enctype { - FormEncType::UrlEncoded => serialize(form_data.iter().map(|d| (d.name.as_slice(), d.value.as_slice()))), + FormEncType::UrlEncoded => { + let mime: mime::Mime = "application/x-www-form-urlencoded".parse().unwrap(); + load_data.headers.set(ContentType(mime)); + serialize(form_data.iter().map(|d| (d.name.as_slice(), d.value.as_slice()))) + } _ => "".to_owned() // TODO: Add serializers for the other encoding types }; - let mut load_data = LoadData::new(action_components); // Step 18 match (scheme.as_slice(), method) { (_, FormMethod::FormDialog) => return, // Unimplemented diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index 745c5a3a135..cdd52e78855 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -1574,7 +1574,7 @@ impl Node { false => IsHTMLDocument::NonHTMLDocument, }; let window = document.window().root(); - let document = Document::new(window.r(), Some(document.url().clone()), + let document = Document::new(window.r(), Some(document.url()), is_html_doc, None, DocumentSource::NotFromParser); NodeCast::from_temporary(document) diff --git a/components/script/dom/webidls/Document.webidl b/components/script/dom/webidls/Document.webidl index 92b7f35c34b..26d2fa03163 100644 --- a/components/script/dom/webidls/Document.webidl +++ b/components/script/dom/webidls/Document.webidl @@ -65,6 +65,8 @@ partial interface Document { readonly attribute DocumentReadyState readyState; readonly attribute DOMString lastModified; readonly attribute Location location; + [Throws] + attribute DOMString cookie; // DOM tree accessors [SetterThrows] diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs index a32045cff75..f9f75fbbf7e 100644 --- a/components/script/dom/xmlhttprequest.rs +++ b/components/script/dom/xmlhttprequest.rs @@ -561,41 +561,35 @@ impl<'a> XMLHttpRequestMethods for JSRef<'a, XMLHttpRequest> { let mut load_data = LoadData::new(self.request_url.borrow().clone().unwrap(), start_chan); load_data.data = extracted; - // Default headers - { - #[inline] - fn join_raw(a: &str, b: &str) -> Vec<u8> { - let len = a.len() + b.len(); - let mut vec = Vec::with_capacity(len); - vec.push_all(a.as_bytes()); - vec.push_all(b.as_bytes()); - vec - } - let ref mut request_headers = self.request_headers.borrow_mut(); - if !request_headers.has::<ContentType>() { - // XHR spec differs from http, and says UTF-8 should be in capitals, - // instead of "utf-8", which is what Hyper defaults to. - let params = ";charset=UTF-8"; - let n = "content-type"; - match data { - Some(eString(_)) => - request_headers.set_raw(n.to_owned(), vec![join_raw("text/plain", params)]), - Some(eURLSearchParams(_)) => - request_headers.set_raw( - n.to_owned(), vec![join_raw("application/x-www-form-urlencoded", params)]), - None => () - } - } + #[inline] + fn join_raw(a: &str, b: &str) -> Vec<u8> { + let len = a.len() + b.len(); + let mut vec = Vec::with_capacity(len); + vec.push_all(a.as_bytes()); + vec.push_all(b.as_bytes()); + vec + } + // XHR spec differs from http, and says UTF-8 should be in capitals, + // instead of "utf-8", which is what Hyper defaults to. + let params = ";charset=UTF-8"; + let n = "content-type"; + match data { + Some(eString(_)) => + load_data.headers.set_raw(n.to_owned(), vec![join_raw("text/plain", params)]), + Some(eURLSearchParams(_)) => + load_data.headers.set_raw( + n.to_owned(), vec![join_raw("application/x-www-form-urlencoded", params)]), + None => () + } - if !request_headers.has::<Accept>() { - let mime = Mime(mime::TopLevel::Star, mime::SubLevel::Star, vec![]); - request_headers.set( - Accept(vec![QualityItem::new(mime, 1.0)])); - } - } // drops the borrow_mut + load_data.preserved_headers = (*self.request_headers.borrow()).clone(); + + if !load_data.preserved_headers.has::<Accept>() { + let mime = Mime(mime::TopLevel::Star, mime::SubLevel::Star, vec![]); + load_data.preserved_headers.set(Accept(vec![QualityItem::new(mime, 1.0)])); + } - load_data.headers = (*self.request_headers.borrow()).clone(); load_data.method = (*self.request_method.borrow()).clone(); let (terminate_sender, terminate_receiver) = channel(); *self.terminate_sender.borrow_mut() = Some(terminate_sender); @@ -607,8 +601,10 @@ impl<'a> XMLHttpRequestMethods for JSRef<'a, XMLHttpRequest> { } 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(), load_data.headers.clone()); + load_data.method.clone(), combined_headers); match cors_request { Ok(None) => { let mut buf = String::new(); |