aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/script/dom
diff options
context:
space:
mode:
authorManish Goregaokar <manishsmail@gmail.com>2014-08-20 01:56:02 +0530
committerManish Goregaokar <manishsmail@gmail.com>2014-08-20 01:56:02 +0530
commit80c001b2f00fa5982ec896d4a19fd6311a3ece97 (patch)
tree77fbf5f169426a046770e1c0f29cf9dc7e7ffed1 /src/components/script/dom
parent024ae42dadbad168e9f5e4892576bd18e15720b6 (diff)
parent1c1db51ccfcc3e7069ed6bf88f8ac1b39de6153e (diff)
downloadservo-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.webidl10
-rw-r--r--src/components/script/dom/window.rs78
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 {