зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1207130 - Add a checkbox for automatic error reporting to about:certerror r=Gijs,past
--HG-- rename : browser/base/content/test/general/pinning_reports.sjs => browser/base/content/test/general/ssl_error_reports.sjs
This commit is contained in:
Родитель
9960a81092
Коммит
d558566d6f
|
@ -260,15 +260,12 @@
|
|||
var event = new CustomEvent("AboutNetErrorSetAutomatic",
|
||||
{bubbles:true, detail:evt.target.checked});
|
||||
document.dispatchEvent(event);
|
||||
if (evt.target.checked && reportBtn.style.display != "none") {
|
||||
if (evt.target.checked) {
|
||||
sendErrorReport();
|
||||
}
|
||||
}, false);
|
||||
|
||||
var reportBtn = document.getElementById('reportCertificateError');
|
||||
var retryBtn = document.getElementById('reportCertificateErrorRetry');
|
||||
|
||||
reportBtn.addEventListener('click', sendErrorReport, false);
|
||||
retryBtn.addEventListener('click', sendErrorReport, false);
|
||||
}
|
||||
}
|
||||
|
@ -532,7 +529,6 @@
|
|||
<label for="automaticallyReportInFuture" id="automaticallyReportInFuture">&errorReporting.automatic2;</label>
|
||||
|
||||
<span id="reportingState">
|
||||
<button id="reportCertificateError">&errorReporting.report;</button>
|
||||
<button id="reportCertificateErrorRetry">&errorReporting.tryAgain;</button>
|
||||
<span id="reportSendingMessage">&errorReporting.sending;</span>
|
||||
<span id="reportSentMessage">&errorReporting.sent;</span>
|
||||
|
|
|
@ -88,6 +88,32 @@
|
|||
toggleVisibility('advancedPanel');
|
||||
}
|
||||
|
||||
var checkbox = document.getElementById("automaticallyReportInFuture");
|
||||
checkbox.addEventListener("change", function ({target: {checked}}) {
|
||||
document.dispatchEvent(new CustomEvent("AboutCertErrorSetAutomatic", {
|
||||
detail: checked,
|
||||
bubbles: true
|
||||
}));
|
||||
});
|
||||
|
||||
var retryBtn = document.getElementById("reportCertificateErrorRetry");
|
||||
retryBtn.addEventListener("click", function () {
|
||||
document.dispatchEvent(new CustomEvent("AboutCertErrorSendReport", {
|
||||
bubbles: true
|
||||
}));
|
||||
});
|
||||
|
||||
addEventListener("AboutCertErrorOptions", function (event) {
|
||||
var options = JSON.parse(event.detail);
|
||||
if (options && options.enabled) {
|
||||
// Display error reporting UI
|
||||
document.getElementById("certificateErrorReporting").style.display = "block";
|
||||
|
||||
// set the checkbox
|
||||
checkbox.checked = !!options.automatic;
|
||||
}
|
||||
}, true, true);
|
||||
|
||||
// Disallow overrides if this is a Strict-Transport-Security
|
||||
// host and the cert is bad (STS Spec section 7.3) or if the
|
||||
// certerror is in a frame (bug 633691).
|
||||
|
@ -254,11 +280,26 @@
|
|||
<div id="buttonSpacer"></div>
|
||||
<button id="advancedButton" autocomplete="off" onclick="toggleVisibility('advancedPanel');" autofocus="true">&certerror.advanced.label;</button>
|
||||
</div>
|
||||
<!-- Advanced panel, which is hidden by default -->
|
||||
<div id="advancedPanel" style="visibility: hidden;">
|
||||
<p id="technicalContentText"/>
|
||||
<button id="exceptionDialogButton">&certerror.addException.label;</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- UI for option to report certificate errors to Mozilla. -->
|
||||
<div id="certificateErrorReporting">
|
||||
<p>
|
||||
<input type="checkbox" id="automaticallyReportInFuture" />
|
||||
<label for="automaticallyReportInFuture" id="automaticallyReportInFuture">&errorReporting.automatic;</label>
|
||||
|
||||
<span id="reportingState">
|
||||
<button id="reportCertificateErrorRetry">&errorReporting.tryAgain;</button>
|
||||
<span id="reportSendingMessage">&errorReporting.sending;</span>
|
||||
<span id="reportSentMessage">&errorReporting.sent;</span>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Advanced panel, which is hidden by default -->
|
||||
<div id="advancedPanel" style="visibility: hidden;">
|
||||
<p id="technicalContentText"/>
|
||||
<button id="exceptionDialogButton">&certerror.addException.label;</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -2673,7 +2673,7 @@ var BrowserOnClick = {
|
|||
}
|
||||
break;
|
||||
case "Browser:SendSSLErrorReport":
|
||||
this.onSSLErrorReport(msg.target, msg.data.elementId,
|
||||
this.onSSLErrorReport(msg.target,
|
||||
msg.data.documentURI,
|
||||
msg.data.location,
|
||||
msg.data.securityInfo);
|
||||
|
@ -2704,7 +2704,7 @@ var BrowserOnClick = {
|
|||
}
|
||||
},
|
||||
|
||||
onSSLErrorReport: function(browser, elementId, documentURI, location, securityInfo) {
|
||||
onSSLErrorReport: function(browser, documentURI, location, securityInfo) {
|
||||
function showReportStatus(reportStatus) {
|
||||
gBrowser.selectedBrowser
|
||||
.messageManager
|
||||
|
|
|
@ -207,6 +207,143 @@ const TLS_ERROR_REPORT_TELEMETRY_EXPANDED = 1;
|
|||
const TLS_ERROR_REPORT_TELEMETRY_SUCCESS = 6;
|
||||
const TLS_ERROR_REPORT_TELEMETRY_FAILURE = 7;
|
||||
|
||||
var AboutCertErrorListener = {
|
||||
init(chromeGlobal) {
|
||||
addMessageListener("AboutCertErrorDetails", this);
|
||||
addMessageListener("Browser:SSLErrorReportStatus", this);
|
||||
chromeGlobal.addEventListener("AboutCertErrorLoad", this, false, true);
|
||||
chromeGlobal.addEventListener("AboutCertErrorSetAutomatic", this, false, true);
|
||||
chromeGlobal.addEventListener("AboutCertErrorSendReport", this, false, true);
|
||||
},
|
||||
|
||||
get isAboutCertError() {
|
||||
return content.document.documentURI.startsWith("about:certerror");
|
||||
},
|
||||
|
||||
handleEvent(event) {
|
||||
if (!this.isAboutCertError) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event.type) {
|
||||
case "AboutCertErrorLoad":
|
||||
this.onLoad(event);
|
||||
break;
|
||||
case "AboutCertErrorSetAutomatic":
|
||||
this.onSetAutomatic(event);
|
||||
break;
|
||||
case "AboutCertErrorSendReport":
|
||||
this.onSendReport();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
receiveMessage(msg) {
|
||||
if (!this.isAboutCertError) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (msg.name) {
|
||||
case "AboutCertErrorDetails":
|
||||
this.onDetails(msg);
|
||||
break;
|
||||
case "Browser:SSLErrorReportStatus":
|
||||
this.onReportStatus(msg);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
onLoad(event) {
|
||||
let originalTarget = event.originalTarget;
|
||||
let ownerDoc = originalTarget.ownerDocument;
|
||||
ClickEventHandler.onAboutCertError(originalTarget, ownerDoc);
|
||||
|
||||
let automatic = Services.prefs.getBoolPref("security.ssl.errorReporting.automatic");
|
||||
content.dispatchEvent(new content.CustomEvent("AboutCertErrorOptions", {
|
||||
detail: JSON.stringify({
|
||||
enabled: Services.prefs.getBoolPref("security.ssl.errorReporting.enabled"),
|
||||
automatic,
|
||||
})
|
||||
}));
|
||||
|
||||
if (automatic) {
|
||||
this.onSendReport();
|
||||
}
|
||||
},
|
||||
|
||||
onDetails(msg) {
|
||||
let div = content.document.getElementById("certificateErrorText");
|
||||
div.textContent = msg.data.info;
|
||||
},
|
||||
|
||||
onSetAutomatic(event) {
|
||||
if (event.detail) {
|
||||
this.onSendReport();
|
||||
}
|
||||
|
||||
sendAsyncMessage("Browser:SetSSLErrorReportAuto", {
|
||||
automatic: event.detail
|
||||
});
|
||||
},
|
||||
|
||||
onSendReport() {
|
||||
let doc = content.document;
|
||||
let location = doc.location.href;
|
||||
|
||||
let serhelper = Cc["@mozilla.org/network/serialization-helper;1"]
|
||||
.getService(Ci.nsISerializationHelper);
|
||||
|
||||
let serializable = docShell.failedChannel.securityInfo
|
||||
.QueryInterface(Ci.nsITransportSecurityInfo)
|
||||
.QueryInterface(Ci.nsISerializable);
|
||||
|
||||
let serializedSecurityInfo = serhelper.serializeToString(serializable);
|
||||
|
||||
sendAsyncMessage("Browser:SendSSLErrorReport", {
|
||||
documentURI: doc.documentURI,
|
||||
location: {hostname: doc.location.hostname, port: doc.location.port},
|
||||
securityInfo: serializedSecurityInfo
|
||||
});
|
||||
},
|
||||
|
||||
onReportStatus(msg) {
|
||||
let doc = content.document;
|
||||
if (doc.documentURI != msg.data.documentURI) {
|
||||
return;
|
||||
}
|
||||
|
||||
let reportSendingMsg = doc.getElementById("reportSendingMessage");
|
||||
let reportSentMsg = doc.getElementById("reportSentMessage");
|
||||
let retryBtn = doc.getElementById("reportCertificateErrorRetry");
|
||||
|
||||
switch (msg.data.reportStatus) {
|
||||
case "activity":
|
||||
// Hide the button that was just clicked
|
||||
retryBtn.style.removeProperty("display");
|
||||
reportSentMsg.style.removeProperty("display");
|
||||
reportSendingMsg.style.display = "block";
|
||||
break;
|
||||
case "error":
|
||||
// show the retry button
|
||||
retryBtn.style.display = "block";
|
||||
reportSendingMsg.style.removeProperty("display");
|
||||
sendAsyncMessage("Browser:SSLErrorReportTelemetry",
|
||||
{reportStatus: TLS_ERROR_REPORT_TELEMETRY_FAILURE});
|
||||
break;
|
||||
case "complete":
|
||||
// Show a success indicator
|
||||
reportSentMsg.style.display = "block";
|
||||
reportSendingMsg.style.removeProperty("display");
|
||||
sendAsyncMessage("Browser:SSLErrorReportTelemetry",
|
||||
{reportStatus: TLS_ERROR_REPORT_TELEMETRY_SUCCESS});
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
AboutCertErrorListener.init(this);
|
||||
|
||||
|
||||
var AboutNetErrorListener = {
|
||||
init: function(chromeGlobal) {
|
||||
chromeGlobal.addEventListener('AboutNetErrorLoad', this, false, true);
|
||||
|
@ -283,7 +420,6 @@ var AboutNetErrorListener = {
|
|||
|
||||
let reportSendingMsg = contentDoc.getElementById("reportSendingMessage");
|
||||
let reportSentMsg = contentDoc.getElementById("reportSentMessage");
|
||||
let reportBtn = contentDoc.getElementById("reportCertificateError");
|
||||
let retryBtn = contentDoc.getElementById("reportCertificateErrorRetry");
|
||||
|
||||
addMessageListener("Browser:SSLErrorReportStatus", function(message) {
|
||||
|
@ -293,7 +429,6 @@ var AboutNetErrorListener = {
|
|||
switch(message.data.reportStatus) {
|
||||
case "activity":
|
||||
// Hide the button that was just clicked
|
||||
reportBtn.style.display = "none";
|
||||
retryBtn.style.display = "none";
|
||||
reportSentMsg.style.display = "none";
|
||||
reportSendingMsg.style.removeProperty("display");
|
||||
|
@ -319,20 +454,22 @@ var AboutNetErrorListener = {
|
|||
let location = contentDoc.location.href;
|
||||
|
||||
let serhelper = Cc["@mozilla.org/network/serialization-helper;1"]
|
||||
.getService(Ci.nsISerializationHelper);
|
||||
.getService(Ci.nsISerializationHelper);
|
||||
|
||||
let serializable = docShell.failedChannel.securityInfo
|
||||
.QueryInterface(Ci.nsITransportSecurityInfo)
|
||||
.QueryInterface(Ci.nsISerializable);
|
||||
let serializable = docShell.failedChannel.securityInfo
|
||||
.QueryInterface(Ci.nsITransportSecurityInfo)
|
||||
.QueryInterface(Ci.nsISerializable);
|
||||
|
||||
let serializedSecurityInfo = serhelper.serializeToString(serializable);
|
||||
|
||||
sendAsyncMessage("Browser:SendSSLErrorReport", {
|
||||
elementId: evt.target.id,
|
||||
documentURI: contentDoc.documentURI,
|
||||
location: {hostname: contentDoc.location.hostname, port: contentDoc.location.port},
|
||||
securityInfo: serializedSecurityInfo
|
||||
});
|
||||
documentURI: contentDoc.documentURI,
|
||||
location: {
|
||||
hostname: contentDoc.location.hostname,
|
||||
port: contentDoc.location.port
|
||||
},
|
||||
securityInfo: serializedSecurityInfo
|
||||
});
|
||||
},
|
||||
|
||||
onOverride: function(evt) {
|
||||
|
@ -553,17 +690,6 @@ addEventListener("DOMServiceWorkerFocusClient", function(event) {
|
|||
sendAsyncMessage("DOMServiceWorkerFocusClient", {});
|
||||
}, false);
|
||||
|
||||
addEventListener("AboutCertErrorLoad", function(event) {
|
||||
let originalTarget = event.originalTarget;
|
||||
let ownerDoc = originalTarget.ownerDocument;
|
||||
ClickEventHandler.onAboutCertError(originalTarget, ownerDoc);
|
||||
}, false, true);
|
||||
|
||||
addMessageListener("AboutCertErrorDetails", function(message) {
|
||||
let div = content.document.getElementById("certificateErrorText");
|
||||
div.textContent = message.data.info;
|
||||
});
|
||||
|
||||
ContentWebRTC.init();
|
||||
addMessageListener("rtcpeer:Allow", ContentWebRTC);
|
||||
addMessageListener("rtcpeer:Deny", ContentWebRTC);
|
||||
|
|
|
@ -16,7 +16,6 @@ support-files =
|
|||
browser_fxa_oauth_with_keys.html
|
||||
browser_fxa_web_channel.html
|
||||
browser_registerProtocolHandler_notification.html
|
||||
browser_ssl_error_reports_content.js
|
||||
browser_star_hsts.sjs
|
||||
browser_tab_dragdrop2_frame1.xul
|
||||
browser_web_channel.html
|
||||
|
@ -79,7 +78,7 @@ support-files =
|
|||
page_style_sample.html
|
||||
parsingTestHelpers.jsm
|
||||
pinning_headers.sjs
|
||||
pinning_reports.sjs
|
||||
ssl_error_reports.sjs
|
||||
popup_blocker.html
|
||||
print_postdata.sjs
|
||||
redirect_bug623155.sjs
|
||||
|
|
|
@ -1,307 +1,217 @@
|
|||
"use strict";
|
||||
|
||||
var badChainURL = "https://badchain.include-subdomains.pinning.example.com";
|
||||
var noCertURL = "https://fail-handshake.example.com";
|
||||
var enabledPref = false;
|
||||
var automaticPref = false;
|
||||
var urlPref = "security.ssl.errorReporting.url";
|
||||
var enforcement_level = 1;
|
||||
var ROOT = getRootDirectory(gTestPath);
|
||||
const URL_REPORTS = "https://example.com/browser/browser/base/content/test/general/ssl_error_reports.sjs?";
|
||||
const URL_BAD_CHAIN = "https://badchain.include-subdomains.pinning.example.com/";
|
||||
const URL_NO_CERT = "https://fail-handshake.example.com/";
|
||||
const URL_BAD_CERT = "https://expired.example.com/";
|
||||
const URL_BAD_STS_CERT = "https://badchain.include-subdomains.pinning.example.com:443/";
|
||||
const ROOT = getRootDirectory(gTestPath);
|
||||
const PREF_REPORT_ENABLED = "security.ssl.errorReporting.enabled";
|
||||
const PREF_REPORT_AUTOMATIC = "security.ssl.errorReporting.automatic";
|
||||
const PREF_REPORT_URL = "security.ssl.errorReporting.url";
|
||||
|
||||
SimpleTest.requestCompleteLog();
|
||||
|
||||
add_task(function* test_send_report_manual_badchain() {
|
||||
yield testSendReportManual(badChainURL, "succeed");
|
||||
});
|
||||
Services.prefs.setIntPref("security.cert_pinning.enforcement_level", 2);
|
||||
|
||||
add_task(function* test_send_report_manual_nocert() {
|
||||
yield testSendReportManual(noCertURL, "nocert");
|
||||
});
|
||||
|
||||
// creates a promise of the message in an error page
|
||||
function createNetworkErrorMessagePromise(aBrowser) {
|
||||
let promise = new Promise(function(resolve, reject) {
|
||||
let originalDocumentURI = aBrowser.contentDocument.documentURI;
|
||||
|
||||
let loadedListener = function() {
|
||||
let doc = aBrowser.contentDocument;
|
||||
|
||||
if (doc && doc.getElementById("reportCertificateError")) {
|
||||
let documentURI = doc.documentURI;
|
||||
|
||||
aBrowser.removeEventListener("DOMContentLoaded", loadedListener, true);
|
||||
let matchArray = /about:neterror\?.*&d=([^&]*)/.exec(documentURI);
|
||||
if (!matchArray) {
|
||||
reject("no network error message found in URI");
|
||||
return;
|
||||
}
|
||||
|
||||
let errorMsg = matchArray[1];
|
||||
resolve(decodeURIComponent(errorMsg));
|
||||
}
|
||||
};
|
||||
aBrowser.addEventListener("DOMContentLoaded", loadedListener, true);
|
||||
});
|
||||
|
||||
return promise;
|
||||
function cleanup() {
|
||||
Services.prefs.clearUserPref(PREF_REPORT_ENABLED);
|
||||
Services.prefs.clearUserPref(PREF_REPORT_AUTOMATIC);
|
||||
Services.prefs.clearUserPref(PREF_REPORT_URL);
|
||||
}
|
||||
|
||||
// check we can set the 'automatically send' pref
|
||||
add_task(function* test_set_automatic() {
|
||||
setup();
|
||||
let tab = gBrowser.addTab(badChainURL, {skipAnimation: true});
|
||||
let browser = tab.linkedBrowser;
|
||||
let mm = browser.messageManager;
|
||||
mm.loadFrameScript(ROOT + "browser_ssl_error_reports_content.js", true);
|
||||
|
||||
gBrowser.selectedTab = tab;
|
||||
|
||||
// ensure we have the correct error message from about:neterror
|
||||
let netError = createNetworkErrorMessagePromise(browser);
|
||||
yield netError;
|
||||
|
||||
// ensure that setting automatic when unset works
|
||||
let prefEnabled = new Promise(function(resolve, reject){
|
||||
let prefUpdateListener = function() {
|
||||
mm.removeMessageListener("ssler-test:AutoPrefUpdated", prefUpdateListener);
|
||||
if (Services.prefs.getBoolPref("security.ssl.errorReporting.automatic")) {
|
||||
resolve();
|
||||
} else {
|
||||
reject();
|
||||
}
|
||||
};
|
||||
mm.addMessageListener("ssler-test:AutoPrefUpdated", prefUpdateListener);
|
||||
});
|
||||
|
||||
mm.sendAsyncMessage("ssler-test:SetAutoPref",{value:true});
|
||||
|
||||
yield prefEnabled;
|
||||
|
||||
// ensure un-setting automatic, when set, works
|
||||
let prefDisabled = new Promise(function(resolve, reject){
|
||||
let prefUpdateListener = function () {
|
||||
mm.removeMessageListener("ssler-test:AutoPrefUpdated", prefUpdateListener);
|
||||
if (!Services.prefs.getBoolPref("security.ssl.errorReporting.automatic")) {
|
||||
resolve();
|
||||
} else {
|
||||
reject();
|
||||
}
|
||||
};
|
||||
mm.addMessageListener("ssler-test:AutoPrefUpdated", prefUpdateListener);
|
||||
});
|
||||
|
||||
mm.sendAsyncMessage("ssler-test:SetAutoPref",{value:false});
|
||||
|
||||
yield prefDisabled;
|
||||
|
||||
gBrowser.removeTab(tab);
|
||||
registerCleanupFunction(() => {
|
||||
Services.prefs.clearUserPref("security.cert_pinning.enforcement_level");
|
||||
cleanup();
|
||||
});
|
||||
|
||||
// test that manual report sending (with button clicks) works
|
||||
var testSendReportManual = function*(testURL, suffix) {
|
||||
setup();
|
||||
Services.prefs.setBoolPref("security.ssl.errorReporting.enabled", true);
|
||||
Services.prefs.setCharPref("security.ssl.errorReporting.url",
|
||||
"https://example.com/browser/browser/base/content/test/general/pinning_reports.sjs?" + suffix);
|
||||
add_task(function* test_send_report_neterror() {
|
||||
yield testSendReportAutomatically(URL_BAD_CHAIN, "succeed", "neterror");
|
||||
yield testSendReportAutomatically(URL_NO_CERT, "nocert", "neterror");
|
||||
yield testSendReportFailRetry(URL_NO_CERT, "nocert", "neterror");
|
||||
yield testSetAutomatic(URL_NO_CERT, "nocert", "neterror");
|
||||
});
|
||||
|
||||
let tab = gBrowser.addTab(testURL, {skipAnimation: true});
|
||||
add_task(function* test_send_report_certerror() {
|
||||
yield testSendReportAutomatically(URL_BAD_CERT, "badcert", "certerror");
|
||||
yield testSendReportFailRetry(URL_BAD_CERT, "badcert", "certerror");
|
||||
yield testSetAutomatic(URL_BAD_CERT, "badcert", "certerror");
|
||||
});
|
||||
|
||||
add_task(function* test_send_disabled() {
|
||||
Services.prefs.setBoolPref(PREF_REPORT_ENABLED, false);
|
||||
Services.prefs.setBoolPref(PREF_REPORT_AUTOMATIC, true);
|
||||
Services.prefs.setCharPref(PREF_REPORT_URL, "https://example.com/invalid");
|
||||
|
||||
// Check with enabled=false but automatic=true.
|
||||
yield testSendReportDisabled(URL_NO_CERT, "neterror");
|
||||
yield testSendReportDisabled(URL_BAD_CERT, "certerror");
|
||||
|
||||
Services.prefs.setBoolPref(PREF_REPORT_AUTOMATIC, false);
|
||||
|
||||
// Check again with both prefs false.
|
||||
yield testSendReportDisabled(URL_NO_CERT, "neterror");
|
||||
yield testSendReportDisabled(URL_BAD_CERT, "certerror");
|
||||
cleanup();
|
||||
});
|
||||
|
||||
function* testSendReportAutomatically(testURL, suffix, errorURISuffix) {
|
||||
Services.prefs.setBoolPref(PREF_REPORT_ENABLED, true);
|
||||
Services.prefs.setBoolPref(PREF_REPORT_AUTOMATIC, true);
|
||||
Services.prefs.setCharPref(PREF_REPORT_URL, URL_REPORTS + suffix);
|
||||
|
||||
// Add a tab and wait until it's loaded.
|
||||
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
|
||||
let browser = tab.linkedBrowser;
|
||||
let mm = browser.messageManager;
|
||||
mm.loadFrameScript(ROOT + "browser_ssl_error_reports_content.js", true);
|
||||
|
||||
gBrowser.selectedTab = tab;
|
||||
// Load the page and wait for the error report submission.
|
||||
let promiseReport = createErrorReportPromise(browser);
|
||||
browser.loadURI(testURL);
|
||||
yield promiseReport;
|
||||
ok(true, "SSL error report submitted successfully");
|
||||
|
||||
// ensure we have the correct error message from about:neterror
|
||||
let netError = createNetworkErrorMessagePromise(browser);
|
||||
yield netError;
|
||||
netError.then(function(val){
|
||||
is(val.startsWith("An error occurred during a connection to"), true,
|
||||
"ensure the correct error message came from about:neterror");
|
||||
});
|
||||
|
||||
let btn = browser.contentDocument.getElementById("reportCertificateError");
|
||||
let deferredReportSucceeds = Promise.defer();
|
||||
|
||||
// ensure we see the correct statuses in the correct order...
|
||||
let statusListener = function() {
|
||||
let active = false;
|
||||
return function(message) {
|
||||
switch(message.data.reportStatus) {
|
||||
case "activity":
|
||||
if (!active) {
|
||||
active = true;
|
||||
}
|
||||
break;
|
||||
case "complete":
|
||||
mm.removeMessageListener("ssler-test:SSLErrorReportStatus", statusListener);
|
||||
if (active) {
|
||||
deferredReportSucceeds.resolve(message.data.reportStatus);
|
||||
} else {
|
||||
deferredReportSucceeds.reject('activity should be seen before success');
|
||||
}
|
||||
break;
|
||||
case "error":
|
||||
mm.removeMessageListener("ssler-test:SSLErrorReportStatus", statusListener);
|
||||
deferredReportSucceeds.reject();
|
||||
break;
|
||||
}
|
||||
};
|
||||
}();
|
||||
mm.addMessageListener("ssler-test:SSLErrorReportStatus", statusListener);
|
||||
|
||||
// ... once the button is clicked, that is
|
||||
mm.sendAsyncMessage("ssler-test:SendBtnClick",{});
|
||||
|
||||
yield deferredReportSucceeds.promise;
|
||||
// Check that we loaded the right error page.
|
||||
yield checkErrorPage(browser, errorURISuffix);
|
||||
|
||||
// Cleanup.
|
||||
gBrowser.removeTab(tab);
|
||||
cleanup();
|
||||
};
|
||||
|
||||
// test that automatic sending works
|
||||
add_task(function* test_send_report_auto() {
|
||||
setup();
|
||||
Services.prefs.setBoolPref("security.ssl.errorReporting.enabled", true);
|
||||
Services.prefs.setBoolPref("security.ssl.errorReporting.automatic", true);
|
||||
Services.prefs.setCharPref("security.ssl.errorReporting.url", "https://example.com/browser/browser/base/content/test/general/pinning_reports.sjs?succeed");
|
||||
function* testSendReportFailRetry(testURL, suffix, errorURISuffix) {
|
||||
try {
|
||||
yield testSendReportAutomatically(testURL, "error", errorURISuffix);
|
||||
ok(false, "sending a report should have failed");
|
||||
} catch (err) {
|
||||
ok(err, "saw a failure notification");
|
||||
}
|
||||
|
||||
let tab = gBrowser.addTab(badChainURL, {skipAnimation: true});
|
||||
let browser = tab.linkedBrowser;
|
||||
let mm = browser.messageManager;
|
||||
mm.loadFrameScript(ROOT + "browser_ssl_error_reports_content.js", true);
|
||||
Services.prefs.setCharPref(PREF_REPORT_URL, URL_REPORTS + suffix);
|
||||
|
||||
gBrowser.selectedTab = tab;
|
||||
|
||||
|
||||
// Ensure the error page loads
|
||||
let netError = createNetworkErrorMessagePromise(browser);
|
||||
yield netError;
|
||||
|
||||
let reportWillStart = Promise.defer();
|
||||
let startListener = function() {
|
||||
mm.removeMessageListener("Browser:SendSSLErrorReport", startListener);
|
||||
reportWillStart.resolve();
|
||||
};
|
||||
mm.addMessageListener("Browser:SendSSLErrorReport", startListener);
|
||||
|
||||
let deferredReportSucceeds = Promise.defer();
|
||||
|
||||
let statusListener = function(message) {
|
||||
switch(message.data.reportStatus) {
|
||||
case "complete":
|
||||
mm.removeMessageListener("ssler-test:SSLErrorReportStatus", statusListener);
|
||||
deferredReportSucceeds.resolve(message.data.reportStatus);
|
||||
break;
|
||||
case "error":
|
||||
mm.removeMessageListener("ssler-test:SSLErrorReportStatus", statusListener);
|
||||
deferredReportSucceeds.reject();
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
mm.addMessageListener("ssler-test:SSLErrorReportStatus", statusListener);
|
||||
|
||||
// Ensure the report is sent with no interaction
|
||||
yield deferredReportSucceeds.promise;
|
||||
|
||||
gBrowser.removeTab(tab);
|
||||
cleanup();
|
||||
});
|
||||
|
||||
// test that an error is shown if there's a problem with the report server
|
||||
add_task(function* test_send_report_error() {
|
||||
setup();
|
||||
// set up prefs so error send is automatic and an error will occur
|
||||
Services.prefs.setBoolPref("security.ssl.errorReporting.enabled", true);
|
||||
Services.prefs.setBoolPref("security.ssl.errorReporting.automatic", true);
|
||||
Services.prefs.setCharPref("security.ssl.errorReporting.url", "https://example.com/browser/browser/base/content/test/general/pinning_reports.sjs?error");
|
||||
|
||||
// load the test URL so error page is seen
|
||||
let tab = gBrowser.addTab(badChainURL, {skipAnimation: true});
|
||||
let browser = tab.linkedBrowser;
|
||||
gBrowser.selectedTab = tab;
|
||||
let mm = browser.messageManager;
|
||||
mm.loadFrameScript(ROOT + "browser_ssl_error_reports_content.js", true);
|
||||
|
||||
let reportErrors = new Promise(function(resolve, reject) {
|
||||
let statusListener = function(message) {
|
||||
switch(message.data.reportStatus) {
|
||||
case "complete":
|
||||
reject(message.data.reportStatus);
|
||||
mm.removeMessageListener("ssler-test:SSLErrorReportStatus", statusListener);
|
||||
break;
|
||||
case "error":
|
||||
resolve(message.data.reportStatus);
|
||||
mm.removeMessageListener("ssler-test:SSLErrorReportStatus", statusListener);
|
||||
break;
|
||||
}
|
||||
};
|
||||
mm.addMessageListener("ssler-test:SSLErrorReportStatus", statusListener);
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
let promiseReport = createErrorReportPromise(browser);
|
||||
let promiseRetry = ContentTask.spawn(browser, null, function* () {
|
||||
content.document.getElementById("reportCertificateErrorRetry").click();
|
||||
});
|
||||
|
||||
// check that errors are sent
|
||||
yield reportErrors;
|
||||
yield Promise.all([promiseReport, promiseRetry]);
|
||||
ok(true, "SSL error report submitted successfully");
|
||||
|
||||
gBrowser.removeTab(tab);
|
||||
// Cleanup.
|
||||
gBrowser.removeCurrentTab();
|
||||
cleanup();
|
||||
});
|
||||
}
|
||||
|
||||
add_task(function* test_send_report_disabled() {
|
||||
setup();
|
||||
Services.prefs.setBoolPref("security.ssl.errorReporting.enabled", false);
|
||||
Services.prefs.setCharPref("security.ssl.errorReporting.url", "https://offdomain.com");
|
||||
function* testSetAutomatic(testURL, suffix, errorURISuffix) {
|
||||
Services.prefs.setBoolPref(PREF_REPORT_ENABLED, true);
|
||||
Services.prefs.setBoolPref(PREF_REPORT_AUTOMATIC, false);
|
||||
Services.prefs.setCharPref(PREF_REPORT_URL, URL_REPORTS + suffix);
|
||||
|
||||
let tab = gBrowser.addTab(badChainURL, {skipAnimation: true});
|
||||
// Add a tab and wait until it's loaded.
|
||||
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
|
||||
let browser = tab.linkedBrowser;
|
||||
let mm = browser.messageManager;
|
||||
mm.loadFrameScript(ROOT + "browser_ssl_error_reports_content.js", true);
|
||||
|
||||
gBrowser.selectedTab = tab;
|
||||
// Load the page.
|
||||
browser.loadURI(testURL);
|
||||
yield promiseErrorPageLoaded(browser);
|
||||
|
||||
// Ensure we have an error page
|
||||
let netError = createNetworkErrorMessagePromise(browser);
|
||||
yield netError;
|
||||
// Check that we loaded the right error page.
|
||||
yield checkErrorPage(browser, errorURISuffix);
|
||||
|
||||
let reportErrors = new Promise(function(resolve, reject) {
|
||||
let statusListener = function(message) {
|
||||
switch(message.data.reportStatus) {
|
||||
case "complete":
|
||||
mm.removeMessageListener("ssler-test:SSLErrorReportStatus", statusListener);
|
||||
reject(message.data.reportStatus);
|
||||
break;
|
||||
case "error":
|
||||
mm.removeMessageListener("ssler-test:SSLErrorReportStatus", statusListener);
|
||||
resolve(message.data.reportStatus);
|
||||
break;
|
||||
}
|
||||
};
|
||||
mm.addMessageListener("ssler-test:SSLErrorReportStatus", statusListener);
|
||||
// Click the checkbox, enable automatic error reports.
|
||||
let promiseReport = createErrorReportPromise(browser);
|
||||
yield ContentTask.spawn(browser, null, function* () {
|
||||
content.document.getElementById("automaticallyReportInFuture").click();
|
||||
});
|
||||
|
||||
// click the button
|
||||
mm.sendAsyncMessage("ssler-test:SendBtnClick",{forceUI:true});
|
||||
// Wait for the error report submission.
|
||||
yield promiseReport;
|
||||
ok(true, "SSL error report submitted successfully");
|
||||
|
||||
// check we get an error
|
||||
yield reportErrors;
|
||||
let isAutomaticReportingEnabled = () =>
|
||||
Services.prefs.getBoolPref(PREF_REPORT_AUTOMATIC);
|
||||
|
||||
// Check that the pref was flipped.
|
||||
ok(isAutomaticReportingEnabled(), "automatic SSL report submission enabled");
|
||||
|
||||
// Disable automatic error reports.
|
||||
yield ContentTask.spawn(browser, null, function* () {
|
||||
content.document.getElementById("automaticallyReportInFuture").click();
|
||||
});
|
||||
|
||||
// Check that the pref was flipped.
|
||||
ok(!isAutomaticReportingEnabled(), "automatic SSL report submission disabled");
|
||||
|
||||
// Cleanup.
|
||||
gBrowser.removeTab(tab);
|
||||
cleanup();
|
||||
});
|
||||
|
||||
function setup() {
|
||||
// ensure the relevant prefs are set
|
||||
enabledPref = Services.prefs.getBoolPref("security.ssl.errorReporting.enabled");
|
||||
automaticPref = Services.prefs.getBoolPref("security.ssl.errorReporting.automatic");
|
||||
urlPref = Services.prefs.getCharPref("security.ssl.errorReporting.url");
|
||||
|
||||
enforcement_level = Services.prefs.getIntPref("security.cert_pinning.enforcement_level");
|
||||
Services.prefs.setIntPref("security.cert_pinning.enforcement_level", 2);
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
// reset prefs for other tests in the run
|
||||
Services.prefs.setBoolPref("security.ssl.errorReporting.enabled", enabledPref);
|
||||
Services.prefs.setBoolPref("security.ssl.errorReporting.automatic", automaticPref);
|
||||
Services.prefs.setCharPref("security.ssl.errorReporting.url", urlPref);
|
||||
function* testSendReportDisabled(testURL, errorURISuffix) {
|
||||
// Add a tab and wait until it's loaded.
|
||||
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
|
||||
let browser = tab.linkedBrowser;
|
||||
|
||||
// Load the page.
|
||||
browser.loadURI(testURL);
|
||||
yield promiseErrorPageLoaded(browser);
|
||||
|
||||
// Check that we loaded the right error page.
|
||||
yield checkErrorPage(browser, errorURISuffix);
|
||||
|
||||
// Check that the error reporting section is hidden.
|
||||
let hidden = yield ContentTask.spawn(browser, null, function* () {
|
||||
let section = content.document.getElementById("certificateErrorReporting");
|
||||
return content.getComputedStyle(section).display == "none";
|
||||
});
|
||||
ok(hidden, "error reporting section should be hidden");
|
||||
|
||||
// Cleanup.
|
||||
gBrowser.removeTab(tab);
|
||||
}
|
||||
|
||||
function createErrorReportPromise(browser) {
|
||||
return ContentTask.spawn(browser, null, function* () {
|
||||
let type = "Browser:SSLErrorReportStatus";
|
||||
let active = false;
|
||||
|
||||
yield new Promise((resolve, reject) => {
|
||||
addMessageListener(type, function onReportStatus(message) {
|
||||
switch (message.data.reportStatus) {
|
||||
case "activity":
|
||||
active = true;
|
||||
break;
|
||||
case "complete":
|
||||
removeMessageListener(type, onReportStatus);
|
||||
if (active) {
|
||||
resolve(message.data.reportStatus);
|
||||
} else {
|
||||
reject("activity should be seen before success");
|
||||
}
|
||||
break;
|
||||
case "error":
|
||||
removeMessageListener(type, onReportStatus);
|
||||
reject("sending the report failed");
|
||||
break;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function promiseErrorPageLoaded(browser) {
|
||||
return new Promise(resolve => {
|
||||
browser.addEventListener("DOMContentLoaded", function onLoad() {
|
||||
browser.removeEventListener("DOMContentLoaded", onLoad, false, true);
|
||||
resolve();
|
||||
}, false, true);
|
||||
});
|
||||
}
|
||||
|
||||
function checkErrorPage(browser, suffix) {
|
||||
return ContentTask.spawn(browser, null, function* () {
|
||||
return content.document.documentURI;
|
||||
}).then(uri => {
|
||||
ok(uri.startsWith(`about:${suffix}`), "correct error page loaded");
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
addMessageListener("Browser:SSLErrorReportStatus", function(message) {
|
||||
sendSyncMessage("ssler-test:SSLErrorReportStatus", {reportStatus:message.data.reportStatus});
|
||||
});
|
||||
|
||||
addMessageListener("ssler-test:SetAutoPref", function(message) {
|
||||
let checkbox = content.document.getElementById("automaticallyReportInFuture");
|
||||
|
||||
// we use "click" because otherwise the 'changed' event will not fire
|
||||
if (checkbox.checked != message.data.value) {
|
||||
checkbox.click();
|
||||
}
|
||||
|
||||
sendSyncMessage("ssler-test:AutoPrefUpdated", {});
|
||||
});
|
||||
|
||||
addMessageListener("ssler-test:SendBtnClick", function(message) {
|
||||
if (message.data && message.data.forceUI) {
|
||||
content.dispatchEvent(new content.CustomEvent("AboutNetErrorOptions",
|
||||
{
|
||||
detail: "{\"enabled\": true, \"automatic\": false}"
|
||||
}));
|
||||
}
|
||||
let btn = content.document.getElementById("reportCertificateError");
|
||||
btn.click();
|
||||
});
|
|
@ -61,6 +61,20 @@ function handleRequest(request, response) {
|
|||
return;
|
||||
}
|
||||
|
||||
// if all is as expected, send the 201 the client expects
|
||||
response.setStatusLine("1.1", 201, "Created");
|
||||
response.write("<html>OK</html>");
|
||||
break;
|
||||
case "badcert":
|
||||
report = parseReport(request);
|
||||
certChain = report.failedCertChain;
|
||||
|
||||
if (!certChain || certChain.length != 2) {
|
||||
response.setStatusLine("1.1", 500, "Server error");
|
||||
response.write("<html>The report contained an unexpected chain</html>");
|
||||
return;
|
||||
}
|
||||
|
||||
// if all is as expected, send the 201 the client expects
|
||||
response.setStatusLine("1.1", 201, "Created");
|
||||
response.write("<html>OK</html>");
|
|
@ -34,3 +34,8 @@ tampering with your connection.</b>">
|
|||
you know there's a good reason why this site doesn't use trusted identification.">
|
||||
<!ENTITY certerror.addException.label "Add Exception…">
|
||||
<!ENTITY certerror.copyToClipboard.label "Copy text to clipboard">
|
||||
|
||||
<!ENTITY errorReporting.automatic "Report errors like this to help Mozilla identify misconfigured sites">
|
||||
<!ENTITY errorReporting.sending "Sending report">
|
||||
<!ENTITY errorReporting.sent "Report sent">
|
||||
<!ENTITY errorReporting.tryAgain "Try again">
|
||||
|
|
|
@ -208,7 +208,6 @@ functionality specific to firefox. -->
|
|||
<!ENTITY errorReporting.learnMore "Learn more…">
|
||||
<!ENTITY errorReporting.sending "Sending report">
|
||||
<!ENTITY errorReporting.sent "Report sent">
|
||||
<!ENTITY errorReporting.report "Report">
|
||||
<!ENTITY errorReporting.tryAgain "Try again">
|
||||
|
||||
<!ENTITY remoteXUL.title "Remote XUL">
|
||||
|
|
|
@ -96,6 +96,7 @@ body {
|
|||
|
||||
/* Advanced section is hidden via inline styles until the link is clicked */
|
||||
#advancedPanel {
|
||||
position: absolute;
|
||||
background-color: white;
|
||||
color: var(--in-content-text-color);
|
||||
border: 1px lightgray solid;
|
||||
|
@ -110,3 +111,10 @@ body {
|
|||
.hostname {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#reportCertificateErrorRetry,
|
||||
#certificateErrorReporting,
|
||||
#reportSendingMessage,
|
||||
#reportSentMessage {
|
||||
display: none;
|
||||
}
|
||||
|
|
|
@ -116,7 +116,6 @@ button:disabled {
|
|||
}
|
||||
|
||||
#certificateErrorReporting,
|
||||
#reportCertificateError,
|
||||
#reportSentMessage {
|
||||
display: none;
|
||||
}
|
||||
|
|
|
@ -265,7 +265,7 @@ user_pref('identity.fxaccounts.skipDeviceRegistration', true);
|
|||
user_pref("apz.content_response_timeout", 60000);
|
||||
|
||||
// Make sure SSL Error reports don't hit the network
|
||||
user_pref("security.ssl.errorReporting.url", "https://example.com/browser/browser/base/content/test/general/pinning_reports.sjs?succeed");
|
||||
user_pref("security.ssl.errorReporting.url", "https://example.com/browser/browser/base/content/test/general/ssl_error_reports.sjs?succeed");
|
||||
|
||||
// Make sure Translation won't hit the network.
|
||||
user_pref("browser.translation.bing.authURL", "http://%(server)s/browser/browser/components/translation/test/bing.sjs");
|
||||
|
|
Загрузка…
Ссылка в новой задаче