diff options
-rw-r--r-- | src/components/script/dom/bindings/codegen/CodegenRust.py | 2 | ||||
-rw-r--r-- | src/components/script/dom/bindings/error.rs | 1 | ||||
-rw-r--r-- | src/components/script/dom/bindings/str.rs | 12 | ||||
-rw-r--r-- | src/components/script/dom/domexception.rs | 3 | ||||
-rw-r--r-- | src/components/script/dom/webidls/XMLHttpRequest.webidl | 2 | ||||
-rw-r--r-- | src/components/script/dom/xmlhttprequest.rs | 66 |
6 files changed, 58 insertions, 28 deletions
diff --git a/src/components/script/dom/bindings/codegen/CodegenRust.py b/src/components/script/dom/bindings/codegen/CodegenRust.py index 7ddf982166b..b31c1d128a4 100644 --- a/src/components/script/dom/bindings/codegen/CodegenRust.py +++ b/src/components/script/dom/bindings/codegen/CodegenRust.py @@ -2627,7 +2627,7 @@ use js::jsapi::JSContext; use js::jsval::JSVal; #[repr(uint)] -#[deriving(Encodable)] +#[deriving(Encodable, Eq)] pub enum valuelist { %s } diff --git a/src/components/script/dom/bindings/error.rs b/src/components/script/dom/bindings/error.rs index db3337b6de2..974ad91d8a6 100644 --- a/src/components/script/dom/bindings/error.rs +++ b/src/components/script/dom/bindings/error.rs @@ -26,6 +26,7 @@ pub enum Error { InvalidState, Syntax, NamespaceError, + InvalidAccess, Security, Network } diff --git a/src/components/script/dom/bindings/str.rs b/src/components/script/dom/bindings/str.rs index e7d84d21c07..ae6c721abea 100644 --- a/src/components/script/dom/bindings/str.rs +++ b/src/components/script/dom/bindings/str.rs @@ -2,7 +2,9 @@ * 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 std::from_str::FromStr; use std::hash::{Hash, sip}; +use std::path::BytesContainer; use std::str; #[deriving(Encodable,Clone,TotalEq,Eq)] @@ -45,6 +47,9 @@ impl ByteString { pub fn is_token(&self) -> bool { let ByteString(ref vec) = *self; + if vec.len() == 0 { + return false; // A token must be at least a single character + } vec.iter().all(|&x| { // http://tools.ietf.org/html/rfc2616#section-2.2 match x { @@ -53,6 +58,7 @@ impl ByteString { 44 | 59 | 58 | 92 | 34 | 47 | 91 | 93 | 63 | 61 | 123 | 125 | 32 => false, // separators + x if x > 127 => false, // non-CHARs _ => true } }) @@ -113,4 +119,10 @@ impl Hash for ByteString { let ByteString(ref vec) = *self; vec.hash(state); } +} + +impl FromStr for ByteString { + fn from_str(s: &str) -> Option<ByteString> { + Some(ByteString::new(s.container_into_owned_bytes())) + } }
\ No newline at end of file diff --git a/src/components/script/dom/domexception.rs b/src/components/script/dom/domexception.rs index bd59020dbbd..262ae5c3fa8 100644 --- a/src/components/script/dom/domexception.rs +++ b/src/components/script/dom/domexception.rs @@ -46,8 +46,9 @@ impl DOMErrorName { error::InvalidCharacter => InvalidCharacterError, error::NotSupported => NotSupportedError, error::InvalidState => InvalidStateError, - error::NamespaceError => NamespaceError, error::Syntax => SyntaxError, + error::NamespaceError => NamespaceError, + error::InvalidAccess => InvalidAccessError, error::Security => SecurityError, error::Network => NetworkError, error::FailureUnknown => fail!(), diff --git a/src/components/script/dom/webidls/XMLHttpRequest.webidl b/src/components/script/dom/webidls/XMLHttpRequest.webidl index ab06165a098..e0aa3710c57 100644 --- a/src/components/script/dom/webidls/XMLHttpRequest.webidl +++ b/src/components/script/dom/webidls/XMLHttpRequest.webidl @@ -56,7 +56,7 @@ interface XMLHttpRequest : XMLHttpRequestEventTarget { readonly attribute DOMString responseURL; readonly attribute unsigned short status; readonly attribute ByteString statusText; - // ByteString? getResponseHeader(ByteString name); + ByteString? getResponseHeader(ByteString name); ByteString getAllResponseHeaders(); // void overrideMimeType(DOMString mime); [SetterThrows] diff --git a/src/components/script/dom/xmlhttprequest.rs b/src/components/script/dom/xmlhttprequest.rs index 50ad87aa1c3..cc99bb4ea88 100644 --- a/src/components/script/dom/xmlhttprequest.rs +++ b/src/components/script/dom/xmlhttprequest.rs @@ -8,7 +8,7 @@ use dom::bindings::codegen::Bindings::XMLHttpRequestBinding::XMLHttpRequestRespo use dom::bindings::codegen::Bindings::XMLHttpRequestBinding::XMLHttpRequestResponseTypeValues::{_empty, Json, Text}; use dom::bindings::codegen::InheritTypes::{EventCast, EventTargetCast, XMLHttpRequestDerived}; use dom::bindings::conversions::ToJSValConvertible; -use dom::bindings::error::{ErrorResult, Fallible, InvalidState, Network, Syntax, Security}; +use dom::bindings::error::{ErrorResult, Fallible, InvalidState, InvalidAccess, Network, Syntax, Security}; use dom::bindings::js::{JS, JSRef, Temporary, OptionalSettable, OptionalRootedRootable}; use dom::bindings::str::ByteString; use dom::bindings::trace::Untraceable; @@ -30,7 +30,7 @@ use RequestHeaderCollection = http::headers::request::HeaderCollection; use http::headers::content_type::MediaType; use http::headers::{HeaderEnum, HeaderValueByteIterator}; use http::headers::request::Header; -use http::method::{Method, Get, Head, Post, Connect, Trace}; +use http::method::{Method, Get, Head, Connect, Trace, ExtensionMethod}; use http::status::Status; use js::jsapi::{JS_AddObjectRoot, JS_ParseJSON, JS_RemoveObjectRoot, JSContext}; @@ -95,7 +95,7 @@ enum SyncOrAsync<'a, 'b> { impl<'a,'b> SyncOrAsync<'a,'b> { fn is_async(&self) -> bool { match *self { - Sync(_) => true, + Async(_,_) => true, _ => false } } @@ -241,7 +241,7 @@ pub trait XMLHttpRequestMethods<'a> { fn ResponseURL(&self) -> DOMString; fn Status(&self) -> u16; fn StatusText(&self) -> ByteString; - fn GetResponseHeader(&self, _name: ByteString) -> Option<ByteString>; + fn GetResponseHeader(&self, name: ByteString) -> Option<ByteString>; fn GetAllResponseHeaders(&self) -> ByteString; fn OverrideMimeType(&self, _mime: DOMString); fn ResponseType(&self) -> XMLHttpRequestResponseType; @@ -267,13 +267,30 @@ impl<'a> XMLHttpRequestMethods<'a> for JSRef<'a, XMLHttpRequest> { } fn Open(&mut self, method: ByteString, url: DOMString) -> ErrorResult { - let maybe_method: Option<Method> = method.as_str().and_then(|s| { - FromStr::from_str(s.to_ascii_upper().as_slice()) // rust-http tests against the uppercase versions + let uppercase_method = method.as_str().map(|s| { + let upper = s.to_ascii_upper(); + match upper.as_slice() { + "DELETE" | "GET" | "HEAD" | "OPTIONS" | + "POST" | "PUT" | "CONNECT" | "TRACE" | + "TRACK" => upper, + _ => s.to_string() + } + }); + let maybe_method: Option<Method> = uppercase_method.and_then(|s| { + // Note: rust-http tests against the uppercase versions + // Since we want to pass methods not belonging to the short list above + // without changing capitalization, this will actually sidestep rust-http's type system + // since methods like "patch" or "PaTcH" will be considered extension methods + // despite the there being a rust-http method variant for them + Method::from_str_or_new(s.as_slice()) }); // Step 2 let base: Option<Url> = Some(self.global.root().get_url()); match maybe_method { - Some(Get) | Some(Post) | Some(Head) => { + // Step 4 + Some(Connect) | Some(Trace) => Err(Security), + Some(ExtensionMethod(ref t)) if t.as_slice() == "TRACK" => Err(Security), + Some(_) if method.is_token() => { *self.request_method = maybe_method.unwrap(); @@ -282,8 +299,14 @@ impl<'a> XMLHttpRequestMethods<'a> for JSRef<'a, XMLHttpRequest> { Ok(parsed) => parsed, Err(_) => return Err(Syntax) // Step 7 }; - // XXXManishearth Do some handling of username/passwords, and abort existing requests - + // XXXManishearth Do some handling of username/passwords + if self.sync { + // FIXME: This should only happen if the global environment is a document environment + if self.timeout != 0 || self.with_credentials || self.response_type != _empty { + return Err(InvalidAccess) + } + } + // XXXManishearth abort existing requests // Step 12 *self.request_url = parsed_url; *self.request_headers = RequestHeaderCollection::new(); @@ -295,22 +318,11 @@ impl<'a> XMLHttpRequestMethods<'a> for JSRef<'a, XMLHttpRequest> { if self.ready_state != Opened { self.change_ready_state(Opened); } - //XXXManishearth fire a progressevent Ok(()) }, - // XXXManishearth Handle other standard methods - Some(Connect) | Some(Trace) => { - // XXXManishearth Track isn't in rust-http, but it should end up in this match arm. - Err(Security) // Step 4 - }, - None => Err(Syntax), // Step 3 - _ => { - if method.is_token() { - Ok(()) // XXXManishearth handle extension methods - } else { - Err(Syntax) // Step 3 - } - } + // This includes cases where as_str() returns None, and when is_token() returns false, + // both of which indicate invalid extension method names + _ => Err(Syntax), // Step 3 } } fn Open_(&mut self, method: ByteString, url: DOMString, async: bool, @@ -491,8 +503,12 @@ impl<'a> XMLHttpRequestMethods<'a> for JSRef<'a, XMLHttpRequest> { fn StatusText(&self) -> ByteString { self.status_text.clone() } - fn GetResponseHeader(&self, _name: ByteString) -> Option<ByteString> { - None + fn GetResponseHeader(&self, name: ByteString) -> Option<ByteString> { + self.response_headers.deref().iter().find(|h| { + name.eq_ignore_case(&FromStr::from_str(h.header_name().as_slice()).unwrap()) + }).map(|h| { + FromStr::from_str(h.header_value().as_slice()).unwrap() + }) } fn GetAllResponseHeaders(&self) -> ByteString { let mut writer = MemWriter::new(); |