From 9cc99f60ae0284a3f9f4a61c18afc1ae02fff9d0 Mon Sep 17 00:00:00 2001 From: Brian Warner Date: Tue, 3 Jan 2012 16:28:07 -0800 Subject: [PATCH] Bug 714994: Restore (limited) url.toFilename and .fromFilename. They only work for addon-provided resource: URLs when the XPI is unpacked. Update the tests to exercise this (but only for whatever value of unpack= the SDK uses: to exercise both sides, you must manually edit python-lib/cuddlefish/rdf.py and python-lib/cuddlefish/app-extension/install.rdf, then re-run 'cfx testall'). This reverts 45859d658a1283e2a5e94940ab100285a6d94056. --- packages/api-utils/lib/url.js | 37 ++++++++++++++++++ packages/api-utils/tests/test-url.js | 56 ++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+) diff --git a/packages/api-utils/lib/url.js b/packages/api-utils/lib/url.js index a6e97fe32..7d41e22e4 100644 --- a/packages/api-utils/lib/url.js +++ b/packages/api-utils/lib/url.js @@ -59,6 +59,43 @@ function newURI(uriStr, base) { } } +function resolveResourceURI(uri) { + var resolved; + try { + resolved = resProt.resolveURI(uri); + } catch (e if e.result == Cr.NS_ERROR_NOT_AVAILABLE) { + throw new Error("resource does not exist: " + uri.spec); + }; + return resolved; +} + +let fromFilename = exports.fromFilename = function fromFilename(path) { + var file = Cc['@mozilla.org/file/local;1'] + .createInstance(Ci.nsILocalFile); + file.initWithPath(path); + return ios.newFileURI(file).spec; +}; + +let toFilename = exports.toFilename = function toFilename(url) { + var uri = newURI(url); + if (uri.scheme == "resource") + uri = newURI(resolveResourceURI(uri)); + if (uri.scheme == "chrome") { + var channel = ios.newChannelFromURI(uri); + try { + channel = channel.QueryInterface(Ci.nsIFileChannel); + return channel.file.path; + } catch (e if e.result == Cr.NS_NOINTERFACE) { + throw new Error("chrome url isn't on filesystem: " + url); + } + } + if (uri.scheme == "file") { + var file = uri.QueryInterface(Ci.nsIFileURL).file; + return file.path; + } + throw new Error("cannot map to filename: " + url); +}; + function URL(url, base) { if (!(this instanceof URL)) { return new URL(url, base); diff --git a/packages/api-utils/tests/test-url.js b/packages/api-utils/tests/test-url.js index f4c96c6fd..935c7d6c4 100644 --- a/packages/api-utils/tests/test-url.js +++ b/packages/api-utils/tests/test-url.js @@ -74,6 +74,62 @@ exports.testParseFTPWithUserPass = function(test) { test.assertEqual(info.userPass, "user:pass"); }; +// rootURI is jar:file://...!/ if we're packed, and file://.../ if we're +// unpacked. url.toFilename() is not required to work for the contents of +// packed XPIs +var unpacked = (require("@packaging").rootURI.indexOf("file:") == 0); + +exports.testToFilename = function(test) { + test.assertRaises( + function() { url.toFilename("resource://nonexistent"); }, + "resource does not exist: resource://nonexistent/", + "url.toFilename() on nonexistent resources should throw" + ); + + if (unpacked) + test.assertMatches(url.toFilename(module.uri), + /.*test-url\.js$/, + "url.toFilename() on resource: URIs should work"); + else + test.assertRaises( + function() { url.toFilename(module.uri); }, + "cannot map to filename: "+module.uri, + "url.toFilename() can fail for packed XPIs"); + + test.assertRaises( + function() { url.toFilename("http://foo.com/"); }, + "cannot map to filename: http://foo.com/", + "url.toFilename() on http: URIs should raise error" + ); + + try { + test.assertMatches( + url.toFilename("chrome://global/content/console.xul"), + /.*console\.xul$/, + "url.toFilename() w/ console.xul works when it maps to filesystem" + ); + } catch (e) { + if (/chrome url isn\'t on filesystem/.test(e.message)) + test.pass("accessing console.xul in jar raises exception"); + else + test.fail("accessing console.xul raises " + e); + } + + // TODO: Are there any chrome URLs that we're certain exist on the + // filesystem? + // test.assertMatches(url.toFilename("chrome://myapp/content/main.js"), + // /.*main\.js$/); +}; + +exports.testFromFilename = function(test) { + var profileDirName = require("system").pathFor("ProfD"); + var fileUrl = url.fromFilename(profileDirName); + test.assertEqual(url.URL(fileUrl).scheme, 'file', + 'url.toFilename() should return a file: url'); + test.assertEqual(url.fromFilename(url.toFilename(fileUrl)), + fileUrl); +}; + exports.testURL = function(test) { let URL = url.URL; test.assert(URL("h:foo") instanceof URL, "instance is of correct type");