Skip to content

Instantly share code, notes, and snippets.

@piroor
Created September 26, 2018 09:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save piroor/77f375ee4598aceb1ebb18dcb32fda0c to your computer and use it in GitHub Desktop.
Save piroor/77f375ee4598aceb1ebb18dcb32fda0c to your computer and use it in GitHub Desktop.
Register security exception automatically on the startup of Firefox ESR60
// the first line is always ignored by Firefox.
const autoAcceptExceptionFor = (host, port = 443) => {
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
const exceptionURL = port == 443 ? `https://${host}` : `https://${host}:${port}`;
const { Services } = Cu.import('resource://gre/modules/Services.jsm', {});
const observer = {
observe(aSubject, aTopic, aData) {
switch (aTopic) {
case 'domwindowopened':
if (!aSubject.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell)
.QueryInterface(Ci.nsIDocShellTreeNode || Ci.nsIDocShellTreeItem) // nsIDocShellTreeNode is merged to nsIDocShellTreeItem by https://bugzilla.mozilla.org/show_bug.cgi?id=331376
.QueryInterface(Ci.nsIDocShellTreeItem)
.parent) {
const win = aSubject.QueryInterface(Ci.nsIDOMWindow);
win.addEventListener('load', () => tryHandleWindow(win), { once: true });
}
return;
}
},
QueryInterface(aIID) {
if (!aIID.equals(Ci.nsIObserver) &&
!aIID.equals(Ci.nsISupports)) {
throw Components.results.NS_ERROR_NO_INTERFACE;
}
return this;
}
};
const waitUntilEventOrTimeout = (target, type, timeout) => {
return new Promise((resolve, reject) => {
const win = (target.ownerDocument || target).defaultView || target;
const listener = () => {
target.removeEventListener(type, listener);
win.clearTimeout(timer);
resolve();
};
const timer = win.setTimeout(listener, timeout);
target.addEventListener(type, listener);
});
};
const WW = Cc['@mozilla.org/embedcomp/window-watcher;1'].getService(Ci.nsIWindowWatcher);
const teardown = () => {
WW.unregisterNotification(observer);
if (tab)
tab.ownerDocument.defaultView.gBrowser.removeTab(tab);
};
let tab;
const steps = [
{ url: 'chrome://browser/content/browser.xul',
onOpen: async (win) => {
await new Promise((resolve, reject) => {
win.addEventListener('MozAfterPaint', resolve, { once: true });
});
const certOverride = Cc['@mozilla.org/security/certoverride;1'].getService(Ci.nsICertOverrideService);
const hash = {}, fingerprint = {}, flags = {}, temporary = {};
if (!certOverride ||
(certOverride.getValidityOverride &&
certOverride.getValidityOverride(host, port, hash, fingerprint, flags, temporary))) {
teardown();
return;
}
win.openNewTabWith(exceptionURL);
const tabs = win.gBrowser.tabs;
tab = tabs[tabs.length-1];
await new Promise((resolve, reject) => {
const listener = (event) => {
if (event.detail.changed == 'busy' &&
tab.getAttribute('busy') != 'true') {
tab.removeEventListener('TabAttrModified', listener);
resolve();
}
};
tab.addEventListener('TabAttrModified', listener);
});
const browser = tab.linkedBrowser;
browser.messageManager.loadFrameScript('data:text/javascript,(' + (async (waitUntilEventOrTimeout) => {
const doc = docShell.QueryInterface(Components.interfaces.nsIWebNavigation).document;
const win = doc.defaultView;
await waitUntilEventOrTimeout(doc, 'AboutNetErrorLoad', 500);
const advancedButton = doc.getElementById('advancedButton');
if (advancedButton) {
advancedButton.dispatchEvent(new win.MouseEvent('click', { button: 0 }));
const exceptionDialogButton = doc.getElementById('exceptionDialogButton');
if (exceptionDialogButton) {
exceptionDialogButton.dispatchEvent(new win.MouseEvent('click', { button: 0 }));
return; /* success case, go to next step: exceptionDialog */
}
}
/* failure case */
teardown();
}).toSource() + ')(' + waitUntilEventOrTimeout.toSource() + ')', false, false);
} },
{ url: 'chrome://pippki/content/exceptionDialog.xul',
onOpen: async (win) => {
win.addEventListener('unload', teardown, { once: true });
await waitUntilEventOrTimeout(win, 'load', 200);
const timer = win.setInterval(() => {
if (!win.gCert || win.gChecking)
return;
win.clearInterval(timer);
win.document.documentElement.getButton('extra1').click();
}, 100);
} }
];
const tryHandleWindow = (win) => {
const step = steps[0];
if (!step || step.url != win.location.href)
return;
step.onOpen(win);
steps.shift();
};
WW.registerNotification(observer);
};
autoAcceptExceptionFor('hostname', 8080);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment