From 6187aa41d758655ce1a7e586fc7aa71210f36986 Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Sun, 27 Dec 2015 19:53:03 +0100 Subject: [PATCH] Support for "web+" protocol prefix - closes #36 - follows consensus from https://github.com/ipfs/go-ipfs/issues/1678#issuecomment-163124489 --- lib/child-main.js | 10 ++-- lib/main.js | 10 ++-- lib/protocols.js | 64 ++++++++++++++++++----- package.json | 2 +- test/test-protocols.js | 116 +++++++++++++++++++++++++++++++++-------- 5 files changed, 152 insertions(+), 50 deletions(-) diff --git a/lib/child-main.js b/lib/child-main.js index 4add5a892..40fc60255 100644 --- a/lib/child-main.js +++ b/lib/child-main.js @@ -1,13 +1,9 @@ 'use strict'; -const proto = require("./protocols.js"); +const protocols = require("./protocols.js"); -proto.fs.register(); -proto.ipfs.register(); -proto.ipns.register(); +protocols.register(); require("sdk/system/unload").when(() => { - proto.fs.unregister(); - proto.ipfs.unregister(); - proto.ipns.unregister(); + protocols.unregister(); }); diff --git a/lib/main.js b/lib/main.js index 18a1223ec..98aeeed1b 100644 --- a/lib/main.js +++ b/lib/main.js @@ -2,23 +2,19 @@ require('./gui.js'); require('./gateways.js'); -var proto = require('./protocols.js'); +var protocols = require('./protocols.js'); const parent = require('sdk/remote/parent'); exports.main = function(options, callbacks) { // jshint unused:false require('./redirects.js'); - proto.fs.register(); - proto.ipfs.register(); - proto.ipns.register(); + protocols.register(); //console.log('Addon loaded.'); parent.remoteRequire("./lib/child-main.js"); }; exports.onUnload = function(reason) { // jshint unused:false - proto.fs.unregister(); - proto.ipfs.unregister(); - proto.ipns.unregister(); + protocols.unregister(); //console.log('Addon unloaded: ' + reason); }; diff --git a/lib/protocols.js b/lib/protocols.js index acb240f2b..18bc5a32f 100644 --- a/lib/protocols.js +++ b/lib/protocols.js @@ -10,14 +10,29 @@ var gw = require('./gateways.js'); const IPFS_SCHEME = 'ipfs'; const IPNS_SCHEME = 'ipns'; const FS_SCHEME = 'fs'; +const WEB_SCHEME_PREFIX = 'web+'; // https://github.com/lidel/ipfs-firefox-addon/issues/36 + function CommonProtocolHandler() {} function IpfsProtocolHandler() {} +function WebIpfsProtocolHandler() {} function IpnsProtocolHandler() {} +function WebIpnsProtocolHandler() {} function FsProtocolHandler() {} +function WebFsProtocolHandler() {} + +const HANDLERS = { + 'fs': FsProtocolHandler, + 'ipfs': IpfsProtocolHandler, + 'ipns': IpnsProtocolHandler, + + 'web+fs': WebFsProtocolHandler, + 'web+ipfs': WebIpfsProtocolHandler, + 'web+ipns': WebIpnsProtocolHandler +}; CommonProtocolHandler.prototype = Object.freeze({ @@ -47,7 +62,8 @@ CommonProtocolHandler.prototype = Object.freeze({ return uri; */ - let ipfsPath = aSpec.replace(new RegExp('^' + this.scheme + '\\:\\/*'), ''); + let schemeExp = this.scheme.replace(/\+/, '\\+'); // web+fs etc + let ipfsPath = aSpec.replace(new RegExp('^' + schemeExp + '\\:\\/*'), ''); let http = gw.publicUri().spec + this.pathPrefix + ipfsPath; let uri = ioservice.newURI(http, aOriginCharset, null); @@ -71,32 +87,46 @@ CommonProtocolHandler.prototype = Object.freeze({ }); +// https://github.com/lidel/ipfs-firefox-addon/issues/36 +function createWebVariant(target, base, uuid) { + target.prototype = Object.create(base.prototype); + target.prototype.constructor = target; + target.prototype.scheme = WEB_SCHEME_PREFIX + base.prototype.scheme; + target.prototype.classDescription = WEB_SCHEME_PREFIX + base.prototype.classDescription; + target.prototype.classID = components.ID(uuid); + target.prototype.contractID = '@mozilla.org/network/protocol;1?name=' + target.prototype.scheme; + target.prototype.QueryInterface = XPCOMUtils.generateQI([Ci.nsIProtocolHandler]); +} + IpfsProtocolHandler.prototype = Object.create(CommonProtocolHandler.prototype); IpfsProtocolHandler.prototype.constructor = IpfsProtocolHandler; -IpfsProtocolHandler.prototype.classDescription = 'IPFS Protocol Handler'; +IpfsProtocolHandler.prototype.classDescription = 'ipfs Protocol Handler'; IpfsProtocolHandler.prototype.contractID = '@mozilla.org/network/protocol;1?name=' + IPFS_SCHEME; IpfsProtocolHandler.prototype.classID = components.ID('{34023afe-f3aa-4b3d-b546-cb66f6e14c4b}'); IpfsProtocolHandler.prototype.QueryInterface = XPCOMUtils.generateQI([Ci.nsIProtocolHandler]); IpfsProtocolHandler.prototype.scheme = IPFS_SCHEME; IpfsProtocolHandler.prototype.pathPrefix = IPFS_SCHEME + '/'; +createWebVariant(WebIpfsProtocolHandler, IpfsProtocolHandler, '{713a4fe5-c5b8-43fa-a0c3-2742b3eea368}'); IpnsProtocolHandler.prototype = Object.create(CommonProtocolHandler.prototype); IpnsProtocolHandler.prototype.constructor = IpnsProtocolHandler; -IpnsProtocolHandler.prototype.classDescription = 'IPNS Protocol Handler'; +IpnsProtocolHandler.prototype.classDescription = 'ipns Protocol Handler'; IpnsProtocolHandler.prototype.contractID = '@mozilla.org/network/protocol;1?name=' + IPNS_SCHEME; IpnsProtocolHandler.prototype.classID = components.ID('{33920c2c-dd6b-11e4-b9d6-1681e6b88ec1}'); IpnsProtocolHandler.prototype.QueryInterface = XPCOMUtils.generateQI([Ci.nsIProtocolHandler]); IpnsProtocolHandler.prototype.scheme = IPNS_SCHEME; IpnsProtocolHandler.prototype.pathPrefix = IPNS_SCHEME + '/'; +createWebVariant(WebIpnsProtocolHandler, IpnsProtocolHandler, '{0f612fe4-5aa5-41ce-9fec-d827b702f5da}'); FsProtocolHandler.prototype = Object.create(CommonProtocolHandler.prototype); FsProtocolHandler.prototype.constructor = FsProtocolHandler; -FsProtocolHandler.prototype.classDescription = 'FS Protocol Handler'; +FsProtocolHandler.prototype.classDescription = 'fs Protocol Handler'; FsProtocolHandler.prototype.contractID = '@mozilla.org/network/protocol;1?name=' + FS_SCHEME; FsProtocolHandler.prototype.classID = components.ID('{6684bdd9-41b5-4de3-ab3e-de3f3d888dcd}'); FsProtocolHandler.prototype.QueryInterface = XPCOMUtils.generateQI([Ci.nsIProtocolHandler]); FsProtocolHandler.prototype.scheme = FS_SCHEME; FsProtocolHandler.prototype.pathPrefix = ''; +createWebVariant(WebFsProtocolHandler, FsProtocolHandler, '{82fbb59e-8349-442e-ad4e-ed3fa705c79d}'); function factory(ProtocolHandler) { return Object.freeze({ @@ -125,14 +155,22 @@ function factory(ProtocolHandler) { }); } -exports.ipfsScheme = IPFS_SCHEME; -exports.ipnsScheme = IPNS_SCHEME; -exports.fsScheme = FS_SCHEME; +// export handler factories (used in tests) +for (var scheme in HANDLERS) { + exports[scheme] = factory(HANDLERS[scheme]); +} + +// register protocols +exports.register = function() { + for (var scheme in HANDLERS) { + (exports[scheme]).register(); + } +}; -exports.ipfsHandler = Object.freeze(IpfsProtocolHandler); -exports.ipnsHandler = Object.freeze(IpnsProtocolHandler); -exports.fsHandler = Object.freeze(FsProtocolHandler); +// unregister protocols +exports.unregister = function() { + for (var scheme in HANDLERS) { + (exports[scheme]).unregister(); + } +}; -exports.ipfs = factory(IpfsProtocolHandler); -exports.ipns = factory(IpnsProtocolHandler); -exports.fs = factory(FsProtocolHandler); diff --git a/package.json b/package.json index 4bd4ab464..df8f8eddc 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "id": "ipfs-firefox-addon@lidel.org", "description": "Access IPFS resources via custom HTTP2IPFS gateway", "author": "Marcin Rataj", - "version": "1.3.2", + "version": "1.3.3", "license": "CC0-1.0", "homepage": "https://github.com/lidel/ipfs-firefox-addon", "icon": "data/icon-on-64.png", diff --git a/test/test-protocols.js b/test/test-protocols.js index 84f713465..c0afeca17 100644 --- a/test/test-protocols.js +++ b/test/test-protocols.js @@ -4,16 +4,32 @@ const pubGwUri = gw.publicUri(); const ipfsPath = 'QmTkzDwWqPbnAh5YiV5VwcTLnGdwSNsNTn2aDxdXBFca7D/example#/ipfs/QmSsNVuALPa1TW1GDahup8fFDqo95iFyPE7E6HpqDivw3p/readme.md'; const ipnsPath = 'ipfs.git.sexy'; -exports['test ipfsScheme'] = function(assert) { - assert.equal(proto.ipfsScheme, 'ipfs', 'handler scheme'); -}; +const ipfsHandler = proto.ipfs.createInstance(); +const ipnsHandler = proto.ipns.createInstance(); +const fsHandler = proto.fs.createInstance(); + +const webIpfsHandler = proto['web+ipfs'].createInstance(); +const webIpnsHandler = proto['web+ipns'].createInstance(); +const webFsHandler = proto['web+fs'].createInstance(); -exports['test ipnsScheme'] = function(assert) { - assert.equal(proto.ipnsScheme, 'ipns', 'handler scheme'); +exports['test ipfs: scheme'] = function(assert) { + assert.equal(ipfsHandler.scheme, 'ipfs', 'handler scheme'); +}; +exports['test ipns: scheme'] = function(assert) { + assert.equal(ipnsHandler.scheme, 'ipns', 'handler scheme'); +}; +exports['test fs: scheme'] = function(assert) { + assert.equal(fsHandler.scheme, 'fs', 'handler scheme'); }; -exports['test fsScheme'] = function(assert) { - assert.equal(proto.fsScheme, 'fs', 'handler scheme'); +exports['test web+ipfs scheme'] = function(assert) { + assert.equal(webIpfsHandler.scheme, 'web+ipfs', 'handler scheme'); +}; +exports['test web+ipns scheme'] = function(assert) { + assert.equal(webIpnsHandler.scheme, 'web+ipns', 'handler scheme'); +}; +exports['test web+fs scheme'] = function(assert) { + assert.equal(webFsHandler.scheme, 'web+fs', 'handler scheme'); }; // ipfs: / ipns: / ipfs:// / ipns:// @@ -21,23 +37,37 @@ exports['test fsScheme'] = function(assert) { // (which can be redirected to custom one in later steps) exports['test newURI(ipfs:)'] = function(assert) { - var newURI = proto.ipfsHandler.prototype.newURI('ipfs:' + ipfsPath, 'utf8', null); + var newURI = ipfsHandler.newURI('ipfs:' + ipfsPath, 'utf8', null); assert.equal(newURI.spec, pubGwUri.spec + 'ipfs/' + ipfsPath, 'newURI spec'); }; - exports['test newURI(ipfs://)'] = function(assert) { - var newURI = proto.ipfsHandler.prototype.newURI('ipfs://' + ipfsPath, 'utf8', null); + var newURI = ipfsHandler.newURI('ipfs://' + ipfsPath, 'utf8', null); + assert.equal(newURI.spec, pubGwUri.spec + 'ipfs/' + ipfsPath, 'newURI spec'); +}; +exports['test newURI(web+ipfs:)'] = function(assert) { + var newURI = webIpfsHandler.newURI('web+ipfs:' + ipfsPath, 'utf8', null); + assert.equal(newURI.spec, pubGwUri.spec + 'ipfs/' + ipfsPath, 'newURI spec'); +}; +exports['test newURI(web+ipfs://)'] = function(assert) { + var newURI = webIpfsHandler.newURI('web+ipfs://' + ipfsPath, 'utf8', null); assert.equal(newURI.spec, pubGwUri.spec + 'ipfs/' + ipfsPath, 'newURI spec'); }; exports['test newURI(ipns:)'] = function(assert) { - var newURI = proto.ipnsHandler.prototype.newURI('ipns:' + ipnsPath, 'utf8', null); + var newURI = ipnsHandler.newURI('ipns:' + ipnsPath, 'utf8', null); assert.equal(newURI.spec, pubGwUri.spec + 'ipns/' + ipnsPath, 'newURI spec'); }; - -exports['test newURI(ipns:)'] = function(assert) { - var newURI = proto.ipnsHandler.prototype.newURI('ipns://' + ipnsPath, 'utf8', null); +exports['test newURI(ipns://)'] = function(assert) { + var newURI = ipnsHandler.newURI('ipns://' + ipnsPath, 'utf8', null); + assert.equal(newURI.spec, pubGwUri.spec + 'ipns/' + ipnsPath, 'newURI spec'); +}; +exports['test newURI(web+ipns:)'] = function(assert) { + var newURI = webIpnsHandler.newURI('web+ipns:' + ipnsPath, 'utf8', null); + assert.equal(newURI.spec, pubGwUri.spec + 'ipns/' + ipnsPath, 'newURI spec'); +}; +exports['test newURI(web+ipns://)'] = function(assert) { + var newURI = webIpnsHandler.newURI('web+ipns://' + ipnsPath, 'utf8', null); assert.equal(newURI.spec, pubGwUri.spec + 'ipns/' + ipnsPath, 'newURI spec'); }; @@ -46,44 +76,86 @@ exports['test newURI(ipns:)'] = function(assert) { // Discussed at length in https://github.com/ipfs/go-ipfs/issues/1678#issuecomment-142600157 exports['test newURI(fs:ipfs/)'] = function(assert) { - var newURI = proto.fsHandler.prototype.newURI('fs:ipfs/' + ipfsPath, 'utf8', null); + var newURI = fsHandler.newURI('fs:ipfs/' + ipfsPath, 'utf8', null); assert.equal(newURI.spec, pubGwUri.spec + 'ipfs/' + ipfsPath, 'newURI spec'); }; exports['test newURI(fs:/ipfs/)'] = function(assert) { - var newURI = proto.fsHandler.prototype.newURI('fs:/ipfs/' + ipfsPath, 'utf8', null); + var newURI = fsHandler.newURI('fs:/ipfs/' + ipfsPath, 'utf8', null); assert.equal(newURI.spec, pubGwUri.spec + 'ipfs/' + ipfsPath, 'newURI spec'); }; exports['test newURI(fs://ipfs/)'] = function(assert) { - var newURI = proto.fsHandler.prototype.newURI('fs://ipfs/' + ipfsPath, 'utf8', null); + var newURI = fsHandler.newURI('fs://ipfs/' + ipfsPath, 'utf8', null); assert.equal(newURI.spec, pubGwUri.spec + 'ipfs/' + ipfsPath, 'newURI spec'); }; exports['test newURI(fs:///ipfs/)'] = function(assert) { - var newURI = proto.fsHandler.prototype.newURI('fs:///ipfs/' + ipfsPath, 'utf8', null); + var newURI = fsHandler.newURI('fs:///ipfs/' + ipfsPath, 'utf8', null); assert.equal(newURI.spec, pubGwUri.spec + 'ipfs/' + ipfsPath, 'newURI spec'); }; exports['test newURI(fs:ipns/)'] = function(assert) { - var newURI = proto.fsHandler.prototype.newURI('fs:ipns/' + ipnsPath, 'utf8', null); + var newURI = fsHandler.newURI('fs:ipns/' + ipnsPath, 'utf8', null); assert.equal(newURI.spec, pubGwUri.spec + 'ipns/' + ipnsPath, 'newURI spec'); }; exports['test newURI(fs:/ipns/)'] = function(assert) { - var newURI = proto.fsHandler.prototype.newURI('fs:/ipns/' + ipnsPath, 'utf8', null); + var newURI = fsHandler.newURI('fs:/ipns/' + ipnsPath, 'utf8', null); assert.equal(newURI.spec, pubGwUri.spec + 'ipns/' + ipnsPath, 'newURI spec'); }; exports['test newURI(fs://ipns/)'] = function(assert) { - var newURI = proto.fsHandler.prototype.newURI('fs://ipns/' + ipnsPath, 'utf8', null); + var newURI = fsHandler.newURI('fs://ipns/' + ipnsPath, 'utf8', null); assert.equal(newURI.spec, pubGwUri.spec + 'ipns/' + ipnsPath, 'newURI spec'); }; exports['test newURI(fs:///ipns/)'] = function(assert) { - var newURI = proto.fsHandler.prototype.newURI('fs:///ipns/' + ipnsPath, 'utf8', null); + var newURI = fsHandler.newURI('fs:///ipns/' + ipnsPath, 'utf8', null); + assert.equal(newURI.spec, pubGwUri.spec + 'ipns/' + ipnsPath, 'newURI spec'); +}; + +// web+ variant (https://github.com/lidel/ipfs-firefox-addon/issues/36) +exports['test newURI(web+fs:ipfs/)'] = function(assert) { + var newURI = webFsHandler.newURI('web+fs:ipfs/' + ipfsPath, 'utf8', null); + assert.equal(newURI.spec, pubGwUri.spec + 'ipfs/' + ipfsPath, 'newURI spec'); +}; + +exports['test newURI(web+fs:/ipfs/)'] = function(assert) { + var newURI = webFsHandler.newURI('web+fs:/ipfs/' + ipfsPath, 'utf8', null); + assert.equal(newURI.spec, pubGwUri.spec + 'ipfs/' + ipfsPath, 'newURI spec'); +}; + +exports['test newURI(web+fs://ipfs/)'] = function(assert) { + var newURI = webFsHandler.newURI('web+fs://ipfs/' + ipfsPath, 'utf8', null); + assert.equal(newURI.spec, pubGwUri.spec + 'ipfs/' + ipfsPath, 'newURI spec'); +}; + +exports['test newURI(web+fs:///ipfs/)'] = function(assert) { + var newURI = webFsHandler.newURI('web+fs:///ipfs/' + ipfsPath, 'utf8', null); + assert.equal(newURI.spec, pubGwUri.spec + 'ipfs/' + ipfsPath, 'newURI spec'); +}; + +exports['test newURI(web+fs:ipns/)'] = function(assert) { + var newURI = webFsHandler.newURI('web+fs:ipns/' + ipnsPath, 'utf8', null); assert.equal(newURI.spec, pubGwUri.spec + 'ipns/' + ipnsPath, 'newURI spec'); }; +exports['test newURI(web+fs:/ipns/)'] = function(assert) { + var newURI = webFsHandler.newURI('web+fs:/ipns/' + ipnsPath, 'utf8', null); + assert.equal(newURI.spec, pubGwUri.spec + 'ipns/' + ipnsPath, 'newURI spec'); +}; + +exports['test newURI(web+fs://ipns/)'] = function(assert) { + var newURI = webFsHandler.newURI('web+fs://ipns/' + ipnsPath, 'utf8', null); + assert.equal(newURI.spec, pubGwUri.spec + 'ipns/' + ipnsPath, 'newURI spec'); +}; + +exports['test newURI(web+fs:///ipns/)'] = function(assert) { + var newURI = webFsHandler.newURI('web+fs:///ipns/' + ipnsPath, 'utf8', null); + assert.equal(newURI.spec, pubGwUri.spec + 'ipns/' + ipnsPath, 'newURI spec'); +}; + + require('sdk/test').run(exports);