michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: 'use strict'; michael@0: michael@0: const { michael@0: URL, michael@0: toFilename, michael@0: fromFilename, michael@0: isValidURI, michael@0: getTLD, michael@0: DataURL, michael@0: isLocalURL } = require('sdk/url'); michael@0: michael@0: const { pathFor } = require('sdk/system'); michael@0: const file = require('sdk/io/file'); michael@0: const tabs = require('sdk/tabs'); michael@0: const { decode } = require('sdk/base64'); michael@0: michael@0: const httpd = require('sdk/test/httpd'); michael@0: const port = 8099; michael@0: michael@0: const defaultLocation = '{\'scheme\':\'about\',\'userPass\':null,\'host\':null,\'hostname\':null,\'port\':null,\'path\':\'addons\',\'pathname\':\'addons\',\'hash\':\'\',\'href\':\'about:addons\',\'origin\':\'about:\',\'protocol\':\'about:\',\'search\':\'\'}'.replace(/'/g, '"'); michael@0: michael@0: exports.testResolve = function(assert) { michael@0: assert.equal(URL('bar', 'http://www.foo.com/').toString(), michael@0: 'http://www.foo.com/bar'); michael@0: michael@0: assert.equal(URL('bar', 'http://www.foo.com'), michael@0: 'http://www.foo.com/bar'); michael@0: michael@0: assert.equal(URL('http://bar.com/', 'http://foo.com/'), michael@0: 'http://bar.com/', michael@0: 'relative should override base'); michael@0: michael@0: assert.throws(function() { URL('blah'); }, michael@0: /malformed URI: blah/i, michael@0: 'url.resolve() should throw malformed URI on base'); michael@0: michael@0: assert.throws(function() { URL('chrome://global'); }, michael@0: /invalid URI: chrome:\/\/global/i, michael@0: 'url.resolve() should throw invalid URI on base'); michael@0: michael@0: assert.throws(function() { URL('chrome://foo/bar'); }, michael@0: /invalid URI: chrome:\/\/foo\/bar/i, michael@0: 'url.resolve() should throw on bad chrome URI'); michael@0: michael@0: assert.equal(URL('', 'http://www.foo.com'), michael@0: 'http://www.foo.com/', michael@0: 'url.resolve() should add slash to end of domain'); michael@0: }; michael@0: michael@0: exports.testParseHttp = function(assert) { michael@0: var aUrl = 'http://sub.foo.com/bar?locale=en-US&otherArg=%20x%20#myhash'; michael@0: var info = URL(aUrl); michael@0: michael@0: assert.equal(info.scheme, 'http'); michael@0: assert.equal(info.protocol, 'http:'); michael@0: assert.equal(info.host, 'sub.foo.com'); michael@0: assert.equal(info.hostname, 'sub.foo.com'); michael@0: assert.equal(info.port, null); michael@0: assert.equal(info.userPass, null); michael@0: assert.equal(info.path, '/bar?locale=en-US&otherArg=%20x%20#myhash'); michael@0: assert.equal(info.pathname, '/bar'); michael@0: assert.equal(info.href, aUrl); michael@0: assert.equal(info.hash, '#myhash'); michael@0: assert.equal(info.search, '?locale=en-US&otherArg=%20x%20'); michael@0: }; michael@0: michael@0: exports.testParseHttpSearchAndHash = function (assert) { michael@0: var info = URL('https://www.moz.com/some/page.html'); michael@0: assert.equal(info.hash, ''); michael@0: assert.equal(info.search, ''); michael@0: michael@0: var hashOnly = URL('https://www.sub.moz.com/page.html#justhash'); michael@0: assert.equal(hashOnly.search, ''); michael@0: assert.equal(hashOnly.hash, '#justhash'); michael@0: michael@0: var queryOnly = URL('https://www.sub.moz.com/page.html?my=query'); michael@0: assert.equal(queryOnly.search, '?my=query'); michael@0: assert.equal(queryOnly.hash, ''); michael@0: michael@0: var qMark = URL('http://www.moz.org?'); michael@0: assert.equal(qMark.search, ''); michael@0: assert.equal(qMark.hash, ''); michael@0: michael@0: var hash = URL('http://www.moz.org#'); michael@0: assert.equal(hash.search, ''); michael@0: assert.equal(hash.hash, ''); michael@0: michael@0: var empty = URL('http://www.moz.org?#'); michael@0: assert.equal(hash.search, ''); michael@0: assert.equal(hash.hash, ''); michael@0: michael@0: var strange = URL('http://moz.org?test1#test2?test3'); michael@0: assert.equal(strange.search, '?test1'); michael@0: assert.equal(strange.hash, '#test2?test3'); michael@0: }; michael@0: michael@0: exports.testParseHttpWithPort = function(assert) { michael@0: var info = URL('http://foo.com:5/bar'); michael@0: assert.equal(info.port, 5); michael@0: }; michael@0: michael@0: exports.testParseChrome = function(assert) { michael@0: var info = URL('chrome://global/content/blah'); michael@0: assert.equal(info.scheme, 'chrome'); michael@0: assert.equal(info.host, 'global'); michael@0: assert.equal(info.port, null); michael@0: assert.equal(info.userPass, null); michael@0: assert.equal(info.path, '/content/blah'); michael@0: }; michael@0: michael@0: exports.testParseAbout = function(assert) { michael@0: var info = URL('about:boop'); michael@0: assert.equal(info.scheme, 'about'); michael@0: assert.equal(info.host, null); michael@0: assert.equal(info.port, null); michael@0: assert.equal(info.userPass, null); michael@0: assert.equal(info.path, 'boop'); michael@0: }; michael@0: michael@0: exports.testParseFTP = function(assert) { michael@0: var info = URL('ftp://1.2.3.4/foo'); michael@0: assert.equal(info.scheme, 'ftp'); michael@0: assert.equal(info.host, '1.2.3.4'); michael@0: assert.equal(info.port, null); michael@0: assert.equal(info.userPass, null); michael@0: assert.equal(info.path, '/foo'); michael@0: }; michael@0: michael@0: exports.testParseFTPWithUserPass = function(assert) { michael@0: var info = URL('ftp://user:pass@1.2.3.4/foo'); michael@0: assert.equal(info.userPass, 'user:pass'); michael@0: }; michael@0: michael@0: exports.testToFilename = function(assert) { michael@0: assert.throws( michael@0: function() { toFilename('resource://nonexistent'); }, michael@0: /resource does not exist: resource:\/\/nonexistent\//i, michael@0: 'toFilename() on nonexistent resources should throw' michael@0: ); michael@0: michael@0: assert.throws( michael@0: function() { toFilename('http://foo.com/'); }, michael@0: /cannot map to filename: http:\/\/foo.com\//i, michael@0: 'toFilename() on http: URIs should raise error' michael@0: ); michael@0: michael@0: try { michael@0: assert.ok( michael@0: /.*console\.xul$/.test(toFilename('chrome://global/content/console.xul')), michael@0: 'toFilename() w/ console.xul works when it maps to filesystem' michael@0: ); michael@0: } michael@0: catch (e) { michael@0: if (/chrome url isn\'t on filesystem/.test(e.message)) michael@0: assert.pass('accessing console.xul in jar raises exception'); michael@0: else michael@0: assert.fail('accessing console.xul raises ' + e); michael@0: } michael@0: michael@0: // TODO: Are there any chrome URLs that we're certain exist on the michael@0: // filesystem? michael@0: // assert.ok(/.*main\.js$/.test(toFilename('chrome://myapp/content/main.js'))); michael@0: }; michael@0: michael@0: exports.testFromFilename = function(assert) { michael@0: var profileDirName = require('sdk/system').pathFor('ProfD'); michael@0: var fileUrl = fromFilename(profileDirName); michael@0: assert.equal(URL(fileUrl).scheme, 'file', michael@0: 'toFilename() should return a file: url'); michael@0: assert.equal(fromFilename(toFilename(fileUrl)), fileUrl); michael@0: }; michael@0: michael@0: exports.testURL = function(assert) { michael@0: assert.ok(URL('h:foo') instanceof URL, 'instance is of correct type'); michael@0: assert.throws(function() URL(), michael@0: /malformed URI: undefined/i, michael@0: 'url.URL should throw on undefined'); michael@0: assert.throws(function() URL(''), michael@0: /malformed URI: /i, michael@0: 'url.URL should throw on empty string'); michael@0: assert.throws(function() URL('foo'), michael@0: /malformed URI: foo/i, michael@0: 'url.URL should throw on invalid URI'); michael@0: assert.ok(URL('h:foo').scheme, 'has scheme'); michael@0: assert.equal(URL('h:foo').toString(), michael@0: 'h:foo', michael@0: 'toString should roundtrip'); michael@0: // test relative + base michael@0: assert.equal(URL('mypath', 'http://foo').toString(), michael@0: 'http://foo/mypath', michael@0: 'relative URL resolved to base'); michael@0: // test relative + no base michael@0: assert.throws(function() URL('path').toString(), michael@0: /malformed URI: path/i, michael@0: 'no base for relative URI should throw'); michael@0: michael@0: let a = URL('h:foo'); michael@0: let b = URL(a); michael@0: assert.equal(b.toString(), michael@0: 'h:foo', michael@0: 'a URL can be initialized from another URL'); michael@0: assert.notStrictEqual(a, b, michael@0: 'a URL initialized from another URL is not the same object'); michael@0: assert.ok(a == 'h:foo', michael@0: 'toString is implicit when a URL is compared to a string via =='); michael@0: assert.strictEqual(a + '', 'h:foo', michael@0: 'toString is implicit when a URL is concatenated to a string'); michael@0: }; michael@0: michael@0: exports.testStringInterface = function(assert) { michael@0: var EM = 'about:addons'; michael@0: var a = URL(EM); michael@0: michael@0: // make sure the standard URL properties are enumerable and not the String interface bits michael@0: assert.equal(Object.keys(a), michael@0: 'scheme,userPass,host,hostname,port,path,pathname,hash,href,origin,protocol,search', michael@0: 'enumerable key list check for URL.'); michael@0: assert.equal( michael@0: JSON.stringify(a), michael@0: defaultLocation, michael@0: 'JSON.stringify should return a object with correct props and vals.'); michael@0: michael@0: // make sure that the String interface exists and works as expected michael@0: assert.equal(a.indexOf(':'), EM.indexOf(':'), 'indexOf on URL works'); michael@0: assert.equal(a.valueOf(), EM.valueOf(), 'valueOf on URL works.'); michael@0: assert.equal(a.toSource(), EM.toSource(), 'toSource on URL works.'); michael@0: assert.equal(a.lastIndexOf('a'), EM.lastIndexOf('a'), 'lastIndexOf on URL works.'); michael@0: assert.equal(a.match('t:').toString(), EM.match('t:').toString(), 'match on URL works.'); michael@0: assert.equal(a.toUpperCase(), EM.toUpperCase(), 'toUpperCase on URL works.'); michael@0: assert.equal(a.toLowerCase(), EM.toLowerCase(), 'toLowerCase on URL works.'); michael@0: assert.equal(a.split(':').toString(), EM.split(':').toString(), 'split on URL works.'); michael@0: assert.equal(a.charAt(2), EM.charAt(2), 'charAt on URL works.'); michael@0: assert.equal(a.charCodeAt(2), EM.charCodeAt(2), 'charCodeAt on URL works.'); michael@0: assert.equal(a.concat(EM), EM.concat(a), 'concat on URL works.'); michael@0: assert.equal(a.substr(2,3), EM.substr(2,3), 'substr on URL works.'); michael@0: assert.equal(a.substring(2,3), EM.substring(2,3), 'substring on URL works.'); michael@0: assert.equal(a.trim(), EM.trim(), 'trim on URL works.'); michael@0: assert.equal(a.trimRight(), EM.trimRight(), 'trimRight on URL works.'); michael@0: assert.equal(a.trimLeft(), EM.trimLeft(), 'trimLeft on URL works.'); michael@0: } michael@0: michael@0: exports.testDataURLwithouthURI = function (assert) { michael@0: let dataURL = new DataURL(); michael@0: michael@0: assert.equal(dataURL.base64, false, 'base64 is false for empty uri') michael@0: assert.equal(dataURL.data, '', 'data is an empty string for empty uri') michael@0: assert.equal(dataURL.mimeType, '', 'mimeType is an empty string for empty uri') michael@0: assert.equal(Object.keys(dataURL.parameters).length, 0, 'parameters is an empty object for empty uri'); michael@0: michael@0: assert.equal(dataURL.toString(), 'data:,'); michael@0: } michael@0: michael@0: exports.testDataURLwithMalformedURI = function (assert) { michael@0: assert.throws(function() { michael@0: let dataURL = new DataURL('http://www.mozilla.com/'); michael@0: }, michael@0: /Malformed Data URL: http:\/\/www.mozilla.com\//i, michael@0: 'DataURL raises an exception for malformed data uri' michael@0: ); michael@0: } michael@0: michael@0: exports.testDataURLparse = function (assert) { michael@0: let dataURL = new DataURL('data:text/html;charset=US-ASCII,%3Ch1%3EHello!%3C%2Fh1%3E'); michael@0: michael@0: assert.equal(dataURL.base64, false, 'base64 is false for non base64 data uri') michael@0: assert.equal(dataURL.data, '