Created
September 26, 2018 09:34
-
-
Save piroor/77f375ee4598aceb1ebb18dcb32fda0c to your computer and use it in GitHub Desktop.
Register security exception automatically on the startup of Firefox ESR60
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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