Skip to content

Commit

Permalink
fix e10s compat by registering protocol handler in child process too
Browse files Browse the repository at this point in the history
  • Loading branch information
the8472 committed Dec 15, 2015
1 parent e7cd8b9 commit 7948b6a
Show file tree
Hide file tree
Showing 9 changed files with 160 additions and 90 deletions.
2 changes: 1 addition & 1 deletion Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ module.exports = function(grunt) {
jshint: {
all: paths,
options: {
'esnext': true,
'jquery': true,
'quotmark': 'single',
'white': true,
'indent': 2,
'latedef': true,
Expand Down
15 changes: 15 additions & 0 deletions lib/child-main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
'use strict';

const proto = require("./protocols.js");

proto.fs.register();
proto.ipfs.register();
proto.ipns.register();

// $0.insertAdjacentHTML('beforeend', `<a href="ipfs://QmXudYwpCqUk77HissMhowbAatLUQyxNAHKWzyFhBfkGaX">foo</a>`)

require("sdk/system/unload").when(() => {
proto.fs.unregister();
proto.ipfs.unregister();
proto.ipns.unregister();
});
75 changes: 25 additions & 50 deletions lib/gateways.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ var {
Cc, Ci
} = require('chrome');

var cm = require('sdk/context-menu');

var prefs = require('sdk/simple-prefs').prefs;
var ioservice = Cc['@mozilla.org/network/io-service;1'].getService(Ci.nsIIOService);
var gui = require('./gui.js');

const IPFS_RESOURCE = /^https?:\/\/[^\/]+\/ip(f|n)s\//;

exports.IPFS_RESOURCE = IPFS_RESOURCE;

var PUBLIC_GATEWAY_HOSTS; // getPublicGatewayHostsRegex()
var PUBLIC_GATEWAY_URI; // getDefaultPublicURI();
var CUSTOM_GATEWAY_URI;
Expand All @@ -36,33 +38,7 @@ function getPublicGatewayHostsRegex() {
}


var ipfsRequestObserver = {
observe: function(subject, topic, data) { // jshint unused:false
if (topic == 'http-on-modify-request') {
let channel = subject.QueryInterface(Ci.nsIHttpChannel);
let httpUrl = channel.URI.spec;
if (httpUrl.match(PUBLIC_GATEWAY_HOSTS) && httpUrl.match(IPFS_RESOURCE)) {
channel.setRequestHeader('x-ipfs-firefox-addon', 'true', false);
if (prefs.useCustomGateway) {
//console.info('Detected HTTP request to the public gateway: ' + channel.URI.spec);
let uri = ioservice.newURI(httpUrl.replace(PUBLIC_GATEWAY_HOSTS, CUSTOM_GATEWAY_URI.spec), null, null);
//console.info('Redirecting to custom gateway: ' + uri.spec);
channel.redirectTo(uri);
}
}
}
},
get observerService() {
return Cc['@mozilla.org/observer-service;1'].getService(Ci.nsIObserverService);
},
register: function() {
this.observerService.addObserver(this, 'http-on-modify-request', false);
},

unregister: function() {
this.observerService.removeObserver(this, 'http-on-modify-request');
}
};
const callbacks = [];

function reloadCachedProperties(changedProperty) { // jshint unused:false
// public gateways
Expand All @@ -72,35 +48,34 @@ function reloadCachedProperties(changedProperty) { // jshint unused:false
// custom gateway
CUSTOM_GATEWAY_URI = ioservice.newURI('http://' + prefs.customGatewayHost + ':' + prefs.customGatewayPort, null, null);

// context menus
let menuContexts = gui.getMenuItemsContexts();
for (var i = 0; i < menuContexts.length; i++) {
let context = menuContexts[i];
context.add(cm.URLContext(CUSTOM_GATEWAY_URI.spec + '*'));
}
callbacks.forEach((c) => c());
}

function enableHttpGatewayRedirect(button) {
reloadCachedProperties();
prefs.useCustomGateway = true;
ipfsRequestObserver.register();
require('sdk/simple-prefs').on('', reloadCachedProperties);
if (button) button.state(button, gui.toggleStateEnabled);
}
require('sdk/simple-prefs').on('', reloadCachedProperties);
reloadCachedProperties();

function disableHttpGatewayRedirect(button) {
if (prefs.useCustomGateway) ipfsRequestObserver.unregister();
prefs.useCustomGateway = false;
require('sdk/simple-prefs').removeListener('', reloadCachedProperties);
if (button) button.state(button, gui.toggleStateDisabled);

function isEnabled() {
return prefs.useCustomGateway;
}

exports.ipfsRequestObserver = ipfsRequestObserver;
exports.enableHttpGatewayRedirect = enableHttpGatewayRedirect;
exports.disableHttpGatewayRedirect = disableHttpGatewayRedirect;
exports.isEnabled = isEnabled;

exports.toggle = function(val) {
prefs.useCustomGateway = !!val;
};


exports.onChange = (f) => {
callbacks.push(f);
};

exports.customUri = function() {
return CUSTOM_GATEWAY_URI;
};
exports.publicUri = function() {
return PUBLIC_GATEWAY_URI;
};
exports.publicHosts = function() {
return PUBLIC_GATEWAY_HOSTS;
};
54 changes: 35 additions & 19 deletions lib/gui.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ var {
var cm = require('sdk/context-menu');
var clipboard = require('sdk/clipboard');
var l10n = require('sdk/l10n').get;
var prefs = require('sdk/simple-prefs').prefs;
var gw = require('./gateways.js');

var {
ToggleButton
} = require('sdk/ui/button/toggle');

exports.toggleStateEnabled = {
const ON_STATE = {
checked: true,
icon: {
'16': './icon-on-16.png',
Expand All @@ -23,7 +23,7 @@ exports.toggleStateEnabled = {
badgeColor: '#4A9EA1'
};

exports.toggleStateDisabled = {
const OFF_STATE = {
checked: false,
icon: {
'16': './icon-off-16.png',
Expand All @@ -34,31 +34,40 @@ exports.toggleStateDisabled = {
badgeColor: '#8C8C8C'
};

exports.toggleButton = new ToggleButton({
let supressRecursion = false;

const button = new ToggleButton({
id: 'ipfs-gateway-status',
label: l10n('toggle_button_label'),
icon: {
'16': './icon-on-16.png',
'32': './icon-on-32.png',
'64': './icon-on-64.png'
},
checked: prefs.useCustomGateway,
checked: gw.isEnabled(),
onChange: function(state) { // jshint unused:false
// we want a global flag
this.state('window', null);
this.checked = !this.checked;

// update GUI to reflect toggled state
if (this.checked) {
gw.enableHttpGatewayRedirect(this);
} else {
gw.disableHttpGatewayRedirect(this);
}
//console.info('prefs.useCustomGateway: ' + prefs.useCustomGateway);
if (supressRecursion)
return;
supressRecursion = true;
toggle(state.checked);
supressRecursion = false;
}

});

exports.toggleButton = button;


function toggle(val) {
let newState = val ? ON_STATE : OFF_STATE;

Object.keys(newState).forEach((k) => {
button[k] = newState[k];
});

gw.toggle(val);
}



const COPY_IPFS_ADDRESS = cm.Item({
Expand Down Expand Up @@ -90,6 +99,13 @@ cm.Menu({
items: [COPY_IPFS_ADDRESS, COPY_PUBLIC_HTTP_URL]
});

exports.getMenuItemsContexts = function() {
return [COPY_PUBLIC_HTTP_URL.context, COPY_IPFS_ADDRESS.context];
};

gw.onChange(() => {
for (let ctx of[COPY_PUBLIC_HTTP_URL.context, COPY_IPFS_ADDRESS.context]) {
let url = gw.customUri().spec + '*';
ctx.add(cm.URLContext(url));
}
toggle(gw.isEnabled());
});

toggle(gw.isEnabled());
10 changes: 6 additions & 4 deletions lib/main.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
'use strict';

var gui = require('./gui.js');
var gw = require('./gateways.js');
require('./gui.js');
require('./gateways.js');
var proto = require('./protocols.js');

const parent = require('sdk/remote/parent');


exports.main = function(options, callbacks) { // jshint unused:false
gw.enableHttpGatewayRedirect(gui.toggleButton);
require('./redirects.js');
proto.fs.register();
proto.ipfs.register();
proto.ipns.register();
//console.log('Addon loaded.');
parent.remoteRequire("./lib/child-main.js");
};

exports.onUnload = function(reason) { // jshint unused:false
gw.disableHttpGatewayRedirect();
proto.fs.unregister();
proto.ipfs.unregister();
proto.ipns.unregister();
Expand Down
9 changes: 7 additions & 2 deletions lib/protocols.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,17 @@ function factory(ProtocolHandler) {
register: function() {
let m = Cm.QueryInterface(Ci.nsIComponentRegistrar);
let p = ProtocolHandler.prototype;
m.registerFactory(p.classID, p.classDescription, p.contractID, this);
if (!m.isContractIDRegistered(p.contractID)) {
m.registerFactory(p.classID, p.classDescription, p.contractID, this);
}
//console.info('Protocol Handler registered: ' + ProtocolHandler.prototype.scheme);
},
unregister: function() {
let m = Cm.QueryInterface(Ci.nsIComponentRegistrar);
m.unregisterFactory(ProtocolHandler.prototype.classID, this);
let p = ProtocolHandler.prototype;
if (!m.isContractIDRegistered(p.contractID)) {
m.unregisterFactory(p.classID, this);
}
//console.info('Protocol Handler unregistered: ' + ProtocolHandler.prototype.scheme);
},
});
Expand Down
59 changes: 59 additions & 0 deletions lib/redirects.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
'use strict';

const gw = require('./gateways');
var prefs = require('sdk/simple-prefs').prefs;

var {
Cc, Ci
} = require('chrome');

var ioservice = Cc['@mozilla.org/network/io-service;1'].getService(Ci.nsIIOService);

var ipfsRequestObserver = {
observe: function(subject, topic, data) { // jshint unused:false
if (topic == 'http-on-modify-request') {
let channel = subject.QueryInterface(Ci.nsIHttpChannel);
let httpUrl = channel.URI.spec;
if (httpUrl.match(gw.publicHosts()) && httpUrl.match(gw.IPFS_RESOURCE)) {
channel.setRequestHeader('x-ipfs-firefox-addon', 'true', false);
if (prefs.useCustomGateway) {
//console.info('Detected HTTP request to the public gateway: ' + channel.URI.spec);
let uri = ioservice.newURI(httpUrl.replace(gw.publicHosts(), gw.customUri().spec), null, null);
//console.info('Redirecting to custom gateway: ' + uri.spec);
channel.redirectTo(uri);
}
}
}
},
get observerService() {
return Cc['@mozilla.org/observer-service;1'].getService(Ci.nsIObserverService);
},
register: function() {
if (this.registered)
return;
this.registered = true;
this.observerService.addObserver(this, 'http-on-modify-request', false);
},

unregister: function() {
if (!this.registered)
return;
this.registered = false;
this.observerService.removeObserver(this, 'http-on-modify-request');
}
};

gw.onChange(() => {
if (gw.isEnabled()) {
ipfsRequestObserver.register();
} else {
ipfsRequestObserver.unregister();
}
});


exports.on = ipfsRequestObserver.register;
exports.off = ipfsRequestObserver.unregister;


exports.ipfsRequestObserver = ipfsRequestObserver;
Loading

0 comments on commit 7948b6a

Please sign in to comment.