diff options
author | Manish Goregaokar <manishsmail@gmail.com> | 2014-08-20 01:56:02 +0530 |
---|---|---|
committer | Manish Goregaokar <manishsmail@gmail.com> | 2014-08-20 01:56:02 +0530 |
commit | 80c001b2f00fa5982ec896d4a19fd6311a3ece97 (patch) | |
tree | 77fbf5f169426a046770e1c0f29cf9dc7e7ffed1 /src/components/script/dom | |
parent | 024ae42dadbad168e9f5e4892576bd18e15720b6 (diff) | |
parent | 1c1db51ccfcc3e7069ed6bf88f8ac1b39de6153e (diff) | |
download | servo-80c001b2f00fa5982ec896d4a19fd6311a3ece97.tar.gz servo-80c001b2f00fa5982ec896d4a19fd6311a3ece97.zip |
Merge pull request #3082 from ChrisParis/atob
Implement window.atob/btoa; r=Manishearth
Diffstat (limited to 'src/components/script/dom')
-rw-r--r-- | src/components/script/dom/webidls/Window.webidl | 10 | ||||
-rw-r--r-- | src/components/script/dom/window.rs | 78 |
2 files changed, 87 insertions, 1 deletions
diff --git a/src/components/script/dom/webidls/Window.webidl b/src/components/script/dom/webidls/Window.webidl index aea9fc784e1..2992abb507c 100644 --- a/src/components/script/dom/webidls/Window.webidl +++ b/src/components/script/dom/webidls/Window.webidl @@ -74,6 +74,16 @@ interface WindowTimers { }; Window implements WindowTimers; +// http://www.whatwg.org/html/#atob +[NoInterfaceObject/*, Exposed=Window,Worker*/] +interface WindowBase64 { + [Throws] + DOMString btoa(DOMString btoa); + [Throws] + DOMString atob(DOMString atob); +}; +Window implements WindowBase64; + // https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/NavigationTiming/Overview.html#sec-window.performance-attribute partial interface Window { /*[Replaceable]*/ readonly attribute Performance performance; diff --git a/src/components/script/dom/window.rs b/src/components/script/dom/window.rs index b73b37c4c66..7d60c09a5fc 100644 --- a/src/components/script/dom/window.rs +++ b/src/components/script/dom/window.rs @@ -6,6 +6,7 @@ use dom::bindings::codegen::Bindings::EventHandlerBinding::{OnErrorEventHandlerN use dom::bindings::codegen::Bindings::WindowBinding; use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; use dom::bindings::codegen::InheritTypes::EventTargetCast; +use dom::bindings::error::{Fallible, InvalidCharacter}; use dom::bindings::global; use dom::bindings::js::{JS, JSRef, Temporary, OptionalSettable}; use dom::bindings::trace::{Traceable, Untraceable}; @@ -25,7 +26,7 @@ use script_traits::ScriptControlChan; use servo_msg::compositor_msg::ScriptListener; use servo_net::image_cache_task::ImageCacheTask; -use servo_util::str::DOMString; +use servo_util::str::{DOMString,HTML_SPACE_CHARACTERS}; use servo_util::task::{spawn_named}; use js::jsapi::JS_CallFunctionValue; @@ -36,6 +37,7 @@ use js::jsval::NullValue; use js::rust::with_compartment; use url::{Url, UrlParser}; +use serialize::base64::{FromBase64, ToBase64, STANDARD}; use std::collections::hashmap::HashMap; use std::cell::{Cell, RefCell}; use std::cmp; @@ -263,6 +265,80 @@ impl<'a> WindowMethods for JSRef<'a, Window> { JS_GC(JS_GetRuntime(self.get_cx())); } } + + // http://www.whatwg.org/html/#atob + fn Btoa(&self, btoa: DOMString) -> Fallible<DOMString> { + let input = btoa.as_slice(); + // "The btoa() method must throw an InvalidCharacterError exception if + // the method's first argument contains any character whose code point + // is greater than U+00FF." + if input.chars().any(|c: char| c > '\u00FF') { + Err(InvalidCharacter) + } else { + // "Otherwise, the user agent must convert that argument to a + // sequence of octets whose nth octet is the eight-bit + // representation of the code point of the nth character of + // the argument," + let octets = input.chars().map(|c: char| c as u8).collect::<Vec<u8>>(); + + // "and then must apply the base64 algorithm to that sequence of + // octets, and return the result. [RFC4648]" + Ok(octets.as_slice().to_base64(STANDARD)) + } + } + + // http://www.whatwg.org/html/#atob + fn Atob(&self, atob: DOMString) -> Fallible<DOMString> { + // "Let input be the string being parsed." + let mut input = atob.as_slice(); + + // "Remove all space characters from input." + // serialize::base64::from_base64 ignores \r and \n, + // but it treats the other space characters as + // invalid input. + fn is_html_space(c: char) -> bool { + HTML_SPACE_CHARACTERS.iter().any(|&m| m == c) + } + let without_spaces = input.chars() + .filter(|&c| ! is_html_space(c)) + .collect::<String>(); + input = without_spaces.as_slice(); + + // "If the length of input divides by 4 leaving no remainder, then: + // if input ends with one or two U+003D EQUALS SIGN (=) characters, + // remove them from input." + if input.len() % 4 == 0 { + if input.ends_with("==") { + input = input.slice_to(input.len() - 2) + } else if input.ends_with("=") { + input = input.slice_to(input.len() - 1) + } + } + + // "If the length of input divides by 4 leaving a remainder of 1, + // throw an InvalidCharacterError exception and abort these steps." + if input.len() % 4 == 1 { + return Err(InvalidCharacter) + } + + // "If input contains a character that is not in the following list of + // characters and character ranges, throw an InvalidCharacterError + // exception and abort these steps: + // + // U+002B PLUS SIGN (+) + // U+002F SOLIDUS (/) + // Alphanumeric ASCII characters" + if input.chars() + .find(|&c| !(c == '+' || c == '/' || c.is_alphanumeric())) + .is_some() { + return Err(InvalidCharacter) + } + + match input.from_base64() { + Ok(data) => Ok(data.iter().map(|&b| b as char).collect::<String>()), + Err(..) => Err(InvalidCharacter) + } + } } impl Reflectable for Window { |