Skip to content

Commit

Permalink
Added "base64" module with docs and unit test, applied review comments.
Browse files Browse the repository at this point in the history
  • Loading branch information
ZER0 committed May 9, 2012
1 parent 8fcd681 commit 2d289b2
Show file tree
Hide file tree
Showing 8 changed files with 196 additions and 22 deletions.
12 changes: 6 additions & 6 deletions packages/addon-kit/lib/clipboard.js
Expand Up @@ -6,7 +6,7 @@

"use strict";

const { Cc, Ci, btoa } = require("chrome");
const { Cc, Ci } = require("chrome");
const { DataURL } = require("api-utils/url");
const errors = require("api-utils/errors");
const apiUtils = require("api-utils/api-utils");
Expand Down Expand Up @@ -249,10 +249,9 @@ exports.get = function(aDataType) {

let image = data.value;

// Due to the differences in how the images in the clipboard could be
// stored, the checks below are needed. The clipboard could be already
// provide the image as byte streams, but also as pointer, or as
// image container.
// Due to the differences in how images could be stored in the clipboard
// the checks below are needed. The clipboard could already provide the
// image as byte streams, but also as pointer, or as image container.
// If it's not possible obtain a byte stream, the function returns `null`.
if (image instanceof Ci.nsISupportsInterfacePointer)
image = image.data;
Expand All @@ -269,7 +268,8 @@ exports.get = function(aDataType) {
dataURL.data = binaryStream.readBytes(binaryStream.available());

data = dataURL.toString();
} else
}
else
data = null;

break;
Expand Down
50 changes: 50 additions & 0 deletions packages/api-utils/docs/base64.md
@@ -0,0 +1,50 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- 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/. -->

The module provides data encoding and decoding using Base64 algorithms.

##Example

var base64 = require("api-utils/base64");

var encodedData = base64.encode("Hello, World");
var decodedData = base64.decode(encodedData);

##Unicode Strings

In order to `encode` and `decode` properly Unicode strings, the `charset`
parameter needs to be set to `"utf-8"`:

var base64 = require("api-utils/base64");

var encodedData = base64.encode(unicodeString, "utf-8");
var decodedData = base64.decode(encodedData, "utf-8");

<api name="encode">
@function
Creates a base-64 encoded ASCII string from a string of binary data.

@param data {string}
The data to encode
@param [charset] {string}
The charset of the string to encode (optional).
The only accepted value is `"utf-8"`.

@returns {string}
The encoded string
</api>

<api name="decode">
@function
Decodes a string of data which has been encoded using base-64 encoding.

@param data {string}
The encoded data
@param [charset] {string}
The charset of the string to encode (optional).
The only accepted value is `"utf-8"`.

@returns {string}
The decoded string
</api>
37 changes: 37 additions & 0 deletions packages/api-utils/lib/base64.js
@@ -0,0 +1,37 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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 strict";

const { Cu } = require("chrome");

// If an object is not given as second argument, the JavaScript Module scope is
// returned, so we can obtain from it the `atob` and `btoa` functions
const { atob, btoa } = Cu.import("resource://gre/modules/Services.jsm");

function isUTF8(charset) {
let type = typeof charset;

if (type === "undefined")
return false;

if (type === "string" && charset.toLowerCase() === "utf-8")
return true;

throw new Error("The charset argument can be only 'utf-8'");
}

exports.decode = function (data, charset) {
if (isUTF8(charset))
return decodeURIComponent(escape(atob(data)))

return atob(data);
}

exports.encode = function (data, charset) {
if (isUTF8(charset))
return btoa(unescape(encodeURIComponent(data)))

return btoa(data);
}
2 changes: 0 additions & 2 deletions packages/api-utils/lib/cuddlefish.js
Expand Up @@ -384,8 +384,6 @@ const Loader = iced(function Loader(options) {
Cu: Cu,
Cr: Cr,
Cm: Cm,
atob: atob,
btoa: btoa,
components: Components
}),
}),
Expand Down
19 changes: 11 additions & 8 deletions packages/api-utils/lib/url.js
Expand Up @@ -4,8 +4,10 @@

"use strict";

const { Cc, Ci, Cr, atob, btoa } = require("chrome");
const { Class } = require('api-utils/heritage');
const { Cc, Ci, Cr } = require("chrome");

const { Class } = require("./heritage");
const base64 = require("./base64");

