mirror of
https://github.com/moparisthebest/FireTray
synced 2024-12-21 21:48:47 -05:00
Initial commit (skeleton extension derived from SkipCertError)
This commit is contained in:
commit
f5e6b887bc
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
bin/
|
19
src/LICENSE
Normal file
19
src/LICENSE
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright (C) 2011 Foudil Brétel <foudil.newbie+amo@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should be able to obtain a copy of the GNU General Public License from
|
||||
http://www.gnu.org/licenses/gpl.txt; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
***
|
||||
|
||||
This extension is a complete re-write of NewMitMMe (Andras TIM -
|
||||
andras.tim@gmail.com, andras.tim@balabit.hu) and MitMMe (Johnathan Nightingale)
|
186
src/Makefile
Executable file
186
src/Makefile
Executable file
@ -0,0 +1,186 @@
|
||||
.PHONY: help
|
||||
help:
|
||||
@echo "BUILD/INSTALL INSTRUCTIONS"
|
||||
@echo
|
||||
@echo "to build Moztray, just:"
|
||||
@echo " make all"
|
||||
@echo
|
||||
@echo "by default, debug calls are stripped from js files and DEBUG_MODE"
|
||||
@echo "is off (performance). If you want to keep debug calls:"
|
||||
@echo " DEBUG=on make all"
|
||||
@echo
|
||||
@echo "to create the dev profile:"
|
||||
@echo " firefox -no-remote -P # then create '$(profile_dir)'"
|
||||
@echo
|
||||
@echo "to deploy to dev profile:"
|
||||
@echo " make clean"
|
||||
@echo " make install"
|
||||
@echo
|
||||
@echo "to test with dev profile:"
|
||||
@echo " firefox -no-remote -P mozilla-dev"
|
||||
@echo
|
||||
@echo "Have fun !"
|
||||
|
||||
# The UUID of the extension.
|
||||
extension_uuid := moztray@foudil.fr
|
||||
|
||||
# The name of the profile dir where the extension can be installed.
|
||||
profile_dir := mozilla-dev
|
||||
|
||||
# The zip application to be used.
|
||||
ZIP := zip
|
||||
|
||||
# The target location of the build and build files.
|
||||
build_dir := ../build
|
||||
|
||||
# The type of operating system this make command is running on.
|
||||
# os_type := $(patsubst darwin%,darwin,$(shell echo $(OSTYPE)))
|
||||
# we don't want to: export OSTYPE; make install
|
||||
os_type := $(patsubst darwin%,darwin,$(shell echo $$OSTYPE))
|
||||
|
||||
# The location of the extension profile.
|
||||
ifeq ($(os_type), darwin)
|
||||
profile_location := \
|
||||
~/Library/Application\ Support/Firefox/Profiles/$(profile_dir)/extensions
|
||||
else
|
||||
ifeq ($(os_type), linux-gnu)
|
||||
profile_location := \
|
||||
~/.mozilla/firefox/$(profile_dir)/extensions
|
||||
else
|
||||
profile_location := \
|
||||
"$(subst \,\\,$(APPDATA))\\Mozilla\\Firefox\\Profiles\\$(profile_dir)\\extensions"
|
||||
endif
|
||||
endif
|
||||
|
||||
# The license file
|
||||
license := LICENSE
|
||||
|
||||
# The install.rdf file.
|
||||
install_rdf := install.rdf
|
||||
|
||||
# Version fetched from install.rdf
|
||||
VERSION := $(shell awk '/<em:version>/ { version=$$1; \
|
||||
version=gensub(/<em:version>(.+)<\/em:version>/, "\\1", "g", version); \
|
||||
print version }' $(install_rdf))
|
||||
|
||||
# The target XPI files.
|
||||
xpi_file := $(extension_uuid)-$(VERSION).xpi
|
||||
xpi_built := $(build_dir)/$(xpi_file)
|
||||
# Since we use <em:unpack>false, we need the same name across versions
|
||||
xpi_deployed := $(extension_uuid).xpi
|
||||
|
||||
# The chrome.manifest file.
|
||||
chrome_manifest := chrome.manifest
|
||||
|
||||
# The preferences dir.
|
||||
preferences_dir := defaults/preferences
|
||||
|
||||
# The root of the chrome sources.
|
||||
chrome_source_root := chrome
|
||||
|
||||
# The chrome sources.
|
||||
chrome_sources_js := $(wildcard $(chrome_source_root)/content/*.js)
|
||||
chrome_sources := $(chrome_sources_js) \
|
||||
$(wildcard $(chrome_source_root)/content/*.xul) \
|
||||
$(wildcard $(chrome_source_root)/content/*.xml) \
|
||||
$(wildcard $(chrome_source_root)/content/*.css) \
|
||||
$(wildcard $(chrome_source_root)/skin/*.css) \
|
||||
$(wildcard $(chrome_source_root)/skin/*.png) \
|
||||
$(wildcard $(chrome_source_root)/locale/*/*.dtd) \
|
||||
$(wildcard $(chrome_source_root)/locale/*/*.properties)
|
||||
|
||||
# The modules (JSM) dir.
|
||||
modules_dir := modules
|
||||
|
||||
# The sources for the module files.
|
||||
modules_sources := $(wildcard $(modules_dir)/*.js)
|
||||
|
||||
# The sources for the XPI file. Uses variables defined in the included
|
||||
# Makefiles.
|
||||
xpi_includes := $(license) \
|
||||
$(install_rdf) \
|
||||
$(chrome_manifest) \
|
||||
$(preferences_dir)/prefs.js \
|
||||
$(chrome_sources) \
|
||||
$(modules_sources)
|
||||
|
||||
# Destination files
|
||||
build_includes := $(foreach f,$(xpi_includes),$(build_dir)/$(f))
|
||||
|
||||
|
||||
$(xpi_built): $(build_dir) $(build_includes)
|
||||
@echo "Creating XPI file."
|
||||
@cd $(build_dir); $(ZIP) $(xpi_file) $(xpi_includes)
|
||||
@echo "Creating XPI file. Done!"
|
||||
|
||||
# This builds the extension XPI file.
|
||||
.PHONY: all
|
||||
all: $(xpi_built)
|
||||
@echo
|
||||
@echo "Build finished successfully."
|
||||
@echo
|
||||
|
||||
# This cleans all temporary files and directories created by 'make'.
|
||||
.PHONY: clean
|
||||
clean: clean_build clean_profile
|
||||
@echo "Cleanup is done."
|
||||
|
||||
# This builds everything except for the actual XPI, and then it copies it to the
|
||||
# specified profile directory, allowing a quick update that requires no install.
|
||||
.PHONY: install
|
||||
install: $(xpi_built) $(profile_location)
|
||||
@echo "Installing in profile folder: $(profile_location)"
|
||||
@cp -f $(xpi_built) $(profile_location)/$(xpi_deployed)
|
||||
@echo "Installing in profile folder. Done!"
|
||||
@echo
|
||||
|
||||
# Regex for 'no'
|
||||
YES_RE := yes|y|Y|true|on
|
||||
|
||||
# called via $(build_includes)
|
||||
$(build_dir)/%: %
|
||||
@mkdir -p $(dir $@)
|
||||
@cp -f $< $@
|
||||
|
||||
# Debug calls are removed for performance.
|
||||
# NOTE: we could also use m4 for filtering source files...
|
||||
$(build_dir)/$(chrome_source_root)/%.js: $(chrome_source_root)/%.js
|
||||
@mkdir -p $(dir $@)
|
||||
@if [[ "$(DEBUG)" =~ $(YES_RE) ]]; \
|
||||
then \
|
||||
cp -f $< $@; \
|
||||
else \
|
||||
echo "Stripping comments from JS file $<"; \
|
||||
sed '/mozt\.Debug\.dump/d' $< > $@; \
|
||||
fi
|
||||
|
||||
$(build_dir)/$(modules_dir)/commons.js: $(modules_dir)/commons.js
|
||||
@mkdir -p $(dir $@)
|
||||
@if [[ "$(DEBUG)" =~ $(YES_RE) ]]; \
|
||||
then \
|
||||
cp -f $< $@; \
|
||||
else \
|
||||
echo "Turning DEBUG_MODE off."; \
|
||||
sed 's/DEBUG_MODE: true/DEBUG_MODE: false/' $< > $@; \
|
||||
fi
|
||||
|
||||
$(build_dir):
|
||||
@if [ ! -x $(build_dir) ]; \
|
||||
then \
|
||||
mkdir -p $(build_dir); \
|
||||
fi
|
||||
|
||||
$(profile_location):
|
||||
@echo "Creating extension folder: $(profile_location)"
|
||||
@if [ ! -x $(profile_location) ]; \
|
||||
then \
|
||||
mkdir -p $(profile_location); \
|
||||
fi
|
||||
|
||||
clean_build:
|
||||
@echo "Removing build dir: $(build_dir)"
|
||||
@rm -rf $(build_dir)
|
||||
|
||||
clean_profile:
|
||||
@echo "Removing extension from extension folder: $(profile_location)"
|
||||
@rm -f $(profile_location)/$(xpi_deployed)
|
6
src/chrome.manifest
Normal file
6
src/chrome.manifest
Normal file
@ -0,0 +1,6 @@
|
||||
content mozt chrome/content/
|
||||
skin mozt classic/1.0 chrome/skin/
|
||||
locale mozt en-US chrome/locale/en-US/
|
||||
resource mozt modules/
|
||||
|
||||
overlay chrome://browser/content/browser.xul chrome://mozt/content/overlay.xul
|
44
src/chrome/content/options.js
Normal file
44
src/chrome/content/options.js
Normal file
@ -0,0 +1,44 @@
|
||||
/* -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
|
||||
Components.utils.import("resource://sce/commons.js");
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
mozt.UIOptions = {
|
||||
|
||||
onLoad: function() {
|
||||
this.toggleDisable_All(mozt.Utils.prefService.getBoolPref('enabled'));
|
||||
this.toggleCheck_BypassIssuerUnknown(
|
||||
document.getElementById('ui_bypass_self_signed').checked);
|
||||
},
|
||||
|
||||
toggleDisable_All: function(enabledChecked) {
|
||||
document.getElementById('ui_add_temporary_exceptions').disabled = !enabledChecked;
|
||||
document.getElementById('ui_notify').disabled = !enabledChecked;
|
||||
this.toggleDisable_BypassErrors(enabledChecked);
|
||||
},
|
||||
|
||||
toggleDisable_BypassErrors: function(checked) {
|
||||
var certErrorCondChildren = document.getElementById('ui_bypass_errors')
|
||||
.childNodes;
|
||||
for (var i = 0; i < certErrorCondChildren.length; i++) {
|
||||
var node = certErrorCondChildren[i];
|
||||
node.disabled = !checked;
|
||||
}
|
||||
|
||||
if (checked)
|
||||
this.toggleCheck_BypassIssuerUnknown(
|
||||
document.getElementById('ui_bypass_self_signed').checked);
|
||||
},
|
||||
|
||||
toggleCheck_BypassIssuerUnknown: function(selfSignedChecked) {
|
||||
if (selfSignedChecked) {
|
||||
document.getElementById('ui_bypass_issuer_unknown').checked = selfSignedChecked;
|
||||
document.getElementById('ui_bypass_issuer_unknown').disabled = true;
|
||||
} else {
|
||||
document.getElementById('ui_bypass_issuer_unknown').disabled = false;
|
||||
}
|
||||
},
|
||||
|
||||
};
|
56
src/chrome/content/options.xul
Normal file
56
src/chrome/content/options.xul
Normal file
@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
<!DOCTYPE prefwindow SYSTEM "chrome://sce/locale/options.dtd">
|
||||
<prefwindow id="sce-preferences"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
title="&prefwindow.title;"
|
||||
onload= "mozt.UIOptions.onLoad()">
|
||||
|
||||
<script type="application/x-javascript" src="options.js" />
|
||||
|
||||
<prefpane id="pane1" label="&pane1.title;">
|
||||
|
||||
<preferences>
|
||||
<preference id="pref_bool_enabled"
|
||||
name="extensions.mozt.enabled" type="bool"/>
|
||||
<preference id="pref_bool_add_temporary_exceptions"
|
||||
name="extensions.mozt.add_temporary_exceptions" type="bool"/>
|
||||
<preference id="pref_bool_notify"
|
||||
name="extensions.mozt.notify" type="bool"/>
|
||||
<preference id="pref_bool_bypass_issuer_unknown"
|
||||
name="extensions.mozt.bypass_issuer_unknown" type="bool"/>
|
||||
<preference id="pref_bool_bypass_self_signed"
|
||||
name="extensions.mozt.bypass_self_signed" type="bool"/>
|
||||
</preferences>
|
||||
|
||||
<groupbox>
|
||||
<caption>
|
||||
<checkbox id="ui_enabled" preference="pref_bool_enabled"
|
||||
label="&bool_enabled.label;"
|
||||
accesskey="&bool_enabled.accesskey;"
|
||||
onclick="mozt.UIOptions.toggleDisable_All(!this.checked); // checked=before click"/>
|
||||
</caption>
|
||||
<checkbox id="ui_add_temporary_exceptions"
|
||||
preference="pref_bool_add_temporary_exceptions"
|
||||
label="&bool_add_temporary_exceptions.label;"
|
||||
accesskey="&bool_add_temporary_exceptions.accesskey;"/>
|
||||
<checkbox id="ui_notify" preference="pref_bool_notify"
|
||||
label="&bool_notify.label;"
|
||||
accesskey="&bool_notify.accesskey;"/>
|
||||
<groupbox id="ui_bypass_errors">
|
||||
<caption label="&bypass_errors;"/>
|
||||
<checkbox id="ui_bypass_issuer_unknown"
|
||||
preference="pref_bool_bypass_issuer_unknown"
|
||||
label="&bool_bypass_issuer_unknown.label;"
|
||||
accesskey="&bool_bypass_issuer_unknown.accesskey;"/>
|
||||
<checkbox id="ui_bypass_self_signed"
|
||||
preference="pref_bool_bypass_self_signed"
|
||||
label="&bool_bypass_self_signed.label;"
|
||||
accesskey="&bool_bypass_self_signed.accesskey;"
|
||||
onclick="mozt.UIOptions.toggleCheck_BypassIssuerUnknown(!this.checked);"/>
|
||||
</groupbox>
|
||||
</groupbox>
|
||||
|
||||
</prefpane>
|
||||
|
||||
</prefwindow>
|
407
src/chrome/content/overlay.js
Normal file
407
src/chrome/content/overlay.js
Normal file
@ -0,0 +1,407 @@
|
||||
/* -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
|
||||
/*
|
||||
* GLOBAL APPROACH:
|
||||
*
|
||||
* since we can't avoid the about:certerr page (1), and can't shortcut the
|
||||
* internal request to about:certerr gracefully (2), we:
|
||||
*
|
||||
* - add the cert exception
|
||||
* - wait for the full load of the about:certerr page (that's the tricky part)
|
||||
* - load the initially requested URL
|
||||
*
|
||||
* (1) certerror is hardly avoidable since it may be displayed whenever a
|
||||
* newsocket is created, see: nsNSSIOLayer.cpp: dialogs->ShowCertError,
|
||||
* nsNSSBadCertHandler, nsSSLIOLayerNewSocket,
|
||||
* ./netwerk/base/src/nsSocketTransport2.cpp
|
||||
*
|
||||
* (2) a raw reload of the requested https page works, but is not very clean
|
||||
* since it shortcuts the internal request to about:certerr, and produces a
|
||||
* harmless *no element found* error (displayed shortly and not too noticeable
|
||||
* though)
|
||||
*/
|
||||
|
||||
Components.utils.import("resource://sce/commons.js");
|
||||
|
||||
mozt.Main = {
|
||||
|
||||
onLoad: function() {
|
||||
// initialization code
|
||||
this.initialized = null;
|
||||
this.strings = document.getElementById("sce-strings");
|
||||
this.overrideService = null;
|
||||
this.recentCertsService = null;
|
||||
this.notification = {};
|
||||
this.stash = {};
|
||||
|
||||
try {
|
||||
// Set up preference change observer
|
||||
mozt.Utils.prefService.QueryInterface(Ci.nsIPrefBranch2);
|
||||
// must stay out of _toggle()
|
||||
mozt.Utils.prefService.addObserver("", this, false);
|
||||
|
||||
// Get cert services
|
||||
this.overrideService =
|
||||
Cc["@mozilla.org/security/certoverride;1"]
|
||||
.getService(Components.interfaces.nsICertOverrideService);
|
||||
this.recentCertsService = Cc["@mozilla.org/security/recentbadcerts;1"]
|
||||
.getService(Ci.nsIRecentBadCertsService);
|
||||
}
|
||||
catch (ex) {
|
||||
Components.utils.reportError(ex);
|
||||
return false;
|
||||
}
|
||||
|
||||
var enabled = mozt.Utils.prefService.getBoolPref('enabled');
|
||||
mozt.Debug.dump('enabled: '+enabled);
|
||||
if (enabled)
|
||||
this._toggle(true);
|
||||
|
||||
mozt.Debug.dump('SkipCertError LOADED !');
|
||||
this.initialized = true;
|
||||
return true;
|
||||
},
|
||||
|
||||
onQuit: function() {
|
||||
// Remove observer
|
||||
mozt.Utils.prefService.removeObserver("", this);
|
||||
|
||||
this._toogle(false);
|
||||
|
||||
mozt.Debug.dump('SkipCertError UNLOADED !');
|
||||
this.initialized = false;
|
||||
},
|
||||
|
||||
// since we are using a TabsProgressListener, it seems we do not need to keep
|
||||
// track of WebProgressListeners as indicated on
|
||||
// https://developer.mozilla.org/en/XUL_School/Intercepting_Page_Loads#WebProgressListeners
|
||||
_toggle: function (enable) {
|
||||
mozt.Debug.dump('toggle: '+enable);
|
||||
try {
|
||||
if (enable) {
|
||||
gBrowser.addTabsProgressListener(this.TabsProgressListener);
|
||||
} else {
|
||||
gBrowser.removeTabsProgressListener(this.TabsProgressListener);
|
||||
}
|
||||
} catch (ex) {
|
||||
Components.utils.reportError(ex);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
observe: function(subject, topic, data) {
|
||||
// Observer for pref changes
|
||||
if (topic != "nsPref:changed") return;
|
||||
mozt.Debug.dump('Pref changed: '+data);
|
||||
|
||||
switch(data) {
|
||||
case 'enabled':
|
||||
var enable = mozt.Utils.prefService.getBoolPref('enabled');
|
||||
this._toggle(enable);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
_getCertException: function(uri, cert) {
|
||||
var outFlags = {};
|
||||
var outTempException = {};
|
||||
var knownCert = mozt.Main.overrideService.hasMatchingOverride(
|
||||
uri.asciiHost,
|
||||
uri.port,
|
||||
cert,
|
||||
outFlags,
|
||||
outTempException);
|
||||
return knownCert;
|
||||
},
|
||||
|
||||
_addCertException: function(SSLStatus, uri, cert) {
|
||||
var flags = 0;
|
||||
if(SSLStatus.isUntrusted)
|
||||
flags |= mozt.Main.overrideService.ERROR_UNTRUSTED;
|
||||
if(SSLStatus.isDomainMismatch)
|
||||
flags |= mozt.Main.overrideService.ERROR_MISMATCH;
|
||||
if(SSLStatus.isNotValidAtThisTime)
|
||||
flags |= mozt.Main.overrideService.ERROR_TIME;
|
||||
mozt.Main.overrideService.rememberValidityOverride(
|
||||
uri.asciiHost, uri.port,
|
||||
cert,
|
||||
flags,
|
||||
mozt.Utils.prefService.getBoolPref('add_temporary_exceptions'));
|
||||
mozt.Debug.dump("CertEx added");
|
||||
mozt.Main.TabsProgressListener._certExceptionJustAdded = true;
|
||||
mozt.Debug.dump("certEx changed: " + mozt.Main.TabsProgressListener._certExceptionJustAdded);
|
||||
|
||||
mozt.Main.TabsProgressListener._goto = uri.spec; // never reset
|
||||
},
|
||||
|
||||
_parseBadCertFlags: function(flags) {
|
||||
var tag = '';
|
||||
var ns = Ci.nsIX509Cert;
|
||||
|
||||
if (flags & ns.NOT_VERIFIED_UNKNOWN)
|
||||
tag += ', ' + mozt.Main.strings.getString('NOT_VERIFIED_UNKNOWN');
|
||||
if (flags & ns.CERT_REVOKED)
|
||||
tag += ', ' + mozt.Main.strings.getString('CERT_REVOKED');
|
||||
if (flags & ns.CERT_EXPIRED)
|
||||
tag += ', ' + mozt.Main.strings.getString('CERT_EXPIRED');
|
||||
if (flags & ns.CERT_NOT_TRUSTED)
|
||||
tag += ', ' + mozt.Main.strings.getString('CERT_NOT_TRUSTED');
|
||||
if (flags & ns.ISSUER_NOT_TRUSTED)
|
||||
tag += ', ' + mozt.Main.strings.getString('ISSUER_NOT_TRUSTED');
|
||||
if (flags & ns.ISSUER_UNKNOWN)
|
||||
tag += ', ' + mozt.Main.strings.getString('ISSUER_UNKNOWN');
|
||||
if (flags & ns.INVALID_CA)
|
||||
tag += ', ' + mozt.Main.strings.getString('INVALID_CA');
|
||||
if (flags & ns.USAGE_NOT_ALLOWED)
|
||||
tag += ', ' + mozt.Main.strings.getString('USAGE_NOT_ALLOWED');
|
||||
if (flags & SCE_CERT_SELF_SIGNED)
|
||||
tag += ', ' + mozt.Main.strings.getString('CERT_SELF_SIGNED');
|
||||
|
||||
if (tag != "") tag = tag.substr(2);
|
||||
|
||||
return tag;
|
||||
},
|
||||
|
||||
notify: function(abrowser) {
|
||||
|
||||
// find the correct tab to display notification on
|
||||
var mainWindow = window
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShellTreeItem).rootTreeItem
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow);
|
||||
var notificationBox = mainWindow.gBrowser.getNotificationBox(abrowser);
|
||||
mozt.Main.stash.notificationBox = notificationBox; // stash for later use
|
||||
|
||||
// check notification not already here
|
||||
var notificationValue = mozt.Main.notification.type + '_' + mozt.Main.notification.host;
|
||||
if (notificationBox.getNotificationWithValue(notificationValue)) {
|
||||
mozt.Debug.dump("notificationBox already here");
|
||||
return;
|
||||
}
|
||||
|
||||
// build notification
|
||||
var temporaryException = mozt.Utils.prefService.getBoolPref('add_temporary_exceptions') ?
|
||||
mozt.Main.strings.getString('temporaryException') : mozt.Main.strings.getString('permanentException');
|
||||
var msgArgs = [];
|
||||
var priority = null; // notificationBox.PRIORITY_INFO_LOW not working ??
|
||||
switch (mozt.Main.notification.type) {
|
||||
case 'exceptionAdded':
|
||||
msgArgs = [temporaryException, mozt.Main.notification.host];
|
||||
priority = 'PRIORITY_INFO_LOW';
|
||||
break;
|
||||
case 'exceptionNotAdded':
|
||||
msgArgs = [mozt.Main.notification.dontBypassFlags];
|
||||
priority = 'PRIORITY_WARNING_LOW';
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
var message = mozt.Main.strings.getFormattedString(
|
||||
mozt.Main.notification.type, msgArgs);
|
||||
|
||||
// appendNotification( label , value , image , priority , buttons )
|
||||
var notification = notificationBox.appendNotification(
|
||||
message, notificationValue, null, notificationBox[priority], null);
|
||||
|
||||
// close notificatioBox if needed (will close automatically if reload)
|
||||
var exceptionDialogButton = abrowser.webProgress.DOMWindow
|
||||
.document.getElementById('exceptionDialogButton');
|
||||
exceptionDialogButton.addEventListener(
|
||||
"click", mozt.Main.exceptionDialogButtonOnClick, false);
|
||||
|
||||
mozt.Main.notification = {}; // reset
|
||||
},
|
||||
|
||||
exceptionDialogButtonOnClick: function(event) {
|
||||
mozt.Main._closeNotificationMaybe();
|
||||
event.originalTarget.removeEventListener(
|
||||
"click", mozt.Main.exceptionDialogButtonOnClick, false);
|
||||
},
|
||||
|
||||
_closeNotificationMaybe: function() {
|
||||
if (!mozt.Main.stash.notificationBox)
|
||||
return;
|
||||
mozt.Main.stash.notificationBox.currentNotification.close();
|
||||
mozt.Main.stash.notificationBox = null;
|
||||
},
|
||||
|
||||
|
||||
// a TabProgressListner seems more appropriate than an Observer, which only
|
||||
// gets notified for document requests (not internal requests)
|
||||
TabsProgressListener: {
|
||||
// can't see the necessity of having QueryInterface(aIID) implemented...
|
||||
|
||||
_certExceptionJustAdded: null, // used for communication btw
|
||||
// onSecurityChange, onStateChange, ...
|
||||
_certerrorCount: 0, // certerr seems called more than once...
|
||||
|
||||
// This method will be called on security transitions (eg HTTP -> HTTPS,
|
||||
// HTTPS -> HTTP, FOO -> HTTPS) and *after document load* completion. It
|
||||
// might also be called if an error occurs during network loading.
|
||||
onSecurityChange: function (aBrowser, aWebProgress, aRequest, aState) {
|
||||
var uri = aBrowser.currentURI;
|
||||
mozt.Debug.dump("onSecurityChange: uri=" + uri.prePath);
|
||||
|
||||
if (!uri.schemeIs("https")) return;
|
||||
|
||||
this._certerrorCount = 0; // reset
|
||||
|
||||
// retrieve bad cert from nsIRecentBadCertsService
|
||||
// NOTE: experience shows that nsIRecentBadCertsService will not provide
|
||||
// SSLStatus when cert is known or trusted. That's why we don't try to
|
||||
// get it from aRequest
|
||||
var port = uri.port;
|
||||
if (port == -1) port = 443; // thx http://gitorious.org/perspectives-notary-server/
|
||||
var hostWithPort = uri.host + ":" + port;
|
||||
mozt.Main.notification.host = uri.host;
|
||||
var SSLStatus = mozt.Main.recentCertsService.getRecentBadCert(hostWithPort);
|
||||
|
||||
if (!SSLStatus) {
|
||||
mozt.Debug.dump("no SSLStatus for: " + hostWithPort);
|
||||
return;
|
||||
}
|
||||
|
||||
mozt.Debug.dump("SSLStatus");
|
||||
mozt.Debug.dumpObj(SSLStatus);
|
||||
var cert = SSLStatus.serverCert;
|
||||
mozt.Debug.dump("cert");
|
||||
mozt.Debug.dumpObj(cert);
|
||||
|
||||
// check if cert already known/added
|
||||
var knownCert = mozt.Main._getCertException(uri, cert);
|
||||
if (knownCert) {
|
||||
mozt.Debug.dump("known cert: " + knownCert);
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine cert problems
|
||||
var dontBypassFlags = 0;
|
||||
|
||||
// we're only interested in certs with characteristics
|
||||
// defined in options (self-signed, issuer unknown, ...)
|
||||
cert.QueryInterface(Ci.nsIX509Cert3);
|
||||
var isSelfSigned = cert.isSelfSigned;
|
||||
mozt.Debug.dump("isSelfSigned:" + isSelfSigned);
|
||||
if (isSelfSigned
|
||||
&& !mozt.Utils.prefService.getBoolPref("bypass_self_signed"))
|
||||
dontBypassFlags |= SCE_CERT_SELF_SIGNED;
|
||||
// NOTE: isSelfSigned *implies* ISSUER_UNKNOWN (should be handled
|
||||
// correctly in option dialog)
|
||||
|
||||
var verificationResult = cert.verifyForUsage(Ci.nsIX509Cert.CERT_USAGE_SSLServer);
|
||||
switch (verificationResult) {
|
||||
case Ci.nsIX509Cert.ISSUER_NOT_TRUSTED: // including self-signed
|
||||
mozt.Debug.dump("issuer not trusted");
|
||||
case Ci.nsIX509Cert.ISSUER_UNKNOWN:
|
||||
mozt.Debug.dump("issuer unknown");
|
||||
mozt.Debug.dump("bypass_issuer_unknown: " + mozt.Utils.prefService.getBoolPref("bypass_issuer_unknown"));
|
||||
if (!mozt.Utils.prefService.getBoolPref("bypass_issuer_unknown"))
|
||||
dontBypassFlags |= Ci.nsIX509Cert.ISSUER_UNKNOWN;
|
||||
default:
|
||||
mozt.Debug.dump("verificationResult: " + verificationResult);
|
||||
break;
|
||||
}
|
||||
var dontBypassTag = mozt.Main._parseBadCertFlags(dontBypassFlags);
|
||||
mozt.Debug.dump("dontBypassFlags=" + dontBypassFlags + ", " + dontBypassTag);
|
||||
|
||||
// trigger notification
|
||||
if (mozt.Utils.prefService.getBoolPref('notify')) {
|
||||
mozt.Main.notification.willNotify = true;
|
||||
mozt.Debug.dump("onSecurityChange: willNotify");
|
||||
}
|
||||
|
||||
// Add cert exception (if bypass allowed by options)
|
||||
if (dontBypassFlags == 0) {
|
||||
mozt.Main._addCertException(SSLStatus, uri, cert);
|
||||
mozt.Main.notification.type = 'exceptionAdded';
|
||||
} else {
|
||||
mozt.Main.notification.type = 'exceptionNotAdded';
|
||||
mozt.Main.notification.dontBypassFlags = dontBypassTag;
|
||||
}
|
||||
|
||||
}, // END onSecurityChange
|
||||
|
||||
_getTabIndex: function(abrowser) {
|
||||
var tabbrowser = abrowser.getTabBrowser();
|
||||
var tabContainer = tabbrowser.tabs;
|
||||
|
||||
var tabIndex = null;
|
||||
for (var i = 0; i < tabContainer.length; ++i) {
|
||||
if (abrowser == tabbrowser.getBrowserAtIndex(i)) {
|
||||
tabIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return tabIndex;
|
||||
},
|
||||
|
||||
// "We can't look for this during onLocationChange since at that point the
|
||||
// document URI is not yet the about:-uri of the error page." (browser.js)
|
||||
// Experience shows that the order is as follows: badcert
|
||||
// (onSecurityChange) leading to about:blank, then request of
|
||||
// about:document-onload-blocker, leading to about:certerror (called at
|
||||
// least twice)
|
||||
onStateChange: function (aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) {
|
||||
|
||||
// aProgress.DOMWindow is the tab/window which triggered the change.
|
||||
var originDoc = aWebProgress.DOMWindow.document;
|
||||
var originURI = originDoc.documentURI;
|
||||
mozt.Debug.dump("onStateChange " + this._getTabIndex(aBrowser) + ": originURI=" + originURI);
|
||||
var safeRequestName = mozt.Utils.safeGetName(aRequest);
|
||||
mozt.Debug.dump("safeRequestName: " + safeRequestName);
|
||||
|
||||
// WE JUST CAN'T CANCEL THE REQUEST FOR about:certerr |
|
||||
// about:document-onload-blocker ...SO WE WAIT FOR IT !
|
||||
if (aStateFlags & (Ci.nsIWebProgressListener.STATE_STOP
|
||||
|Ci.nsIWebProgressListener.STATE_IS_REQUEST)) {
|
||||
|
||||
if (/^about:certerr/.test(originURI)) {
|
||||
this._certerrorCount++;
|
||||
mozt.Debug.dump("certerrorCount=" + this._certerrorCount);
|
||||
|
||||
if (this._certerrorCount < 2) {
|
||||
if (aStateFlags & (Ci.nsIWebProgressListener.STATE_STOP
|
||||
|Ci.nsIWebProgressListener.STATE_RESTORING)) {
|
||||
// experienced only one certerr call during sessoin restore
|
||||
mozt.Debug.dump("restoring");
|
||||
} else {
|
||||
mozt.Debug.dump("certerrorCount not sufficient");
|
||||
return; // wait for last (?) call
|
||||
}
|
||||
}
|
||||
|
||||
if (this._certExceptionJustAdded) {
|
||||
this._certExceptionJustAdded = false; // reset
|
||||
mozt.Debug.dump("certEx changed: " + this._certExceptionJustAdded);
|
||||
|
||||
aRequest.cancel(Components.results.NS_BINDING_ABORTED);
|
||||
aBrowser.loadURI(this._goto, null, null);
|
||||
}
|
||||
|
||||
if (mozt.Main.notification.willNotify) {
|
||||
mozt.Debug.dump("onStateChange: willNotify");
|
||||
mozt.Main.notify.willNotify = false; // reset
|
||||
mozt.Main.notify(aBrowser);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}, // END onStateChange
|
||||
|
||||
onLocationChange: function() { },
|
||||
onProgressChange: function() { },
|
||||
onStatusChange: function() { },
|
||||
|
||||
}, // END TabsProgressListener
|
||||
|
||||
};
|
||||
|
||||
|
||||
// should be sufficient for a delayed Startup (no need for window.setTimeout())
|
||||
// https://developer.mozilla.org/en/Extensions/Performance_best_practices_in_extensions
|
||||
// https://developer.mozilla.org/en/XUL_School/JavaScript_Object_Management.html
|
||||
window.addEventListener("load", function (e) { mozt.Main.onLoad(); }, false);
|
||||
window.addEventListener("unload", function(e) { mozt.Main.onQuit(); }, false);
|
11
src/chrome/content/overlay.xul
Normal file
11
src/chrome/content/overlay.xul
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?xml-stylesheet href="chrome://mozt/skin/overlay.css" type="text/css"?>
|
||||
<!DOCTYPE overlay SYSTEM "chrome://mozt/locale/overlay.dtd">
|
||||
<overlay id="mozt-overlay" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script src="overlay.js"/>
|
||||
|
||||
<stringbundleset id="stringbundleset">
|
||||
<stringbundle id="mozt-strings" src="chrome://mozt/locale/overlay.properties"/>
|
||||
</stringbundleset>
|
||||
|
||||
</overlay>
|
13
src/chrome/locale/en-US/options.dtd
Normal file
13
src/chrome/locale/en-US/options.dtd
Normal file
@ -0,0 +1,13 @@
|
||||
<!ENTITY prefwindow.title "Skip Cert Error preferences">
|
||||
<!ENTITY pane1.title "Skip Cert Error preferences">
|
||||
<!ENTITY bool_enabled.label "Enable bypass">
|
||||
<!ENTITY bool_enabled.accesskey "E">
|
||||
<!ENTITY bool_add_temporary_exceptions.label "Add the exceptions as temporary">
|
||||
<!ENTITY bool_add_temporary_exceptions.accesskey "T">
|
||||
<!ENTITY bool_notify.label "Notifications">
|
||||
<!ENTITY bool_notify.accesskey "N">
|
||||
<!ENTITY bypass_errors "Bypass error when cert is:">
|
||||
<!ENTITY bool_bypass_issuer_unknown.label "from unknown issuer">
|
||||
<!ENTITY bool_bypass_issuer_unknown.accesskey "I">
|
||||
<!ENTITY bool_bypass_self_signed.label "self-signed">
|
||||
<!ENTITY bool_bypass_self_signed.accesskey "G">
|
1
src/chrome/locale/en-US/overlay.dtd
Normal file
1
src/chrome/locale/en-US/overlay.dtd
Normal file
@ -0,0 +1 @@
|
||||
<!ENTITY mozt.label "My localized menuitem">
|
14
src/chrome/locale/en-US/overlay.properties
Normal file
14
src/chrome/locale/en-US/overlay.properties
Normal file
@ -0,0 +1,14 @@
|
||||
extensions.skipcerterror@foudil.fr.description=This Firefox extension enables skipping the SSL/TLS certificate error page, for specific configurable conditions, like self-signed cert or unknown issuer, by adding a temporary exception.
|
||||
exceptionAdded=A %1$S was added by SkipCertError for %2$S
|
||||
exceptionNotAdded=An exception could not be added by SkipCertError: %1$S
|
||||
temporaryException=temporary exception
|
||||
permanentException=permanent exception
|
||||
NOT_VERIFIED_UNKNOWN=not verified unknown
|
||||
CERT_REVOKED=cert revoked
|
||||
CERT_EXPIRED=cert expired
|
||||
CERT_NOT_TRUSTED=cert not trusted
|
||||
ISSUER_NOT_TRUSTED=issuer not trusted
|
||||
ISSUER_UNKNOWN=issuer unknown
|
||||
INVALID_CA=invalid ca
|
||||
USAGE_NOT_ALLOWED=usage not allowed
|
||||
CERT_SELF_SIGNED=cert self signed
|
BIN
src/chrome/skin/icon48.png
Normal file
BIN
src/chrome/skin/icon48.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.1 KiB |
BIN
src/chrome/skin/icon64.png
Normal file
BIN
src/chrome/skin/icon64.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.5 KiB |
22
src/chrome/skin/overlay.css
Normal file
22
src/chrome/skin/overlay.css
Normal file
@ -0,0 +1,22 @@
|
||||
/* This is just an example. You shouldn't do this. */
|
||||
#sce-hello
|
||||
{
|
||||
color: red ! important;
|
||||
}
|
||||
#sce-toolbar-button
|
||||
{
|
||||
list-style-image: url("chrome://sce/skin/toolbar-button.png");
|
||||
-moz-image-region: rect(0px 24px 24px 0px);
|
||||
}
|
||||
#sce-toolbar-button:hover
|
||||
{
|
||||
-moz-image-region: rect(24px 24px 48px 0px);
|
||||
}
|
||||
[iconsize="small"] #sce-toolbar-button
|
||||
{
|
||||
-moz-image-region: rect( 0px 40px 16px 24px);
|
||||
}
|
||||
[iconsize="small"] #sce-toolbar-button:hover
|
||||
{
|
||||
-moz-image-region: rect(24px 40px 40px 24px);
|
||||
}
|
13
src/defaults/preferences/prefs.js
Normal file
13
src/defaults/preferences/prefs.js
Normal file
@ -0,0 +1,13 @@
|
||||
// https://developer.mozilla.org/en/Localizing_extension_descriptions
|
||||
pref("extensions.skipcerterror@foudil.fr.description", "chrome://sce/locale/overlay.properties");
|
||||
|
||||
// Extension prefs
|
||||
pref("extensions.mozt.enabled", true);
|
||||
pref("extensions.mozt.add_temporary_exceptions", true);
|
||||
pref("extensions.mozt.notify", true);
|
||||
pref("extensions.mozt.bypass_issuer_unknown", true);
|
||||
pref("extensions.mozt.bypass_self_signed", true);
|
||||
|
||||
// Set the environment settings
|
||||
pref("browser.ssl_override_behavior", 2);
|
||||
pref("browser.xul.error_pages.expert_bad_cert", true);
|
25
src/install.rdf
Normal file
25
src/install.rdf
Normal file
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:em="http://www.mozilla.org/2004/em-rdf#">
|
||||
<Description about="urn:mozilla:install-manifest">
|
||||
<em:id>skipcerterror@foudil.fr</em:id>
|
||||
<em:unpack>false</em:unpack>
|
||||
<em:type>2</em:type>
|
||||
<em:name>Mozilla Tray</em:name>
|
||||
<em:version>0.0.1</em:version>
|
||||
<em:creator>Foudil BRÉTEL</em:creator>
|
||||
<em:contributor></em:contributor>
|
||||
<em:contributor>Hua Luo, Francesco Solero (Firetray original authors)</em:contributor>
|
||||
<em:homepageURL>https://github.com/foudfou/moztray</em:homepageURL>
|
||||
<em:description></em:description>
|
||||
<em:optionsURL>chrome://mozt/content/options.xul</em:optionsURL>
|
||||
<em:iconURL>chrome://mozt/skin/icon48.png</em:iconURL>
|
||||
<em:icon64URL>chrome://mozt/skin/icon64.png</em:icon64URL>
|
||||
<em:targetApplication>
|
||||
<Description>
|
||||
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> <!-- Firefox -->
|
||||
<em:minVersion>4.0</em:minVersion>
|
||||
<em:maxVersion>6.*</em:maxVersion>
|
||||
</Description>
|
||||
</em:targetApplication>
|
||||
</Description>
|
||||
</RDF>
|
73
src/modules/commons.js
Normal file
73
src/modules/commons.js
Normal file
@ -0,0 +1,73 @@
|
||||
/* -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
|
||||
/*
|
||||
* should contain our business logic in JSM, available through service objects,
|
||||
* and keep chrome scripts limited to handle presentation logic.
|
||||
* http://developer.mozilla.org/en/XUL_School/JavaScript_Object_Management.html
|
||||
*/
|
||||
|
||||
var EXPORTED_SYMBOLS = [ "mozt" ];
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
/**
|
||||
* mozt namespace.
|
||||
*/
|
||||
if ("undefined" == typeof(mozt)) {
|
||||
var mozt = {
|
||||
DEBUG_MODE: true,
|
||||
};
|
||||
};
|
||||
|
||||
mozt.Debug = {
|
||||
|
||||
_initialized: false,
|
||||
|
||||
_consoleService: null,
|
||||
|
||||
/**
|
||||
* Object constructor.
|
||||
*/
|
||||
init: function() {
|
||||
if (this.initialized) return;
|
||||
this.consoleService = Cc['@mozilla.org/consoleservice;1'].getService(Ci.nsIConsoleService);
|
||||
this.dump("SkipCertError Debug initialized");
|
||||
this.initialized = true;
|
||||
},
|
||||
|
||||
/* Console logging functions */
|
||||
/* NOTE: Web Console inappropriates: doesn't catch all messages */
|
||||
/*
|
||||
* CAUTION: dump() dumpObj() may be stripped from .js files during xpi build.
|
||||
* IT'S IMPORTANT THAT DEBUG CALLS ARE WRITTEN ON A SINGLE LINE !
|
||||
*/
|
||||
dump: function(message) { // Debuging function -- prints to javascript console
|
||||
if(!mozt.DEBUG_MODE) return;
|
||||
this.consoleService.logStringMessage(message);
|
||||
},
|
||||
|
||||
dumpObj: function(obj) {
|
||||
if(!mozt.DEBUG_MODE) return;
|
||||
var str = "";
|
||||
for(i in obj) {
|
||||
try {
|
||||
str += "obj["+i+"]: " + obj[i] + "\n";
|
||||
} catch(e) {
|
||||
str += "obj["+i+"]: Unavailable\n";
|
||||
}
|
||||
}
|
||||
this.dump(str);
|
||||
},
|
||||
|
||||
};
|
||||
// build it !
|
||||
mozt.Debug.init();
|
||||
|
||||
|
||||
mozt.Utils = {
|
||||
|
||||
prefService: Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService)
|
||||
.getBranch("extensions.mozt."),
|
||||
|
||||
};
|
Loading…
Reference in New Issue
Block a user