Skip to content

Commit

Permalink
Fix for issue #3238
Browse files Browse the repository at this point in the history
Moved the Atob and Btoa methods ouside the impl for WorkerMethod trait
and made them publicly accessible from WorkerGlobalScopeMethods via
proxy methods.
  • Loading branch information
Prasoon Shukla committed Sep 17, 2014
1 parent aa935c7 commit e0f2c9e
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 70 deletions.
2 changes: 1 addition & 1 deletion components/script/dom/webidls/WorkerGlobalScope.webidl
Expand Up @@ -23,7 +23,7 @@ partial interface WorkerGlobalScope { // not obsolete
readonly attribute WorkerNavigator navigator;
};
//WorkerGlobalScope implements WindowTimers;
//WorkerGlobalScope implements WindowBase64;
WorkerGlobalScope implements WindowBase64;

// Proprietary
partial interface WorkerGlobalScope {
Expand Down
145 changes: 77 additions & 68 deletions components/script/dom/window.rs
Expand Up @@ -125,6 +125,81 @@ pub struct TimerData {
pub funval: Traceable<JSVal>,
}

// http://www.whatwg.org/html/#atob
pub fn base64_btoa(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
pub fn base64_atob(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<'a> WindowMethods for JSRef<'a, Window> {
fn Alert(&self, s: DOMString) {
// Right now, just print to the console
Expand Down Expand Up @@ -272,78 +347,12 @@ impl<'a> WindowMethods for JSRef<'a, Window> {
}
}

// 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))
}
base64_btoa(btoa)
}

// 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)
}
base64_atob(atob)
}
}

Expand Down
11 changes: 10 additions & 1 deletion components/script/dom/workerglobalscope.rs
Expand Up @@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::Bindings::WorkerGlobalScopeBinding::WorkerGlobalScopeMethods;
use dom::bindings::error::{ErrorResult, Syntax, Network, FailureUnknown};
use dom::bindings::error::{ErrorResult, Fallible, Syntax, Network, FailureUnknown};
use dom::bindings::trace::Untraceable;
use dom::bindings::global;
use dom::bindings::js::{JS, JSRef, Temporary, OptionalSettable};
Expand All @@ -12,6 +12,7 @@ use dom::console::Console;
use dom::eventtarget::{EventTarget, WorkerGlobalScopeTypeId};
use dom::workerlocation::WorkerLocation;
use dom::workernavigator::WorkerNavigator;
use dom::window::{base64_atob, base64_btoa};
use script_task::ScriptChan;

use servo_net::resource_task::{ResourceTask, load_whole_resource};
Expand Down Expand Up @@ -136,6 +137,14 @@ impl<'a> WorkerGlobalScopeMethods for JSRef<'a, WorkerGlobalScope> {
}
Temporary::new(self.console.get().get_ref().clone())
}

fn Btoa(&self, btoa: DOMString) -> Fallible<DOMString> {
base64_btoa(btoa)
}

fn Atob(&self, atob: DOMString) -> Fallible<DOMString> {
base64_atob(atob)
}
}

impl Reflectable for WorkerGlobalScope {
Expand Down

0 comments on commit e0f2c9e

Please sign in to comment.