var ios = Cc['@mozilla.org/network/io-service;1']
.getService(Ci.nsIIOService);
Expand Down Expand Up @@ -134,14 +136,14 @@ const DataURL = Class({
delete this.parameters["base64"];
},
/**
* Initialize the Data URL object. If a uri is give, it will be parsed.
* Initialize the Data URL object. If a uri is given, it will be parsed.
*
* @param {String} [uri] The uri to parse
*
* @throws {URIError} if the Data URL is malformed
*/
initialize: function(uri) {
// Due to the bug 751834 is not possible document and define these
// Due to bug 751834 it is not possible document and define these
// properties in the prototype.

/**
Expand All @@ -166,7 +168,7 @@ const DataURL = Class({

uri = String(uri);

let matches = uri.match(/^data:([^,]*),([\s\S]*)/i);
let matches = uri.match(/^data:([^,]*),(.*)$/i);

if (!matches)
throw new URIError("Malformed Data URL: " + uri);
Expand All @@ -191,7 +193,7 @@ const DataURL = Class({
}

if (this.base64)
this.data = atob(this.data);
this.data = base64.decode(this.data);

},

Expand All @@ -213,11 +215,12 @@ const DataURL = Class({
parametersList.push(encodedParameter);
}

// If there is at least a parameter, add an empty string in order
// to start with a `;` on join call.
if (parametersList.length > 0)
parametersList.unshift("");


let data = this.base64 ? btoa(this.data) : this.data;
let data = this.base64 ? base64.encode(this.data) : this.data;

return "data:" +
this.mimeType +
Expand Down
19 changes: 15 additions & 4 deletions packages/api-utils/lib/utils/data.js
Expand Up @@ -4,7 +4,9 @@

"use strict";

const { Cc, Ci, Cu, btoa, atob } = require("chrome");
const { Cc, Ci, Cu } = require("chrome");
const base64 = require("../base64");

const IOService = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);

Expand Down Expand Up @@ -32,7 +34,7 @@ exports.getFaviconURIForLocation = function getFaviconURIForLocation(uri) {
catch(e) {
if (!DEF_FAVICON) {
DEF_FAVICON = PNG_B64 +
btoa(getChromeURIContent(DEF_FAVICON_URI));
base64.encode(getChromeURIContent(DEF_FAVICON_URI));
}
return DEF_FAVICON;
}
Expand All @@ -59,9 +61,18 @@ exports.getChromeURIContent = getChromeURIContent;
/**
* Creates a base-64 encoded ASCII string from a string of binary data.
*/
exports.base64Encode = btoa;
exports.base64Encode = function base64Encode(data) {
console.warn('require("api-utils/utils/data").base64Encode is deprecated, ' +
'please use require("api-utils/base64").encode instead');

return base64.encode(data);
}
/**
* Decodes a string of data which has been encoded using base-64 encoding.
*/
exports.base64Decode = atob;
exports.base64Decode = function base64Decode(data) {
console.warn('require("api-utils/utils/data").base64Dencode is deprecated, ' +
'please use require("api-utils/base64").decode instead');

return base64.decode(data);
}
75 changes: 75 additions & 0 deletions packages/api-utils/tests/test-base64.js
@@ -0,0 +1,75 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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 strict";

const base64 = require("api-utils/base64");

const text = "Awesome!";
const b64text = "QXdlc29tZSE=";

const utf8text = "✓ à la mode";
const b64utf8text = "4pyTIMOgIGxhIG1vZGU=";

exports["test base64.encode"] = function (assert) {
assert.equal(base64.encode(text), b64text, "encode correctly")
}

exports["test base64.decode"] = function (assert) {
assert.equal(base64.decode(b64text), text, "decode correctly")
}

exports["test base64.encode Unicode"] = function (assert) {

assert.equal(base64.encode(utf8text, "utf-8"), b64utf8text,
"encode correctly Unicode strings.")
}

exports["test base64.decode Unicode"] = function (assert) {

assert.equal(base64.decode(b64utf8text, "utf-8"), utf8text,
"decode correctly Unicode strings.")
}

exports["test base64.encode with wrong charset"] = function (assert) {

assert.throws(function() {
base64.encode(utf8text, "utf-16");
}, "The charset argument can be only 'utf-8'");

assert.throws(function() {
base64.encode(utf8text, "");
}, "The charset argument can be only 'utf-8'");

assert.throws(function() {
base64.encode(utf8text, 8);
}, "The charset argument can be only 'utf-8'");

}

exports["test base64.decode with wrong charset"] = function (assert) {

assert.throws(function() {
base64.decode(utf8text, "utf-16");
}, "The charset argument can be only 'utf-8'");

assert.throws(function() {
base64.decode(utf8text, "");
}, "The charset argument can be only 'utf-8'");

assert.throws(function() {
base64.decode(utf8text, 8);
}, "The charset argument can be only 'utf-8'");

}

exports["test encode/decode Unicode without utf-8 as charset"] = function (assert) {

assert.notEqual(base64.decode(base64.encode(utf8text)), utf8text,
"Unicode strings needs 'utf-8' charset"
);

}

require("test").run(exports);
4 changes: 2 additions & 2 deletions packages/api-utils/tests/test-url.js
Expand Up @@ -243,13 +243,13 @@ exports.testDataURLparse = function (test) {

exports.testDataURLparseBase64 = function (test) {
const { DataURL } = url;
const { base64Decode } = require("api-utils/utils/data");
const { decode } = require("./base64");

let base64Data = "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAQ0lEQVRYhe3OwQkAIBTD0Oyqg7idbqUr9B9EhBRyLY8F+0akEyBAgIBvAI1eCuaIEiBAgAABzwH50sNqAgQIEPAYcABJQw5EXdmcNgAAAABJRU5ErkJggg==";
let dataURL = new DataURL("data:image/png;base64," + base64Data);

test.assertEqual(dataURL.base64, true, "base64 is true for base64 encoded data uri")
test.assertEqual(dataURL.data, base64Decode(base64Data), "data is properly decoded")
test.assertEqual(dataURL.data, decode(base64Data), "data is properly decoded")
test.assertEqual(dataURL.mimeType, "image/png", "mimeType is set properly")
test.assertEqual(Object.keys(dataURL.parameters).length, 1, "one parameters specified");

Expand Down

0 comments on commit 2d289b2

Please sign in to comment.