Bug 1561435 - Format browser/base/, a=automatic-formatting

# ignore-this-changeset

Differential Revision: https://phabricator.services.mozilla.com/D36041

--HG--
extra : source : 96b3895a3b2aa2fcb064c85ec5857b7216884556
This commit is contained in:
Victor Porof 2019-07-05 09:48:57 +02:00
Родитель 55d8d8e0e0
Коммит f9f5914039
582 изменённых файлов: 52966 добавлений и 29572 удалений

Просмотреть файл

@ -7,46 +7,64 @@
/* import-globals-from aboutDialog.js */
var {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
var { XPCOMUtils } = ChromeUtils.import(
"resource://gre/modules/XPCOMUtils.jsm"
);
ChromeUtils.defineModuleGetter(this, "DownloadUtils",
"resource://gre/modules/DownloadUtils.jsm");
ChromeUtils.defineModuleGetter(this, "UpdateUtils",
"resource://gre/modules/UpdateUtils.jsm");
ChromeUtils.defineModuleGetter(
this,
"DownloadUtils",
"resource://gre/modules/DownloadUtils.jsm"
);
ChromeUtils.defineModuleGetter(
this,
"UpdateUtils",
"resource://gre/modules/UpdateUtils.jsm"
);
const PREF_APP_UPDATE_CANCELATIONS_OSX = "app.update.cancelations.osx";
const PREF_APP_UPDATE_ELEVATE_NEVER = "app.update.elevate.never";
const PREF_APP_UPDATE_ELEVATE_NEVER = "app.update.elevate.never";
var gAppUpdater;
function onUnload(aEvent) {
if (gAppUpdater) {
if (gAppUpdater.isChecking)
if (gAppUpdater.isChecking) {
gAppUpdater.checker.stopCurrentCheck();
}
// Safe to call even when there isn't a download in progress.
gAppUpdater.removeDownloadListener();
gAppUpdater = null;
}
}
function appUpdater(options = {}) {
XPCOMUtils.defineLazyServiceGetter(this, "aus",
"@mozilla.org/updates/update-service;1",
"nsIApplicationUpdateService");
XPCOMUtils.defineLazyServiceGetter(this, "checker",
"@mozilla.org/updates/update-checker;1",
"nsIUpdateChecker");
XPCOMUtils.defineLazyServiceGetter(this, "um",
"@mozilla.org/updates/update-manager;1",
"nsIUpdateManager");
XPCOMUtils.defineLazyServiceGetter(
this,
"aus",
"@mozilla.org/updates/update-service;1",
"nsIApplicationUpdateService"
);
XPCOMUtils.defineLazyServiceGetter(
this,
"checker",
"@mozilla.org/updates/update-checker;1",
"nsIUpdateChecker"
);
XPCOMUtils.defineLazyServiceGetter(
this,
"um",
"@mozilla.org/updates/update-manager;1",
"nsIUpdateManager"
);
this.options = options;
this.updateDeck = document.getElementById("updateDeck");
this.promiseAutoUpdateSetting = null;
this.bundle = Services.strings.
createBundle("chrome://browser/locale/browser.properties");
this.bundle = Services.strings.createBundle(
"chrome://browser/locale/browser.properties"
);
let manualURL = Services.urlFormatter.formatURLPref("app.update.url.manual");
let manualLink = document.getElementById("manualLink");
@ -92,32 +110,39 @@ function appUpdater(options = {}) {
this.checkForUpdates();
}
appUpdater.prototype =
{
appUpdater.prototype = {
// true when there is an update check in progress.
isChecking: false,
// true when there is an update ready to be applied on restart or staged.
get isPending() {
if (this.update) {
return this.update.state == "pending" ||
this.update.state == "pending-service" ||
this.update.state == "pending-elevate";
return (
this.update.state == "pending" ||
this.update.state == "pending-service" ||
this.update.state == "pending-elevate"
);
}
return this.um.activeUpdate &&
(this.um.activeUpdate.state == "pending" ||
this.um.activeUpdate.state == "pending-service" ||
this.um.activeUpdate.state == "pending-elevate");
return (
this.um.activeUpdate &&
(this.um.activeUpdate.state == "pending" ||
this.um.activeUpdate.state == "pending-service" ||
this.um.activeUpdate.state == "pending-elevate")
);
},
// true when there is an update already staged.
get isApplied() {
if (this.update)
return this.update.state == "applied" ||
this.update.state == "applied-service";
return this.um.activeUpdate &&
(this.um.activeUpdate.state == "applied" ||
this.um.activeUpdate.state == "applied-service");
if (this.update) {
return (
this.update.state == "applied" || this.update.state == "applied-service"
);
}
return (
this.um.activeUpdate &&
(this.um.activeUpdate.state == "applied" ||
this.um.activeUpdate.state == "applied-service")
);
},
get isStaging() {
@ -154,10 +179,10 @@ appUpdater.prototype =
// true when there is an update download in progress.
get isDownloading() {
if (this.update)
if (this.update) {
return this.update.state == "downloading";
return this.um.activeUpdate &&
this.um.activeUpdate.state == "downloading";
}
return this.um.activeUpdate && this.um.activeUpdate.state == "downloading";
},
// true when updating has been disabled by enterprise policy
@ -167,8 +192,7 @@ appUpdater.prototype =
// true when updating in background is enabled.
get updateStagingEnabled() {
return !this.updateDisabledByPolicy &&
this.aus.canStageUpdates;
return !this.updateDisabledByPolicy && this.aus.canStageUpdates;
},
/**
@ -192,13 +216,21 @@ appUpdater.prototype =
let day = buildID.slice(6, 8);
updateVersion += ` (${year}-${month}-${day})`;
}
button.label = this.bundle.formatStringFromName("update.downloadAndInstallButton.label", [updateVersion]);
button.accessKey = this.bundle.GetStringFromName("update.downloadAndInstallButton.accesskey");
button.label = this.bundle.formatStringFromName(
"update.downloadAndInstallButton.label",
[updateVersion]
);
button.accessKey = this.bundle.GetStringFromName(
"update.downloadAndInstallButton.accesskey"
);
}
this.updateDeck.selectedPanel = panel;
if (this.options.buttonAutoFocus &&
(!document.commandDispatcher.focusedElement || // don't steal the focus
document.commandDispatcher.focusedElement.localName == "button")) { // except from the other buttons
if (
this.options.buttonAutoFocus &&
(!document.commandDispatcher.focusedElement || // don't steal the focus
document.commandDispatcher.focusedElement.localName == "button")
) {
// except from the other buttons
button.focus();
}
} else {
@ -235,9 +267,14 @@ appUpdater.prototype =
gAppUpdater.selectPanel("restarting");
// Notify all windows that an application quit has been requested.
let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"].
createInstance(Ci.nsISupportsPRBool);
Services.obs.notifyObservers(cancelQuit, "quit-application-requested", "restart");
let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"].createInstance(
Ci.nsISupportsPRBool
);
Services.obs.notifyObservers(
cancelQuit,
"quit-application-requested",
"restart"
);
// Something aborted the quit process.
if (cancelQuit.data) {
@ -251,8 +288,9 @@ appUpdater.prototype =
return;
}
Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit |
Ci.nsIAppStartup.eRestart);
Services.startup.quit(
Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart
);
},
/**
@ -266,8 +304,7 @@ appUpdater.prototype =
*/
onCheckComplete(aRequest, aUpdates) {
gAppUpdater.isChecking = false;
gAppUpdater.update = gAppUpdater.aus.
selectUpdate(aUpdates);
gAppUpdater.update = gAppUpdater.aus.selectUpdate(aUpdates);
if (!gAppUpdater.update) {
gAppUpdater.selectPanel("noUpdatesFound");
return;
@ -291,9 +328,11 @@ appUpdater.prototype =
gAppUpdater.promiseAutoUpdateSetting = UpdateUtils.getAppUpdateAutoEnabled();
}
gAppUpdater.promiseAutoUpdateSetting.then(updateAuto => {
if (updateAuto) { // automatically download and install
if (updateAuto) {
// automatically download and install
gAppUpdater.startDownload();
} else { // ask
} else {
// ask
gAppUpdater.selectPanel("downloadAndInstall");
}
});
@ -320,8 +359,9 @@ appUpdater.prototype =
* Shows the applying UI until the update has finished staging
*/
waitForUpdateToStage() {
if (!this.update)
if (!this.update) {
this.update = this.um.activeUpdate;
}
this.update.QueryInterface(Ci.nsIWritablePropertyBag);
this.update.setProperty("foregroundDownload", "true");
this.selectPanel("applying");
@ -332,8 +372,9 @@ appUpdater.prototype =
* Starts the download of an update mar.
*/
startDownload() {
if (!this.update)
if (!this.update) {
this.update = this.um.activeUpdate;
}
this.update.QueryInterface(Ci.nsIWritablePropertyBag);
this.update.setProperty("foregroundDownload", "true");
@ -351,8 +392,10 @@ appUpdater.prototype =
*/
setupDownloadingUI() {
this.downloadStatus = document.getElementById("downloadStatus");
this.downloadStatus.textContent =
DownloadUtils.getTransferTotal(0, this.update.selectedPatch.size);
this.downloadStatus.textContent = DownloadUtils.getTransferTotal(
0,
this.update.selectedPatch.size
);
this.selectPanel("downloading");
this.aus.addDownloadListener(this);
},
@ -366,57 +409,59 @@ appUpdater.prototype =
/**
* See nsIRequestObserver.idl
*/
onStartRequest(aRequest) {
},
onStartRequest(aRequest) {},
/**
* See nsIRequestObserver.idl
*/
onStopRequest(aRequest, aStatusCode) {
switch (aStatusCode) {
case Cr.NS_ERROR_UNEXPECTED:
if (this.update.selectedPatch.state == "download-failed" &&
(this.update.isCompleteUpdate || this.update.patchCount != 2)) {
// Verification error of complete patch, informational text is held in
// the update object.
case Cr.NS_ERROR_UNEXPECTED:
if (
this.update.selectedPatch.state == "download-failed" &&
(this.update.isCompleteUpdate || this.update.patchCount != 2)
) {
// Verification error of complete patch, informational text is held in
// the update object.
this.removeDownloadListener();
this.selectPanel("downloadFailed");
break;
}
// Verification failed for a partial patch, complete patch is now
// downloading so return early and do NOT remove the download listener!
break;
case Cr.NS_BINDING_ABORTED:
// Do not remove UI listener since the user may resume downloading again.
break;
case Cr.NS_OK:
this.removeDownloadListener();
if (this.updateStagingEnabled) {
this.selectPanel("applying");
this.updateUIWhenStagingComplete();
} else {
this.selectPanel("apply");
}
break;
default:
this.removeDownloadListener();
this.selectPanel("downloadFailed");
break;
}
// Verification failed for a partial patch, complete patch is now
// downloading so return early and do NOT remove the download listener!
break;
case Cr.NS_BINDING_ABORTED:
// Do not remove UI listener since the user may resume downloading again.
break;
case Cr.NS_OK:
this.removeDownloadListener();
if (this.updateStagingEnabled) {
this.selectPanel("applying");
this.updateUIWhenStagingComplete();
} else {
this.selectPanel("apply");
}
break;
default:
this.removeDownloadListener();
this.selectPanel("downloadFailed");
break;
}
},
/**
* See nsIProgressEventSink.idl
*/
onStatus(aRequest, aContext, aStatus, aStatusArg) {
},
onStatus(aRequest, aContext, aStatus, aStatusArg) {},
/**
* See nsIProgressEventSink.idl
*/
onProgress(aRequest, aContext, aProgress, aProgressMax) {
this.downloadStatus.textContent =
DownloadUtils.getTransferTotal(aProgress, aProgressMax);
this.downloadStatus.textContent = DownloadUtils.getTransferTotal(
aProgress,
aProgressMax
);
},
/**
@ -430,9 +475,13 @@ appUpdater.prototype =
let observer = (aSubject, aTopic, aData) => {
// Update the UI when the background updater is finished
let status = aData;
if (status == "applied" || status == "applied-service" ||
status == "pending" || status == "pending-service" ||
status == "pending-elevate") {
if (
status == "applied" ||
status == "applied-service" ||
status == "pending" ||
status == "pending-service" ||
status == "pending-elevate"
) {
// If the update is successfully applied, or if the updater has
// fallen back to non-staged updates, show the "Restart to Update"
// button.
@ -456,5 +505,8 @@ appUpdater.prototype =
/**
* See nsISupports.idl
*/
QueryInterface: ChromeUtils.generateQI(["nsIProgressEventSink", "nsIRequestObserver"]),
QueryInterface: ChromeUtils.generateQI([
"nsIProgressEventSink",
"nsIRequestObserver",
]),
};

Просмотреть файл

@ -7,12 +7,15 @@
/* import-globals-from aboutDialog-appUpdater.js */
// Services = object with smart getters for common XPCOM services
var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
var {AppConstants} = ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
var { AppConstants } = ChromeUtils.import(
"resource://gre/modules/AppConstants.jsm"
);
async function init(aEvent) {
if (aEvent.target != document)
if (aEvent.target != document) {
return;
}
var distroId = Services.prefs.getCharPref("distribution.id", "");
if (distroId) {
@ -66,7 +69,9 @@ async function init(aEvent) {
let relNotesLink = document.getElementById("releasenotes");
let relNotesPrefType = Services.prefs.getPrefType("app.releaseNotesURL");
if (relNotesPrefType != Services.prefs.PREF_INVALID) {
let relNotesURL = Services.urlFormatter.formatURLPref("app.releaseNotesURL");
let relNotesURL = Services.urlFormatter.formatURLPref(
"app.releaseNotesURL"
);
if (relNotesURL != "about:blank") {
relNotesLink.href = relNotesURL;
relNotesLink.hidden = false;
@ -79,8 +84,9 @@ async function init(aEvent) {
let channelLabel = document.getElementById("currentChannel");
let currentChannelText = document.getElementById("currentChannelText");
channelLabel.value = UpdateUtils.UpdateChannel;
if (/^release($|\-)/.test(channelLabel.value))
currentChannelText.hidden = true;
if (/^release($|\-)/.test(channelLabel.value)) {
currentChannelText.hidden = true;
}
}
if (AppConstants.MOZ_APP_VERSION_DISPLAY.endsWith("esr")) {
@ -90,6 +96,9 @@ async function init(aEvent) {
window.sizeToContent();
if (AppConstants.platform == "macosx") {
window.moveTo((screen.availWidth / 2) - (window.outerWidth / 2), screen.availHeight / 5);
window.moveTo(
screen.availWidth / 2 - window.outerWidth / 2,
screen.availHeight / 5
);
}
}

Просмотреть файл

@ -56,8 +56,8 @@ function retryThis(buttonEl) {
function toggleDisplay(node) {
const toggle = {
"": "block",
"none": "block",
"block": "none",
none: "block",
block: "none",
};
return (node.style.display = toggle[node.style.display]);
}
@ -71,10 +71,14 @@ function showPrefChangeContainer() {
const panel = document.getElementById("prefChangeContainer");
panel.style.display = "block";
document.getElementById("netErrorButtonContainer").style.display = "none";
document.getElementById("prefResetButton").addEventListener("click", function resetPreferences(e) {
const event = new CustomEvent("AboutNetErrorResetPreferences", {bubbles: true});
document.dispatchEvent(event);
});
document
.getElementById("prefResetButton")
.addEventListener("click", function resetPreferences(e) {
const event = new CustomEvent("AboutNetErrorResetPreferences", {
bubbles: true,
});
document.dispatchEvent(event);
});
addAutofocus("#prefResetButton", "beforeend");
}
@ -86,7 +90,9 @@ function setupAdvancedButton() {
}
// Register click handler for the weakCryptoAdvancedPanel
document.getElementById("advancedButton").addEventListener("click", togglePanelVisibility);
document
.getElementById("advancedButton")
.addEventListener("click", togglePanelVisibility);
function togglePanelVisibility() {
toggleDisplay(panel);
@ -100,7 +106,7 @@ function setupAdvancedButton() {
if (panel.style.display == "block") {
// send event to trigger telemetry ping
var event = new CustomEvent("AboutNetErrorUIExpanded", {bubbles: true});
var event = new CustomEvent("AboutNetErrorUIExpanded", { bubbles: true });
document.dispatchEvent(event);
}
}
@ -127,19 +133,27 @@ function disallowCertOverridesIfNeeded() {
// host and the cert is bad (STS Spec section 7.3) or if the
// certerror is in a frame (bug 633691).
if (cssClass == "badStsCert" || window != top) {
document.getElementById("exceptionDialogButton").setAttribute("hidden", "true");
document
.getElementById("exceptionDialogButton")
.setAttribute("hidden", "true");
}
if (cssClass == "badStsCert") {
document.getElementById("badStsCertExplanation").removeAttribute("hidden");
let stsReturnButtonText = document.getElementById("stsReturnButtonText").textContent;
let stsReturnButtonText = document.getElementById("stsReturnButtonText")
.textContent;
document.getElementById("returnButton").textContent = stsReturnButtonText;
document.getElementById("advancedPanelReturnButton").textContent = stsReturnButtonText;
document.getElementById(
"advancedPanelReturnButton"
).textContent = stsReturnButtonText;
let stsMitmWhatCanYouDoAboutIt3 =
document.getElementById("stsMitmWhatCanYouDoAboutIt3").innerHTML;
let stsMitmWhatCanYouDoAboutIt3 = document.getElementById(
"stsMitmWhatCanYouDoAboutIt3"
).innerHTML;
// eslint-disable-next-line no-unsanitized/property
document.getElementById("mitmWhatCanYouDoAboutIt3").innerHTML = stsMitmWhatCanYouDoAboutIt3;
document.getElementById(
"mitmWhatCanYouDoAboutIt3"
).innerHTML = stsMitmWhatCanYouDoAboutIt3;
}
}
@ -147,8 +161,13 @@ function initPage() {
var err = getErrorCode();
// List of error pages with an illustration.
let illustratedErrors = [
"malformedURI", "dnsNotFound", "connectionFailure", "netInterrupt",
"netTimeout", "netReset", "netOffline",
"malformedURI",
"dnsNotFound",
"connectionFailure",
"netInterrupt",
"netTimeout",
"netReset",
"netOffline",
];
if (illustratedErrors.includes(err)) {
document.body.classList.add("illustrated", err);
@ -157,7 +176,7 @@ function initPage() {
document.body.classList.add("blocked");
}
gIsCertError = (err == "nssBadCert");
gIsCertError = err == "nssBadCert";
// Only worry about captive portals if this is a cert error.
let showCaptivePortalUI = isCaptive() && gIsCertError;
if (showCaptivePortalUI) {
@ -182,10 +201,10 @@ function initPage() {
// if it's an unknown error or there's no title or description
// defined, get the generic message
var errTitle = document.getElementById("et_" + l10nErrId);
var errDesc = document.getElementById("ed_" + l10nErrId);
var errDesc = document.getElementById("ed_" + l10nErrId);
if (!errTitle || !errDesc) {
errTitle = document.getElementById("et_generic");
errDesc = document.getElementById("ed_generic");
errDesc = document.getElementById("ed_generic");
}
// eslint-disable-next-line no-unsanitized/property
@ -240,45 +259,57 @@ function initPage() {
document.getElementById("netErrorButtonContainer").style.display = "none";
}
window.addEventListener("AboutNetErrorOptions", function(evt) {
// Pinning errors are of type nssFailure2
if (getErrorCode() == "nssFailure2") {
let shortDesc = document.getElementById("errorShortDescText").textContent;
document.getElementById("learnMoreContainer").style.display = "block";
var options = JSON.parse(evt.detail);
if (options && options.enabled) {
var checkbox = document.getElementById("automaticallyReportInFuture");
showCertificateErrorReporting();
if (options.automatic) {
// set the checkbox
checkbox.checked = true;
}
window.addEventListener(
"AboutNetErrorOptions",
function(evt) {
// Pinning errors are of type nssFailure2
if (getErrorCode() == "nssFailure2") {
let shortDesc = document.getElementById("errorShortDescText")
.textContent;
document.getElementById("learnMoreContainer").style.display = "block";
var options = JSON.parse(evt.detail);
if (options && options.enabled) {
var checkbox = document.getElementById("automaticallyReportInFuture");
showCertificateErrorReporting();
if (options.automatic) {
// set the checkbox
checkbox.checked = true;
}
checkbox.addEventListener("change", function(changeEvt) {
var event = new CustomEvent("AboutNetErrorSetAutomatic",
{bubbles: true,
detail: changeEvt.target.checked});
checkbox.addEventListener("change", function(changeEvt) {
var event = new CustomEvent("AboutNetErrorSetAutomatic", {
bubbles: true,
detail: changeEvt.target.checked,
});
document.dispatchEvent(event);
});
}
const hasPrefStyleError = [
"interrupted", // This happens with subresources that are above the max tls
"SSL_ERROR_PROTOCOL_VERSION_ALERT",
"SSL_ERROR_UNSUPPORTED_VERSION",
"SSL_ERROR_NO_CYPHER_OVERLAP",
"SSL_ERROR_NO_CIPHERS_SUPPORTED",
].some(substring => shortDesc.includes(substring));
// If it looks like an error that is user config based
if (
getErrorCode() == "nssFailure2" &&
hasPrefStyleError &&
options &&
options.changedCertPrefs
) {
showPrefChangeContainer();
}
}
const hasPrefStyleError = [
"interrupted", // This happens with subresources that are above the max tls
"SSL_ERROR_PROTOCOL_VERSION_ALERT",
"SSL_ERROR_UNSUPPORTED_VERSION",
"SSL_ERROR_NO_CYPHER_OVERLAP",
"SSL_ERROR_NO_CIPHERS_SUPPORTED",
].some((substring) => shortDesc.includes(substring));
// If it looks like an error that is user config based
if (getErrorCode() == "nssFailure2" && hasPrefStyleError && options && options.changedCertPrefs) {
showPrefChangeContainer();
if (getErrorCode() == "sslv3Used") {
document.getElementById("advancedButton").style.display = "none";
}
}
if (getErrorCode() == "sslv3Used") {
document.getElementById("advancedButton").style.display = "none";
}
}, true, true);
},
true,
true
);
var event = new CustomEvent("AboutNetErrorLoad", {bubbles: true});
var event = new CustomEvent("AboutNetErrorLoad", { bubbles: true });
document.dispatchEvent(event);
if (err == "inadequateSecurityError" || err == "blockedByPolicy") {
@ -304,9 +335,12 @@ function updateContainerPosition() {
// Unfortunately, this doesn't work correctly in iframes, which is why we need
// to manually compute the height there.
if (window.parent == window) {
textContainer.style.marginTop = `calc(50vh - ${textContainer.clientHeight / 2}px)`;
textContainer.style.marginTop = `calc(50vh - ${textContainer.clientHeight /
2}px)`;
} else {
let offset = (document.documentElement.clientHeight / 2) - (textContainer.clientHeight / 2);
let offset =
document.documentElement.clientHeight / 2 -
textContainer.clientHeight / 2;
if (offset > 0) {
textContainer.style.marginTop = `${offset}px`;
}
@ -315,10 +349,11 @@ function updateContainerPosition() {
function initPageCaptivePortal() {
document.body.className = "captiveportal";
document.getElementById("openPortalLoginPageButton")
.addEventListener("click", () => {
RPMSendAsyncMessage("Browser:OpenCaptivePortalPage");
});
document
.getElementById("openPortalLoginPageButton")
.addEventListener("click", () => {
RPMSendAsyncMessage("Browser:OpenCaptivePortalPage");
});
addAutofocus("#openPortalLoginPageButton");
setupAdvancedButton();
@ -342,20 +377,29 @@ function initPageCertError() {
document.getElementById("learnMoreContainer").style.display = "block";
let checkbox = document.getElementById("automaticallyReportInFuture");
checkbox.addEventListener("change", function({target: {checked}}) {
document.dispatchEvent(new CustomEvent("AboutNetErrorSetAutomatic", {
detail: checked,
bubbles: true,
}));
checkbox.addEventListener("change", function({ target: { checked } }) {
document.dispatchEvent(
new CustomEvent("AboutNetErrorSetAutomatic", {
detail: checked,
bubbles: true,
})
);
});
let errorReportingEnabled = RPMGetBoolPref("security.ssl.errorReporting.enabled");
let errorReportingEnabled = RPMGetBoolPref(
"security.ssl.errorReporting.enabled"
);
if (errorReportingEnabled) {
document.getElementById("certificateErrorReporting").style.display = "block";
let errorReportingAutomatic = RPMGetBoolPref("security.ssl.errorReporting.automatic");
document.getElementById("certificateErrorReporting").style.display =
"block";
let errorReportingAutomatic = RPMGetBoolPref(
"security.ssl.errorReporting.automatic"
);
checkbox.checked = !!errorReportingAutomatic;
}
let hideAddExceptionButton = RPMGetBoolPref("security.certerror.hideAddException");
let hideAddExceptionButton = RPMGetBoolPref(
"security.certerror.hideAddException"
);
if (hideAddExceptionButton) {
document.querySelector(".exceptionDialogButtonContainer").hidden = true;
}
@ -365,7 +409,7 @@ function initPageCertError() {
// Telemetry values for events are max. 80 bytes.
errorCode: failedCertInfo.errorCodeString.substring(0, 40),
has_sts: getCSSClass() == "badStsCert",
is_frame: window.parent != window,
is_frame: window.parent != window,
});
let certErrorButtons = ["advancedButton", "copyToClipboard"];
@ -378,7 +422,7 @@ function initPageCertError() {
setTechnicalDetailsOnCertError();
// Dispatch this event only for tests.
let event = new CustomEvent("AboutNetErrorLoad", {bubbles: true});
let event = new CustomEvent("AboutNetErrorLoad", { bubbles: true });
document.dispatchEvent(event);
}
@ -400,23 +444,38 @@ async function getCertErrorInfo() {
let errorMessage = failedCertInfo.errorMessage;
let hasHSTS = failedCertInfo.hasHSTS.toString();
let hasHPKP = failedCertInfo.hasHPKP.toString();
let [hstsLabel] =
await document.l10n.formatValues([{id: "cert-error-details-hsts-label", args: { hasHSTS }}]);
let [hpkpLabel] =
await document.l10n.formatValues([{id: "cert-error-details-key-pinning-label", args: { hasHPKP }}]);
let [hstsLabel] = await document.l10n.formatValues([
{ id: "cert-error-details-hsts-label", args: { hasHSTS } },
]);
let [hpkpLabel] = await document.l10n.formatValues([
{ id: "cert-error-details-key-pinning-label", args: { hasHPKP } },
]);
let certStrings = failedCertInfo.certChainStrings;
let failedChainCertificates = "";
for (let der64 of certStrings) {
let wrapped = der64.replace(/(\S{64}(?!$))/g, "$1\r\n");
failedChainCertificates += "-----BEGIN CERTIFICATE-----\r\n"
+ wrapped
+ "\r\n-----END CERTIFICATE-----\r\n";
failedChainCertificates +=
"-----BEGIN CERTIFICATE-----\r\n" +
wrapped +
"\r\n-----END CERTIFICATE-----\r\n";
}
let [failedChainLabel] = await document.l10n.formatValues([{id: "cert-error-details-cert-chain-label"}]);
let [failedChainLabel] = await document.l10n.formatValues([
{ id: "cert-error-details-cert-chain-label" },
]);
let details = location + "\r\n\r\n" + errorMessage + "\r\n\r\n" + hstsLabel + "\r\n" + hpkpLabel +
"\r\n\r\n" + failedChainLabel + "\r\n\r\n" + failedChainCertificates;
let details =
location +
"\r\n\r\n" +
errorMessage +
"\r\n\r\n" +
hstsLabel +
"\r\n" +
hpkpLabel +
"\r\n\r\n" +
failedChainLabel +
"\r\n\r\n" +
failedChainCertificates;
return details;
}
@ -425,11 +484,15 @@ async function setCertErrorDetails(event) {
// detects an intercepted connection, the page may be reloaded with a new
// error code (MOZILLA_PKIX_ERROR_MITM_DETECTED).
let failedCertInfo = document.getFailedCertSecurityInfo();
let mitmPrimingEnabled = RPMGetBoolPref("security.certerrors.mitm.priming.enabled");
if (mitmPrimingEnabled &&
failedCertInfo.errorCodeString == "SEC_ERROR_UNKNOWN_ISSUER" &&
// Only do this check for top-level failures.
window.parent == window) {
let mitmPrimingEnabled = RPMGetBoolPref(
"security.certerrors.mitm.priming.enabled"
);
if (
mitmPrimingEnabled &&
failedCertInfo.errorCodeString == "SEC_ERROR_UNKNOWN_ISSUER" &&
// Only do this check for top-level failures.
window.parent == window
) {
RPMSendAsyncMessage("Browser:PrimeMitm");
}
@ -438,7 +501,9 @@ async function setCertErrorDetails(event) {
let learnMoreLink = document.getElementById("learnMoreLink");
let baseURL = RPMGetFormatURLPref("app.support.baseURL");
learnMoreLink.setAttribute("href", baseURL + "connection-not-secure");
let errWhatToDo = document.getElementById("es_nssBadCert_" + failedCertInfo.errorCodeString);
let errWhatToDo = document.getElementById(
"es_nssBadCert_" + failedCertInfo.errorCodeString
);
let es = document.getElementById("errorWhatToDoText");
let errWhatToDoTitle = document.getElementById("edd_nssBadCert");
let est = document.getElementById("errorWhatToDoTitleText");
@ -453,7 +518,10 @@ async function setCertErrorDetails(event) {
// nssFailure2 also gets us other non-overrideable errors. Choose
// a "learn more" link based on description:
if (shortDesc.includes("MOZILLA_PKIX_ERROR_KEY_PINNING_FAILURE")) {
learnMoreLink.setAttribute("href", baseURL + "certificate-pinning-reports");
learnMoreLink.setAttribute(
"href",
baseURL + "certificate-pinning-reports"
);
}
}
@ -485,19 +553,28 @@ async function setCertErrorDetails(event) {
case "MOZILLA_PKIX_ERROR_ADDITIONAL_POLICY_CONSTRAINT_FAILED":
desc = document.getElementById("errorShortDescText2");
let hostname = document.location.hostname;
document.l10n.setAttributes(desc, "cert-error-symantec-distrust-description", {
hostname,
});
document.l10n.setAttributes(
desc,
"cert-error-symantec-distrust-description",
{
hostname,
}
);
let adminDesc = document.createElement("p");
document.l10n.setAttributes(adminDesc, "cert-error-symantec-distrust-admin");
document.l10n.setAttributes(
adminDesc,
"cert-error-symantec-distrust-admin"
);
learnMoreLink.href = baseURL + "symantec-warning";
updateContainerPosition();
break;
case "MOZILLA_PKIX_ERROR_MITM_DETECTED":
let autoEnabledEnterpriseRoots = RPMGetBoolPref("security.enterprise_roots.auto-enabled");
let autoEnabledEnterpriseRoots = RPMGetBoolPref(
"security.enterprise_roots.auto-enabled"
);
if (mitmPrimingEnabled && autoEnabledEnterpriseRoots) {
RPMSendAsyncMessage("Browser:ResetEnterpriseRootsPref");
}
@ -543,7 +620,8 @@ async function setCertErrorDetails(event) {
// We check against the remote-settings server time first if available, because that allows us
// to give the user an approximation of what the correct time is.
let difference = RPMGetIntPref("services.settings.clock_skew_seconds");
let lastFetched = RPMGetIntPref("services.settings.last_update_seconds") * 1000;
let lastFetched =
RPMGetIntPref("services.settings.last_update_seconds") * 1000;
let now = Date.now();
let certRange = {
@ -553,11 +631,15 @@ async function setCertErrorDetails(event) {
let approximateDate = now - difference * 1000;
// If the difference is more than a day, we last fetched the date in the last 5 days,
// and adjusting the date per the interval would make the cert valid, warn the user:
if (Math.abs(difference) > 60 * 60 * 24 && (now - lastFetched) <= 60 * 60 * 24 * 5 &&
certRange.notBefore < approximateDate && certRange.notAfter > approximateDate) {
if (
Math.abs(difference) > 60 * 60 * 24 &&
now - lastFetched <= 60 * 60 * 24 * 5 &&
certRange.notBefore < approximateDate &&
certRange.notAfter > approximateDate
) {
clockSkew = true;
// If there is no clock skew with Kinto servers, check against the build date.
// (The Kinto ping could have happened when the time was still right, or not at all)
// If there is no clock skew with Kinto servers, check against the build date.
// (The Kinto ping could have happened when the time was still right, or not at all)
} else {
let appBuildID = RPMGetAppBuildID();
let year = parseInt(appBuildID.substr(0, 4), 10);
@ -571,36 +653,48 @@ async function setCertErrorDetails(event) {
// as it is of course almost certain that it is now later than the build date,
// so we shouldn't exclude the possibility that the cert has become valid
// since the build date.
if (buildDate > systemDate && new Date(certRange.notAfter) > buildDate) {
if (
buildDate > systemDate &&
new Date(certRange.notAfter) > buildDate
) {
clockSkew = true;
}
}
let systemDate = formatter.format(new Date());
document.getElementById("wrongSystemTime_systemDate1").textContent = systemDate;
document.getElementById(
"wrongSystemTime_systemDate1"
).textContent = systemDate;
if (clockSkew) {
document.body.classList.add("illustrated", "clockSkewError");
let clockErrTitle = document.getElementById("et_clockSkewError");
let clockErrDesc = document.getElementById("ed_clockSkewError");
// eslint-disable-next-line no-unsanitized/property
document.querySelector(".title-text").textContent = clockErrTitle.textContent;
document.querySelector(".title-text").textContent =
clockErrTitle.textContent;
desc = document.getElementById("errorShortDescText");
document.getElementById("errorShortDesc").style.display = "block";
document.getElementById("certificateErrorReporting").style.display = "none";
document.getElementById("certificateErrorReporting").style.display =
"none";
if (desc) {
// eslint-disable-next-line no-unsanitized/property
desc.innerHTML = clockErrDesc.innerHTML;
}
let errorPageContainer = document.getElementById("errorPageContainer");
let textContainer = document.getElementById("text-container");
errorPageContainer.style.backgroundPosition = `left top calc(50vh - ${textContainer.clientHeight / 2}px)`;
errorPageContainer.style.backgroundPosition = `left top calc(50vh - ${textContainer.clientHeight /
2}px)`;
} else {
let targetElems = document.querySelectorAll("#wrongSystemTime_systemDate2");
let targetElems = document.querySelectorAll(
"#wrongSystemTime_systemDate2"
);
for (let elem of targetElems) {
elem.textContent = systemDate;
}
let errDesc = document.getElementById("ed_nssBadCert_SEC_ERROR_EXPIRED_CERTIFICATE");
let errDesc = document.getElementById(
"ed_nssBadCert_SEC_ERROR_EXPIRED_CERTIFICATE"
);
let sd = document.getElementById("errorShortDescText");
// eslint-disable-next-line no-unsanitized/property
sd.innerHTML = errDesc.innerHTML;
@ -615,7 +709,8 @@ async function setCertErrorDetails(event) {
let cssClass = getCSSClass();
let stsSuffix = cssClass == "badStsCert" ? "_sts" : "";
let errDesc2 = document.getElementById(
`ed2_nssBadCert_SEC_ERROR_EXPIRED_CERTIFICATE${stsSuffix}`);
`ed2_nssBadCert_SEC_ERROR_EXPIRED_CERTIFICATE${stsSuffix}`
);
let sd2 = document.getElementById("errorShortDescText2");
// eslint-disable-next-line no-unsanitized/property
sd2.innerHTML = errDesc2.innerHTML;
@ -627,8 +722,8 @@ async function setCertErrorDetails(event) {
}
if (est) {
// eslint-disable-next-line no-unsanitized/property
est.textContent = errWhatToDoTitle.textContent;
est.style.fontWeight = "bold";
est.textContent = errWhatToDoTitle.textContent;
est.style.fontWeight = "bold";
}
updateContainerPosition();
}
@ -639,13 +734,16 @@ async function setCertErrorDetails(event) {
// show that the error is harmless or can not be skipped anyway.
let cssClass = getCSSClass();
// Don't alarm users when they can't continue to the website anyway...
if (cssClass != "badStsCert" &&
// Errors in iframes can't be skipped either...
window.parent == window &&
// Also don't bother if it's just the user's clock being off...
!clockSkew &&
// Symantec distrust is likely harmless as well.
failedCertInfo.erroCodeString != "MOZILLA_PKIX_ERROR_ADDITIONAL_POLICY_CONSTRAINT_FAILED") {
if (
cssClass != "badStsCert" &&
// Errors in iframes can't be skipped either...
window.parent == window &&
// Also don't bother if it's just the user's clock being off...
!clockSkew &&
// Symantec distrust is likely harmless as well.
failedCertInfo.erroCodeString !=
"MOZILLA_PKIX_ERROR_ADDITIONAL_POLICY_CONSTRAINT_FAILED"
) {
document.body.classList.add("caution");
}
}
@ -679,7 +777,7 @@ function setTechnicalDetailsOnCertError() {
}
let cssClass = getCSSClass();
let error = getErrorCode();
let error = getErrorCode();
let hostString = document.location.hostname;
let port = document.location.port;
@ -713,7 +811,12 @@ function setTechnicalDetailsOnCertError() {
break;
case "SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED":
setL10NLabel("cert-error-intro", args);
setL10NLabel("cert-error-trust-signature-algorithm-disabled", {}, {}, false);
setL10NLabel(
"cert-error-trust-signature-algorithm-disabled",
{},
{},
false
);
break;
case "SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE":
setL10NLabel("cert-error-intro", args);
@ -765,41 +868,44 @@ function setTechnicalDetailsOnCertError() {
* which would allow spurious and possibly hostile matches.
*/
if (okHost.endsWith("." + thisHost)) {
href = proto + okHost;
}
/* case #2:
* browser.garage.maemo.org uses an invalid security certificate.
*
* The certificate is only valid for garage.maemo.org
*/
if (thisHost.endsWith("." + okHost)) {
href = proto + okHost;
}
if (okHost.endsWith("." + thisHost)) {
href = proto + okHost;
}
/* case #2:
* browser.garage.maemo.org uses an invalid security certificate.
*
* The certificate is only valid for garage.maemo.org
*/
if (thisHost.endsWith("." + okHost)) {
href = proto + okHost;
}
// If we set a link, meaning there's something helpful for
// the user here, expand the section by default
if (href && cssClass != "expertBadCert") {
document.getElementById("badCertAdvancedPanel").style.display = "block";
if (error == "nssBadCert") {
// Toggling the advanced panel must ensure that the debugging
// information panel is hidden as well, since it's opened by the
// error code link in the advanced panel.
let div = document.getElementById("certificateErrorDebugInformation");
div.style.display = "none";
}
}
// If we set a link, meaning there's something helpful for
// the user here, expand the section by default
if (href && cssClass != "expertBadCert") {
document.getElementById("badCertAdvancedPanel").style.display =
"block";
if (error == "nssBadCert") {
// Toggling the advanced panel must ensure that the debugging
// information panel is hidden as well, since it's opened by the
// error code link in the advanced panel.
let div = document.getElementById(
"certificateErrorDebugInformation"
);
div.style.display = "none";
}
}
// Set the link if we want it.
if (href) {
setL10NLabel("cert-error-domain-mismatch-single", args, {
"href": href,
"data-l10n-name": "domain-mismatch-link",
"id": "cert_domain_link",
});
} else {
setL10NLabel("cert-error-domain-mismatch-single-nolink", args);
}
// Set the link if we want it.
if (href) {
setL10NLabel("cert-error-domain-mismatch-single", args, {
href,
"data-l10n-name": "domain-mismatch-link",
id: "cert_domain_link",
});
} else {
setL10NLabel("cert-error-domain-mismatch-single-nolink", args);
}
} else {
let names = subjectAltNames.join(", ");
args["subject-alt-names"] = names;
@ -816,7 +922,7 @@ function setTechnicalDetailsOnCertError() {
args = {
hostname: hostString,
};
if (notBefore && (Date.now() < notAfter)) {
if (notBefore && Date.now() < notAfter) {
let notBeforeLocalTime = formatter.format(new Date(notBefore));
l10nId = "cert-error-not-yet-valid-now";
args["not-before-local-time"] = notBeforeLocalTime;
@ -828,12 +934,17 @@ function setTechnicalDetailsOnCertError() {
setL10NLabel(l10nId, args);
}
setL10NLabel("cert-error-code-prefix-link", { error: failedCertInfo.errorCodeString }, {
"title": failedCertInfo.errorCodeString,
"id": "errorCode",
"data-l10n-name": "error-code-link",
"data-telemetry-id": "error_code_link",
}, false);
setL10NLabel(
"cert-error-code-prefix-link",
{ error: failedCertInfo.errorCodeString },
{
title: failedCertInfo.errorCodeString,
id: "errorCode",
"data-l10n-name": "error-code-link",
"data-telemetry-id": "error_code_link",
},
false
);
let errorCodeLink = document.getElementById("errorCode");
if (errorCodeLink) {
// We're attaching the event listener to the parent element and not on
@ -850,7 +961,7 @@ function handleErrorCodeClick(event) {
let debugInfo = document.getElementById("certificateErrorDebugInformation");
debugInfo.style.display = "block";
debugInfo.scrollIntoView({block: "start", behavior: "smooth"});
debugInfo.scrollIntoView({ block: "start", behavior: "smooth" });
}
/* Only do autofocus if we're the toplevel frame; otherwise we
@ -861,11 +972,11 @@ function handleErrorCodeClick(event) {
*/
function addAutofocus(selector, position = "afterbegin") {
if (window.top == window) {
var button = document.querySelector(selector);
var parent = button.parentNode;
button.remove();
button.setAttribute("autofocus", "true");
parent.insertAdjacentElement(position, button);
var button = document.querySelector(selector);
var parent = button.parentNode;
button.remove();
button.setAttribute("autofocus", "true");
parent.insertAdjacentElement(position, button);
}
}

Просмотреть файл

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* eslint-env mozilla/frame-script */
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
var AboutRestartRequired = {
/* Only do autofocus if we're the toplevel frame; otherwise we
@ -22,8 +22,9 @@ var AboutRestartRequired = {
}
},
restart() {
Services.startup.quit(Ci.nsIAppStartup.eRestart |
Ci.nsIAppStartup.eAttemptQuit);
Services.startup.quit(
Ci.nsIAppStartup.eRestart | Ci.nsIAppStartup.eAttemptQuit
);
},
init() {
this.addAutofocus();

Просмотреть файл

@ -14,21 +14,12 @@ var AboutTabCrashed = {
/**
* The messages that we might receive from the parent.
*/
MESSAGES: [
"SetCrashReportAvailable",
"CrashReportSent",
"UpdateCount",
],
MESSAGES: ["SetCrashReportAvailable", "CrashReportSent", "UpdateCount"],
/**
* Items for which we will listen for click events.
*/
CLICK_TARGETS: [
"closeTab",
"restoreTab",
"restoreAll",
"sendReport",
],
CLICK_TARGETS: ["closeTab", "restoreTab", "restoreAll", "sendReport"],
/**
* Returns information about this crashed tab.
@ -48,14 +39,17 @@ var AboutTabCrashed = {
let titleMatch = queryString.match(/d=([^&]*)/);
let URLMatch = queryString.match(/u=([^&]*)/);
return this.pageData = {
title: titleMatch && titleMatch[1] ? decodeURIComponent(titleMatch[1]) : "",
return (this.pageData = {
title:
titleMatch && titleMatch[1] ? decodeURIComponent(titleMatch[1]) : "",
URL: URLMatch && URLMatch[1] ? decodeURIComponent(URLMatch[1]) : "",
};
});
},
init() {
this.MESSAGES.forEach((msg) => RPMAddMessageListener(msg, this.receiveMessage.bind(this)));
this.MESSAGES.forEach(msg =>
RPMAddMessageListener(msg, this.receiveMessage.bind(this))
);
addEventListener("DOMContentLoaded", this);
document.title = this.pageData.title;
@ -96,7 +90,7 @@ var AboutTabCrashed = {
},
onDOMContentLoaded() {
this.CLICK_TARGETS.forEach((targetID) => {
this.CLICK_TARGETS.forEach(targetID => {
let el = document.getElementById(targetID);
el.addEventListener("click", this);
});
@ -105,7 +99,7 @@ var AboutTabCrashed = {
document.getElementById("email").addEventListener("input", this);
// Error pages are loaded as LOAD_BACKGROUND, so they don't get load events.
let event = new CustomEvent("AboutTabCrashedLoad", {bubbles: true});
let event = new CustomEvent("AboutTabCrashedLoad", { bubbles: true });
document.dispatchEvent(event);
RPMSendAsyncMessage("Load");
@ -202,7 +196,7 @@ var AboutTabCrashed = {
document.getElementById("requestAutoSubmit").hidden = false;
}
let event = new CustomEvent("AboutTabCrashedReady", {bubbles: true});
let event = new CustomEvent("AboutTabCrashedReady", { bubbles: true });
document.dispatchEvent(event);
},

Просмотреть файл

@ -21,14 +21,16 @@ function getURL() {
// match == null if not found; if so, return an empty string
// instead of what would turn out to be portions of the URI
if (!match)
if (!match) {
return "";
}
url = decodeURIComponent(match[1]);
// If this is a view-source page, then get then real URI of the page
if (url.startsWith("view-source:"))
if (url.startsWith("view-source:")) {
url = url.slice(12);
}
return url;
}
@ -67,16 +69,16 @@ function onClickSeeDetails() {
function initPage() {
var error = "";
switch (getErrorCode()) {
case "malwareBlocked" :
case "malwareBlocked":
error = "malware";
break;
case "deceptiveBlocked" :
case "deceptiveBlocked":
error = "phishing";
break;
case "unwantedBlocked" :
case "unwantedBlocked":
error = "unwanted";
break;
case "harmfulBlocked" :
case "harmfulBlocked":
error = "harmful";
break;
default:
@ -86,9 +88,15 @@ function initPage() {
// Set page contents depending on type of blocked page
// Prepare the title and short description text
let titleText = document.getElementById("errorTitleText");
document.l10n.setAttributes(titleText, "safeb-blocked-" + error + "-page-title");
document.l10n.setAttributes(
titleText,
"safeb-blocked-" + error + "-page-title"
);
let shortDesc = document.getElementById("errorShortDescText");
document.l10n.setAttributes(shortDesc, "safeb-blocked-" + error + "-page-short-desc");
document.l10n.setAttributes(
shortDesc,
"safeb-blocked-" + error + "-page-short-desc"
);
// Prepare the inner description, ensuring any redundant inner elements are removed.
let innerDesc = document.getElementById("errorInnerDescription");
@ -103,29 +111,36 @@ function initPage() {
document.getElementById("report_detection").remove();
}
document.l10n.setAttributes(innerDesc, innerDescL10nID, {sitename: getHostString()});
document.l10n.setAttributes(innerDesc, innerDescL10nID, {
sitename: getHostString(),
});
// Add the learn more content:
let learnMore = document.getElementById("learn_more");
document.l10n.setAttributes(learnMore, "safeb-blocked-" + error + "-page-learn-more");
document.l10n.setAttributes(
learnMore,
"safeb-blocked-" + error + "-page-learn-more"
);
// Set sitename to bold by adding class
let errorSitename = document.getElementById("error_desc_sitename");
errorSitename.setAttribute("class", "sitename");
let titleEl = document.createElement("title");
document.l10n.setAttributes(titleEl, "safeb-blocked-" + error + "-page-title");
document.l10n.setAttributes(
titleEl,
"safeb-blocked-" + error + "-page-title"
);
document.head.appendChild(titleEl);
// Inform the test harness that we're done loading the page.
var event = new CustomEvent("AboutBlockedLoaded",
{
bubbles: true,
detail: {
url: this.getURL(),
err: error,
},
});
var event = new CustomEvent("AboutBlockedLoaded", {
bubbles: true,
detail: {
url: this.getURL(),
err: error,
},
});
document.dispatchEvent(event);
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -5,8 +5,11 @@
// This file is loaded into the browser window scope.
/* eslint-env mozilla/browser-window */
ChromeUtils.defineModuleGetter(this, "TabsPanel",
"resource:///modules/TabsList.jsm");
ChromeUtils.defineModuleGetter(
this,
"TabsPanel",
"resource:///modules/TabsList.jsm"
);
var gTabsPanel = {
kElements: {
@ -21,7 +24,9 @@ var gTabsPanel = {
_initializedElements: false,
initElements() {
if (this._initializedElements) return;
if (this._initializedElements) {
return;
}
for (let [name, id] of Object.entries(this.kElements)) {
this[name] = document.getElementById(id);
@ -30,52 +35,65 @@ var gTabsPanel = {
},
init() {
if (this._initialized) return;
if (this._initialized) {
return;
}
this.initElements();
this.hiddenAudioTabsPopup = new TabsPanel({
view: this.allTabsView,
insertBefore: document.getElementById("allTabsMenu-tabsSeparator"),
filterFn: (tab) => tab.hidden && tab.soundPlaying,
filterFn: tab => tab.hidden && tab.soundPlaying,
});
this.allTabsPanel = new TabsPanel({
view: this.allTabsView,
containerNode: this.allTabsViewTabs,
filterFn: (tab) => !tab.pinned && !tab.hidden,
filterFn: tab => !tab.pinned && !tab.hidden,
});
this.allTabsView.addEventListener("ViewShowing", (e) => {
this.allTabsView.addEventListener("ViewShowing", e => {
PanelUI._ensureShortcutsShown(this.allTabsView);
document.getElementById("allTabsMenu-undoCloseTab").disabled =
SessionStore.getClosedTabCount(window) == 0;
SessionStore.getClosedTabCount(window) == 0;
let containersEnabled = Services.prefs.getBoolPref("privacy.userContext.enabled")
&& !PrivateBrowsingUtils.isWindowPrivate(window);
document.getElementById("allTabsMenu-containerTabsButton")
.hidden = !containersEnabled;
let containersEnabled =
Services.prefs.getBoolPref("privacy.userContext.enabled") &&
!PrivateBrowsingUtils.isWindowPrivate(window);
document.getElementById(
"allTabsMenu-containerTabsButton"
).hidden = !containersEnabled;
let hasHiddenTabs = gBrowser.visibleTabs.length < gBrowser.tabs.length;
document.getElementById("allTabsMenu-hiddenTabsButton")
.hidden = !hasHiddenTabs;
document.getElementById("allTabsMenu-hiddenTabsSeparator")
.hidden = !hasHiddenTabs;
document.getElementById(
"allTabsMenu-hiddenTabsButton"
).hidden = !hasHiddenTabs;
document.getElementById(
"allTabsMenu-hiddenTabsSeparator"
).hidden = !hasHiddenTabs;
});
this.allTabsView.addEventListener("ViewShown", (e) => {
let selectedRow = this.allTabsView.querySelector(".all-tabs-item[selected]");
selectedRow.scrollIntoView({block: "center"});
this.allTabsView.addEventListener("ViewShown", e => {
let selectedRow = this.allTabsView.querySelector(
".all-tabs-item[selected]"
);
selectedRow.scrollIntoView({ block: "center" });
});
let containerTabsMenuSeparator = this.containerTabsView.querySelector("toolbarseparator");
this.containerTabsView.addEventListener("ViewShowing", (e) => {
let containerTabsMenuSeparator = this.containerTabsView.querySelector(
"toolbarseparator"
);
this.containerTabsView.addEventListener("ViewShowing", e => {
let elements = [];
let frag = document.createDocumentFragment();
ContextualIdentityService.getPublicIdentities().forEach(identity => {
let menuitem = document.createXULElement("toolbarbutton");
menuitem.setAttribute("class", "subviewbutton subviewbutton-iconic");
menuitem.setAttribute("label", ContextualIdentityService.getUserContextLabel(identity.userContextId));
menuitem.setAttribute(
"label",
ContextualIdentityService.getUserContextLabel(identity.userContextId)
);
// The styles depend on this.
menuitem.setAttribute("usercontextid", identity.userContextId);
// The command handler depends on this.
@ -89,17 +107,24 @@ var gTabsPanel = {
elements.push(menuitem);
});
e.target.addEventListener("ViewHiding", () => {
for (let element of elements) {
element.remove();
}
}, {once: true});
containerTabsMenuSeparator.parentNode.insertBefore(frag, containerTabsMenuSeparator);
e.target.addEventListener(
"ViewHiding",
() => {
for (let element of elements) {
element.remove();
}
},
{ once: true }
);
containerTabsMenuSeparator.parentNode.insertBefore(
frag,
containerTabsMenuSeparator
);
});
this.hiddenTabsPopup = new TabsPanel({
view: this.hiddenTabsView,
filterFn: (tab) => tab.hidden,
filterFn: tab => tab.hidden,
});
this._initialized = true;
@ -127,9 +152,16 @@ var gTabsPanel = {
if (!this.canOpen) {
return;
}
this.allTabsView.addEventListener("ViewShown", (e) => {
PanelUI.showSubView(this.kElements.hiddenTabsView, this.hiddenTabsButton);
}, {once: true});
this.allTabsView.addEventListener(
"ViewShown",
e => {
PanelUI.showSubView(
this.kElements.hiddenTabsView,
this.hiddenTabsButton
);
},
{ once: true }
);
this.showAllTabsPanel();
},

Просмотреть файл

@ -24,7 +24,8 @@ var CaptivePortalWatcher = {
get _captivePortalNotification() {
return gHighPriorityNotificationBox.getNotificationWithValue(
this.PORTAL_NOTIFICATION_VALUE);
this.PORTAL_NOTIFICATION_VALUE
);
},
get canonicalURL() {
@ -33,8 +34,9 @@ var CaptivePortalWatcher = {
get _browserBundle() {
delete this._browserBundle;
return this._browserBundle =
Services.strings.createBundle("chrome://browser/locale/browser.properties");
return (this._browserBundle = Services.strings.createBundle(
"chrome://browser/locale/browser.properties"
));
},
init() {
@ -43,8 +45,9 @@ var CaptivePortalWatcher = {
Services.obs.addObserver(this, "captive-portal-login-abort");
Services.obs.addObserver(this, "captive-portal-login-success");
this._cps = Cc["@mozilla.org/network/captive-portal-service;1"]
.getService(Ci.nsICaptivePortalService);
this._cps = Cc["@mozilla.org/network/captive-portal-service;1"].getService(
Ci.nsICaptivePortalService
);
if (this._cps.state == this._cps.LOCKED_PORTAL) {
// A captive portal has already been detected.
@ -63,8 +66,12 @@ var CaptivePortalWatcher = {
// This constant is chosen to be large enough for a portal recheck to complete,
// and small enough that the delay in opening a tab isn't too noticeable.
// Please see comments for _delayedCaptivePortalDetected for more details.
XPCOMUtils.defineLazyPreferenceGetter(this, "PORTAL_RECHECK_DELAY_MS",
"captivedetect.portalRecheckDelayMS", 500);
XPCOMUtils.defineLazyPreferenceGetter(
this,
"PORTAL_RECHECK_DELAY_MS",
"captivedetect.portalRecheckDelayMS",
500
);
},
uninit() {
@ -217,7 +224,9 @@ var CaptivePortalWatcher = {
let buttons = [
{
label: this._browserBundle.GetStringFromName("captivePortal.showLoginPage2"),
label: this._browserBundle.GetStringFromName(
"captivePortal.showLoginPage2"
),
callback: () => {
this.ensureCaptivePortalTab();
@ -227,9 +236,11 @@ var CaptivePortalWatcher = {
},
];
let message = this._browserBundle.GetStringFromName("captivePortal.infoMessage3");
let message = this._browserBundle.GetStringFromName(
"captivePortal.infoMessage3"
);
let closeHandler = (aEventName) => {
let closeHandler = aEventName => {
if (aEventName != "removed") {
return;
}
@ -237,8 +248,13 @@ var CaptivePortalWatcher = {
};
gHighPriorityNotificationBox.appendNotification(
message, this.PORTAL_NOTIFICATION_VALUE, "",
gHighPriorityNotificationBox.PRIORITY_INFO_MEDIUM, buttons, closeHandler);
message,
this.PORTAL_NOTIFICATION_VALUE,
"",
gHighPriorityNotificationBox.PRIORITY_INFO_MEDIUM,
buttons,
closeHandler
);
gBrowser.tabContainer.addEventListener("TabSelect", this);
},
@ -261,9 +277,11 @@ var CaptivePortalWatcher = {
if (!tab || tab.closing || !tab.parentNode) {
tab = gBrowser.addWebTab(this.canonicalURL, {
ownerTab: gBrowser.selectedTab,
triggeringPrincipal: Services.scriptSecurityManager.createNullPrincipal({
userContextId: gBrowser.contentPrincipal.userContextId,
}),
triggeringPrincipal: Services.scriptSecurityManager.createNullPrincipal(
{
userContextId: gBrowser.contentPrincipal.userContextId,
}
),
});
this._captivePortalTab = Cu.getWeakReference(tab);
}
@ -276,8 +294,13 @@ var CaptivePortalWatcher = {
let tabCloser = () => {
Services.obs.removeObserver(tabCloser, "captive-portal-login-abort");
Services.obs.removeObserver(tabCloser, "captive-portal-login-success");
if (!tab || tab.closing || !tab.parentNode || !tab.linkedBrowser ||
!tab.linkedBrowser.currentURI.equalsExceptRef(canonicalURI)) {
if (
!tab ||
tab.closing ||
!tab.parentNode ||
!tab.linkedBrowser ||
!tab.linkedBrowser.currentURI.equalsExceptRef(canonicalURI)
) {
return;
}
gBrowser.removeTab(tab);

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -10,26 +10,28 @@
*/
var tabPreviews = {
get aspectRatio() {
let { PageThumbUtils } = ChromeUtils.import("resource://gre/modules/PageThumbUtils.jsm");
let [ width, height ] = PageThumbUtils.getThumbnailSize(window);
let { PageThumbUtils } = ChromeUtils.import(
"resource://gre/modules/PageThumbUtils.jsm"
);
let [width, height] = PageThumbUtils.getThumbnailSize(window);
delete this.aspectRatio;
return this.aspectRatio = height / width;
return (this.aspectRatio = height / width);
},
get: function tabPreviews_get(aTab) {
let uri = aTab.linkedBrowser.currentURI.spec;
if (aTab.__thumbnail_lastURI &&
aTab.__thumbnail_lastURI != uri) {
if (aTab.__thumbnail_lastURI && aTab.__thumbnail_lastURI != uri) {
aTab.__thumbnail = null;
aTab.__thumbnail_lastURI = null;
}
if (aTab.__thumbnail)
if (aTab.__thumbnail) {
return aTab.__thumbnail;
}
if (aTab.getAttribute("pending") == "true") {
let img = new Image;
let img = new Image();
img.src = PageThumbs.getThumbnailURL(uri);
return img;
}
@ -41,10 +43,10 @@ var tabPreviews = {
let browser = aTab.linkedBrowser;
let uri = browser.currentURI.spec;
let canvas = PageThumbs.createCanvas(window);
PageThumbs.shouldStoreThumbnail(browser, (aDoStore) => {
PageThumbs.shouldStoreThumbnail(browser, aDoStore => {
if (aDoStore && aShouldCache) {
PageThumbs.captureAndStore(browser, function() {
let img = new Image;
let img = new Image();
img.src = PageThumbs.getThumbnailURL(uri);
aTab.__thumbnail = img;
aTab.__thumbnail_lastURI = uri;
@ -83,15 +85,20 @@ var tabPreviewPanelHelper = {
};
},
_popupshown(host) {
if ("setupGUI" in host)
if ("setupGUI" in host) {
host.setupGUI();
}
},
_popuphiding(host) {
if ("suspendGUI" in host)
if ("suspendGUI" in host) {
host.suspendGUI();
}
if (host._prevFocus) {
Services.focus.setFocus(host._prevFocus, Ci.nsIFocusManager.FLAG_NOSCROLL);
Services.focus.setFocus(
host._prevFocus,
Ci.nsIFocusManager.FLAG_NOSCROLL
);
host._prevFocus = null;
} else {
gBrowser.selectedBrowser.focus();
@ -111,14 +118,14 @@ var ctrlTab = {
maxTabPreviews: 6,
get panel() {
delete this.panel;
return this.panel = document.getElementById("ctrlTab-panel");
return (this.panel = document.getElementById("ctrlTab-panel"));
},
get showAllButton() {
delete this.showAllButton;
let button = this.makePreview(true);
button.setAttribute("id", "ctrlTab-showAll");
document.getElementById("ctrlTab-showAll-container").appendChild(button);
return this.showAllButton = button;
return (this.showAllButton = button);
},
get previews() {
delete this.previews;
@ -129,34 +136,44 @@ var ctrlTab = {
// Ensure that showAllButton is in the document before returning the single
// node list that includes both the previews and the button.
this.showAllButton;
return this.previews = this.panel.getElementsByClassName("ctrlTab-preview");
return (this.previews = this.panel.getElementsByClassName(
"ctrlTab-preview"
));
},
get canvasWidth() {
delete this.canvasWidth;
return this.canvasWidth = Math.ceil(screen.availWidth * .85 / this.maxTabPreviews);
return (this.canvasWidth = Math.ceil(
(screen.availWidth * 0.85) / this.maxTabPreviews
));
},
get canvasHeight() {
delete this.canvasHeight;
return this.canvasHeight = Math.round(this.canvasWidth * tabPreviews.aspectRatio);
return (this.canvasHeight = Math.round(
this.canvasWidth * tabPreviews.aspectRatio
));
},
get keys() {
var keys = {};
["close", "find", "selectAll"].forEach(function(key) {
keys[key] = document.getElementById("key_" + key)
.getAttribute("key")
.toLocaleLowerCase().charCodeAt(0);
keys[key] = document
.getElementById("key_" + key)
.getAttribute("key")
.toLocaleLowerCase()
.charCodeAt(0);
});
delete this.keys;
return this.keys = keys;
return (this.keys = keys);
},
_selectedIndex: 0,
get selected() {
return this._selectedIndex < 0 ?
document.activeElement :
this.previews.item(this._selectedIndex);
return this._selectedIndex < 0
? document.activeElement
: this.previews.item(this._selectedIndex);
},
get isOpen() {
return this.panel.state == "open" || this.panel.state == "showing" || this._timer;
return (
this.panel.state == "open" || this.panel.state == "showing" || this._timer
);
},
get tabCount() {
return this.tabList.length;
@ -187,12 +204,16 @@ var ctrlTab = {
readPref: function ctrlTab_readPref() {
var enable =
Services.prefs.getBoolPref(this.prefName) &&
!Services.prefs.getBoolPref("browser.ctrlTab.disallowForScreenReaders", false);
!Services.prefs.getBoolPref(
"browser.ctrlTab.disallowForScreenReaders",
false
);
if (enable)
if (enable) {
this.init();
else
} else {
this.uninit();
}
},
observe(aSubject, aTopic, aPrefName) {
this.readPref();
@ -224,7 +245,7 @@ var ctrlTab = {
let canvasWidth = this.canvasWidth;
let canvasHeight = this.canvasHeight;
let canvas = preview._canvas = document.createXULElement("hbox");
let canvas = (preview._canvas = document.createXULElement("hbox"));
canvas.setAttribute("class", "ctrlTab-canvas");
canvas.setAttribute("width", canvasWidth);
canvas.style.minWidth = canvasWidth + "px";
@ -237,12 +258,12 @@ var ctrlTab = {
faviconContainer.setAttribute("class", "ctrlTab-favicon-container");
previewInner.appendChild(faviconContainer);
let favicon = preview._favicon = document.createXULElement("image");
let favicon = (preview._favicon = document.createXULElement("image"));
favicon.setAttribute("class", "ctrlTab-favicon");
faviconContainer.appendChild(favicon);
}
let label = preview._label = document.createXULElement("label");
let label = (preview._label = document.createXULElement("label"));
label.setAttribute("class", "ctrlTab-label plain");
label.setAttribute("crop", "end");
previewInner.appendChild(label);
@ -251,18 +272,22 @@ var ctrlTab = {
},
updatePreviews: function ctrlTab_updatePreviews() {
for (let i = 0; i < this.previews.length; i++)
for (let i = 0; i < this.previews.length; i++) {
this.updatePreview(this.previews[i], this.tabList[i]);
}
var showAllLabel = gNavigatorBundle.getString("ctrlTab.listAllTabs.label");
this.showAllButton._label.setAttribute("value",
PluralForm.get(this.tabCount, showAllLabel).replace("#1", this.tabCount));
this.showAllButton._label.setAttribute(
"value",
PluralForm.get(this.tabCount, showAllLabel).replace("#1", this.tabCount)
);
this.showAllButton.hidden = !gTabsPanel.canOpen;
},
updatePreview: function ctrlTab_updatePreview(aPreview, aTab) {
if (aPreview == this.showAllButton)
if (aPreview == this.showAllButton) {
return;
}
aPreview._tab = aTab;
@ -289,14 +314,17 @@ var ctrlTab = {
},
advanceFocus: function ctrlTab_advanceFocus(aForward) {
let selectedIndex = Array.prototype.indexOf.call(this.previews,
this.selected);
let selectedIndex = Array.prototype.indexOf.call(
this.previews,
this.selected
);
do {
selectedIndex += aForward ? 1 : -1;
if (selectedIndex < 0)
if (selectedIndex < 0) {
selectedIndex = this.previews.length - 1;
else if (selectedIndex >= this.previews.length)
} else if (selectedIndex >= this.previews.length) {
selectedIndex = 0;
}
} while (this.previews[selectedIndex].hidden);
if (this._selectedIndex == -1) {
@ -318,20 +346,23 @@ var ctrlTab = {
},
_mouseOverFocus: function ctrlTab_mouseOverFocus(aPreview) {
if (this._trackMouseOver)
if (this._trackMouseOver) {
aPreview.focus();
}
},
pick: function ctrlTab_pick(aPreview) {
if (!this.tabCount)
if (!this.tabCount) {
return;
}
var select = (aPreview || this.selected);
var select = aPreview || this.selected;
if (select == this.showAllButton)
if (select == this.showAllButton) {
this.showAllTabs();
else
} else {
this.close(select._tab);
}
},
showAllTabs: function ctrlTab_showAllTabs(aPreview) {
@ -340,31 +371,36 @@ var ctrlTab = {
},
remove: function ctrlTab_remove(aPreview) {
if (aPreview._tab)
if (aPreview._tab) {
gBrowser.removeTab(aPreview._tab);
}
},
attachTab: function ctrlTab_attachTab(aTab, aPos) {
if (aTab.closing)
if (aTab.closing) {
return;
}
if (aPos == 0)
if (aPos == 0) {
this._recentlyUsedTabs.unshift(aTab);
else if (aPos)
} else if (aPos) {
this._recentlyUsedTabs.splice(aPos, 0, aTab);
else
} else {
this._recentlyUsedTabs.push(aTab);
}
},
detachTab: function ctrlTab_detachTab(aTab) {
var i = this._recentlyUsedTabs.indexOf(aTab);
if (i >= 0)
if (i >= 0) {
this._recentlyUsedTabs.splice(i, 1);
}
},
open: function ctrlTab_open() {
if (this.isOpen)
if (this.isOpen) {
return;
}
document.addEventListener("keyup", this, true);
@ -374,33 +410,43 @@ var ctrlTab = {
// Add a slight delay before showing the UI, so that a quick
// "ctrl-tab" keypress just flips back to the MRU tab.
this._timer = setTimeout(function(self) {
self._timer = null;
self._openPanel();
}, 200, this);
this._timer = setTimeout(
function(self) {
self._timer = null;
self._openPanel();
},
200,
this
);
},
_openPanel: function ctrlTab_openPanel() {
tabPreviewPanelHelper.opening(this);
this.panel.width = Math.min(screen.availWidth * .99,
this.canvasWidth * 1.25 * this.tabPreviewCount);
this.panel.width = Math.min(
screen.availWidth * 0.99,
this.canvasWidth * 1.25 * this.tabPreviewCount
);
var estimateHeight = this.canvasHeight * 1.25 + 75;
this.panel.openPopupAtScreen(screen.availLeft + (screen.availWidth - this.panel.width) / 2,
screen.availTop + (screen.availHeight - estimateHeight) / 2,
false);
this.panel.openPopupAtScreen(
screen.availLeft + (screen.availWidth - this.panel.width) / 2,
screen.availTop + (screen.availHeight - estimateHeight) / 2,
false
);
},
close: function ctrlTab_close(aTabToSelect) {
if (!this.isOpen)
if (!this.isOpen) {
return;
}
if (this._timer) {
clearTimeout(this._timer);
this._timer = null;
this.suspendGUI();
if (aTabToSelect)
if (aTabToSelect) {
gBrowser.selectedTab = aTabToSelect;
}
return;
}
@ -415,10 +461,15 @@ var ctrlTab = {
// Track mouse movement after a brief delay so that the item that happens
// to be under the mouse pointer initially won't be selected unintentionally.
this._trackMouseOver = false;
setTimeout(function(self) {
if (self.isOpen)
self._trackMouseOver = true;
}, 0, this);
setTimeout(
function(self) {
if (self.isOpen) {
self._trackMouseOver = true;
}
},
0,
this
);
},
suspendGUI: function ctrlTab_suspendGUI() {
@ -458,8 +509,7 @@ var ctrlTab = {
},
onKeyPress(event) {
if (!this.isOpen ||
!event.ctrlKey) {
if (!this.isOpen || !event.ctrlKey) {
return;
}
@ -490,16 +540,22 @@ var ctrlTab = {
this.updatePreviews();
if (this.selected.hidden)
if (this.selected.hidden) {
this.advanceFocus(false);
if (this.selected == this.showAllButton)
}
if (this.selected == this.showAllButton) {
this.advanceFocus(false);
}
// If the current tab is removed, another tab can steal our focus.
if (aTab.selected && this.panel.state == "open") {
setTimeout(function(selected) {
selected.focus();
}, 0, this.selected);
setTimeout(
function(selected) {
selected.focus();
},
0,
this.selected
);
}
},
@ -511,10 +567,16 @@ var ctrlTab = {
case "TabAttrModified":
// tab attribute modified (i.e. label, busy, image)
// update preview only if tab attribute modified in the list
if (event.detail.changed.some(
(elem, ind, arr) => ["label", "busy", "image"].includes(elem))) {
if (
event.detail.changed.some((elem, ind, arr) =>
["label", "busy", "image"].includes(elem)
)
) {
for (let i = this.previews.length - 1; i >= 0; i--) {
if (this.previews[i]._tab && this.previews[i]._tab == event.target) {
if (
this.previews[i]._tab &&
this.previews[i]._tab == event.target
) {
this.updatePreview(this.previews[i], event.target);
break;
}
@ -530,8 +592,9 @@ var ctrlTab = {
break;
case "TabClose":
this.detachTab(event.target);
if (this.isOpen)
if (this.isOpen) {
this.removeClosingTabFromUI(event.target);
}
break;
case "keydown":
this.onKeyDown(event);
@ -540,12 +603,16 @@ var ctrlTab = {
this.onKeyPress(event);
break;
case "keyup":
if (event.keyCode == event.DOM_VK_CONTROL)
if (event.keyCode == event.DOM_VK_CONTROL) {
this.pick();
}
break;
case "popupshowing":
if (event.target.id == "menu_viewPopup")
document.getElementById("menu_showAllTabs").hidden = !gTabsPanel.canOpen;
if (event.target.id == "menu_viewPopup") {
document.getElementById(
"menu_showAllTabs"
).hidden = !gTabsPanel.canOpen;
}
break;
}
},
@ -554,24 +621,29 @@ var ctrlTab = {
// Save a few more thumbnails than we actually display, so that when tabs
// are closed, the previews we add instead still get thumbnails.
const extraThumbnails = 3;
const thumbnailCount = Math.min(this.tabPreviewCount + extraThumbnails,
this.tabCount);
const thumbnailCount = Math.min(
this.tabPreviewCount + extraThumbnails,
this.tabCount
);
let urls = [];
for (let i = 0; i < thumbnailCount; i++)
for (let i = 0; i < thumbnailCount; i++) {
urls.push(this.tabList[i].linkedBrowser.currentURI.spec);
}
aCallback(urls);
},
_initRecentlyUsedTabs() {
this._recentlyUsedTabs =
Array.prototype.filter.call(gBrowser.tabs, tab => !tab.closing)
.sort((tab1, tab2) => tab2.lastAccessed - tab1.lastAccessed);
this._recentlyUsedTabs = Array.prototype.filter
.call(gBrowser.tabs, tab => !tab.closing)
.sort((tab1, tab2) => tab2.lastAccessed - tab1.lastAccessed);
},
_init: function ctrlTab__init(enable) {
var toggleEventListener = enable ? "addEventListener" : "removeEventListener";
var toggleEventListener = enable
? "addEventListener"
: "removeEventListener";
window[toggleEventListener]("SSWindowRestored", this);
@ -589,14 +661,17 @@ var ctrlTab = {
document[toggleEventListener]("keypress", this);
gBrowser.tabbox.handleCtrlTab = !enable;
if (enable)
if (enable) {
PageThumbs.addExpirationFilter(this);
else
} else {
PageThumbs.removeExpirationFilter(this);
}
// If we're not running, hide the "Show All Tabs" menu item,
// as Shift+Ctrl+Tab will be handled by the tab bar.
document.getElementById("menu_showAllTabs").hidden = !enable;
document.getElementById("menu_viewPopup")[toggleEventListener]("popupshowing", this);
document
.getElementById("menu_viewPopup")
[toggleEventListener]("popupshowing", this);
},
};

Просмотреть файл

@ -30,8 +30,9 @@ var CustomizationHandler = {
_customizationStarting() {
// Disable the toolbar context menu items
let menubar = document.getElementById("main-menubar");
for (let childNode of menubar.children)
for (let childNode of menubar.children) {
childNode.setAttribute("disabled", true);
}
let cmd = document.getElementById("cmd_CustomizeToolbars");
cmd.setAttribute("disabled", "true");
@ -45,8 +46,7 @@ var CustomizationHandler = {
_customizationEnding(aDetails) {
// Update global UI elements that may have been added or removed
if (aDetails.changed &&
AppConstants.platform != "macosx") {
if (aDetails.changed && AppConstants.platform != "macosx") {
updateEditUIVisibility();
}
@ -60,8 +60,9 @@ var CustomizationHandler = {
// Re-enable parts of the UI we disabled during the dialog
let menubar = document.getElementById("main-menubar");
for (let childNode of menubar.children)
for (let childNode of menubar.children) {
childNode.setAttribute("disabled", false);
}
let cmd = document.getElementById("cmd_CustomizeToolbars");
cmd.removeAttribute("disabled");
@ -74,7 +75,7 @@ var CustomizationHandler = {
var AutoHideMenubar = {
get _node() {
delete this._node;
return this._node = document.getElementById("toolbar-menubar");
return (this._node = document.getElementById("toolbar-menubar"));
},
_contextMenuListener: {
@ -128,7 +129,12 @@ var AutoHideMenubar = {
}
},
_events: ["DOMMenuBarInactive", "DOMMenuBarActive", "popupshowing", "mousedown"],
_events: [
"DOMMenuBarInactive",
"DOMMenuBarActive",
"popupshowing",
"mousedown",
],
_enable() {
this._node.setAttribute("inactive", "true");
for (let event of this._events) {
@ -149,7 +155,7 @@ var AutoHideMenubar = {
this._updateState();
break;
case "popupshowing":
// fall through
// fall through
case "DOMMenuBarActive":
this._setActive();
break;
@ -159,8 +165,9 @@ var AutoHideMenubar = {
}
break;
case "DOMMenuBarInactive":
if (!this._contextMenuListener.active)
if (!this._contextMenuListener.active) {
this._setInactiveAsync();
}
break;
}
},

Просмотреть файл

@ -16,8 +16,10 @@ var gDataNotificationInfoBar = {
get _log() {
let { Log } = ChromeUtils.import("resource://gre/modules/Log.jsm");
delete this._log;
return this._log = Log.repository.getLoggerWithMessagePrefix(
"Toolkit.Telemetry", "DataNotificationInfoBar::");
return (this._log = Log.repository.getLoggerWithMessagePrefix(
"Toolkit.Telemetry",
"DataNotificationInfoBar::"
));
},
init() {
@ -47,19 +49,26 @@ var gDataNotificationInfoBar = {
let message = gNavigatorBundle.getFormattedString(
"dataReportingNotification.message",
[appName, vendorName]);
[appName, vendorName]
);
this._actionTaken = false;
let buttons = [{
label: gNavigatorBundle.getString("dataReportingNotification.button.label"),
accessKey: gNavigatorBundle.getString("dataReportingNotification.button.accessKey"),
popup: null,
callback: () => {
this._actionTaken = true;
window.openPreferences("privacy-reports");
let buttons = [
{
label: gNavigatorBundle.getString(
"dataReportingNotification.button.label"
),
accessKey: gNavigatorBundle.getString(
"dataReportingNotification.button.accessKey"
),
popup: null,
callback: () => {
this._actionTaken = true;
window.openPreferences("privacy-reports");
},
},
}];
];
this._log.info("Creating data reporting policy notification.");
gNotificationBox.appendNotification(
@ -70,7 +79,10 @@ var gDataNotificationInfoBar = {
buttons,
event => {
if (event == "removed") {
Services.obs.notifyObservers(null, "datareporting:notify-data-policy:close");
Services.obs.notifyObservers(
null,
"datareporting:notify-data-policy:close"
);
}
}
);

Просмотреть файл

@ -16,11 +16,14 @@ var DevelopmentHelpers = {
quickRestart() {
Services.obs.notifyObservers(null, "startupcache-invalidate");
let env = Cc["@mozilla.org/process/environment;1"].
getService(Ci.nsIEnvironment);
let env = Cc["@mozilla.org/process/environment;1"].getService(
Ci.nsIEnvironment
);
env.set("MOZ_DISABLE_SAFE_MODE_KEY", "1");
Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart);
Services.startup.quit(
Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart
);
},
addRestartShortcut() {

Просмотреть файл

@ -7,7 +7,6 @@
/* eslint-env mozilla/browser-window */
var PointerlockFsWarning = {
_element: null,
_origin: null,
@ -43,7 +42,9 @@ var PointerlockFsWarning = {
showPointerLock(aOrigin) {
if (!document.fullscreen) {
let timeout = Services.prefs.getIntPref("pointer-lock-api.warning.timeout");
let timeout = Services.prefs.getIntPref(
"pointer-lock-api.warning.timeout"
);
this.show(aOrigin, "pointerlock-warning", timeout, 0);
}
},
@ -81,13 +82,17 @@ var PointerlockFsWarning = {
let host = null;
try {
host = uri.host;
} catch (e) { }
let textElem = this._element.querySelector(".pointerlockfswarning-domain-text");
} catch (e) {}
let textElem = this._element.querySelector(
".pointerlockfswarning-domain-text"
);
if (!host) {
textElem.setAttribute("hidden", true);
} else {
textElem.removeAttribute("hidden");
let hostElem = this._element.querySelector(".pointerlockfswarning-domain");
let hostElem = this._element.querySelector(
".pointerlockfswarning-domain"
);
// Document's principal's URI has a host. Display a warning including it.
let utils = {};
ChromeUtils.import("resource://gre/modules/DownloadUtils.jsm", utils);
@ -181,56 +186,56 @@ var PointerlockFsWarning = {
handleEvent(event) {
switch (event.type) {
case "mousemove": {
let state = this._state;
if (state == "hidden") {
// If the warning box is currently hidden, show it after
// a short delay if the pointer is at the top.
if (event.clientY != 0) {
this._timeoutShow.cancel();
} else if (this._timeoutShow.delay >= 0) {
this._timeoutShow.start();
}
} else {
let elemRect = this._element.getBoundingClientRect();
if (state == "hiding" && this._lastState != "hidden") {
// If we are on the hiding transition, and the pointer
// moved near the box, restore to the previous state.
if (event.clientY <= elemRect.bottom + 50) {
this._state = this._lastState;
this._timeoutHide.start();
case "mousemove": {
let state = this._state;
if (state == "hidden") {
// If the warning box is currently hidden, show it after
// a short delay if the pointer is at the top.
if (event.clientY != 0) {
this._timeoutShow.cancel();
} else if (this._timeoutShow.delay >= 0) {
this._timeoutShow.start();
}
} else if (state == "ontop" || this._lastState != "hidden") {
// State being "ontop" or the previous state not being
// "hidden" indicates this current warning box is shown
// in response to user's action. Hide it immediately when
// the pointer leaves that area.
if (event.clientY > elemRect.bottom + 50) {
this._state = "hidden";
this._timeoutHide.cancel();
} else {
let elemRect = this._element.getBoundingClientRect();
if (state == "hiding" && this._lastState != "hidden") {
// If we are on the hiding transition, and the pointer
// moved near the box, restore to the previous state.
if (event.clientY <= elemRect.bottom + 50) {
this._state = this._lastState;
this._timeoutHide.start();
}
} else if (state == "ontop" || this._lastState != "hidden") {
// State being "ontop" or the previous state not being
// "hidden" indicates this current warning box is shown
// in response to user's action. Hide it immediately when
// the pointer leaves that area.
if (event.clientY > elemRect.bottom + 50) {
this._state = "hidden";
this._timeoutHide.cancel();
}
}
}
break;
}
break;
}
case "transitionend": {
if (this._state == "hiding") {
this._element.setAttribute("hidden", true);
case "transitionend": {
if (this._state == "hiding") {
this._element.setAttribute("hidden", true);
}
break;
}
break;
}
}
},
};
var PointerLock = {
entered(originNoSuffix) {
PointerlockFsWarning.showPointerLock(originNoSuffix);
},
entered(originNoSuffix) {
PointerlockFsWarning.showPointerLock(originNoSuffix);
},
exited() {
PointerlockFsWarning.close();
},
exited() {
PointerlockFsWarning.close();
},
};
var FullScreen = {
@ -246,18 +251,25 @@ var FullScreen = {
window.addEventListener("fullscreen", this, true);
window.addEventListener("willenterfullscreen", this, true);
window.addEventListener("willexitfullscreen", this, true);
window.addEventListener("MozDOMFullscreen:Entered", this,
/* useCapture */ true,
/* wantsUntrusted */ false);
window.addEventListener("MozDOMFullscreen:Exited", this,
/* useCapture */ true,
/* wantsUntrusted */ false);
window.addEventListener(
"MozDOMFullscreen:Entered",
this,
/* useCapture */ true,
/* wantsUntrusted */ false
);
window.addEventListener(
"MozDOMFullscreen:Exited",
this,
/* useCapture */ true,
/* wantsUntrusted */ false
);
for (let type of this._MESSAGES) {
window.messageManager.addMessageListener(type, this);
}
if (window.fullScreen)
if (window.fullScreen) {
this.toggle();
}
},
uninit() {
@ -297,30 +309,35 @@ var FullScreen = {
this._fullScrToggler = document.getElementById("fullscr-toggler");
this._fullScrToggler.addEventListener("mouseover", this._expandCallback);
this._fullScrToggler.addEventListener("dragenter", this._expandCallback);
this._fullScrToggler.addEventListener("touchmove", this._expandCallback, {passive: true});
this._fullScrToggler.addEventListener("touchmove", this._expandCallback, {
passive: true,
});
}
if (enterFS) {
gNavToolbox.setAttribute("inFullscreen", true);
document.documentElement.setAttribute("inFullscreen", true);
if (!document.fullscreenElement && this.useLionFullScreen)
if (!document.fullscreenElement && this.useLionFullScreen) {
document.documentElement.setAttribute("OSXLionFullscreen", true);
}
} else {
gNavToolbox.removeAttribute("inFullscreen");
document.documentElement.removeAttribute("inFullscreen");
document.documentElement.removeAttribute("OSXLionFullscreen");
}
if (!document.fullscreenElement)
if (!document.fullscreenElement) {
this._updateToolbars(enterFS);
}
if (enterFS) {
document.addEventListener("keypress", this._keyToggleCallback);
document.addEventListener("popupshown", this._setPopupOpen);
document.addEventListener("popuphidden", this._setPopupOpen);
// In DOM fullscreen mode, we hide toolbars with CSS
if (!document.fullscreenElement)
if (!document.fullscreenElement) {
this.hideNavToolbox(true);
}
} else {
this.showNavToolbox(false);
// This is needed if they use the context menu to quit fullscreen
@ -329,8 +346,7 @@ var FullScreen = {
}
if (enterFS && !document.fullscreenElement) {
Services.telemetry.getHistogramById("FX_BROWSER_FULLSCREEN_USED")
.add(1);
Services.telemetry.getHistogramById("FX_BROWSER_FULLSCREEN_USED").add(1);
}
},
@ -430,10 +446,13 @@ var FullScreen = {
// element that's requesting fullscreen belongs to the browser that's currently
// active. If not, we exit fullscreen since the "full-screen document" isn't
// actually visible now.
if (!aBrowser || gBrowser.selectedBrowser != aBrowser ||
// The top-level window has lost focus since the request to enter
// full-screen was made. Cancel full-screen.
Services.focus.activeWindow != window) {
if (
!aBrowser ||
gBrowser.selectedBrowser != aBrowser ||
// The top-level window has lost focus since the request to enter
// full-screen was made. Cancel full-screen.
Services.focus.activeWindow != window
) {
// This function is called synchronously in fullscreen change, so
// we have to avoid calling exitFullscreen synchronously here.
setTimeout(() => document.exitFullscreen(), 0);
@ -465,11 +484,13 @@ var FullScreen = {
},
cleanupDomFullscreen() {
window.messageManager
.broadcastAsyncMessage("DOMFullscreen:CleanUp");
window.messageManager.broadcastAsyncMessage("DOMFullscreen:CleanUp");
PointerlockFsWarning.close();
gBrowser.tabContainer.removeEventListener("TabSelect", this.exitDomFullScreen);
gBrowser.tabContainer.removeEventListener(
"TabSelect",
this.exitDomFullScreen
);
window.removeEventListener("activate", this);
document.documentElement.removeAttribute("inDOMFullscreen");
@ -510,12 +531,19 @@ var FullScreen = {
// Otherwise, they would not affect chrome and the user would expect the chrome to go away.
// e.g. we wouldn't want the autoscroll icon firing this event, so when the user
// toggles chrome when moving mouse to the top, it doesn't go away again.
if (aEvent.type == "popupshown" && !FullScreen._isChromeCollapsed &&
aEvent.target.localName != "tooltip" && aEvent.target.localName != "window" &&
aEvent.target.getAttribute("nopreventnavboxhide") != "true") {
if (
aEvent.type == "popupshown" &&
!FullScreen._isChromeCollapsed &&
aEvent.target.localName != "tooltip" &&
aEvent.target.localName != "window" &&
aEvent.target.getAttribute("nopreventnavboxhide") != "true"
) {
FullScreen._isPopupOpen = true;
} else if (aEvent.type == "popuphidden" && aEvent.target.localName != "tooltip" &&
aEvent.target.localName != "window") {
} else if (
aEvent.type == "popuphidden" &&
aEvent.target.localName != "tooltip" &&
aEvent.target.localName != "window"
) {
FullScreen._isPopupOpen = false;
// Try again to hide toolbar when we close the popup.
FullScreen.hideNavToolbox(true);
@ -528,10 +556,16 @@ var FullScreen = {
// Autohide helpers for the context menu item
getAutohide(aItem) {
aItem.setAttribute("checked", Services.prefs.getBoolPref("browser.fullscreen.autohide"));
aItem.setAttribute(
"checked",
Services.prefs.getBoolPref("browser.fullscreen.autohide")
);
},
setAutohide() {
Services.prefs.setBoolPref("browser.fullscreen.autohide", !Services.prefs.getBoolPref("browser.fullscreen.autohide"));
Services.prefs.setBoolPref(
"browser.fullscreen.autohide",
!Services.prefs.getBoolPref("browser.fullscreen.autohide")
);
// Try again to hide toolbar when we change the pref.
FullScreen.hideNavToolbox(true);
},
@ -579,8 +613,11 @@ var FullScreen = {
// a textbox in chrome is focused (location bar anyone?): don't collapse chrome
let focused = document.commandDispatcher.focusedElement;
if (focused && focused.ownerDocument == document &&
focused.localName == "input") {
if (
focused &&
focused.ownerDocument == document &&
focused.localName == "input"
) {
// But try collapse the chrome again when anything happens which can make
// it lose the focus. We cannot listen on "blur" event on focused here
// because that event can be triggered by "mousedown", and hiding chrome
@ -608,13 +645,17 @@ var FullScreen = {
this._fullScrToggler.hidden = false;
if (aAnimate && Services.prefs.getBoolPref("toolkit.cosmeticAnimations.enabled")) {
if (
aAnimate &&
Services.prefs.getBoolPref("toolkit.cosmeticAnimations.enabled")
) {
gNavToolbox.setAttribute("fullscreenShouldAnimate", true);
// Hide the fullscreen toggler until the transition ends.
let listener = () => {
gNavToolbox.removeEventListener("transitionend", listener, true);
if (this._isChromeCollapsed)
if (this._isChromeCollapsed) {
this._fullScrToggler.hidden = false;
}
};
gNavToolbox.addEventListener("transitionend", listener, true);
this._fullScrToggler.hidden = true;
@ -629,15 +670,18 @@ var FullScreen = {
},
_updateToolbars(aEnterFS) {
for (let el of document.querySelectorAll("toolbar[fullscreentoolbar=true]")) {
for (let el of document.querySelectorAll(
"toolbar[fullscreentoolbar=true]"
)) {
if (aEnterFS) {
// Give the main nav bar and the tab bar the fullscreen context menu,
// otherwise remove context menu to prevent breakage
el.setAttribute("saved-context", el.getAttribute("context"));
if (el.id == "nav-bar" || el.id == "TabsToolbar")
if (el.id == "nav-bar" || el.id == "TabsToolbar") {
el.setAttribute("context", "autohide-context");
else
} else {
el.removeAttribute("context");
}
// Set the inFullscreen attribute to allow specific styling
// in fullscreen mode
@ -653,7 +697,6 @@ var FullScreen = {
ToolbarIconColor.inferFromText("fullscreen", aEnterFS);
// For Lion fullscreen, all fullscreen controls are hidden, don't
// bother to touch them. If we don't stop here, the following code
// could cause the native fullscreen button be shown unexpectedly.
@ -680,6 +723,8 @@ XPCOMUtils.defineLazyGetter(FullScreen, "useLionFullScreen", function() {
// * on OS X
// * on Lion or higher (Darwin 11+)
// * have fullscreenbutton="true"
return AppConstants.isPlatformAndVersionAtLeast("macosx", 11) &&
document.documentElement.getAttribute("fullscreenbutton") == "true";
return (
AppConstants.isPlatformAndVersionAtLeast("macosx", 11) &&
document.documentElement.getAttribute("fullscreenbutton") == "true"
);
});

Просмотреть файл

@ -39,7 +39,11 @@ var FullZoom = {
// nsISupports
QueryInterface: ChromeUtils.generateQI([Ci.nsIObserver, Ci.nsIContentPrefObserver, Ci.nsISupportsWeakReference]),
QueryInterface: ChromeUtils.generateQI([
Ci.nsIObserver,
Ci.nsIContentPrefObserver,
Ci.nsISupportsWeakReference,
]),
// Initialization & Destruction
@ -47,12 +51,14 @@ var FullZoom = {
gBrowser.addEventListener("ZoomChangeUsingMouseWheel", this);
// Register ourselves with the service so we know when our pref changes.
this._cps2 = Cc["@mozilla.org/content-pref/service;1"].
getService(Ci.nsIContentPrefService2);
this._cps2 = Cc["@mozilla.org/content-pref/service;1"].getService(
Ci.nsIContentPrefService2
);
this._cps2.addObserverForName(this.name, this);
this.updateBackgroundTabs =
Services.prefs.getBoolPref("browser.zoom.updateBackgroundTabs");
this.updateBackgroundTabs = Services.prefs.getBoolPref(
"browser.zoom.updateBackgroundTabs"
);
// Listen for changes to the browser.zoom branch so we can enable/disable
// updating background tabs and per-site saving and restoring of zoom levels.
@ -80,7 +86,6 @@ var FullZoom = {
gBrowser.removeEventListener("ZoomChangeUsingMouseWheel", this);
},
// Event Handlers
// EventListener
@ -102,14 +107,15 @@ var FullZoom = {
case "nsPref:changed":
switch (aData) {
case "privacy.resistFingerprinting":
// fall through
// fall through
case "browser.zoom.siteSpecific":
// Invalidate pref cache.
this._siteSpecificPref = undefined;
break;
case "browser.zoom.updateBackgroundTabs":
this.updateBackgroundTabs =
Services.prefs.getBoolPref("browser.zoom.updateBackgroundTabs");
this.updateBackgroundTabs = Services.prefs.getBoolPref(
"browser.zoom.updateBackgroundTabs"
);
break;
}
break;
@ -118,11 +124,20 @@ var FullZoom = {
// nsIContentPrefObserver
onContentPrefSet: function FullZoom_onContentPrefSet(aGroup, aName, aValue, aIsPrivate) {
onContentPrefSet: function FullZoom_onContentPrefSet(
aGroup,
aName,
aValue,
aIsPrivate
) {
this._onContentPrefChanged(aGroup, aValue, aIsPrivate);
},
onContentPrefRemoved: function FullZoom_onContentPrefRemoved(aGroup, aName, aIsPrivate) {
onContentPrefRemoved: function FullZoom_onContentPrefRemoved(
aGroup,
aName,
aIsPrivate
) {
this._onContentPrefChanged(aGroup, undefined, aIsPrivate);
},
@ -134,7 +149,11 @@ var FullZoom = {
* @param aValue The new value of the changed preference. Pass undefined to
* indicate the preference's removal.
*/
_onContentPrefChanged: function FullZoom__onContentPrefChanged(aGroup, aValue, aIsPrivate) {
_onContentPrefChanged: function FullZoom__onContentPrefChanged(
aGroup,
aValue,
aIsPrivate
) {
if (this._isNextContentPrefChangeInternal) {
// Ignore changes that FullZoom itself makes. This works because the
// content pref service calls callbacks before notifying observers, and it
@ -144,19 +163,21 @@ var FullZoom = {
}
let browser = gBrowser.selectedBrowser;
if (!browser.currentURI)
if (!browser.currentURI) {
return;
}
let ctxt = this._loadContextFromBrowser(browser);
let domain = this._cps2.extractDomain(browser.currentURI.spec);
if (aGroup) {
if (aGroup == domain && ctxt.usePrivateBrowsing == aIsPrivate)
if (aGroup == domain && ctxt.usePrivateBrowsing == aIsPrivate) {
this._applyPrefToZoom(aValue, browser);
}
return;
}
this._globalValue = aValue === undefined ? aValue :
this._ensureValid(aValue);
this._globalValue =
aValue === undefined ? aValue : this._ensureValid(aValue);
// If the current page doesn't have a site-specific preference, then its
// zoom should be set to the new global preference now that the global
@ -164,10 +185,13 @@ var FullZoom = {
let hasPref = false;
let token = this._getBrowserToken(browser);
this._cps2.getByDomainAndName(browser.currentURI.spec, this.name, ctxt, {
handleResult() { hasPref = true; },
handleResult() {
hasPref = true;
},
handleCompletion: () => {
if (!hasPref && token.isCurrent)
if (!hasPref && token.isCurrent) {
this._applyPrefToZoom(undefined, browser);
}
},
});
},
@ -185,7 +209,11 @@ var FullZoom = {
* @param aBrowser
* (optional) browser object displaying the document
*/
onLocationChange: function FullZoom_onLocationChange(aURI, aIsTabSwitch, aBrowser) {
onLocationChange: function FullZoom_onLocationChange(
aURI,
aIsTabSwitch,
aBrowser
) {
let browser = aBrowser || gBrowser.selectedBrowser;
// If we haven't been initialized yet but receive an onLocationChange
@ -206,19 +234,28 @@ var FullZoom = {
}
if (aURI.spec == "about:blank") {
if (!browser.contentPrincipal || browser.contentPrincipal.isNullPrincipal) {
if (
!browser.contentPrincipal ||
browser.contentPrincipal.isNullPrincipal
) {
// For an about:blank with a null principal, zooming any amount does not
// make any sense - so simply do 100%.
this._applyPrefToZoom(1, browser,
this._notifyOnLocationChange.bind(this, browser));
this._applyPrefToZoom(
1,
browser,
this._notifyOnLocationChange.bind(this, browser)
);
} else {
// If it's not a null principal, there may be content loaded into it,
// so use the global pref. This will avoid a cps2 roundtrip if we've
// already loaded the global pref once. Really, this should probably
// use the contentPrincipal's origin if it's an http(s) principal.
// (See bug 1457597)
this._applyPrefToZoom(undefined, browser,
this._notifyOnLocationChange.bind(this, browser));
this._applyPrefToZoom(
undefined,
browser,
this._notifyOnLocationChange.bind(this, browser)
);
}
return;
}
@ -235,8 +272,11 @@ var FullZoom = {
let ctxt = this._loadContextFromBrowser(browser);
let pref = this._cps2.getCachedByDomainAndName(aURI.spec, this.name, ctxt);
if (pref) {
this._applyPrefToZoom(pref.value, browser,
this._notifyOnLocationChange.bind(this, browser));
this._applyPrefToZoom(
pref.value,
browser,
this._notifyOnLocationChange.bind(this, browser)
);
return;
}
@ -244,14 +284,19 @@ var FullZoom = {
let value = undefined;
let token = this._getBrowserToken(browser);
this._cps2.getByDomainAndName(aURI.spec, this.name, ctxt, {
handleResult(resultPref) { value = resultPref.value; },
handleResult(resultPref) {
value = resultPref.value;
},
handleCompletion: () => {
if (!token.isCurrent) {
this._notifyOnLocationChange(browser);
return;
}
this._applyPrefToZoom(value, browser,
this._notifyOnLocationChange.bind(this, browser));
this._applyPrefToZoom(
value,
browser,
this._notifyOnLocationChange.bind(this, browser)
);
},
});
},
@ -319,7 +364,10 @@ var FullZoom = {
let token = this._getBrowserToken(browser);
let result = this._getGlobalValue(browser).then(value => {
if (token.isCurrent) {
ZoomManager.setZoomForBrowser(browser, value === undefined ? 1 : value);
ZoomManager.setZoomForBrowser(
browser,
value === undefined ? 1 : value
);
this._ignorePendingZoomAccesses(browser);
}
});
@ -351,7 +399,11 @@ var FullZoom = {
* @param aBrowser The zoom is set in this browser. Required.
* @param aCallback If given, it's asynchronously called when complete.
*/
_applyPrefToZoom: function FullZoom__applyPrefToZoom(aValue, aBrowser, aCallback) {
_applyPrefToZoom: function FullZoom__applyPrefToZoom(
aValue,
aBrowser,
aCallback
) {
if (!this.siteSpecific || gInPrintPreviewMode) {
this._executeSoon(aCallback);
return;
@ -375,7 +427,10 @@ var FullZoom = {
let token = this._getBrowserToken(aBrowser);
this._getGlobalValue(aBrowser).then(value => {
if (token.isCurrent) {
ZoomManager.setZoomForBrowser(aBrowser, value === undefined ? 1 : value);
ZoomManager.setZoomForBrowser(
aBrowser,
value === undefined ? 1 : value
);
this._ignorePendingZoomAccesses(aBrowser);
}
this._executeSoon(aCallback);
@ -389,20 +444,27 @@ var FullZoom = {
* @param browser The zoom of this browser will be saved. Required.
*/
_applyZoomToPref: function FullZoom__applyZoomToPref(browser) {
if (!this.siteSpecific ||
gInPrintPreviewMode ||
browser.isSyntheticDocument)
if (
!this.siteSpecific ||
gInPrintPreviewMode ||
browser.isSyntheticDocument
) {
return null;
}
return new Promise(resolve => {
this._cps2.set(browser.currentURI.spec, this.name,
ZoomManager.getZoomForBrowser(browser),
this._loadContextFromBrowser(browser), {
handleCompletion: () => {
this._isNextContentPrefChangeInternal = true;
resolve();
},
});
this._cps2.set(
browser.currentURI.spec,
this.name,
ZoomManager.getZoomForBrowser(browser),
this._loadContextFromBrowser(browser),
{
handleCompletion: () => {
this._isNextContentPrefChangeInternal = true;
resolve();
},
}
);
});
},
@ -412,8 +474,9 @@ var FullZoom = {
* @param browser The zoom of this browser will be removed. Required.
*/
_removePref: function FullZoom__removePref(browser) {
if (browser.isSyntheticDocument)
if (browser.isSyntheticDocument) {
return;
}
let ctxt = this._loadContextFromBrowser(browser);
this._cps2.removeByDomainAndName(browser.currentURI.spec, this.name, ctxt, {
handleCompletion: () => {
@ -438,8 +501,9 @@ var FullZoom = {
*/
_getBrowserToken: function FullZoom__getBrowserToken(browser) {
let map = this._browserTokenMap;
if (!map.has(browser))
if (!map.has(browser)) {
map.set(browser, 0);
}
return {
token: map.get(browser),
get isCurrent() {
@ -463,11 +527,15 @@ var FullZoom = {
// With remote content browsers, the event's target is the browser
// we're looking for.
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
if (target instanceof window.XULElement &&
target.localName == "browser" &&
target.namespaceURI == XUL_NS)
const XUL_NS =
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
if (
target instanceof window.XULElement &&
target.localName == "browser" &&
target.namespaceURI == XUL_NS
) {
return target;
}
// With in-process content browsers, the event's target is the content
// document.
@ -485,7 +553,9 @@ var FullZoom = {
*
* @param browser Pending accesses in this browser will be ignored.
*/
_ignorePendingZoomAccesses: function FullZoom__ignorePendingZoomAccesses(browser) {
_ignorePendingZoomAccesses: function FullZoom__ignorePendingZoomAccesses(
browser
) {
let map = this._browserTokenMap;
map.set(browser, (map.get(browser) || 0) + 1);
},
@ -493,14 +563,17 @@ var FullZoom = {
_ensureValid: function FullZoom__ensureValid(aValue) {
// Note that undefined is a valid value for aValue that indicates a known-
// not-to-exist value.
if (isNaN(aValue))
if (isNaN(aValue)) {
return 1;
}
if (aValue < ZoomManager.MIN)
if (aValue < ZoomManager.MIN) {
return ZoomManager.MIN;
}
if (aValue > ZoomManager.MAX)
if (aValue > ZoomManager.MAX) {
return ZoomManager.MAX;
}
return aValue;
},
@ -523,8 +596,10 @@ var FullZoom = {
}
let value = undefined;
this._cps2.getGlobal(this.name, this._loadContextFromBrowser(browser), {
handleResult(pref) { value = pref.value; },
handleCompletion: (reason) => {
handleResult(pref) {
value = pref.value;
},
handleCompletion: reason => {
this._globalValue = this._ensureValid(value);
resolve(this._globalValue);
},
@ -555,8 +630,9 @@ var FullZoom = {
},
_executeSoon: function FullZoom__executeSoon(callback) {
if (!callback)
if (!callback) {
return;
}
Services.tm.dispatchToMainThread(callback);
},
};

Просмотреть файл

@ -19,7 +19,7 @@
var gGestureSupport = {
_currentRotation: 0,
_lastRotateDelta: 0,
_rotateMomentumThreshold: .75,
_rotateMomentumThreshold: 0.75,
/**
* Add or remove mouse gesture event listeners
@ -28,14 +28,25 @@ var gGestureSupport = {
* True to add/init listeners and false to remove/uninit
*/
init: function GS_init(aAddListener) {
const gestureEvents = ["SwipeGestureMayStart", "SwipeGestureStart",
"SwipeGestureUpdate", "SwipeGestureEnd", "SwipeGesture",
"MagnifyGestureStart", "MagnifyGestureUpdate", "MagnifyGesture",
"RotateGestureStart", "RotateGestureUpdate", "RotateGesture",
"TapGesture", "PressTapGesture"];
const gestureEvents = [
"SwipeGestureMayStart",
"SwipeGestureStart",
"SwipeGestureUpdate",
"SwipeGestureEnd",
"SwipeGesture",
"MagnifyGestureStart",
"MagnifyGestureUpdate",
"MagnifyGesture",
"RotateGestureStart",
"RotateGestureUpdate",
"RotateGesture",
"TapGesture",
"PressTapGesture",
];
let addRemove = aAddListener ? window.addEventListener :
window.removeEventListener;
let addRemove = aAddListener
? window.addEventListener
: window.removeEventListener;
for (let event of gestureEvents) {
addRemove("Moz" + event, this, true);
@ -51,14 +62,19 @@ var gGestureSupport = {
* The gesture event to handle
*/
handleEvent: function GS_handleEvent(aEvent) {
if (!Services.prefs.getBoolPref(
"dom.debug.propagate_gesture_events_through_content")) {
if (
!Services.prefs.getBoolPref(
"dom.debug.propagate_gesture_events_through_content"
)
) {
aEvent.stopPropagation();
}
// Create a preference object with some defaults
let def = (aThreshold, aLatched) =>
({ threshold: aThreshold, latched: !!aLatched });
let def = (aThreshold, aLatched) => ({
threshold: aThreshold,
latched: !!aLatched,
});
switch (aEvent.type) {
case "MozSwipeGestureMayStart":
@ -84,9 +100,8 @@ var gGestureSupport = {
break;
case "MozMagnifyGestureStart":
aEvent.preventDefault();
let pinchPref = AppConstants.platform == "win"
? def(25, 0)
: def(150, 1);
let pinchPref =
AppConstants.platform == "win" ? def(25, 0) : def(150, 1);
this._setupGesture(aEvent, "pinch", pinchPref, "out", "in");
break;
case "MozRotateGestureStart":
@ -126,10 +141,17 @@ var gGestureSupport = {
* @param aDec
* Command to trigger for decreasing motion (without gesture name)
*/
_setupGesture: function GS__setupGesture(aEvent, aGesture, aPref, aInc, aDec) {
_setupGesture: function GS__setupGesture(
aEvent,
aGesture,
aPref,
aInc,
aDec
) {
// Try to load user-set values from preferences
for (let [pref, def] of Object.entries(aPref))
for (let [pref, def] of Object.entries(aPref)) {
aPref[pref] = this._getPref(aGesture + "." + pref, def);
}
// Keep track of the total deltas and latching behavior
let offset = 0;
@ -147,7 +169,7 @@ var gGestureSupport = {
// sure either we're not latched and going the same direction of the
// initial motion; or we're latched and going the opposite way
let sameDir = (latchDir ^ offset) >= 0;
if (!aPref.latched || (isLatched ^ sameDir)) {
if (!aPref.latched || isLatched ^ sameDir) {
this._doAction(updateEvent, [aGesture, offset > 0 ? aInc : aDec]);
// We must be getting latched or leaving it, so just toggle
@ -172,10 +194,12 @@ var gGestureSupport = {
* @return true if the swipe event may navigate the history, false othwerwise.
*/
_swipeNavigatesHistory: function GS__swipeNavigatesHistory(aEvent) {
return this._getCommand(aEvent, ["swipe", "left"])
== "Browser:BackOrBackDuplicate" &&
this._getCommand(aEvent, ["swipe", "right"])
== "Browser:ForwardOrForwardDuplicate";
return (
this._getCommand(aEvent, ["swipe", "left"]) ==
"Browser:BackOrBackDuplicate" &&
this._getCommand(aEvent, ["swipe", "right"]) ==
"Browser:ForwardOrForwardDuplicate"
);
},
/**
@ -199,7 +223,10 @@ var gGestureSupport = {
}
isVerticalSwipe = true;
} else if (aEvent.direction == aEvent.DIRECTION_DOWN) {
if (gMultiProcessBrowser || window.content.pageYOffset < window.content.scrollMaxY) {
if (
gMultiProcessBrowser ||
window.content.pageYOffset < window.content.scrollMaxY
) {
return false;
}
isVerticalSwipe = true;
@ -215,12 +242,14 @@ var gGestureSupport = {
let isLTR = gHistorySwipeAnimation.isLTR;
if (canGoBack) {
aEvent.allowedDirections |= isLTR ? aEvent.DIRECTION_LEFT :
aEvent.DIRECTION_RIGHT;
aEvent.allowedDirections |= isLTR
? aEvent.DIRECTION_LEFT
: aEvent.DIRECTION_RIGHT;
}
if (canGoForward) {
aEvent.allowedDirections |= isLTR ? aEvent.DIRECTION_RIGHT :
aEvent.DIRECTION_LEFT;
aEvent.allowedDirections |= isLTR
? aEvent.DIRECTION_RIGHT
: aEvent.DIRECTION_LEFT;
}
return true;
@ -264,8 +293,9 @@ var gGestureSupport = {
while (--num >= 0) {
// Only select array elements where the current bit is set
yield aArray.reduce(function(aPrev, aCurr, aIndex) {
if (num & 1 << aIndex)
if (num & (1 << aIndex)) {
aPrev.push(aCurr);
}
return aPrev;
}, []);
}
@ -302,8 +332,9 @@ var gGestureSupport = {
// command for both don't exist)
let keyCombos = [];
for (let key of ["shift", "alt", "ctrl", "meta"]) {
if (aEvent[key + "Key"])
if (aEvent[key + "Key"]) {
keyCombos.push(key);
}
}
// Try each combination of key presses in decreasing order for commands
@ -316,8 +347,9 @@ var gGestureSupport = {
command = this._getPref(aGesture.concat(subCombo).join("."));
} catch (e) {}
if (command)
if (command) {
return command;
}
}
return null;
},
@ -335,10 +367,19 @@ var gGestureSupport = {
if (node) {
if (node.getAttribute("disabled") != "true") {
let cmdEvent = document.createEvent("xulcommandevent");
cmdEvent.initCommandEvent("command", true, true, window, 0,
aEvent.ctrlKey, aEvent.altKey,
aEvent.shiftKey, aEvent.metaKey,
aEvent, aEvent.mozInputSource);
cmdEvent.initCommandEvent(
"command",
true,
true,
window,
0,
aEvent.ctrlKey,
aEvent.altKey,
aEvent.shiftKey,
aEvent.metaKey,
aEvent,
aEvent.mozInputSource
);
node.dispatchEvent(cmdEvent);
}
} else {
@ -402,8 +443,10 @@ var gGestureSupport = {
* @param aDir
* The direction for the swipe event
*/
_coordinateSwipeEventWithAnimation:
function GS__coordinateSwipeEventWithAnimation(aEvent, aDir) {
_coordinateSwipeEventWithAnimation: function GS__coordinateSwipeEventWithAnimation(
aEvent,
aDir
) {
gHistorySwipeAnimation.stopAnimation();
this.processSwipeEvent(aEvent, aDir);
},
@ -424,10 +467,11 @@ var gGestureSupport = {
// Determine what type of data to load based on default value's type
let type = typeof aDef;
let getFunc = "Char";
if (type == "boolean")
if (type == "boolean") {
getFunc = "Bool";
else if (type == "number")
} else if (type == "number") {
getFunc = "Int";
}
return Services.prefs["get" + getFunc + "Pref"](branch + aPref);
} catch (e) {
return aDef;
@ -441,15 +485,18 @@ var gGestureSupport = {
* The MozRotateGestureUpdate event triggering this call
*/
rotate(aEvent) {
if (!(window.content.document instanceof ImageDocument))
if (!(window.content.document instanceof ImageDocument)) {
return;
}
let contentElement = window.content.document.body.firstElementChild;
if (!contentElement)
if (!contentElement) {
return;
}
// If we're currently snapping, cancel that snap
if (contentElement.classList.contains("completeRotation"))
if (contentElement.classList.contains("completeRotation")) {
this._clearCompleteRotation();
}
this.rotation = Math.round(this.rotation + aEvent.delta);
contentElement.style.transform = "rotate(" + this.rotation + "deg)";
@ -460,42 +507,53 @@ var gGestureSupport = {
* Perform a rotation end for ImageDocuments
*/
rotateEnd() {
if (!(window.content.document instanceof ImageDocument))
if (!(window.content.document instanceof ImageDocument)) {
return;
}
let contentElement = window.content.document.body.firstElementChild;
if (!contentElement)
if (!contentElement) {
return;
}
let transitionRotation = 0;
// The reason that 360 is allowed here is because when rotating between
// 315 and 360, setting rotate(0deg) will cause it to rotate the wrong
// direction around--spinning wildly.
if (this.rotation <= 45)
if (this.rotation <= 45) {
transitionRotation = 0;
else if (this.rotation > 45 && this.rotation <= 135)
} else if (this.rotation > 45 && this.rotation <= 135) {
transitionRotation = 90;
else if (this.rotation > 135 && this.rotation <= 225)
} else if (this.rotation > 135 && this.rotation <= 225) {
transitionRotation = 180;
else if (this.rotation > 225 && this.rotation <= 315)
} else if (this.rotation > 225 && this.rotation <= 315) {
transitionRotation = 270;
else
} else {
transitionRotation = 360;
}
// If we're going fast enough, and we didn't already snap ahead of rotation,
// then snap ahead of rotation to simulate momentum
if (this._lastRotateDelta > this._rotateMomentumThreshold &&
this.rotation > transitionRotation)
if (
this._lastRotateDelta > this._rotateMomentumThreshold &&
this.rotation > transitionRotation
) {
transitionRotation += 90;
else if (this._lastRotateDelta < -1 * this._rotateMomentumThreshold &&
this.rotation < transitionRotation)
} else if (
this._lastRotateDelta < -1 * this._rotateMomentumThreshold &&
this.rotation < transitionRotation
) {
transitionRotation -= 90;
}
// Only add the completeRotation class if it is is necessary
if (transitionRotation != this.rotation) {
contentElement.classList.add("completeRotation");
contentElement.addEventListener("transitionend", this._clearCompleteRotation);
contentElement.addEventListener(
"transitionend",
this._clearCompleteRotation
);
}
contentElement.style.transform = "rotate(" + transitionRotation + "deg)";
@ -518,8 +576,9 @@ var gGestureSupport = {
*/
set rotation(aVal) {
this._currentRotation = aVal % 360;
if (this._currentRotation < 0)
if (this._currentRotation < 0) {
this._currentRotation += 360;
}
return this._currentRotation;
},
@ -529,15 +588,17 @@ var gGestureSupport = {
*/
restoreRotationState() {
// Bug 1108553 - Cannot rotate images in stand-alone image documents with e10s
if (gMultiProcessBrowser)
if (gMultiProcessBrowser) {
return;
}
if (!(window.content.document instanceof ImageDocument))
if (!(window.content.document instanceof ImageDocument)) {
return;
}
let contentElement = window.content.document.body.firstElementChild;
let transformValue = window.content.window.getComputedStyle(contentElement)
.transform;
.transform;
if (transformValue == "none") {
this.rotation = 0;
@ -546,31 +607,37 @@ var gGestureSupport = {
// transformValue is a rotation matrix--split it and do mathemagic to
// obtain the real rotation value
transformValue = transformValue.split("(")[1]
.split(")")[0]
.split(",");
this.rotation = Math.round(Math.atan2(transformValue[1], transformValue[0]) *
(180 / Math.PI));
transformValue = transformValue
.split("(")[1]
.split(")")[0]
.split(",");
this.rotation = Math.round(
Math.atan2(transformValue[1], transformValue[0]) * (180 / Math.PI)
);
},
/**
* Removes the transition rule by removing the completeRotation class
*/
_clearCompleteRotation() {
let contentElement = window.content.document &&
window.content.document instanceof ImageDocument &&
window.content.document.body &&
window.content.document.body.firstElementChild;
if (!contentElement)
let contentElement =
window.content.document &&
window.content.document instanceof ImageDocument &&
window.content.document.body &&
window.content.document.body.firstElementChild;
if (!contentElement) {
return;
}
contentElement.classList.remove("completeRotation");
contentElement.removeEventListener("transitionend", this._clearCompleteRotation);
contentElement.removeEventListener(
"transitionend",
this._clearCompleteRotation
);
},
};
// History Swipe Animation Support (bug 678392)
var gHistorySwipeAnimation = {
active: false,
isLTR: false,
@ -585,8 +652,12 @@ var gHistorySwipeAnimation = {
this.isLTR = document.documentElement.matches(":-moz-locale-dir(ltr)");
this._isStoppingAnimation = false;
if (!Services.prefs.getBoolPref("browser.history_swipe_animation.disabled",
false)) {
if (
!Services.prefs.getBoolPref(
"browser.history_swipe_animation.disabled",
false
)
) {
this.active = true;
}
},
@ -655,8 +726,7 @@ var gHistorySwipeAnimation = {
// trigger history navigation, hence the multiplier 4 to set the arrows to
// full opacity at 0.25 or greater.
let opacity = Math.abs(aVal) * 4;
if ((aVal >= 0 && this.isLTR) ||
(aVal <= 0 && !this.isLTR)) {
if ((aVal >= 0 && this.isLTR) || (aVal <= 0 && !this.isLTR)) {
// The intention is to go back.
if (this._canGoBack) {
this._prevBox.collapsed = false;
@ -726,18 +796,24 @@ var gHistorySwipeAnimation = {
*/
_addBoxes: function HSA__addBoxes() {
let browserStack = gBrowser.getPanel().querySelector(".browserStack");
this._container = this._createElement("historySwipeAnimationContainer",
"stack");
this._container = this._createElement(
"historySwipeAnimationContainer",
"stack"
);
browserStack.appendChild(this._container);
this._prevBox = this._createElement("historySwipeAnimationPreviousArrow",
"box");
this._prevBox = this._createElement(
"historySwipeAnimationPreviousArrow",
"box"
);
this._prevBox.collapsed = true;
this._prevBox.style.opacity = 0;
this._container.appendChild(this._prevBox);
this._nextBox = this._createElement("historySwipeAnimationNextArrow",
"box");
this._nextBox = this._createElement(
"historySwipeAnimationNextArrow",
"box"
);
this._nextBox.collapsed = true;
this._nextBox.style.opacity = 0;
this._container.appendChild(this._nextBox);
@ -749,8 +825,9 @@ var gHistorySwipeAnimation = {
_removeBoxes: function HSA__removeBoxes() {
this._prevBox = null;
this._nextBox = null;
if (this._container)
if (this._container) {
this._container.remove();
}
this._container = null;
},

Просмотреть файл

@ -10,16 +10,19 @@ var gEMEHandler = {
let emeUIEnabled = Services.prefs.getBoolPref("browser.eme.ui.enabled");
// Force-disable on WinXP:
if (navigator.platform.toLowerCase().startsWith("win")) {
emeUIEnabled = emeUIEnabled && parseFloat(Services.sysinfo.get("version")) >= 6;
emeUIEnabled =
emeUIEnabled && parseFloat(Services.sysinfo.get("version")) >= 6;
}
return emeUIEnabled;
},
ensureEMEEnabled(browser, keySystem) {
Services.prefs.setBoolPref("media.eme.enabled", true);
if (keySystem &&
keySystem == "com.widevine.alpha" &&
Services.prefs.getPrefType("media.gmp-widevinecdm.enabled") &&
!Services.prefs.getBoolPref("media.gmp-widevinecdm.enabled")) {
if (
keySystem &&
keySystem == "com.widevine.alpha" &&
Services.prefs.getPrefType("media.gmp-widevinecdm.enabled") &&
!Services.prefs.getBoolPref("media.gmp-widevinecdm.enabled")
) {
Services.prefs.setBoolPref("media.gmp-widevinecdm.enabled", true);
}
browser.reload();
@ -28,17 +31,23 @@ var gEMEHandler = {
if (!keySystem) {
return false;
}
if (keySystem == "com.widevine.alpha" &&
Services.prefs.getPrefType("media.gmp-widevinecdm.visible")) {
if (
keySystem == "com.widevine.alpha" &&
Services.prefs.getPrefType("media.gmp-widevinecdm.visible")
) {
return Services.prefs.getBoolPref("media.gmp-widevinecdm.visible");
}
return true;
},
getEMEDisabledFragment(msgId) {
let mainMessage = gNavigatorBundle.getString("emeNotifications.drmContentDisabled.message");
let text = gNavigatorBundle.getString("emeNotifications.drmContentDisabled.learnMoreLabel");
let mainMessage = gNavigatorBundle.getString(
"emeNotifications.drmContentDisabled.message"
);
let text = gNavigatorBundle.getString(
"emeNotifications.drmContentDisabled.learnMoreLabel"
);
let baseURL = Services.urlFormatter.formatURLPref("app.support.baseURL");
let link = document.createXULElement("label", {is: "text-link"});
let link = document.createXULElement("label", { is: "text-link" });
link.setAttribute("href", baseURL + "drm-content");
link.textContent = text;
return BrowserUtils.getLocalizedFragment(document, mainMessage, link);
@ -47,7 +56,7 @@ var gEMEHandler = {
let msgId = "emeNotifications." + notificationId + ".message";
return gNavigatorBundle.getFormattedString(msgId, [this._brandShortName]);
},
receiveMessage({target: browser, data: data}) {
receiveMessage({ target: browser, data: data }) {
let parsedData;
try {
parsedData = JSON.parse(data);
@ -55,7 +64,7 @@ var gEMEHandler = {
Cu.reportError("Malformed EME video message with data: " + data);
return;
}
let {status: status, keySystem: keySystem} = parsedData;
let { status: status, keySystem: keySystem } = parsedData;
// Don't need to show if disabled or keysystem not visible.
if (!this.uiEnabled || !this.isKeySystemVisible(keySystem)) {
return;
@ -78,7 +87,11 @@ var gEMEHandler = {
case "api-disabled":
case "cdm-disabled":
notificationId = "drmContentDisabled";
buttonCallback = gEMEHandler.ensureEMEEnabled.bind(gEMEHandler, browser, keySystem);
buttonCallback = gEMEHandler.ensureEMEEnabled.bind(
gEMEHandler,
browser,
keySystem
);
notificationMessage = this.getEMEDisabledFragment();
break;
@ -92,7 +105,14 @@ var gEMEHandler = {
// about it.
return;
default:
Cu.reportError(new Error("Unknown message ('" + status + "') dealing with EME key request: " + data));
Cu.reportError(
new Error(
"Unknown message ('" +
status +
"') dealing with EME key request: " +
data
)
);
return;
}
@ -116,19 +136,23 @@ var gEMEHandler = {
}
let iconURL = "chrome://browser/skin/drm-icon.svg";
box.appendNotification(notificationMessage, notificationId, iconURL, box.PRIORITY_WARNING_MEDIUM,
buttons);
box.appendNotification(
notificationMessage,
notificationId,
iconURL,
box.PRIORITY_WARNING_MEDIUM,
buttons
);
},
showPopupNotificationForSuccess(browser, keySystem) {
// We're playing EME content! Remove any "we can't play because..." messages.
var box = gBrowser.getNotificationBox(browser);
["drmContentDisabled",
"drmContentCDMInstalling",
].forEach(function(value) {
var notification = box.getNotificationWithValue(value);
if (notification)
box.removeNotification(notification);
});
["drmContentDisabled", "drmContentCDMInstalling"].forEach(function(value) {
var notification = box.getNotificationWithValue(value);
if (notification) {
box.removeNotification(notification);
}
});
// Don't bother creating it if it's already there:
if (PopupNotifications.getNotification("drmContentPlaying", browser)) {
@ -140,11 +164,15 @@ var gEMEHandler = {
let btnLabelId = msgPrefix + "button.label";
let btnAccessKeyId = msgPrefix + "button.accesskey";
let message = gNavigatorBundle.getFormattedString(msgId, [this._brandShortName]);
let message = gNavigatorBundle.getFormattedString(msgId, [
this._brandShortName,
]);
let anchorId = "eme-notification-icon";
let firstPlayPref = "browser.eme.ui.firstContentShown";
if (!Services.prefs.getPrefType(firstPlayPref) ||
!Services.prefs.getBoolPref(firstPlayPref)) {
if (
!Services.prefs.getPrefType(firstPlayPref) ||
!Services.prefs.getBoolPref(firstPlayPref)
) {
document.getElementById(anchorId).setAttribute("firstplay", "true");
Services.prefs.setBoolPref(firstPlayPref, true);
} else {
@ -162,9 +190,19 @@ var gEMEHandler = {
let options = {
dismissed: true,
eventCallback: aTopic => aTopic == "swapping",
learnMoreURL: Services.urlFormatter.formatURLPref("app.support.baseURL") + "drm-content",
learnMoreURL:
Services.urlFormatter.formatURLPref("app.support.baseURL") +
"drm-content",
};
PopupNotifications.show(browser, "drmContentPlaying", message, anchorId, mainAction, null, options);
PopupNotifications.show(
browser,
"drmContentPlaying",
message,
anchorId,
mainAction,
null,
options
);
},
};
@ -191,9 +229,10 @@ let gDecoderDoctorHandler = {
if (type == "cannot-initialize-pulseaudio") {
return gNavigatorBundle.getString("decoder.noPulseAudio.message");
}
if (type == "unsupported-libavcodec" &&
AppConstants.platform == "linux") {
return gNavigatorBundle.getString("decoder.unsupportedLibavcodec.message");
if (type == "unsupported-libavcodec" && AppConstants.platform == "linux") {
return gNavigatorBundle.getString(
"decoder.unsupportedLibavcodec.message"
);
}
if (type == "decode-error") {
return gNavigatorBundle.getString("decoder.decodeError.message");
@ -205,8 +244,10 @@ let gDecoderDoctorHandler = {
},
getSumoForLearnHowButton(type) {
if (type == "platform-decoder-not-found" &&
AppConstants.platform == "win") {
if (
type == "platform-decoder-not-found" &&
AppConstants.platform == "win"
) {
return "fix-video-audio-problems-firefox-windows";
}
if (type == "cannot-initialize-pulseaudio") {
@ -217,12 +258,15 @@ let gDecoderDoctorHandler = {
getEndpointForReportIssueButton(type) {
if (type == "decode-error" || type == "decode-warning") {
return Services.prefs.getStringPref("media.decoder-doctor.new-issue-endpoint", "");
return Services.prefs.getStringPref(
"media.decoder-doctor.new-issue-endpoint",
""
);
}
return "";
},
receiveMessage({target: browser, data: data}) {
receiveMessage({ target: browser, data: data }) {
let box = gBrowser.getNotificationBox(browser);
let notificationId = "decoder-doctor-notification";
if (box.getNotificationWithValue(notificationId)) {
@ -251,11 +295,18 @@ let gDecoderDoctorHandler = {
// uses to later find when an issue is resolved.
// - 'decodeIssue' is a description of the decode error/warning.
// - 'resourceURL' is the resource with the issue.
let {type, isSolved, decoderDoctorReportId,
formats, decodeIssue, docURL, resourceURL} = parsedData;
let {
type,
isSolved,
decoderDoctorReportId,
formats,
decodeIssue,
docURL,
resourceURL,
} = parsedData;
type = type.toLowerCase();
// Error out early on invalid ReportId
if (!(/^\w+$/mi).test(decoderDoctorReportId)) {
if (!/^\w+$/im.test(decoderDoctorReportId)) {
return;
}
let title = gDecoderDoctorHandler.getLabelForNotificationBox(type);
@ -266,14 +317,15 @@ let gDecoderDoctorHandler = {
// We keep the list of formats in prefs for the sake of the decoder itself,
// which reads it to determine when issues get solved for these formats.
// (Writing prefs from e10s content is not allowed.)
let formatsPref = formats &&
"media.decoder-doctor." + decoderDoctorReportId + ".formats";
let buttonClickedPref = "media.decoder-doctor." + decoderDoctorReportId + ".button-clicked";
let histogram =
Services.telemetry.getKeyedHistogramById("DECODER_DOCTOR_INFOBAR_STATS");
let formatsPref =
formats && "media.decoder-doctor." + decoderDoctorReportId + ".formats";
let buttonClickedPref =
"media.decoder-doctor." + decoderDoctorReportId + ".button-clicked";
let histogram = Services.telemetry.getKeyedHistogramById(
"DECODER_DOCTOR_INFOBAR_STATS"
);
let formatsInPref = formats &&
Services.prefs.getCharPref(formatsPref, "");
let formatsInPref = formats && Services.prefs.getCharPref(formatsPref, "");
if (!isSolved) {
if (formats) {
@ -284,16 +336,22 @@ let gDecoderDoctorHandler = {
// Split existing formats into an array of strings.
let existing = formatsInPref.split(",").map(x => x.trim());
// Keep given formats that were not already recorded.
let newbies = formats.split(",").map(x => x.trim())
.filter(x => !existing.includes(x));
let newbies = formats
.split(",")
.map(x => x.trim())
.filter(x => !existing.includes(x));
// And rewrite pref with the added new formats (if any).
if (newbies.length) {
Services.prefs.setCharPref(formatsPref,
existing.concat(newbies).join(", "));
Services.prefs.setCharPref(
formatsPref,
existing.concat(newbies).join(", ")
);
}
}
} else if (!decodeIssue) {
Cu.reportError("Malformed Decoder Doctor unsolved message with no formats nor decode issue");
Cu.reportError(
"Malformed Decoder Doctor unsolved message with no formats nor decode issue"
);
return;
}
histogram.add(decoderDoctorReportId, TELEMETRY_DDSTAT_SHOWN);
@ -305,40 +363,56 @@ let gDecoderDoctorHandler = {
label: gNavigatorBundle.getString("decoder.noCodecs.button"),
accessKey: gNavigatorBundle.getString("decoder.noCodecs.accesskey"),
callback() {
let clickedInPref =
Services.prefs.getBoolPref(buttonClickedPref, false);
let clickedInPref = Services.prefs.getBoolPref(
buttonClickedPref,
false
);
if (!clickedInPref) {
Services.prefs.setBoolPref(buttonClickedPref, true);
histogram.add(decoderDoctorReportId, TELEMETRY_DDSTAT_CLICKED_FIRST);
histogram.add(
decoderDoctorReportId,
TELEMETRY_DDSTAT_CLICKED_FIRST
);
}
histogram.add(decoderDoctorReportId, TELEMETRY_DDSTAT_CLICKED);
let baseURL = Services.urlFormatter.formatURLPref("app.support.baseURL");
let baseURL = Services.urlFormatter.formatURLPref(
"app.support.baseURL"
);
openTrustedLinkIn(baseURL + sumo, "tab");
},
});
}
let endpoint = gDecoderDoctorHandler.getEndpointForReportIssueButton(type);
let endpoint = gDecoderDoctorHandler.getEndpointForReportIssueButton(
type
);
if (endpoint) {
buttons.push({
label: gNavigatorBundle.getString("decoder.decodeError.button"),
accessKey: gNavigatorBundle.getString("decoder.decodeError.accesskey"),
accessKey: gNavigatorBundle.getString(
"decoder.decodeError.accesskey"
),
callback() {
let clickedInPref =
Services.prefs.getBoolPref(buttonClickedPref, false);
let clickedInPref = Services.prefs.getBoolPref(
buttonClickedPref,
false
);
if (!clickedInPref) {
Services.prefs.setBoolPref(buttonClickedPref, true);
histogram.add(decoderDoctorReportId, TELEMETRY_DDSTAT_CLICKED_FIRST);
histogram.add(
decoderDoctorReportId,
TELEMETRY_DDSTAT_CLICKED_FIRST
);
}
histogram.add(decoderDoctorReportId, TELEMETRY_DDSTAT_CLICKED);
let params = new URLSearchParams;
let params = new URLSearchParams();
params.append("url", docURL);
params.append("label", "type-media");
params.append("problem_type", "video_bug");
params.append("src", "media-decode-error");
let details = {"Technical Information:": decodeIssue};
let details = { "Technical Information:": decodeIssue };
if (resourceURL) {
details["Resource:"] = resourceURL;
}
@ -350,11 +424,11 @@ let gDecoderDoctorHandler = {
}
box.appendNotification(
title,
notificationId,
"", // This uses the info icon as specified below.
box.PRIORITY_INFO_LOW,
buttons
title,
notificationId,
"", // This uses the info icon as specified below.
box.PRIORITY_INFO_LOW,
buttons
);
} else if (formatsInPref) {
// Issue is solved, and prefs haven't been cleared yet, meaning it's the
@ -366,9 +440,17 @@ let gDecoderDoctorHandler = {
},
};
window.getGroupMessageManager("browsers").addMessageListener("DecoderDoctor:Notification", gDecoderDoctorHandler);
window.getGroupMessageManager("browsers").addMessageListener("EMEVideo:ContentMediaKeysRequest", gEMEHandler);
window
.getGroupMessageManager("browsers")
.addMessageListener("DecoderDoctor:Notification", gDecoderDoctorHandler);
window
.getGroupMessageManager("browsers")
.addMessageListener("EMEVideo:ContentMediaKeysRequest", gEMEHandler);
window.addEventListener("unload", function() {
window.getGroupMessageManager("browsers").removeMessageListener("EMEVideo:ContentMediaKeysRequest", gEMEHandler);
window.getGroupMessageManager("browsers").removeMessageListener("DecoderDoctor:Notification", gDecoderDoctorHandler);
window
.getGroupMessageManager("browsers")
.removeMessageListener("EMEVideo:ContentMediaKeysRequest", gEMEHandler);
window
.getGroupMessageManager("browsers")
.removeMessageListener("DecoderDoctor:Notification", gDecoderDoctorHandler);
});

Просмотреть файл

@ -8,7 +8,7 @@ var BrowserPageActions = {
*/
get mainButtonNode() {
delete this.mainButtonNode;
return this.mainButtonNode = document.getElementById("pageActionButton");
return (this.mainButtonNode = document.getElementById("pageActionButton"));
},
/**
@ -16,7 +16,7 @@ var BrowserPageActions = {
*/
get panelNode() {
delete this.panelNode;
return this.panelNode = document.getElementById("pageActionPanel");
return (this.panelNode = document.getElementById("pageActionPanel"));
},
/**
@ -24,7 +24,9 @@ var BrowserPageActions = {
*/
get multiViewNode() {
delete this.multiViewNode;
return this.multiViewNode = document.getElementById("pageActionPanelMultiView");
return (this.multiViewNode = document.getElementById(
"pageActionPanelMultiView"
));
},
/**
@ -32,7 +34,9 @@ var BrowserPageActions = {
*/
get mainViewNode() {
delete this.mainViewNode;
return this.mainViewNode = document.getElementById("pageActionPanelMainView");
return (this.mainViewNode = document.getElementById(
"pageActionPanelMainView"
));
},
/**
@ -40,7 +44,9 @@ var BrowserPageActions = {
*/
get mainViewBodyNode() {
delete this.mainViewBodyNode;
return this.mainViewBodyNode = this.mainViewNode.querySelector(".panel-subview-body");
return (this.mainViewBodyNode = this.mainViewNode.querySelector(
".panel-subview-body"
));
},
/**
@ -143,8 +149,9 @@ var BrowserPageActions = {
},
_removeActionFromPanel(action) {
let lazyIndex =
this._actionsToLazilyPlaceInPanel.findIndex(a => a.id == action.id);
let lazyIndex = this._actionsToLazilyPlaceInPanel.findIndex(
a => a.id == action.id
);
if (lazyIndex >= 0) {
this._actionsToLazilyPlaceInPanel.splice(lazyIndex, 1);
}
@ -194,19 +201,17 @@ var BrowserPageActions = {
* given action. Null if the action should be inserted at the end.
*/
_getNextNode(action, forUrlbar) {
let actions =
forUrlbar ?
PageActions.actionsInUrlbar(window) :
PageActions.actionsInPanel(window);
let actions = forUrlbar
? PageActions.actionsInUrlbar(window)
: PageActions.actionsInPanel(window);
let index = actions.findIndex(a => a.id == action.id);
if (index < 0) {
return null;
}
for (let i = index + 1; i < actions.length; i++) {
let node =
forUrlbar ?
this.urlbarButtonNodeForActionID(actions[i].id) :
this.panelButtonNodeForActionID(actions[i].id);
let node = forUrlbar
? this.urlbarButtonNodeForActionID(actions[i].id)
: this.panelButtonNodeForActionID(actions[i].id);
if (node) {
return node;
}
@ -299,9 +304,13 @@ var BrowserPageActions = {
let anchorNode = this.panelAnchorNodeForAction(action);
anchorNode.setAttribute("open", "true");
panelNode.addEventListener("popuphiding", () => {
anchorNode.removeAttribute("open");
}, { once: true });
panelNode.addEventListener(
"popuphiding",
() => {
anchorNode.removeAttribute("open");
},
{ once: true }
);
PanelMultiView.openPopup(panelNode, anchorNode, {
position: "bottomcenter topright",
@ -338,27 +347,47 @@ var BrowserPageActions = {
let popupSet = document.getElementById("mainPopupSet");
popupSet.appendChild(panelNode);
panelNode.addEventListener("popuphidden", () => {
PanelMultiView.removePopup(panelNode);
}, { once: true });
panelNode.addEventListener(
"popuphidden",
() => {
PanelMultiView.removePopup(panelNode);
},
{ once: true }
);
if (iframeNode) {
panelNode.addEventListener("popupshowing", () => {
action.onIframeShowing(iframeNode, panelNode);
}, { once: true });
panelNode.addEventListener("popuphiding", () => {
action.onIframeHiding(iframeNode, panelNode);
}, { once: true });
panelNode.addEventListener("popuphidden", () => {
action.onIframeHidden(iframeNode, panelNode);
}, { once: true });
panelNode.addEventListener(
"popupshowing",
() => {
action.onIframeShowing(iframeNode, panelNode);
},
{ once: true }
);
panelNode.addEventListener(
"popuphiding",
() => {
action.onIframeHiding(iframeNode, panelNode);
},
{ once: true }
);
panelNode.addEventListener(
"popuphidden",
() => {
action.onIframeHidden(iframeNode, panelNode);
},
{ once: true }
);
}
if (panelViewNode) {
action.onSubviewPlaced(panelViewNode);
panelNode.addEventListener("popupshowing", () => {
action.onSubviewShowing(panelViewNode);
}, { once: true });
panelNode.addEventListener(
"popupshowing",
() => {
action.onSubviewShowing(panelViewNode);
},
{ once: true }
);
}
return panelNode;
@ -511,18 +540,20 @@ var BrowserPageActions = {
*/
updateAction(action, propertyName = null, opts = {}) {
let anyNodeGiven = "panelNode" in opts || "urlbarNode" in opts;
let panelNode =
anyNodeGiven ?
opts.panelNode || null :
this.panelButtonNodeForActionID(action.id);
let urlbarNode =
anyNodeGiven ?
opts.urlbarNode || null :
this.urlbarButtonNodeForActionID(action.id);
let panelNode = anyNodeGiven
? opts.panelNode || null
: this.panelButtonNodeForActionID(action.id);
let urlbarNode = anyNodeGiven
? opts.urlbarNode || null
: this.urlbarButtonNodeForActionID(action.id);
let value = opts.value || undefined;
if (propertyName) {
this[this._updateMethods[propertyName]](action, panelNode, urlbarNode,
value);
this[this._updateMethods[propertyName]](
action,
panelNode,
urlbarNode,
value
);
} else {
for (let name of ["iconURL", "title", "tooltip", "wantsSubview"]) {
this[this._updateMethods[name]](action, panelNode, urlbarNode, value);
@ -538,8 +569,12 @@ var BrowserPageActions = {
wantsSubview: "_updateActionWantsSubview",
},
_updateActionDisabled(action, panelNode, urlbarNode,
disabled = action.getDisabled(window)) {
_updateActionDisabled(
action,
panelNode,
urlbarNode,
disabled = action.getDisabled(window)
) {
if (action.__transient) {
this.placeActionInPanel(action);
} else {
@ -548,8 +583,11 @@ var BrowserPageActions = {
this.placeActionInUrlbar(action);
},
_updateActionDisabledInPanel(action, panelNode,
disabled = action.getDisabled(window)) {
_updateActionDisabledInPanel(
action,
panelNode,
disabled = action.getDisabled(window)
) {
if (panelNode) {
if (disabled) {
panelNode.setAttribute("disabled", "true");
@ -559,8 +597,12 @@ var BrowserPageActions = {
}
},
_updateActionIconURL(action, panelNode, urlbarNode,
properties = action.getIconProperties(window)) {
_updateActionIconURL(
action,
panelNode,
urlbarNode,
properties = action.getIconProperties(window)
) {
for (let [prop, value] of Object.entries(properties)) {
if (panelNode) {
panelNode.style.setProperty(prop, value);
@ -571,8 +613,12 @@ var BrowserPageActions = {
}
},
_updateActionTitle(action, panelNode, urlbarNode,
title = action.getTitle(window)) {
_updateActionTitle(
action,
panelNode,
urlbarNode,
title = action.getTitle(window)
) {
if (!title) {
// `title` is a required action property, but the bookmark action's is an
// empty string since its actual title is set via
@ -600,8 +646,12 @@ var BrowserPageActions = {
}
},
_updateActionTooltip(action, panelNode, urlbarNode,
tooltip = action.getTooltip(window)) {
_updateActionTooltip(
action,
panelNode,
urlbarNode,
tooltip = action.getTooltip(window)
) {
if (urlbarNode) {
if (!tooltip) {
tooltip = action.getTitle(window);
@ -612,8 +662,12 @@ var BrowserPageActions = {
}
},
_updateActionWantsSubview(action, panelNode, urlbarNode,
wantsSubview = action.getWantsSubview(window)) {
_updateActionWantsSubview(
action,
panelNode,
urlbarNode,
wantsSubview = action.getWantsSubview(window)
) {
if (!panelNode) {
return;
}
@ -647,9 +701,11 @@ var BrowserPageActions = {
// If we're in the panel, open a subview inside the panel:
// Note that we can't use this.panelNode.contains(buttonNode) here
// because of XBL boundaries breaking Element.contains.
if (action.getWantsSubview(window) &&
buttonNode &&
buttonNode.closest("panel") == this.panelNode) {
if (
action.getWantsSubview(window) &&
buttonNode &&
buttonNode.closest("panel") == this.panelNode
) {
let panelViewNodeID = this._panelViewNodeIDForActionID(action.id, false);
let panelViewNode = document.getElementById(panelViewNodeID);
action.onSubviewShowing(panelViewNode);
@ -729,7 +785,9 @@ var BrowserPageActions = {
* @return (DOM node) The action's urlbar button node.
*/
urlbarButtonNodeForActionID(actionID) {
return document.getElementById(this.urlbarButtonNodeIDForActionID(actionID));
return document.getElementById(
this.urlbarButtonNodeIDForActionID(actionID)
);
},
/**
@ -780,9 +838,12 @@ var BrowserPageActions = {
*/
mainButtonClicked(event) {
event.stopPropagation();
if ((event.type == "mousedown" && event.button != 0) ||
(event.type == "keypress" && event.charCode != KeyEvent.DOM_VK_SPACE &&
event.keyCode != KeyEvent.DOM_VK_RETURN)) {
if (
(event.type == "mousedown" && event.button != 0) ||
(event.type == "keypress" &&
event.charCode != KeyEvent.DOM_VK_SPACE &&
event.keyCode != KeyEvent.DOM_VK_RETURN)
) {
return;
}
@ -838,15 +899,13 @@ var BrowserPageActions = {
let state;
if (this._contextAction._isMozillaAction) {
state =
this._contextAction.pinnedToUrlbar ?
"builtInPinned" :
"builtInUnpinned";
state = this._contextAction.pinnedToUrlbar
? "builtInPinned"
: "builtInUnpinned";
} else {
state =
this._contextAction.pinnedToUrlbar ?
"extensionPinned" :
"extensionUnpinned";
state = this._contextAction.pinnedToUrlbar
? "extensionPinned"
: "extensionUnpinned";
}
popup.setAttribute("state", state);
},
@ -881,7 +940,7 @@ var BrowserPageActions = {
AMTelemetry.recordActionEvent({
object: "pageAction",
action: "manage",
extra: {addonId: action.extensionID},
extra: { addonId: action.extensionID },
});
let viewID = "addons://detail/" + encodeURIComponent(action.extensionID);
@ -949,7 +1008,6 @@ var BrowserPageActions = {
},
};
/**
* Shows the feedback popup for an action.
*
@ -963,7 +1021,10 @@ var BrowserPageActions = {
function showBrowserPageActionFeedback(action, event = null, messageId = null) {
let anchor = BrowserPageActions.panelAnchorNodeForAction(action, event);
ConfirmationHint.show(anchor, messageId || action.id, {event, hideArrow: true});
ConfirmationHint.show(anchor, messageId || action.id, {
event,
hideArrow: true,
});
}
// built-in actions below //////////////////////////////////////////////////////
@ -987,16 +1048,22 @@ BrowserPageActions.pinTab = {
let action = PageActions.actionForID("pinTab");
let { pinned } = gBrowser.selectedTab;
if (pinned) {
action.setTitle(BrowserPageActions.panelNode.getAttribute("unpinTab-title"));
action.setTitle(
BrowserPageActions.panelNode.getAttribute("unpinTab-title")
);
} else {
action.setTitle(BrowserPageActions.panelNode.getAttribute("pinTab-title"));
action.setTitle(
BrowserPageActions.panelNode.getAttribute("pinTab-title")
);
}
let panelButton = BrowserPageActions.panelButtonNodeForActionID(action.id);
if (panelButton) {
panelButton.toggleAttribute("pinned", pinned);
}
let urlbarButton = BrowserPageActions.urlbarButtonNodeForActionID(action.id);
let urlbarButton = BrowserPageActions.urlbarButtonNodeForActionID(
action.id
);
if (urlbarButton) {
urlbarButton.toggleAttribute("pinned", pinned);
}
@ -1022,7 +1089,9 @@ BrowserPageActions.copyURL = {
PanelMultiView.hidePopup(BrowserPageActions.panelNode);
Cc["@mozilla.org/widget/clipboardhelper;1"]
.getService(Ci.nsIClipboardHelper)
.copyString(gURLBar.makeURIReadable(gBrowser.selectedBrowser.currentURI).displaySpec);
.copyString(
gURLBar.makeURIReadable(gBrowser.selectedBrowser.currentURI).displaySpec
);
let action = PageActions.actionForID("copyURL");
showBrowserPageActionFeedback(action, event);
},
@ -1054,8 +1123,9 @@ BrowserPageActions.sendToDevice = {
// selected.
_updateTitle() {
let action = PageActions.actionForID("sendToDevice");
let string =
gBrowserBundle.GetStringFromName("pageAction.sendTabsToDevice.label");
let string = gBrowserBundle.GetStringFromName(
"pageAction.sendTabsToDevice.label"
);
let tabCount = gBrowser.selectedTabs.length;
let title = PluralForm.get(tabCount, string).replace("#1", tabCount);
action.setTitle(title, window);
@ -1086,7 +1156,10 @@ BrowserPageActions.sendToDevice = {
},
onShowingSubview(panelViewNode) {
gSync.populateSendTabToDevicesView(panelViewNode, this.onShowingSubview.bind(this));
gSync.populateSendTabToDevicesView(
panelViewNode,
this.onShowingSubview.bind(this)
);
},
};
@ -1103,7 +1176,7 @@ BrowserPageActions.addSearchEngine = {
get strings() {
delete this.strings;
let uri = "chrome://browser/locale/search.properties";
return this.strings = Services.strings.createBundle(uri);
return (this.strings = Services.strings.createBundle(uri));
},
updateEngines() {
@ -1148,8 +1221,10 @@ BrowserPageActions.addSearchEngine = {
button.addEventListener("command", event => {
let panelNode = panelViewNode.closest("panel");
PanelMultiView.hidePopup(panelNode);
this._installEngine(button.getAttribute("uri"),
button.getAttribute("image"));
this._installEngine(
button.getAttribute("uri"),
button.getAttribute("image")
);
});
body.appendChild(button);
}
@ -1184,15 +1259,23 @@ BrowserPageActions.addSearchEngine = {
// Download error is shown by the search service
return;
}
const kSearchBundleURI = "chrome://global/locale/search/search.properties";
const kSearchBundleURI =
"chrome://global/locale/search/search.properties";
let searchBundle = Services.strings.createBundle(kSearchBundleURI);
let brandBundle = document.getElementById("bundle_brand");
let brandName = brandBundle.getString("brandShortName");
let title = searchBundle.GetStringFromName("error_invalid_engine_title");
let text = searchBundle.formatStringFromName("error_duplicate_engine_msg",
[brandName, uri]);
let title = searchBundle.GetStringFromName(
"error_invalid_engine_title"
);
let text = searchBundle.formatStringFromName(
"error_duplicate_engine_msg",
[brandName, uri]
);
Services.prompt.QueryInterface(Ci.nsIPromptFactory);
let prompt = Services.prompt.getPrompt(gBrowser.contentWindow, Ci.nsIPrompt);
let prompt = Services.prompt.getPrompt(
gBrowser.contentWindow,
Ci.nsIPrompt
);
prompt.QueryInterface(Ci.nsIWritablePropertyBag2);
prompt.setPropertyAsBool("allowTabModal", true);
prompt.alert(title, text);
@ -1236,9 +1319,11 @@ BrowserPageActions.shareURL = {
let onCommand = event => {
let shareName = event.target.getAttribute("share-name");
if (shareName) {
sharingService.shareUrl(shareName,
currentURI,
gBrowser.selectedBrowser.contentTitle);
sharingService.shareUrl(
shareName,
currentURI,
gBrowser.selectedBrowser.contentTitle
);
} else if (event.target.classList.contains("share-more-button")) {
sharingService.openSharingPreferences();
}
@ -1256,8 +1341,15 @@ BrowserPageActions.shareURL = {
});
let item = document.createXULElement("toolbarbutton");
item.setAttribute("label", BrowserPageActions.panelNode.getAttribute("shareMore-label"));
item.classList.add("subviewbutton", "subviewbutton-iconic", "share-more-button");
item.setAttribute(
"label",
BrowserPageActions.panelNode.getAttribute("shareMore-label")
);
item.classList.add(
"subviewbutton",
"subviewbutton-iconic",
"share-more-button"
);
item.addEventListener("command", onCommand);
fragment.appendChild(item);
@ -1271,6 +1363,9 @@ BrowserPageActions.shareURL = {
// Attach sharingService here so tests can override the implementation
XPCOMUtils.defineLazyServiceGetters(BrowserPageActions.shareURL, {
_sharingService: ["@mozilla.org/widget/macsharingservice;1", "nsIMacSharingService"],
_sharingService: [
"@mozilla.org/widget/macsharingservice;1",
"nsIMacSharingService",
],
_windowsUIUtils: ["@mozilla.org/windows-ui-utils;1", "nsIWindowsUIUtils"],
});

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -41,8 +41,13 @@ var gPluginHandler = {
receiveMessage(msg) {
switch (msg.name) {
case "PluginContent:ShowClickToPlayNotification":
this.showClickToPlayNotification(msg.target, msg.data.plugins, msg.data.showNow,
msg.principal, msg.data.location);
this.showClickToPlayNotification(
msg.target,
msg.data.plugins,
msg.data.showNow,
msg.principal,
msg.data.location
);
break;
case "PluginContent:RemoveNotification":
this.removeNotification(msg.target, msg.data.name);
@ -51,12 +56,19 @@ var gPluginHandler = {
this.installSinglePlugin(msg.data.pluginInfo);
break;
case "PluginContent:ShowPluginCrashedNotification":
this.showPluginCrashedNotification(msg.target, msg.data.messageString,
msg.data.pluginID);
this.showPluginCrashedNotification(
msg.target,
msg.data.messageString,
msg.data.pluginID
);
break;
case "PluginContent:SubmitReport":
if (AppConstants.MOZ_CRASHREPORTER) {
this.submitReport(msg.data.runID, msg.data.keyVals, msg.data.submitURLOptIn);
this.submitReport(
msg.data.runID,
msg.data.keyVals,
msg.data.submitURLOptIn
);
}
break;
case "PluginContent:LinkClickCallback":
@ -69,7 +81,9 @@ var gPluginHandler = {
}
break;
default:
Cu.reportError("gPluginHandler did not expect to handle message " + msg.name);
Cu.reportError(
"gPluginHandler did not expect to handle message " + msg.name
);
break;
}
},
@ -82,7 +96,9 @@ var gPluginHandler = {
// Callback for user clicking on the link in a click-to-play plugin
// (where the plugin has an update)
async openPluginUpdatePage(pluginTag) {
let { Blocklist } = ChromeUtils.import("resource://gre/modules/Blocklist.jsm");
let { Blocklist } = ChromeUtils.import(
"resource://gre/modules/Blocklist.jsm"
);
let url = await Blocklist.getPluginBlockURL(pluginTag);
openTrustedLinkIn(url, "tab");
},
@ -91,7 +107,10 @@ var gPluginHandler = {
if (!AppConstants.MOZ_CRASHREPORTER) {
return;
}
Services.prefs.setBoolPref("dom.ipc.plugins.reportCrashURL", submitURLOptIn);
Services.prefs.setBoolPref(
"dom.ipc.plugins.reportCrashURL",
submitURLOptIn
);
PluginCrashReporter.submitCrashReport(runID, keyVals);
},
@ -107,14 +126,16 @@ var gPluginHandler = {
_clickToPlayNotificationEventCallback: function PH_ctpEventCallback(event) {
if (event == "showing") {
Services.telemetry.getHistogramById("PLUGINS_NOTIFICATION_SHOWN")
Services.telemetry
.getHistogramById("PLUGINS_NOTIFICATION_SHOWN")
.add(!this.options.primaryPlugin);
// Histograms always start at 0, even though our data starts at 1
let histogramCount = this.options.pluginData.size - 1;
if (histogramCount > 4) {
histogramCount = 4;
}
Services.telemetry.getHistogramById("PLUGINS_NOTIFICATION_PLUGIN_COUNT")
Services.telemetry
.getHistogramById("PLUGINS_NOTIFICATION_PLUGIN_COUNT")
.add(histogramCount);
} else if (event == "dismissed") {
// Once the popup is dismissed, clicking the icon should show the full
@ -136,10 +157,14 @@ var gPluginHandler = {
let permission;
let expireType;
let expireTime;
let histogram =
Services.telemetry.getHistogramById("PLUGINS_NOTIFICATION_USER_ACTION_2");
let histogram = Services.telemetry.getHistogramById(
"PLUGINS_NOTIFICATION_USER_ACTION_2"
);
let notification = PopupNotifications.getNotification("click-to-play-plugins", aBrowser);
let notification = PopupNotifications.getNotification(
"click-to-play-plugins",
aBrowser
);
// Update the permission manager.
// Also update the current state of pluginInfo.fallbackType so that
@ -148,7 +173,11 @@ var gPluginHandler = {
case "allownow":
permission = Ci.nsIPermissionManager.ALLOW_ACTION;
expireType = Ci.nsIPermissionManager.EXPIRE_SESSION;
expireTime = Date.now() + Services.prefs.getIntPref(this.PREF_SESSION_PERSIST_MINUTES) * 60 * 1000;
expireTime =
Date.now() +
Services.prefs.getIntPref(this.PREF_SESSION_PERSIST_MINUTES) *
60 *
1000;
histogram.add(0);
aPluginInfo.fallbackType = Ci.nsIObjectLoadingContent.PLUGIN_ACTIVE;
notification.options.extraAttr = "active";
@ -161,15 +190,18 @@ var gPluginHandler = {
histogram.add(2);
switch (aPluginInfo.blocklistState) {
case Ci.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE:
aPluginInfo.fallbackType = Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE;
aPluginInfo.fallbackType =
Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE;
break;
case Ci.nsIBlocklistService.STATE_VULNERABLE_NO_UPDATE:
aPluginInfo.fallbackType = Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE;
aPluginInfo.fallbackType =
Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE;
break;
default:
// PLUGIN_CLICK_TO_PLAY_QUIET will only last until they reload the page, at
// which point it will be PLUGIN_CLICK_TO_PLAY (the overlays will appear)
aPluginInfo.fallbackType = Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY_QUIET;
aPluginInfo.fallbackType =
Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY_QUIET;
}
notification.options.extraAttr = "inactive";
break;
@ -183,7 +215,8 @@ var gPluginHandler = {
break;
case "continueblocking":
aPluginInfo.fallbackType = Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY_QUIET;
aPluginInfo.fallbackType =
Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY_QUIET;
notification.options.extraAttr = "inactive";
break;
@ -194,8 +227,13 @@ var gPluginHandler = {
if (aNewState != "continue" && aNewState != "continueblocking") {
let principal = notification.options.principal;
Services.perms.addFromPrincipal(principal, aPluginInfo.permissionString,
permission, expireType, expireTime);
Services.perms.addFromPrincipal(
principal,
aPluginInfo.permissionString,
permission,
expireType,
expireTime
);
aPluginInfo.pluginPermissionType = expireType;
}
@ -205,8 +243,7 @@ var gPluginHandler = {
});
},
showClickToPlayNotification(browser, plugins, showNow,
principal, location) {
showClickToPlayNotification(browser, plugins, showNow, principal, location) {
// It is possible that we've received a message from the frame script to show
// a click to play notification for a principal that no longer matches the one
// that the browser's content now has assigned (ie, the browser has browsed away
@ -225,7 +262,10 @@ var gPluginHandler = {
return;
}
let notification = PopupNotifications.getNotification("click-to-play-plugins", browser);
let notification = PopupNotifications.getNotification(
"click-to-play-plugins",
browser
);
// If this is a new notification, create a pluginData map, otherwise append
let pluginData;
@ -259,7 +299,8 @@ var gPluginHandler = {
if (plugins.length == 1) {
let pluginInfo = plugins[0];
let active = pluginInfo.fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_ACTIVE;
let active =
pluginInfo.fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_ACTIVE;
let options = {
dismissed: !showNow,
@ -274,8 +315,13 @@ var gPluginHandler = {
};
let description;
if (pluginInfo.fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE) {
description = gNavigatorBundle.getString("flashActivate.outdated.message");
if (
pluginInfo.fallbackType ==
Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE
) {
description = gNavigatorBundle.getString(
"flashActivate.outdated.message"
);
} else {
description = gNavigatorBundle.getString("flashActivate.message");
}
@ -283,8 +329,10 @@ var gPluginHandler = {
let badge = document.getElementById("plugin-icon-badge");
badge.setAttribute("animate", "true");
badge.addEventListener("animationend", function animListener(event) {
if (event.animationName == "blink-badge" &&
badge.hasAttribute("animate")) {
if (
event.animationName == "blink-badge" &&
badge.hasAttribute("animate")
) {
badge.removeAttribute("animate");
badge.removeEventListener("animationend", animListener);
}
@ -295,7 +343,10 @@ var gPluginHandler = {
callback: () => {
let browserRef = weakBrowser.get();
if (browserRef) {
if (pluginInfo.fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_ACTIVE) {
if (
pluginInfo.fallbackType ==
Ci.nsIObjectLoadingContent.PLUGIN_ACTIVE
) {
this._updatePluginPermission(browserRef, pluginInfo, "continue");
} else {
this._updatePluginPermission(browserRef, pluginInfo, "allownow");
@ -306,25 +357,42 @@ var gPluginHandler = {
accessKey: gNavigatorBundle.getString("flashActivate.allow.accesskey"),
dismiss: true,
};
let secondaryActions = [{
callback: () => {
let browserRef = weakBrowser.get();
if (browserRef) {
if (pluginInfo.fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_ACTIVE) {
this._updatePluginPermission(browserRef, pluginInfo, "block");
} else {
this._updatePluginPermission(browserRef, pluginInfo, "continueblocking");
let secondaryActions = [
{
callback: () => {
let browserRef = weakBrowser.get();
if (browserRef) {
if (
pluginInfo.fallbackType ==
Ci.nsIObjectLoadingContent.PLUGIN_ACTIVE
) {
this._updatePluginPermission(browserRef, pluginInfo, "block");
} else {
this._updatePluginPermission(
browserRef,
pluginInfo,
"continueblocking"
);
}
}
}
},
label: gNavigatorBundle.getString("flashActivate.noAllow"),
accessKey: gNavigatorBundle.getString(
"flashActivate.noAllow.accesskey"
),
dismiss: true,
},
label: gNavigatorBundle.getString("flashActivate.noAllow"),
accessKey: gNavigatorBundle.getString("flashActivate.noAllow.accesskey"),
dismiss: true,
}];
];
PopupNotifications.show(browser, "click-to-play-plugins",
description, "plugins-notification-icon",
mainAction, secondaryActions, options);
PopupNotifications.show(
browser,
"click-to-play-plugins",
description,
"plugins-notification-icon",
mainAction,
secondaryActions,
options
);
// Check if the plugin is insecure and update the notification icon accordingly.
let haveInsecure = false;
@ -336,8 +404,9 @@ var gPluginHandler = {
haveInsecure = true;
}
document.getElementById("plugins-notification-icon").classList.
toggle("plugin-blocked", haveInsecure);
document
.getElementById("plugins-notification-icon")
.classList.toggle("plugin-blocked", haveInsecure);
} else {
this.removeNotification(browser, "click-to-play-plugins");
}
@ -345,25 +414,33 @@ var gPluginHandler = {
removeNotification(browser, name) {
let notification = PopupNotifications.getNotification(name, browser);
if (notification)
if (notification) {
PopupNotifications.remove(notification);
}
},
contextMenuCommand(browser, plugin, command) {
browser.messageManager.sendAsyncMessage("BrowserPlugins:ContextMenuCommand",
{ command }, { plugin });
browser.messageManager.sendAsyncMessage(
"BrowserPlugins:ContextMenuCommand",
{ command },
{ plugin }
);
},
// Crashed-plugin observer. Notified once per plugin crash, before events
// are dispatched to individual plugin instances.
NPAPIPluginCrashed(subject, topic, data) {
let propertyBag = subject;
if (!(propertyBag instanceof Ci.nsIPropertyBag2) ||
!(propertyBag instanceof Ci.nsIWritablePropertyBag2) ||
!propertyBag.hasKey("runID") ||
!propertyBag.hasKey("pluginName")) {
Cu.reportError("A NPAPI plugin crashed, but the properties of this plugin " +
"cannot be read.");
if (
!(propertyBag instanceof Ci.nsIPropertyBag2) ||
!(propertyBag instanceof Ci.nsIWritablePropertyBag2) ||
!propertyBag.hasKey("runID") ||
!propertyBag.hasKey("pluginName")
) {
Cu.reportError(
"A NPAPI plugin crashed, but the properties of this plugin " +
"cannot be read."
);
return;
}
@ -388,8 +465,11 @@ var gPluginHandler = {
}
let mm = window.getGroupMessageManager("browsers");
mm.broadcastAsyncMessage("BrowserPlugins:NPAPIPluginProcessCrashed",
{ pluginName, runID, state });
mm.broadcastAsyncMessage("BrowserPlugins:NPAPIPluginProcessCrashed", {
pluginName,
runID,
state,
});
},
/**
@ -408,7 +488,9 @@ var gPluginHandler = {
showPluginCrashedNotification(browser, messageString, pluginID) {
// If there's already an existing notification bar, don't do anything.
let notificationBox = gBrowser.getNotificationBox(browser);
let notification = notificationBox.getNotificationWithValue("plugin-crashed");
let notification = notificationBox.getNotificationWithValue(
"plugin-crashed"
);
if (notification) {
return;
}
@ -416,20 +498,34 @@ var gPluginHandler = {
// Configure the notification bar
let priority = notificationBox.PRIORITY_WARNING_MEDIUM;
let iconURL = "chrome://global/skin/plugins/pluginGeneric.svg";
let reloadLabel = gNavigatorBundle.getString("crashedpluginsMessage.reloadButton.label");
let reloadKey = gNavigatorBundle.getString("crashedpluginsMessage.reloadButton.accesskey");
let reloadLabel = gNavigatorBundle.getString(
"crashedpluginsMessage.reloadButton.label"
);
let reloadKey = gNavigatorBundle.getString(
"crashedpluginsMessage.reloadButton.accesskey"
);
let buttons = [{
label: reloadLabel,
accessKey: reloadKey,
popup: null,
callback() { browser.reload(); },
}];
let buttons = [
{
label: reloadLabel,
accessKey: reloadKey,
popup: null,
callback() {
browser.reload();
},
},
];
if (AppConstants.MOZ_CRASHREPORTER &&
PluginCrashReporter.hasCrashReport(pluginID)) {
let submitLabel = gNavigatorBundle.getString("crashedpluginsMessage.submitButton.label");
let submitKey = gNavigatorBundle.getString("crashedpluginsMessage.submitButton.accesskey");
if (
AppConstants.MOZ_CRASHREPORTER &&
PluginCrashReporter.hasCrashReport(pluginID)
) {
let submitLabel = gNavigatorBundle.getString(
"crashedpluginsMessage.submitButton.label"
);
let submitKey = gNavigatorBundle.getString(
"crashedpluginsMessage.submitButton.accesskey"
);
let submitButton = {
label: submitLabel,
accessKey: submitKey,
@ -442,12 +538,22 @@ var gPluginHandler = {
buttons.push(submitButton);
}
notification = notificationBox.appendNotification(messageString, "plugin-crashed",
iconURL, priority, buttons);
notification = notificationBox.appendNotification(
messageString,
"plugin-crashed",
iconURL,
priority,
buttons
);
// Add the "learn more" link.
let link = notification.ownerDocument.createXULElement("label", {is: "text-link"});
link.setAttribute("value", gNavigatorBundle.getString("crashedpluginsMessage.learnMore"));
let link = notification.ownerDocument.createXULElement("label", {
is: "text-link",
});
link.setAttribute(
"value",
gNavigatorBundle.getString("crashedpluginsMessage.learnMore")
);
let crashurl = formatURL("app.support.baseURL", true);
crashurl += "plugin-crashed-notificationbar";
link.href = crashurl;

Просмотреть файл

@ -6,7 +6,6 @@
/* eslint-env mozilla/browser-window */
var gSafeBrowsing = {
setReportPhishingMenu() {
// In order to detect whether or not we're at the phishing warning
// page, we have to check the documentURI instead of the currentURI.
@ -18,9 +17,13 @@ var gSafeBrowsing = {
docURI && docURI.spec.startsWith("about:blocked?e=deceptiveBlocked");
// Show/hide the appropriate menu item.
const reportMenu = document.getElementById("menu_HelpPopup_reportPhishingtoolmenu");
const reportMenu = document.getElementById(
"menu_HelpPopup_reportPhishingtoolmenu"
);
reportMenu.hidden = isPhishingPage;
const reportErrorMenu = document.getElementById("menu_HelpPopup_reportPhishingErrortoolmenu");
const reportErrorMenu = document.getElementById(
"menu_HelpPopup_reportPhishingErrortoolmenu"
);
reportErrorMenu.hidden = !isPhishingPage;
if (isPhishingPage && !reportErrorMenu.hasAttribute("data-l10n-id")) {
MozXULElement.insertFTLIfNeeded("browser/safebrowsing/blockedSite.ftl");
@ -30,7 +33,8 @@ var gSafeBrowsing = {
// Now look at the currentURI to learn which page we were trying
// to browse to.
const uri = gBrowser.currentURI;
const isReportablePage = uri && (uri.schemeIs("http") || uri.schemeIs("https"));
const isReportablePage =
uri && (uri.schemeIs("http") || uri.schemeIs("https"));
const disabledByPolicy = !Services.policies.isAllowed("feedbackCommands");
@ -65,9 +69,10 @@ var gSafeBrowsing = {
// Remove the query to avoid including potentially sensitive data
if (pageUri instanceof Ci.nsIURL) {
pageUri = pageUri.mutate()
.setQuery("")
.finalize();
pageUri = pageUri
.mutate()
.setQuery("")
.finalize();
}
reportInfo = { uri: pageUri.asciiSpec };

Просмотреть файл

@ -10,39 +10,52 @@ var SidebarUI = {
if (this._sidebars) {
return this._sidebars;
}
return this._sidebars = new Map([
["viewBookmarksSidebar", {
title: document.getElementById("sidebar-switcher-bookmarks")
.getAttribute("label"),
url: "chrome://browser/content/places/bookmarksSidebar.xul",
menuId: "menu_bookmarksSidebar",
buttonId: "sidebar-switcher-bookmarks",
}],
["viewHistorySidebar", {
title: document.getElementById("sidebar-switcher-history")
.getAttribute("label"),
url: "chrome://browser/content/places/historySidebar.xul",
menuId: "menu_historySidebar",
buttonId: "sidebar-switcher-history",
triggerButtonId: "appMenuViewHistorySidebar",
}],
["viewTabsSidebar", {
title: document.getElementById("sidebar-switcher-tabs")
.getAttribute("label"),
url: "chrome://browser/content/syncedtabs/sidebar.xhtml",
menuId: "menu_tabsSidebar",
buttonId: "sidebar-switcher-tabs",
triggerButtonId: "PanelUI-remotetabs-view-sidebar",
}],
]);
return (this._sidebars = new Map([
[
"viewBookmarksSidebar",
{
title: document
.getElementById("sidebar-switcher-bookmarks")
.getAttribute("label"),
url: "chrome://browser/content/places/bookmarksSidebar.xul",
menuId: "menu_bookmarksSidebar",
buttonId: "sidebar-switcher-bookmarks",
},
],
[
"viewHistorySidebar",
{
title: document
.getElementById("sidebar-switcher-history")
.getAttribute("label"),
url: "chrome://browser/content/places/historySidebar.xul",
menuId: "menu_historySidebar",
buttonId: "sidebar-switcher-history",
triggerButtonId: "appMenuViewHistorySidebar",
},
],
[
"viewTabsSidebar",
{
title: document
.getElementById("sidebar-switcher-tabs")
.getAttribute("label"),
url: "chrome://browser/content/syncedtabs/sidebar.xhtml",
menuId: "menu_tabsSidebar",
buttonId: "sidebar-switcher-tabs",
triggerButtonId: "PanelUI-remotetabs-view-sidebar",
},
],
]));
},
// Avoid getting the browser element from init() to avoid triggering the
// <browser> constructor during startup if the sidebar is hidden.
get browser() {
if (this._browser)
if (this._browser) {
return this._browser;
return this._browser = document.getElementById("sidebar");
}
return (this._browser = document.getElementById("sidebar"));
},
POSITION_START_PREF: "sidebar.position_start",
DEFAULT_SIDEBAR_ID: "viewBookmarksSidebar",
@ -55,9 +68,10 @@ var SidebarUI = {
// The constructor of this label accesses the browser element due to the
// control="sidebar" attribute, so avoid getting this label during startup.
get _title() {
if (this.__title)
if (this.__title) {
return this.__title;
return this.__title = document.getElementById("sidebar-title");
}
return (this.__title = document.getElementById("sidebar-title"));
},
_splitter: null,
_icon: null,
@ -81,7 +95,9 @@ var SidebarUI = {
this._box = document.getElementById("sidebar-box");
this._splitter = document.getElementById("sidebar-splitter");
this._icon = document.getElementById("sidebar-icon");
this._reversePositionButton = document.getElementById("sidebar-reverse-position");
this._reversePositionButton = document.getElementById(
"sidebar-reverse-position"
);
this._switcherPanel = document.getElementById("sidebarMenu-popup");
this._switcherTarget = document.getElementById("sidebar-switcher-target");
this._switcherArrow = document.getElementById("sidebar-switcher-arrow");
@ -106,7 +122,11 @@ var SidebarUI = {
if (this._box.hasAttribute("positionend")) {
xulStore.persist(this._box, "positionend");
} else {
xulStore.removeValue(document.documentURI, "sidebar-box", "positionend");
xulStore.removeValue(
document.documentURI,
"sidebar-box",
"positionend"
);
}
if (this._box.hasAttribute("checked")) {
xulStore.persist(this._box, "checked");
@ -123,7 +143,10 @@ var SidebarUI = {
* Opens the switcher panel if it's closed, or closes it if it's open.
*/
toggleSwitcherPanel() {
if (this._switcherPanel.state == "open" || this._switcherPanel.state == "showing") {
if (
this._switcherPanel.state == "open" ||
this._switcherPanel.state == "showing"
) {
this.hideSwitcherPanel();
} else if (this._switcherPanel.state == "closed") {
this.showSwitcherPanel();
@ -136,14 +159,19 @@ var SidebarUI = {
showSwitcherPanel() {
this._ensureShortcutsShown();
this._switcherPanel.addEventListener("popuphiding", () => {
this._switcherTarget.classList.remove("active");
}, {once: true});
this._switcherPanel.addEventListener(
"popuphiding",
() => {
this._switcherTarget.classList.remove("active");
},
{ once: true }
);
// Combine start/end position with ltr/rtl to set the label in the popup appropriately.
let label = this._positionStart == RTL_UI ?
gNavigatorBundle.getString("sidebar.moveToLeft") :
gNavigatorBundle.getString("sidebar.moveToRight");
let label =
this._positionStart == RTL_UI
? gNavigatorBundle.getString("sidebar.moveToLeft")
: gNavigatorBundle.getString("sidebar.moveToRight");
this._reversePositionButton.setAttribute("label", label);
this._switcherPanel.hidden = false;
@ -151,7 +179,7 @@ var SidebarUI = {
this._switcherTarget.classList.add("active");
},
updateShortcut({button, key}) {
updateShortcut({ button, key }) {
// If the shortcuts haven't been rendered yet then it will be set correctly
// on the first render so there's nothing to do now.
if (!this._addedShortcuts) {
@ -176,8 +204,10 @@ var SidebarUI = {
return;
}
this._addedShortcuts = true;
for (let button of this._switcherPanel.querySelectorAll("toolbarbutton[key]")) {
this.updateShortcut({button});
for (let button of this._switcherPanel.querySelectorAll(
"toolbarbutton[key]"
)) {
this.updateShortcut({ button });
}
},
@ -255,14 +285,20 @@ var SidebarUI = {
return true;
}
this._box.setAttribute("width", sourceUI._box.getBoundingClientRect().width);
this._box.setAttribute(
"width",
sourceUI._box.getBoundingClientRect().width
);
this.showInitially(commandID);
return true;
},
windowPrivacyMatches(w1, w2) {
return PrivateBrowsingUtils.isWindowPrivate(w1) === PrivateBrowsingUtils.isWindowPrivate(w2);
return (
PrivateBrowsingUtils.isWindowPrivate(w1) ===
PrivateBrowsingUtils.isWindowPrivate(w2)
);
},
/**
@ -274,8 +310,11 @@ var SidebarUI = {
// opened from another window, check that it is one we might open a sidebar
// for.
if (sourceWindow) {
if (sourceWindow.closed || sourceWindow.location.protocol != "chrome:" ||
!this.windowPrivacyMatches(sourceWindow, window)) {
if (
sourceWindow.closed ||
sourceWindow.location.protocol != "chrome:" ||
!this.windowPrivacyMatches(sourceWindow, window)
) {
return;
}
// Try to adopt the sidebar state from the source window
@ -316,7 +355,7 @@ var SidebarUI = {
* a chance to update the button or whatever.
*/
_fireShowEvent() {
let event = new CustomEvent("SidebarShown", {bubbles: true});
let event = new CustomEvent("SidebarShown", { bubbles: true });
this._switcherTarget.dispatchEvent(event);
},
@ -327,7 +366,7 @@ var SidebarUI = {
* window, only when the user opens the sidebar.
*/
_fireFocusedEvent() {
let event = new CustomEvent("SidebarFocused", {bubbles: true});
let event = new CustomEvent("SidebarFocused", { bubbles: true });
this.browser.contentWindow.dispatchEvent(event);
},
@ -384,10 +423,13 @@ var SidebarUI = {
_loadSidebarExtension(commandID) {
let sidebar = this.sidebars.get(commandID);
let {extensionId} = sidebar;
let { extensionId } = sidebar;
if (extensionId) {
SidebarUI.browser.contentWindow.loadPanel(extensionId, sidebar.panel,
sidebar.browserStyle);
SidebarUI.browser.contentWindow.loadPanel(
extensionId,
sidebar.panel,
sidebar.browserStyle
);
}
},
@ -459,21 +501,25 @@ var SidebarUI = {
this._box.setAttribute("sidebarcommand", commandID);
this.lastOpenedId = commandID;
let {url, title} = this.sidebars.get(commandID);
let { url, title } = this.sidebars.get(commandID);
this.title = title;
this.browser.setAttribute("src", url); // kick off async load
if (this.browser.contentDocument.location.href != url) {
this.browser.addEventListener("load", event => {
// We're handling the 'load' event before it bubbles up to the usual
// (non-capturing) event handlers. Let it bubble up before resolving.
setTimeout(() => {
resolve();
this.browser.addEventListener(
"load",
event => {
// We're handling the 'load' event before it bubbles up to the usual
// (non-capturing) event handlers. Let it bubble up before resolving.
setTimeout(() => {
resolve();
// Now that the currentId is updated, fire a show event.
this._fireShowEvent();
}, 0);
}, {capture: true, once: true});
// Now that the currentId is updated, fire a show event.
this._fireShowEvent();
}, 0);
},
{ capture: true, once: true }
);
} else {
resolve();
@ -482,9 +528,10 @@ var SidebarUI = {
}
let selBrowser = gBrowser.selectedBrowser;
selBrowser.messageManager.sendAsyncMessage("Sidebar:VisibilityChange",
{commandID, isOpen: true}
);
selBrowser.messageManager.sendAsyncMessage("Sidebar:VisibilityChange", {
commandID,
isOpen: true,
});
});
},
@ -517,9 +564,10 @@ var SidebarUI = {
let selBrowser = gBrowser.selectedBrowser;
selBrowser.focus();
selBrowser.messageManager.sendAsyncMessage("Sidebar:VisibilityChange",
{commandID, isOpen: false}
);
selBrowser.messageManager.sendAsyncMessage("Sidebar:VisibilityChange", {
commandID,
isOpen: false,
});
if (triggerNode) {
updateToggleControlLabel(triggerNode);
}
@ -530,10 +578,11 @@ var SidebarUI = {
* none if the argument is an empty string.
*/
selectMenuItem(commandID) {
for (let [id, {menuId, buttonId, triggerButtonId}] of this.sidebars) {
for (let [id, { menuId, buttonId, triggerButtonId }] of this.sidebars) {
let menu = document.getElementById(menuId);
let button = document.getElementById(buttonId);
let triggerbutton = triggerButtonId && document.getElementById(triggerButtonId);
let triggerbutton =
triggerButtonId && document.getElementById(triggerButtonId);
if (id == commandID) {
menu.setAttribute("checked", "true");
button.setAttribute("checked", "true");
@ -555,5 +604,10 @@ var SidebarUI = {
// Add getters related to the position here, since we will want them
// available for both startDelayedLoad and init.
XPCOMUtils.defineLazyPreferenceGetter(SidebarUI, "_positionStart",
SidebarUI.POSITION_START_PREF, true, SidebarUI.setPosition.bind(SidebarUI));
XPCOMUtils.defineLazyPreferenceGetter(
SidebarUI,
"_positionStart",
SidebarUI.POSITION_START_PREF,
true,
SidebarUI.setPosition.bind(SidebarUI)
);

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -11,84 +11,105 @@ var gProtectionsHandler = {
// smart getters
get _protectionsPopup() {
delete this._protectionsPopup;
return this._protectionsPopup = document.getElementById("protections-popup");
return (this._protectionsPopup = document.getElementById(
"protections-popup"
));
},
get _protectionsIconBox() {
delete this._protectionsIconBox;
return this._protectionsIconBox = document.getElementById("tracking-protection-icon-animatable-box");
return (this._protectionsIconBox = document.getElementById(
"tracking-protection-icon-animatable-box"
));
},
get _protectionsPopupMultiView() {
delete this._protectionsPopupMultiView;
return this._protectionsPopupMultiView =
document.getElementById("protections-popup-multiView");
return (this._protectionsPopupMultiView = document.getElementById(
"protections-popup-multiView"
));
},
get _protectionsPopupMainView() {
delete this._protectionsPopupMainView;
return this._protectionsPopupMainView =
document.getElementById("protections-popup-mainView");
return (this._protectionsPopupMainView = document.getElementById(
"protections-popup-mainView"
));
},
get _protectionsPopupMainViewHeaderLabel() {
delete this._protectionsPopupMainViewHeaderLabel;
return this._protectionsPopupMainViewHeaderLabel =
document.getElementById("protections-popup-mainView-panel-header-span");
return (this._protectionsPopupMainViewHeaderLabel = document.getElementById(
"protections-popup-mainView-panel-header-span"
));
},
get _protectionsPopupTPSwitchBreakageLink() {
delete this._protectionsPopupTPSwitchBreakageLink;
return this._protectionsPopupTPSwitchBreakageLink =
document.getElementById("protections-popup-tp-switch-breakage-link");
return (this._protectionsPopupTPSwitchBreakageLink = document.getElementById(
"protections-popup-tp-switch-breakage-link"
));
},
get _protectionsPopupTPSwitch() {
delete this._protectionsPopupTPSwitch;
return this._protectionsPopupTPSwitch =
document.getElementById("protections-popup-tp-switch");
return (this._protectionsPopupTPSwitch = document.getElementById(
"protections-popup-tp-switch"
));
},
get _protectionPopupSettingsButton() {
delete this._protectionPopupSettingsButton;
return this._protectionPopupSettingsButton =
document.getElementById("protections-popup-settings-button");
return (this._protectionPopupSettingsButton = document.getElementById(
"protections-popup-settings-button"
));
},
get _protectionPopupFooter() {
delete this._protectionPopupFooter;
return this._protectionPopupFooter =
document.getElementById("protections-popup-footer");
return (this._protectionPopupFooter = document.getElementById(
"protections-popup-footer"
));
},
get _protectionPopupTrackersCounterDescription() {
delete this._protectionPopupTrackersCounterDescription;
return this._protectionPopupTrackersCounterDescription =
document.getElementById("protections-popup-trackers-blocked-counter-description");
return (this._protectionPopupTrackersCounterDescription = document.getElementById(
"protections-popup-trackers-blocked-counter-description"
));
},
get _protectionsPopupSiteNotWorkingTPSwitch() {
delete this._protectionsPopupSiteNotWorkingTPSwitch;
return this._protectionsPopupSiteNotWorkingTPSwitch =
document.getElementById("protections-popup-siteNotWorking-tp-switch");
return (this._protectionsPopupSiteNotWorkingTPSwitch = document.getElementById(
"protections-popup-siteNotWorking-tp-switch"
));
},
get _protectionsPopupSendReportLearnMore() {
delete this._protectionsPopupSendReportLearnMore;
return this._protectionsPopupSendReportLearnMore =
document.getElementById("protections-popup-sendReportView-learn-more");
return (this._protectionsPopupSendReportLearnMore = document.getElementById(
"protections-popup-sendReportView-learn-more"
));
},
get _protectionsPopupSendReportURL() {
delete this._protectionsPopupSendReportURL;
return this._protectionsPopupSendReportURL =
document.getElementById("protections-popup-sendReportView-collection-url");
return (this._protectionsPopupSendReportURL = document.getElementById(
"protections-popup-sendReportView-collection-url"
));
},
get _protectionsPopupToastTimeout() {
delete this._protectionsPopupToastTimeout;
XPCOMUtils.defineLazyPreferenceGetter(this, "_protectionsPopupToastTimeout",
"browser.protections_panel.toast.timeout",
5000);
XPCOMUtils.defineLazyPreferenceGetter(
this,
"_protectionsPopupToastTimeout",
"browser.protections_panel.toast.timeout",
5000
);
return this._protectionsPopupToastTimeout;
},
handleProtectionsButtonEvent(event) {
event.stopPropagation();
if ((event.type == "click" && event.button != 0) ||
(event.type == "keypress" && event.charCode != KeyEvent.DOM_VK_SPACE &&
event.keyCode != KeyEvent.DOM_VK_RETURN)) {
if (
(event.type == "click" && event.button != 0) ||
(event.type == "keypress" &&
event.charCode != KeyEvent.DOM_VK_SPACE &&
event.keyCode != KeyEvent.DOM_VK_RETURN)
) {
return; // Left click, space or enter only
}
this.showProtectionsPopup({event});
this.showProtectionsPopup({ event });
},
onPopupShown(event) {
@ -111,7 +132,7 @@ var gProtectionsHandler = {
PanelMultiView.hidePopup(this._protectionsPopup);
// Open the full protections panel.
this.showProtectionsPopup({event});
this.showProtectionsPopup({ event });
}
},
@ -123,8 +144,10 @@ var gProtectionsHandler = {
this._showToastAfterRefresh = false;
// We only display the toast if we're still on the same page.
if (this._previousURI != gBrowser.currentURI.spec ||
this._previousOuterWindowID != gBrowser.selectedBrowser.outerWindowID) {
if (
this._previousURI != gBrowser.currentURI.spec ||
this._previousOuterWindowID != gBrowser.selectedBrowser.outerWindowID
) {
return;
}
@ -137,9 +160,13 @@ var gProtectionsHandler = {
let elem = document.activeElement;
let position = elem.compareDocumentPosition(this._protectionsPopup);
if (!(position & (Node.DOCUMENT_POSITION_CONTAINS |
Node.DOCUMENT_POSITION_CONTAINED_BY)) &&
!this._protectionsPopup.hasAttribute("noautohide")) {
if (
!(
position &
(Node.DOCUMENT_POSITION_CONTAINS | Node.DOCUMENT_POSITION_CONTAINED_BY)
) &&
!this._protectionsPopup.hasAttribute("noautohide")
) {
// Hide the panel when focusing an element that is
// neither an ancestor nor descendant unless the panel has
// @noautohide (e.g. for a tour).
@ -155,11 +182,12 @@ var gProtectionsHandler = {
// gNavigatorBundle.getFormattedString("protections.header", [host]);
`Tracking Protections for ${host}`;
let currentlyEnabled =
!this._protectionsPopup.hasAttribute("hasException");
let currentlyEnabled = !this._protectionsPopup.hasAttribute("hasException");
for (let tpSwitch of [this._protectionsPopupTPSwitch,
this._protectionsPopupSiteNotWorkingTPSwitch]) {
for (let tpSwitch of [
this._protectionsPopupTPSwitch,
this._protectionsPopupSiteNotWorkingTPSwitch,
]) {
tpSwitch.toggleAttribute("enabled", currentlyEnabled);
}
@ -188,10 +216,13 @@ var gProtectionsHandler = {
// Toggling the 'hasException' on the protections panel in order to do some
// styling after toggling the TP switch.
let newExceptionState =
this._protectionsPopup.toggleAttribute("hasException");
for (let tpSwitch of [this._protectionsPopupTPSwitch,
this._protectionsPopupSiteNotWorkingTPSwitch]) {
let newExceptionState = this._protectionsPopup.toggleAttribute(
"hasException"
);
for (let tpSwitch of [
this._protectionsPopupTPSwitch,
this._protectionsPopupSiteNotWorkingTPSwitch,
]) {
tpSwitch.toggleAttribute("enabled", !newExceptionState);
}
@ -202,7 +233,7 @@ var gProtectionsHandler = {
this._previousURI = gBrowser.currentURI.spec;
this._previousOuterWindowID = gBrowser.selectedBrowser.outerWindowID;
await new Promise((resolve) => setTimeout(resolve, 500));
await new Promise(resolve => setTimeout(resolve, 500));
if (newExceptionState) {
ContentBlocking.disableForCurrentPage();
@ -236,7 +267,7 @@ var gProtectionsHandler = {
* will be hidden after a certain amount of time.
*/
showProtectionsPopup(options = {}) {
const {event, toast} = options;
const { event, toast } = options;
// We need to clear the toast timer if it exists before showing the
// protections popup.
@ -256,41 +287,58 @@ var gProtectionsHandler = {
}
if (toast) {
this._protectionsPopup.addEventListener("popupshown", () => {
this._toastPanelTimer = setTimeout(() => {
PanelMultiView.hidePopup(this._protectionsPopup);
delete this._toastPanelTimer;
}, this._protectionsPopupToastTimeout);
}, {once: true});
this._protectionsPopup.addEventListener(
"popupshown",
() => {
this._toastPanelTimer = setTimeout(() => {
PanelMultiView.hidePopup(this._protectionsPopup);
delete this._toastPanelTimer;
}, this._protectionsPopupToastTimeout);
},
{ once: true }
);
}
// Now open the popup, anchored off the primary chrome element
PanelMultiView.openPopup(this._protectionsPopup, gIdentityHandler._identityIcon, {
position: "bottomcenter topleft",
triggerEvent: event,
}).catch(Cu.reportError);
PanelMultiView.openPopup(
this._protectionsPopup,
gIdentityHandler._identityIcon,
{
position: "bottomcenter topleft",
triggerEvent: event,
}
).catch(Cu.reportError);
},
showSiteNotWorkingView() {
this._protectionsPopupMultiView.showSubView("protections-popup-siteNotWorkingView");
this._protectionsPopupMultiView.showSubView(
"protections-popup-siteNotWorkingView"
);
},
showSendReportView() {
// Save this URI to make sure that the user really only submits the location
// they see in the report breakage dialog.
this.reportURI = gBrowser.currentURI;
let urlWithoutQuery = this.reportURI.asciiSpec.replace("?" + this.reportURI.query, "");
let urlWithoutQuery = this.reportURI.asciiSpec.replace(
"?" + this.reportURI.query,
""
);
this._protectionsPopupSendReportURL.value = urlWithoutQuery;
this._protectionsPopupMultiView.showSubView("protections-popup-sendReportView");
this._protectionsPopupMultiView.showSubView(
"protections-popup-sendReportView"
);
},
onSendReportClicked() {
this._protectionsPopup.hidePopup();
let comments = document.getElementById(
"protections-popup-sendReportView-collection-comments");
"protections-popup-sendReportView-collection-comments"
);
ContentBlocking.submitBreakageReport(this.reportURI, comments);
},
};
let baseURL = Services.urlFormatter.formatURLPref("app.support.baseURL");
gProtectionsHandler._protectionsPopupSendReportLearnMore.href = baseURL + "blocking-breakage";
gProtectionsHandler._protectionsPopupSendReportLearnMore.href =
baseURL + "blocking-breakage";

Просмотреть файл

@ -5,14 +5,23 @@
// This file is loaded into the browser window scope.
/* eslint-env mozilla/browser-window */
const {UIState} = ChromeUtils.import("resource://services-sync/UIState.jsm");
const { UIState } = ChromeUtils.import("resource://services-sync/UIState.jsm");
ChromeUtils.defineModuleGetter(this, "FxAccounts",
"resource://gre/modules/FxAccounts.jsm");
ChromeUtils.defineModuleGetter(this, "EnsureFxAccountsWebChannel",
"resource://gre/modules/FxAccountsWebChannel.jsm");
ChromeUtils.defineModuleGetter(this, "Weave",
"resource://services-sync/main.js");
ChromeUtils.defineModuleGetter(
this,
"FxAccounts",
"resource://gre/modules/FxAccounts.jsm"
);
ChromeUtils.defineModuleGetter(
this,
"EnsureFxAccountsWebChannel",
"resource://gre/modules/FxAccountsWebChannel.jsm"
);
ChromeUtils.defineModuleGetter(
this,
"Weave",
"resource://services-sync/main.js"
);
const MIN_STATUS_ANIMATION_DURATION = 1600;
@ -23,37 +32,36 @@ var gSync = {
_syncStartTime: 0,
_syncAnimationTimer: 0,
_obs: [
"weave:engine:sync:finish",
"quit-application",
UIState.ON_UPDATE,
],
_obs: ["weave:engine:sync:finish", "quit-application", UIState.ON_UPDATE],
get fxaStrings() {
delete this.fxaStrings;
return this.fxaStrings = Services.strings.createBundle(
return (this.fxaStrings = Services.strings.createBundle(
"chrome://browser/locale/accounts.properties"
);
));
},
get syncStrings() {
delete this.syncStrings;
// XXXzpao these strings should probably be moved from /services to /browser... (bug 583381)
// but for now just make it work
return this.syncStrings = Services.strings.createBundle(
return (this.syncStrings = Services.strings.createBundle(
"chrome://weave/locale/sync.properties"
);
));
},
get syncReady() {
return Cc["@mozilla.org/weave/service;1"].getService().wrappedJSObject.ready;
return Cc["@mozilla.org/weave/service;1"].getService().wrappedJSObject
.ready;
},
// Returns true if sync is configured but hasn't loaded or the send tab
// targets list isn't ready yet.
get sendTabConfiguredAndLoading() {
return UIState.get().status == UIState.STATUS_SIGNED_IN &&
(!this.syncReady || !Weave.Service.clientsEngine.hasSyncedThisSession);
return (
UIState.get().status == UIState.STATUS_SIGNED_IN &&
(!this.syncReady || !Weave.Service.clientsEngine.hasSyncedThisSession)
);
},
get isSignedIn() {
@ -63,7 +71,11 @@ var gSync = {
get sendTabTargets() {
return Weave.Service.clientsEngine.fxaDevices
.sort((a, b) => a.name.localeCompare(b.name))
.filter(d => !d.isCurrentDevice && (fxAccounts.commands.sendTab.isDeviceCompatible(d) || d.clientRecord));
.filter(
d =>
!d.isCurrentDevice &&
(fxAccounts.commands.sendTab.isDeviceCompatible(d) || d.clientRecord)
);
},
get offline() {
@ -77,25 +89,39 @@ var gSync = {
delete this[prop];
this.__defineGetter__(prop, function() {
delete this[prop];
return this[prop] = document.getElementById("appMenu-fxa-" + suffix);
return (this[prop] = document.getElementById("appMenu-fxa-" + suffix));
});
}
},
_definePrefGetters() {
XPCOMUtils.defineLazyPreferenceGetter(this, "UNSENDABLE_URL_REGEXP",
"services.sync.engine.tabs.filteredUrls", null, null, rx => {
try {
return new RegExp(rx, "i");
} catch (e) {
Cu.reportError(`Failed to build url filter regexp for send tab: ${e}`);
return null;
}
});
XPCOMUtils.defineLazyPreferenceGetter(this, "PRODUCT_INFO_BASE_URL",
"app.productInfo.baseURL");
XPCOMUtils.defineLazyPreferenceGetter(this, "SYNC_ENABLED",
"identity.fxaccounts.enabled");
XPCOMUtils.defineLazyPreferenceGetter(
this,
"UNSENDABLE_URL_REGEXP",
"services.sync.engine.tabs.filteredUrls",
null,
null,
rx => {
try {
return new RegExp(rx, "i");
} catch (e) {
Cu.reportError(
`Failed to build url filter regexp for send tab: ${e}`
);
return null;
}
}
);
XPCOMUtils.defineLazyPreferenceGetter(
this,
"PRODUCT_INFO_BASE_URL",
"app.productInfo.baseURL"
);
XPCOMUtils.defineLazyPreferenceGetter(
this,
"SYNC_ENABLED",
"identity.fxaccounts.enabled"
);
},
maybeUpdateUIState() {
@ -205,13 +231,18 @@ var gSync = {
title = PluralForm.get(tabCount, string).replace("#1", tabCount);
}
document.getElementById("PanelUI-fxa-menu-sendtab-button").setAttribute("label", title);
document
.getElementById("PanelUI-fxa-menu-sendtab-button")
.setAttribute("label", title);
},
showSendToDeviceView(anchor) {
PanelUI.showSubView("PanelUI-sendTabToDevice", anchor);
let panelViewNode = document.getElementById("PanelUI-sendTabToDevice");
this.populateSendTabToDevicesView(panelViewNode, this.populateSendTabToDevicesView.bind(this));
this.populateSendTabToDevicesView(
panelViewNode,
this.populateSendTabToDevicesView.bind(this)
);
},
showSendToDeviceViewFromFxaMenu(anchor) {
@ -239,33 +270,42 @@ var gSync = {
// This is on top because it also clears the device list between state
// changes.
this.populateSendTabToDevicesMenu(bodyNode, url, title, multiselected, (clientId, name, clientType, lastModified) => {
if (!name) {
return document.createXULElement("toolbarseparator");
}
let item = document.createXULElement("toolbarbutton");
item.classList.add("pageAction-sendToDevice-device", "subviewbutton");
if (clientId) {
item.classList.add("subviewbutton-iconic");
if (lastModified) {
item.setAttribute("tooltiptext", gSync.formatLastSyncDate(lastModified));
this.populateSendTabToDevicesMenu(
bodyNode,
url,
title,
multiselected,
(clientId, name, clientType, lastModified) => {
if (!name) {
return document.createXULElement("toolbarseparator");
}
let item = document.createXULElement("toolbarbutton");
item.classList.add("pageAction-sendToDevice-device", "subviewbutton");
if (clientId) {
item.classList.add("subviewbutton-iconic");
if (lastModified) {
item.setAttribute(
"tooltiptext",
gSync.formatLastSyncDate(lastModified)
);
}
}
}
item.addEventListener("command", event => {
if (panelNode) {
PanelMultiView.hidePopup(panelNode);
}
// There are items in the subview that don't represent devices: "Sign
// in", "Learn about Sync", etc. Device items will be .sendtab-target.
if (event.target.classList.contains("sendtab-target")) {
let action = PageActions.actionForID("sendToDevice");
let messageId = gSync.offline && "sendToDeviceOffline";
showBrowserPageActionFeedback(action, event, messageId);
}
});
return item;
});
item.addEventListener("command", event => {
if (panelNode) {
PanelMultiView.hidePopup(panelNode);
}
// There are items in the subview that don't represent devices: "Sign
// in", "Learn about Sync", etc. Device items will be .sendtab-target.
if (event.target.classList.contains("sendtab-target")) {
let action = PageActions.actionForID("sendToDevice");
let messageId = gSync.offline && "sendToDeviceOffline";
showBrowserPageActionFeedback(action, event, messageId);
}
});
return item;
}
);
bodyNode.removeAttribute("state");
// In the first ~10 sec after startup, Sync may not be loaded and the list
@ -274,7 +314,7 @@ var gSync = {
bodyNode.setAttribute("state", "notready");
// Force a background Sync
Services.tm.dispatchToMainThread(async () => {
await Weave.Service.sync({why: "pageactions", engines: []}); // [] = clients engine only
await Weave.Service.sync({ why: "pageactions", engines: [] }); // [] = clients engine only
// There's no way Sync is still syncing at this point, but we check
// anyway to avoid infinite looping.
if (!window.closed && !gSync.sendTabConfiguredAndLoading) {
@ -290,9 +330,12 @@ var gSync = {
return;
}
if ((aEvent.type == "mousedown" && aEvent.button != 0) ||
(aEvent.type == "keypress" && aEvent.charCode != KeyEvent.DOM_VK_SPACE &&
aEvent.keyCode != KeyEvent.DOM_VK_RETURN)) {
if (
(aEvent.type == "mousedown" && aEvent.button != 0) ||
(aEvent.type == "keypress" &&
aEvent.charCode != KeyEvent.DOM_VK_SPACE &&
aEvent.keyCode != KeyEvent.DOM_VK_RETURN)
) {
return;
}
@ -321,7 +364,10 @@ var gSync = {
// the users custom profile image or a filled avatar.
let stateValue = "not_configured";
document.getElementById("PanelUI-fxa").removeAttribute("title");
if (state.status === UIState.STATUS_LOGIN_FAILED || state.status === UIState.STATUS_NOT_VERIFIED) {
if (
state.status === UIState.STATUS_LOGIN_FAILED ||
state.status === UIState.STATUS_NOT_VERIFIED
) {
stateValue = "unverified";
} else if (state.status === UIState.STATUS_SIGNED_IN) {
stateValue = "signedin";
@ -346,8 +392,15 @@ var gSync = {
document.getElementById("fxa-menu-email").value = state.email;
let defaultPanelTitle = this.fxaStrings.GetStringFromName("account.title");
document.getElementById("PanelUI-fxa").setAttribute("title", state.displayName ? state.displayName : defaultPanelTitle);
let defaultPanelTitle = this.fxaStrings.GetStringFromName(
"account.title"
);
document
.getElementById("PanelUI-fxa")
.setAttribute(
"title",
state.displayName ? state.displayName : defaultPanelTitle
);
}
mainWindowEl.setAttribute("fxastatus", stateValue);
},
@ -355,12 +408,18 @@ var gSync = {
enableSendTabIfValidTab() {
// All tabs selected must be sendable for the Send Tab button to be enabled
// on the FxA menu.
let canSendAllURIs = gBrowser.selectedTabs.every(t => this.isSendableURI(t.linkedBrowser.currentURI.spec));
let canSendAllURIs = gBrowser.selectedTabs.every(t =>
this.isSendableURI(t.linkedBrowser.currentURI.spec)
);
if (canSendAllURIs) {
document.getElementById("PanelUI-fxa-menu-sendtab-button").removeAttribute("disabled");
document
.getElementById("PanelUI-fxa-menu-sendtab-button")
.removeAttribute("disabled");
} else {
document.getElementById("PanelUI-fxa-menu-sendtab-button").setAttribute("disabled", true);
document
.getElementById("PanelUI-fxa-menu-sendtab-button")
.setAttribute("disabled", true);
}
},
@ -368,7 +427,10 @@ var gSync = {
if (UIState.isReady() && panel) {
const state = UIState.get();
const hasAvatar = state.avatarURL && !state.avatarIsDefault;
let extraOptions = {"fxa_status": state.status, "fxa_avatar": hasAvatar ? "true" : "false"};
let extraOptions = {
fxa_status: state.status,
fxa_avatar: hasAvatar ? "true" : "false",
};
// When the fxa avatar panel is within the Firefox app menu,
// we emit different telemetry.
@ -377,7 +439,13 @@ var gSync = {
eventName = "fxa_app_menu";
}
Services.telemetry.recordEvent(eventName, "click", type, null, extraOptions);
Services.telemetry.recordEvent(
eventName,
"click",
type,
null,
extraOptions
);
}
},
@ -404,14 +472,20 @@ var gSync = {
// At this point we consider sync to be configured (but still can be in an error state).
if (status == UIState.STATUS_LOGIN_FAILED) {
let tooltipDescription = this.fxaStrings.formatStringFromName("reconnectDescription", [state.email]);
let tooltipDescription = this.fxaStrings.formatStringFromName(
"reconnectDescription",
[state.email]
);
let errorLabel = this.appMenuStatus.getAttribute("errorlabel");
this.appMenuStatus.setAttribute("fxastatus", "login-failed");
this.appMenuLabel.setAttribute("label", errorLabel);
this.appMenuStatus.setAttribute("tooltiptext", tooltipDescription);
return;
} else if (status == UIState.STATUS_NOT_VERIFIED) {
let tooltipDescription = this.fxaStrings.formatStringFromName("verifyDescription", [state.email]);
let tooltipDescription = this.fxaStrings.formatStringFromName(
"verifyDescription",
[state.email]
);
let unverifiedLabel = this.appMenuStatus.getAttribute("unverifiedlabel");
this.appMenuStatus.setAttribute("fxastatus", "unverified");
this.appMenuLabel.setAttribute("label", unverifiedLabel);
@ -428,47 +502,57 @@ var gSync = {
updateState(state) {
for (let [status, menuId, boxId] of [
[UIState.STATUS_NOT_CONFIGURED, "sync-setup",
"PanelUI-remotetabs-setupsync"],
[UIState.STATUS_LOGIN_FAILED, "sync-reauthitem",
"PanelUI-remotetabs-reauthsync"],
[UIState.STATUS_NOT_VERIFIED, "sync-unverifieditem",
"PanelUI-remotetabs-unverified"],
[UIState.STATUS_SIGNED_IN, "sync-syncnowitem",
"PanelUI-remotetabs-main"],
[
UIState.STATUS_NOT_CONFIGURED,
"sync-setup",
"PanelUI-remotetabs-setupsync",
],
[
UIState.STATUS_LOGIN_FAILED,
"sync-reauthitem",
"PanelUI-remotetabs-reauthsync",
],
[
UIState.STATUS_NOT_VERIFIED,
"sync-unverifieditem",
"PanelUI-remotetabs-unverified",
],
[UIState.STATUS_SIGNED_IN, "sync-syncnowitem", "PanelUI-remotetabs-main"],
]) {
document.getElementById(menuId).hidden =
document.getElementById(boxId).hidden = (status != state.status);
document.getElementById(menuId).hidden = document.getElementById(
boxId
).hidden = status != state.status;
}
},
updateSyncStatus(state) {
let syncNow = document.getElementById("PanelUI-remotetabs-syncnow");
const syncingUI = syncNow.getAttribute("syncstatus") == "active";
if (state.syncing != syncingUI) { // Do we need to update the UI?
if (state.syncing != syncingUI) {
// Do we need to update the UI?
state.syncing ? this.onActivityStart() : this.onActivityStop();
}
},
onMenuPanelCommand() {
switch (this.appMenuStatus.getAttribute("fxastatus")) {
case "signedin":
const panel = document.getElementById("appMenu-fxa-status");
this.emitFxaToolbarTelemetry("toolbar_icon", panel);
PanelUI.showSubView("PanelUI-fxa", panel);
break;
case "unverified":
this.openPrefs("menupanel", "fxaError");
PanelUI.hide();
break;
case "error":
this.openSignInAgainPage("menupanel");
PanelUI.hide();
break;
default:
this.openPrefs("menupanel", "fxa");
PanelUI.hide();
break;
case "signedin":
const panel = document.getElementById("appMenu-fxa-status");
this.emitFxaToolbarTelemetry("toolbar_icon", panel);
PanelUI.showSubView("PanelUI-fxa", panel);
break;
case "unverified":
this.openPrefs("menupanel", "fxaError");
PanelUI.hide();
break;
case "error":
this.openSignInAgainPage("menupanel");
PanelUI.hide();
break;
default:
this.openPrefs("menupanel", "fxa");
PanelUI.hide();
break;
}
},
@ -517,7 +601,7 @@ var gSync = {
this.emitFxaToolbarTelemetry("login", panel);
let entryPoint = "fxa_discoverability_native";
if (this.isPanelInsideAppMenu(panel)) {
entryPoint = "fxa_app_menu";
entryPoint = "fxa_app_menu";
}
this.openFxAEmailFirstPage(entryPoint);
},
@ -531,7 +615,7 @@ var gSync = {
this.emitFxaToolbarTelemetry("account_settings", panel);
let entryPoint = "fxa_discoverability_native";
if (this.isPanelInsideAppMenu(panel)) {
entryPoint = "fxa_app_menu";
entryPoint = "fxa_app_menu";
}
this.openFxAManagePage(entryPoint);
},
@ -549,13 +633,25 @@ var gSync = {
}
}
if (fxaCommandsDevices.length) {
console.log(`Sending a tab to ${fxaCommandsDevices.map(d => d.name).join(", ")} using FxA commands.`);
const report = await fxAccounts.commands.sendTab.send(fxaCommandsDevices, {url, title});
for (let {device, error} of report.failed) {
console.error(`Failed to send a tab with FxA commands for ${device.name}.
Falling back on the Sync back-end`, error);
console.log(
`Sending a tab to ${fxaCommandsDevices
.map(d => d.name)
.join(", ")} using FxA commands.`
);
const report = await fxAccounts.commands.sendTab.send(
fxaCommandsDevices,
{ url, title }
);
for (let { device, error } of report.failed) {
console.error(
`Failed to send a tab with FxA commands for ${device.name}.
Falling back on the Sync back-end`,
error
);
if (!device.clientRecord) {
console.error(`Could not find associated Sync device for ${device.name}`);
console.error(
`Could not find associated Sync device for ${device.name}`
);
continue;
}
oldSendTabClients.push(device.clientRecord);
@ -564,14 +660,24 @@ var gSync = {
for (let client of oldSendTabClients) {
try {
console.log(`Sending a tab to ${client.name} using Sync.`);
await Weave.Service.clientsEngine.sendURIToClientForDisplay(url, client.id, title);
await Weave.Service.clientsEngine.sendURIToClientForDisplay(
url,
client.id,
title
);
} catch (e) {
console.error("Could not send tab to device.", e);
}
}
},
populateSendTabToDevicesMenu(devicesPopup, url, title, multiselected, createDeviceNodeFn) {
populateSendTabToDevicesMenu(
devicesPopup,
url,
title,
multiselected,
createDeviceNodeFn
) {
if (!createDeviceNodeFn) {
createDeviceNodeFn = (targetId, name, targetType, lastModified) => {
let eltName = name ? "menuitem" : "menuseparator";
@ -595,14 +701,25 @@ var gSync = {
const fragment = document.createDocumentFragment();
const state = UIState.get();
if (state.status == UIState.STATUS_SIGNED_IN && this.sendTabTargets.length > 0) {
this._appendSendTabDeviceList(fragment, createDeviceNodeFn, url, title, multiselected);
if (
state.status == UIState.STATUS_SIGNED_IN &&
this.sendTabTargets.length > 0
) {
this._appendSendTabDeviceList(
fragment,
createDeviceNodeFn,
url,
title,
multiselected
);
} else if (state.status == UIState.STATUS_SIGNED_IN) {
this._appendSendTabSingleDevice(fragment, createDeviceNodeFn);
} else if (state.status == UIState.STATUS_NOT_VERIFIED ||
state.status == UIState.STATUS_LOGIN_FAILED) {
} else if (
state.status == UIState.STATUS_NOT_VERIFIED ||
state.status == UIState.STATUS_LOGIN_FAILED
) {
this._appendSendTabVerify(fragment, createDeviceNodeFn);
} else /* status is STATUS_NOT_CONFIGURED */ {
} /* status is STATUS_NOT_CONFIGURED */ else {
this._appendSendTabUnconfigured(fragment, createDeviceNodeFn);
}
@ -612,23 +729,30 @@ var gSync = {
// TODO: once our transition from the old-send tab world is complete,
// this list should be built using the FxA device list instead of the client
// collection.
_appendSendTabDeviceList(fragment, createDeviceNodeFn, url, title, multiselected) {
_appendSendTabDeviceList(
fragment,
createDeviceNodeFn,
url,
title,
multiselected
) {
const targets = this.sendTabTargets;
let tabsToSend = multiselected ?
gBrowser.selectedTabs.map(t => {
return {
url: t.linkedBrowser.currentURI.spec,
title: t.linkedBrowser.contentTitle,
};
}) : [{url, title}];
let tabsToSend = multiselected
? gBrowser.selectedTabs.map(t => {
return {
url: t.linkedBrowser.currentURI.spec,
title: t.linkedBrowser.contentTitle,
};
})
: [{ url, title }];
const onSendAllCommand = (event) => {
const onSendAllCommand = event => {
for (let t of tabsToSend) {
this.sendTabToDevice(t.url, targets, t.title);
}
};
const onTargetDeviceCommand = (event) => {
const onTargetDeviceCommand = event => {
const targetId = event.target.getAttribute("clientId");
const target = targets.find(t => t.id == targetId);
for (let t of tabsToSend) {
@ -637,9 +761,17 @@ var gSync = {
};
function addTargetDevice(targetId, name, targetType, lastModified) {
const targetDevice = createDeviceNodeFn(targetId, name, targetType, lastModified);
targetDevice.addEventListener("command", targetId ? onTargetDeviceCommand :
onSendAllCommand, true);
const targetDevice = createDeviceNodeFn(
targetId,
name,
targetType,
lastModified
);
targetDevice.addEventListener(
"command",
targetId ? onTargetDeviceCommand : onSendAllCommand,
true
);
targetDevice.classList.add("sync-menuitem", "sendtab-target");
targetDevice.setAttribute("clientId", targetId);
targetDevice.setAttribute("clientType", targetType);
@ -650,7 +782,9 @@ var gSync = {
for (let target of targets) {
let type, lastModified;
if (target.clientRecord) {
type = Weave.Service.clientsEngine.getClientType(target.clientRecord.id);
type = Weave.Service.clientsEngine.getClientType(
target.clientRecord.id
);
lastModified = new Date(target.clientRecord.serverLastModified * 1000);
} else {
type = target.type === "desktop" ? "desktop" : "phone"; // Normalizing the FxA types just in case.
@ -664,35 +798,77 @@ var gSync = {
const separator = createDeviceNodeFn();
separator.classList.add("sync-menuitem");
fragment.appendChild(separator);
const allDevicesLabel = this.fxaStrings.GetStringFromName("sendToAllDevices.menuitem");
const allDevicesLabel = this.fxaStrings.GetStringFromName(
"sendToAllDevices.menuitem"
);
addTargetDevice("", allDevicesLabel, "");
}
},
_appendSendTabSingleDevice(fragment, createDeviceNodeFn) {
const noDevices = this.fxaStrings.GetStringFromName("sendTabToDevice.singledevice.status");
const learnMore = this.fxaStrings.GetStringFromName("sendTabToDevice.singledevice");
const connectDevice = this.fxaStrings.GetStringFromName("sendTabToDevice.connectdevice");
const actions = [{label: connectDevice, command: () => this.openConnectAnotherDevice("sendtab")},
{label: learnMore, command: () => this.openSendToDevicePromo()}];
this._appendSendTabInfoItems(fragment, createDeviceNodeFn, noDevices, actions);
const noDevices = this.fxaStrings.GetStringFromName(
"sendTabToDevice.singledevice.status"
);
const learnMore = this.fxaStrings.GetStringFromName(
"sendTabToDevice.singledevice"
);
const connectDevice = this.fxaStrings.GetStringFromName(
"sendTabToDevice.connectdevice"
);
const actions = [
{
label: connectDevice,
command: () => this.openConnectAnotherDevice("sendtab"),
},
{ label: learnMore, command: () => this.openSendToDevicePromo() },
];
this._appendSendTabInfoItems(
fragment,
createDeviceNodeFn,
noDevices,
actions
);
},
_appendSendTabVerify(fragment, createDeviceNodeFn) {
const notVerified = this.fxaStrings.GetStringFromName("sendTabToDevice.verify.status");
const verifyAccount = this.fxaStrings.GetStringFromName("sendTabToDevice.verify");
const actions = [{label: verifyAccount, command: () => this.openPrefs("sendtab")}];
this._appendSendTabInfoItems(fragment, createDeviceNodeFn, notVerified, actions);
const notVerified = this.fxaStrings.GetStringFromName(
"sendTabToDevice.verify.status"
);
const verifyAccount = this.fxaStrings.GetStringFromName(
"sendTabToDevice.verify"
);
const actions = [
{ label: verifyAccount, command: () => this.openPrefs("sendtab") },
];
this._appendSendTabInfoItems(
fragment,
createDeviceNodeFn,
notVerified,
actions
);
},
_appendSendTabUnconfigured(fragment, createDeviceNodeFn) {
const notConnected = this.fxaStrings.GetStringFromName("sendTabToDevice.unconfigured.status");
const learnMore = this.fxaStrings.GetStringFromName("sendTabToDevice.unconfigured");
const actions = [{label: learnMore, command: () => this.openSendToDevicePromo()}];
this._appendSendTabInfoItems(fragment, createDeviceNodeFn, notConnected, actions);
const notConnected = this.fxaStrings.GetStringFromName(
"sendTabToDevice.unconfigured.status"
);
const learnMore = this.fxaStrings.GetStringFromName(
"sendTabToDevice.unconfigured"
);
const actions = [
{ label: learnMore, command: () => this.openSendToDevicePromo() },
];
this._appendSendTabInfoItems(
fragment,
createDeviceNodeFn,
notConnected,
actions
);
// Now add a 'sign in to sync' item above the 'learn more' item.
const signInToSync = this.fxaStrings.GetStringFromName("sendTabToDevice.signintosync");
const signInToSync = this.fxaStrings.GetStringFromName(
"sendTabToDevice.signintosync"
);
let signInItem = createDeviceNodeFn(null, signInToSync, null);
signInItem.classList.add("sync-menuitem");
signInItem.setAttribute("label", signInToSync);
@ -717,7 +893,7 @@ var gSync = {
separator.classList.add("sync-menuitem");
fragment.appendChild(separator);
for (let {label, command} of actions) {
for (let { label, command } of actions) {
const actionItem = createDeviceNodeFn(null, label, null);
actionItem.addEventListener("command", command, true);
actionItem.classList.add("sync-menuitem");
@ -755,7 +931,9 @@ var gSync = {
return;
}
let hasASendableURI = false;
for (let tab of aTargetTab.multiselected ? gBrowser.selectedTabs : [aTargetTab]) {
for (let tab of aTargetTab.multiselected
? gBrowser.selectedTabs
: [aTargetTab]) {
if (this.isSendableURI(tab.linkedBrowser.currentURI.spec)) {
hasASendableURI = true;
break;
@ -766,11 +944,16 @@ var gSync = {
let sendTabsToDevice = document.getElementById("context_sendTabToDevice");
sendTabsToDevice.disabled = !enabled;
let tabCount = aTargetTab.multiselected ? gBrowser.multiSelectedTabsCount : 1;
sendTabsToDevice.label = PluralForm.get(tabCount,
gNavigatorBundle.getString("sendTabsToDevice.label"))
.replace("#1", tabCount.toLocaleString());
sendTabsToDevice.accessKey = gNavigatorBundle.getString("sendTabsToDevice.accesskey");
let tabCount = aTargetTab.multiselected
? gBrowser.multiSelectedTabsCount
: 1;
sendTabsToDevice.label = PluralForm.get(
tabCount,
gNavigatorBundle.getString("sendTabsToDevice.label")
).replace("#1", tabCount.toLocaleString());
sendTabsToDevice.accessKey = gNavigatorBundle.getString(
"sendTabsToDevice.accesskey"
);
},
// "Send Page to Device" and "Send Link to Device" menu items
@ -780,31 +963,48 @@ var gSync = {
return;
}
// showSendLink and showSendPage are mutually exclusive
const showSendLink = contextMenu.onSaveableLink || contextMenu.onPlainTextLink;
const showSendPage = !showSendLink
&& !(contextMenu.isContentSelected ||
contextMenu.onImage || contextMenu.onCanvas ||
contextMenu.onVideo || contextMenu.onAudio ||
contextMenu.onLink || contextMenu.onTextInput);
const showSendLink =
contextMenu.onSaveableLink || contextMenu.onPlainTextLink;
const showSendPage =
!showSendLink &&
!(
contextMenu.isContentSelected ||
contextMenu.onImage ||
contextMenu.onCanvas ||
contextMenu.onVideo ||
contextMenu.onAudio ||
contextMenu.onLink ||
contextMenu.onTextInput
);
// Avoids double separator on images with links.
const hideSeparator = contextMenu.isContentSelected &&
contextMenu.onLink && contextMenu.onImage;
["context-sendpagetodevice", ...(hideSeparator ? [] : ["context-sep-sendpagetodevice"])]
.forEach(id => contextMenu.showItem(id, showSendPage));
["context-sendlinktodevice", ...(hideSeparator ? [] : ["context-sep-sendlinktodevice"])]
.forEach(id => contextMenu.showItem(id, showSendLink));
const hideSeparator =
contextMenu.isContentSelected &&
contextMenu.onLink &&
contextMenu.onImage;
[
"context-sendpagetodevice",
...(hideSeparator ? [] : ["context-sep-sendpagetodevice"]),
].forEach(id => contextMenu.showItem(id, showSendPage));
[
"context-sendlinktodevice",
...(hideSeparator ? [] : ["context-sep-sendlinktodevice"]),
].forEach(id => contextMenu.showItem(id, showSendLink));
if (!showSendLink && !showSendPage) {
return;
}
const targetURI = showSendLink ? contextMenu.linkURL :
contextMenu.browser.currentURI.spec;
const enabled = !this.sendTabConfiguredAndLoading && this.isSendableURI(targetURI);
contextMenu.setItemAttr(showSendPage ? "context-sendpagetodevice" :
"context-sendlinktodevice",
"disabled", !enabled || null);
const targetURI = showSendLink
? contextMenu.linkURL
: contextMenu.browser.currentURI.spec;
const enabled =
!this.sendTabConfiguredAndLoading && this.isSendableURI(targetURI);
contextMenu.setItemAttr(
showSendPage ? "context-sendpagetodevice" : "context-sendlinktodevice",
"disabled",
!enabled || null
);
},
// Functions called by observers
@ -813,25 +1013,30 @@ var gSync = {
this._syncStartTime = Date.now();
let label = this.syncStrings.GetStringFromName("syncingtabs.label");
let remotetabsSyncNowEl = document.getElementById("PanelUI-remotetabs-syncnow");
let fxaMenuSyncNowEl = document.getElementById("PanelUI-fxa-menu-syncnow-button");
let syncElements = [
remotetabsSyncNowEl,
fxaMenuSyncNowEl,
];
let remotetabsSyncNowEl = document.getElementById(
"PanelUI-remotetabs-syncnow"
);
let fxaMenuSyncNowEl = document.getElementById(
"PanelUI-fxa-menu-syncnow-button"
);
let syncElements = [remotetabsSyncNowEl, fxaMenuSyncNowEl];
syncElements.forEach((el) => {
syncElements.forEach(el => {
el.setAttribute("syncstatus", "active");
el.setAttribute("disabled", "true");
});
remotetabsSyncNowEl.setAttribute("label", label);
fxaMenuSyncNowEl.setAttribute("label", fxaMenuSyncNowEl.getAttribute("syncinglabel"));
fxaMenuSyncNowEl.setAttribute(
"label",
fxaMenuSyncNowEl.getAttribute("syncinglabel")
);
},
_onActivityStop() {
if (!gBrowser)
if (!gBrowser) {
return;
}
let label = this.syncStrings.GetStringFromName("syncnow.label");
let syncElements = [
@ -839,7 +1044,7 @@ var gSync = {
document.getElementById("PanelUI-fxa-menu-syncnow-button"),
];
syncElements.forEach((el) => {
syncElements.forEach(el => {
el.removeAttribute("syncstatus");
el.removeAttribute("disabled");
el.setAttribute("label", label);
@ -855,7 +1060,10 @@ var gSync = {
if (syncDuration < MIN_STATUS_ANIMATION_DURATION) {
let animationTime = MIN_STATUS_ANIMATION_DURATION - syncDuration;
clearTimeout(this._syncAnimationTimer);
this._syncAnimationTimer = setTimeout(() => this._onActivityStop(), animationTime);
this._syncAnimationTimer = setTimeout(
() => this._onActivityStop(),
animationTime
);
} else {
this._onActivityStop();
}
@ -888,7 +1096,10 @@ var gSync = {
},
openPrefs(entryPoint = "syncbutton", origin = undefined) {
window.openPreferences("paneSync", { origin, urlParams: { entrypoint: entryPoint } });
window.openPreferences("paneSync", {
origin,
urlParams: { entrypoint: entryPoint },
});
},
openPrefsFromFxaMenu(type, panel) {
@ -903,8 +1114,9 @@ var gSync = {
openSyncedTabsPanel() {
let placement = CustomizableUI.getPlacementOfWidget("sync-button");
let area = placement && placement.area;
let anchor = document.getElementById("sync-button") ||
document.getElementById("PanelUI-menu-button");
let anchor =
document.getElementById("sync-button") ||
document.getElementById("PanelUI-menu-button");
if (area == CustomizableUI.AREA_FIXED_OVERFLOW_PANEL) {
// The button is in the overflow panel, so we need to show the panel,
// then show our subview.
@ -937,13 +1149,20 @@ var gSync = {
let tooltiptext;
if (status == UIState.STATUS_NOT_VERIFIED) {
// "needs verification"
tooltiptext = this.fxaStrings.formatStringFromName("verifyDescription", [state.email]);
tooltiptext = this.fxaStrings.formatStringFromName("verifyDescription", [
state.email,
]);
} else if (status == UIState.STATUS_NOT_CONFIGURED) {
// "needs setup".
tooltiptext = this.syncStrings.GetStringFromName("signInToSync.description");
tooltiptext = this.syncStrings.GetStringFromName(
"signInToSync.description"
);
} else if (status == UIState.STATUS_LOGIN_FAILED) {
// "need to reconnect/re-enter your password"
tooltiptext = this.fxaStrings.formatStringFromName("reconnectDescription", [state.email]);
tooltiptext = this.fxaStrings.formatStringFromName(
"reconnectDescription",
[state.email]
);
} else {
// Sync appears configured - format the "last synced at" time.
tooltiptext = this.formatLastSyncDate(state.lastSync);
@ -961,15 +1180,21 @@ var gSync = {
get relativeTimeFormat() {
delete this.relativeTimeFormat;
return this.relativeTimeFormat = new Services.intl.RelativeTimeFormat(undefined, {style: "long"});
return (this.relativeTimeFormat = new Services.intl.RelativeTimeFormat(
undefined,
{ style: "long" }
));
},
formatLastSyncDate(date) {
if (!date) { // Date can be null before the first sync!
if (!date) {
// Date can be null before the first sync!
return null;
}
const relativeDateStr = this.relativeTimeFormat.formatBestUnit(date);
return this.syncStrings.formatStringFromName("lastSync2.label", [relativeDateStr]);
return this.syncStrings.formatStringFromName("lastSync2.label", [
relativeDateStr,
]);
},
onClientsSynced() {

Просмотреть файл

@ -5,124 +5,129 @@
var TabsInTitlebar;
{ // start private TabsInTitlebar scope
TabsInTitlebar = {
init() {
this._readPref();
Services.prefs.addObserver(this._prefName, this);
{
// start private TabsInTitlebar scope
TabsInTitlebar = {
init() {
this._readPref();
Services.prefs.addObserver(this._prefName, this);
dragSpaceObserver.init();
this._initialized = true;
this._update();
},
dragSpaceObserver.init();
this._initialized = true;
this._update();
},
allowedBy(condition, allow) {
if (allow) {
if (condition in this._disallowed) {
delete this._disallowed[condition];
allowedBy(condition, allow) {
if (allow) {
if (condition in this._disallowed) {
delete this._disallowed[condition];
this._update();
}
} else if (!(condition in this._disallowed)) {
this._disallowed[condition] = null;
this._update();
}
} else if (!(condition in this._disallowed)) {
this._disallowed[condition] = null;
this._update();
}
},
},
get systemSupported() {
let isSupported = false;
switch (AppConstants.MOZ_WIDGET_TOOLKIT) {
case "windows":
case "cocoa":
isSupported = true;
break;
case "gtk3":
isSupported = window.matchMedia("(-moz-gtk-csd-available)").matches;
break;
}
delete this.systemSupported;
return this.systemSupported = isSupported;
},
get systemSupported() {
let isSupported = false;
switch (AppConstants.MOZ_WIDGET_TOOLKIT) {
case "windows":
case "cocoa":
isSupported = true;
break;
case "gtk3":
isSupported = window.matchMedia("(-moz-gtk-csd-available)").matches;
break;
}
delete this.systemSupported;
return (this.systemSupported = isSupported);
},
get enabled() {
return document.documentElement.getAttribute("tabsintitlebar") == "true";
},
get enabled() {
return document.documentElement.getAttribute("tabsintitlebar") == "true";
},
observe(subject, topic, data) {
if (topic == "nsPref:changed")
this._readPref();
},
observe(subject, topic, data) {
if (topic == "nsPref:changed") {
this._readPref();
}
},
_initialized: false,
_disallowed: {},
_prefName: "browser.tabs.drawInTitlebar",
_initialized: false,
_disallowed: {},
_prefName: "browser.tabs.drawInTitlebar",
_readPref() {
let hiddenTitlebar =
Services.prefs.getBoolPref("browser.tabs.drawInTitlebar",
window.matchMedia("(-moz-gtk-csd-hide-titlebar-by-default)").matches);
this.allowedBy("pref", hiddenTitlebar);
},
_readPref() {
let hiddenTitlebar = Services.prefs.getBoolPref(
"browser.tabs.drawInTitlebar",
window.matchMedia("(-moz-gtk-csd-hide-titlebar-by-default)").matches
);
this.allowedBy("pref", hiddenTitlebar);
},
_update() {
if (!this._initialized) {
return;
}
_update() {
if (!this._initialized) {
return;
}
let allowed = this.systemSupported &&
!window.fullScreen &&
(Object.keys(this._disallowed)).length == 0;
if (allowed) {
document.documentElement.setAttribute("tabsintitlebar", "true");
if (AppConstants.platform == "macosx") {
document.documentElement.setAttribute("chromemargin", "0,-1,-1,-1");
document.documentElement.removeAttribute("drawtitle");
let allowed =
this.systemSupported &&
!window.fullScreen &&
Object.keys(this._disallowed).length == 0;
if (allowed) {
document.documentElement.setAttribute("tabsintitlebar", "true");
if (AppConstants.platform == "macosx") {
document.documentElement.setAttribute("chromemargin", "0,-1,-1,-1");
document.documentElement.removeAttribute("drawtitle");
} else {
document.documentElement.setAttribute("chromemargin", "0,2,2,2");
}
} else {
document.documentElement.setAttribute("chromemargin", "0,2,2,2");
document.documentElement.removeAttribute("tabsintitlebar");
document.documentElement.removeAttribute("chromemargin");
if (AppConstants.platform == "macosx") {
document.documentElement.setAttribute("drawtitle", "true");
}
}
} else {
document.documentElement.removeAttribute("tabsintitlebar");
document.documentElement.removeAttribute("chromemargin");
if (AppConstants.platform == "macosx") {
document.documentElement.setAttribute("drawtitle", "true");
ToolbarIconColor.inferFromText("tabsintitlebar", allowed);
},
uninit() {
Services.prefs.removeObserver(this._prefName, this);
dragSpaceObserver.uninit();
},
};
// Adds additional drag space to the window by listening to
// the corresponding preference.
let dragSpaceObserver = {
pref: "browser.tabs.extraDragSpace",
init() {
Services.prefs.addObserver(this.pref, this);
this.observe();
},
uninit() {
Services.prefs.removeObserver(this.pref, this);
},
observe() {
if (Services.prefs.getBoolPref(this.pref)) {
document.documentElement.setAttribute("extradragspace", "true");
} else {
document.documentElement.removeAttribute("extradragspace");
}
}
ToolbarIconColor.inferFromText("tabsintitlebar", allowed);
},
uninit() {
Services.prefs.removeObserver(this._prefName, this);
dragSpaceObserver.uninit();
},
};
// Adds additional drag space to the window by listening to
// the corresponding preference.
let dragSpaceObserver = {
pref: "browser.tabs.extraDragSpace",
init() {
Services.prefs.addObserver(this.pref, this);
this.observe();
},
uninit() {
Services.prefs.removeObserver(this.pref, this);
},
observe() {
if (Services.prefs.getBoolPref(this.pref)) {
document.documentElement.setAttribute("extradragspace", "true");
} else {
document.documentElement.removeAttribute("extradragspace");
}
},
};
},
};
} // end private TabsInTitlebar scope
function onTitlebarMaxClick() {
if (window.windowState == window.STATE_MAXIMIZED)
if (window.windowState == window.STATE_MAXIMIZED) {
window.restore();
else
} else {
window.maximize();
}
}

Просмотреть файл

@ -40,8 +40,9 @@ var gBrowserThumbnails = {
gBrowser.addTabsProgressListener(this);
Services.prefs.addObserver(this.PREF_DISK_CACHE_SSL, this);
this._sslDiskCacheEnabled =
Services.prefs.getBoolPref(this.PREF_DISK_CACHE_SSL);
this._sslDiskCacheEnabled = Services.prefs.getBoolPref(
this.PREF_DISK_CACHE_SSL
);
this._tabEvents.forEach(function(aEvent) {
gBrowser.tabContainer.addEventListener(aEvent, this);
@ -68,8 +69,9 @@ var gBrowserThumbnails = {
switch (aEvent.type) {
case "scroll":
let browser = aEvent.currentTarget;
if (this._timeouts.has(browser))
if (this._timeouts.has(browser)) {
this._delayedCapture(browser);
}
break;
case "TabSelect":
this._delayedCapture(aEvent.target.linkedBrowser);
@ -84,8 +86,9 @@ var gBrowserThumbnails = {
observe: function Thumbnails_observe(subject, topic, data) {
switch (data) {
case this.PREF_DISK_CACHE_SSL:
this._sslDiskCacheEnabled =
Services.prefs.getBoolPref(this.PREF_DISK_CACHE_SSL);
this._sslDiskCacheEnabled = Services.prefs.getBoolPref(
this.PREF_DISK_CACHE_SSL
);
break;
}
},
@ -108,19 +111,27 @@ var gBrowserThumbnails = {
/**
* State change progress listener for all tabs.
*/
onStateChange: function Thumbnails_onStateChange(aBrowser, aWebProgress,
aRequest, aStateFlags, aStatus) {
if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP &&
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK)
onStateChange: function Thumbnails_onStateChange(
aBrowser,
aWebProgress,
aRequest,
aStateFlags,
aStatus
) {
if (
aStateFlags & Ci.nsIWebProgressListener.STATE_STOP &&
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK
) {
this._delayedCapture(aBrowser);
}
},
async _capture(aBrowser) {
// Only capture about:newtab top sites.
const topSites = await this._topSiteURLs;
if (!aBrowser.currentURI ||
!topSites.includes(aBrowser.currentURI.spec))
if (!aBrowser.currentURI || !topSites.includes(aBrowser.currentURI.spec)) {
return;
}
this._shouldCapture(aBrowser, function(aResult) {
if (aResult) {
PageThumbs.captureAndStoreIfStale(aBrowser);
@ -154,8 +165,10 @@ var gBrowserThumbnails = {
_shouldCapture: function Thumbnails_shouldCapture(aBrowser, aCallback) {
// Capture only if it's the currently selected tab and not an about: page.
if (aBrowser != gBrowser.selectedBrowser ||
gBrowser.currentURI.schemeIs("about")) {
if (
aBrowser != gBrowser.selectedBrowser ||
gBrowser.currentURI.schemeIs("about")
) {
aCallback(false);
return;
}
@ -170,7 +183,9 @@ var gBrowserThumbnails = {
}
},
_cancelDelayedCallbacks: function Thumbnails_cancelDelayedCallbacks(aBrowser) {
_cancelDelayedCallbacks: function Thumbnails_cancelDelayedCallbacks(
aBrowser
) {
let timeoutData = this._timeouts.get(aBrowser);
if (timeoutData.isTimeout) {
@ -186,11 +201,14 @@ async function getTopSiteURLs() {
// The _topSiteURLs getter can be expensive to run, but its return value can
// change frequently on new profiles, so as a compromise we cache its return
// value as a lazy getter for 1 minute every time it's called.
gBrowserThumbnails._topSiteURLsRefreshTimer =
Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
gBrowserThumbnails._topSiteURLsRefreshTimer.initWithCallback(gBrowserThumbnails,
60 * 1000,
Ci.nsITimer.TYPE_ONE_SHOT);
gBrowserThumbnails._topSiteURLsRefreshTimer = Cc[
"@mozilla.org/timer;1"
].createInstance(Ci.nsITimer);
gBrowserThumbnails._topSiteURLsRefreshTimer.initWithCallback(
gBrowserThumbnails,
60 * 1000,
Ci.nsITimer.TYPE_ONE_SHOT
);
let sites = [];
// Get both the top sites returned by the query, and also any pinned sites
// that the user might have added manually that also need a screenshot.
@ -199,7 +217,9 @@ async function getTopSiteURLs() {
sites.push(...topSites.filter(link => !(link.faviconSize >= 96)));
sites.push(...NewTabUtils.pinnedLinks.links);
return sites.reduce((urls, link) => {
if (link) urls.push(link.url);
if (link) {
urls.push(link.url);
}
return urls;
}, []);
}

Просмотреть файл

@ -26,8 +26,9 @@ ToolbarKeyboardNavigator = {
kToolbars: [CustomizableUI.AREA_NAVBAR, CustomizableUI.AREA_BOOKMARKS],
_isButton(aElem) {
return aElem.tagName == "toolbarbutton" ||
aElem.getAttribute("role") == "button";
return (
aElem.tagName == "toolbarbutton" || aElem.getAttribute("role") == "button"
);
},
// Get a TreeWalker which includes only controls which should be keyboard
@ -37,22 +38,27 @@ ToolbarKeyboardNavigator = {
return aRoot._toolbarKeyNavWalker;
}
let filter = (aNode) => {
let filter = aNode => {
if (aNode.tagName == "toolbartabstop") {
return NodeFilter.FILTER_ACCEPT;
}
// Special case for the "View site information" button, which isn't
// actionable in some cases but is still visible.
if (aNode.id == "identity-box" &&
document.getElementById("urlbar").getAttribute("pageproxystate") ==
"invalid") {
if (
aNode.id == "identity-box" &&
document.getElementById("urlbar").getAttribute("pageproxystate") ==
"invalid"
) {
return NodeFilter.FILTER_REJECT;
}
// Skip invisible or disabled elements.
if (aNode.hidden || aNode.disabled
|| aNode.style.visibility == "hidden") {
if (
aNode.hidden ||
aNode.disabled ||
aNode.style.visibility == "hidden"
) {
return NodeFilter.FILTER_REJECT;
}
// This width check excludes the overflow button when there's no overflow.
@ -66,8 +72,11 @@ ToolbarKeyboardNavigator = {
}
return NodeFilter.FILTER_SKIP;
};
aRoot._toolbarKeyNavWalker = document.createTreeWalker(aRoot,
NodeFilter.SHOW_ELEMENT, filter);
aRoot._toolbarKeyNavWalker = document.createTreeWalker(
aRoot,
NodeFilter.SHOW_ELEMENT,
filter
);
return aRoot._toolbarKeyNavWalker;
},
@ -185,8 +194,13 @@ ToolbarKeyboardNavigator = {
_onKeyDown(aEvent) {
let focus = document.activeElement;
if (aEvent.altKey || aEvent.controlKey || aEvent.metaKey ||
aEvent.shiftKey || !this._isButton(focus)) {
if (
aEvent.altKey ||
aEvent.controlKey ||
aEvent.metaKey ||
aEvent.shiftKey ||
!this._isButton(focus)
) {
return;
}
@ -207,8 +221,10 @@ ToolbarKeyboardNavigator = {
_onKeyPress(aEvent) {
let focus = document.activeElement;
if ((aEvent.key != "Enter" && aEvent.key != " ") ||
!this._isButton(focus)) {
if (
(aEvent.key != "Enter" && aEvent.key != " ") ||
!this._isButton(focus)
) {
return;
}
@ -222,13 +238,15 @@ ToolbarKeyboardNavigator = {
// Command events have their own keyboard handling: keypress for enter
// and keyup for space. We rely on that behavior, since there's no way
// for us to reliably know what events a button handles.
focus.dispatchEvent(new MouseEvent("click", {
bubbles: true,
ctrlKey: aEvent.ctrlKey,
altKey: aEvent.altKey,
shiftKey: aEvent.shiftKey,
metaKey: aEvent.metaKey,
}));
focus.dispatchEvent(
new MouseEvent("click", {
bubbles: true,
ctrlKey: aEvent.ctrlKey,
altKey: aEvent.altKey,
shiftKey: aEvent.shiftKey,
metaKey: aEvent.metaKey,
})
);
}
// We deliberately don't call aEvent.preventDefault() here so that enter
// will trigger a command event handler if appropriate.
@ -251,5 +269,4 @@ ToolbarKeyboardNavigator = {
break;
}
},
};

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -4,8 +4,8 @@
/* eslint-env mozilla/frame-script */
var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
const {setTimeout} = ChromeUtils.import("resource://gre/modules/Timer.jsm");
var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
const { setTimeout } = ChromeUtils.import("resource://gre/modules/Timer.jsm");
var RefreshBlocker = {
PREF: "accessibility.blockautorefresh",
@ -69,21 +69,24 @@ var RefreshBlocker = {
},
enable() {
this._filter = Cc["@mozilla.org/appshell/component/browser-status-filter;1"]
.createInstance(Ci.nsIWebProgress);
this._filter = Cc[
"@mozilla.org/appshell/component/browser-status-filter;1"
].createInstance(Ci.nsIWebProgress);
this._filter.addProgressListener(this, Ci.nsIWebProgress.NOTIFY_ALL);
this._filter.target = tabEventTarget;
let webProgress = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebProgress);
let webProgress = docShell
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebProgress);
webProgress.addProgressListener(this._filter, Ci.nsIWebProgress.NOTIFY_ALL);
addMessageListener("RefreshBlocker:Refresh", this);
},
disable() {
let webProgress = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebProgress);
let webProgress = docShell
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebProgress);
webProgress.removeProgressListener(this._filter);
this._filter.removeProgressListener(this);
@ -107,8 +110,10 @@ var RefreshBlocker = {
* blockedWindows.
*/
onStateChange(aWebProgress, aRequest, aStateFlags, aStatus) {
if (aStateFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW &&
aStateFlags & Ci.nsIWebProgressListener.STATE_STOP) {
if (
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW &&
aStateFlags & Ci.nsIWebProgressListener.STATE_STOP
) {
this.blockedWindows.delete(aWebProgress.DOMWindow);
}
},
@ -174,7 +179,11 @@ var RefreshBlocker = {
}
},
QueryInterface: ChromeUtils.generateQI([Ci.nsIWebProgressListener2, Ci.nsIWebProgressListener, Ci.nsISupportsWeakReference]),
QueryInterface: ChromeUtils.generateQI([
Ci.nsIWebProgressListener2,
Ci.nsIWebProgressListener,
Ci.nsISupportsWeakReference,
]),
};
RefreshBlocker.init();

Просмотреть файл

@ -9,7 +9,9 @@
/* eslint-env mozilla/frame-script */
/* eslint no-unused-vars: ["error", {args: "none"}] */
var {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
var { XPCOMUtils } = ChromeUtils.import(
"resource://gre/modules/XPCOMUtils.jsm"
);
// BrowserChildGlobal
var global = this;

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -5,150 +5,167 @@
"use strict";
{
function _isTextColorDark(r, g, b) {
return (0.2125 * r + 0.7154 * g + 0.0721 * b) <= 110;
}
function _isTextColorDark(r, g, b) {
return 0.2125 * r + 0.7154 * g + 0.0721 * b <= 110;
}
const inContentVariableMap = [
["--newtab-background-color", {
lwtProperty: "ntp_background",
}],
["--newtab-text-primary-color", {
lwtProperty: "ntp_text",
processColor(rgbaChannels, element) {
if (!rgbaChannels) {
element.removeAttribute("lwt-newtab");
element.removeAttribute("lwt-newtab-brighttext");
return null;
const inContentVariableMap = [
[
"--newtab-background-color",
{
lwtProperty: "ntp_background",
},
],
[
"--newtab-text-primary-color",
{
lwtProperty: "ntp_text",
processColor(rgbaChannels, element) {
if (!rgbaChannels) {
element.removeAttribute("lwt-newtab");
element.removeAttribute("lwt-newtab-brighttext");
return null;
}
element.setAttribute("lwt-newtab", "true");
const { r, g, b, a } = rgbaChannels;
if (!_isTextColorDark(r, g, b)) {
element.setAttribute("lwt-newtab-brighttext", "true");
} else {
element.removeAttribute("lwt-newtab-brighttext");
}
return `rgba(${r}, ${g}, ${b}, ${a})`;
},
},
],
[
"--lwt-sidebar-background-color",
{
lwtProperty: "sidebar",
processColor(rgbaChannels) {
if (!rgbaChannels) {
return null;
}
const { r, g, b } = rgbaChannels;
// Drop alpha channel
return `rgb(${r}, ${g}, ${b})`;
},
},
],
[
"--lwt-sidebar-text-color",
{
lwtProperty: "sidebar_text",
processColor(rgbaChannels, element) {
if (!rgbaChannels) {
element.removeAttribute("lwt-sidebar");
element.removeAttribute("lwt-sidebar-brighttext");
return null;
}
element.setAttribute("lwt-sidebar", "true");
const { r, g, b, a } = rgbaChannels;
if (!_isTextColorDark(r, g, b)) {
element.setAttribute("lwt-sidebar-brighttext", "true");
} else {
element.removeAttribute("lwt-sidebar-brighttext");
}
return `rgba(${r}, ${g}, ${b}, ${a})`;
},
},
],
[
"--lwt-sidebar-highlight-background-color",
{
lwtProperty: "sidebar_highlight",
},
],
[
"--lwt-sidebar-highlight-text-color",
{
lwtProperty: "sidebar_highlight_text",
processColor(rgbaChannels, element) {
if (!rgbaChannels) {
element.removeAttribute("lwt-sidebar-highlight");
return null;
}
element.setAttribute("lwt-sidebar-highlight", "true");
const { r, g, b, a } = rgbaChannels;
return `rgba(${r}, ${g}, ${b}, ${a})`;
},
},
],
];
/**
* ContentThemeController handles theme updates sent by the frame script.
* To be able to use ContentThemeController, you must add your page to the whitelist
* in LightweightThemeChildListener.jsm
*/
const ContentThemeController = {
/**
* Tell the frame script that the page supports theming, and watch for updates
* from the frame script.
*/
init() {
addEventListener("LightweightTheme:Set", this);
},
/**
* Handle theme updates from the frame script.
* @param {Object} event object containing the theme update.
*/
handleEvent({ type, detail }) {
if (type == "LightweightTheme:Set") {
let { data } = detail;
if (!data) {
data = {};
}
// XUL documents don't have a body
const element = document.body
? document.body
: document.documentElement;
this._setProperties(element, data);
}
},
element.setAttribute("lwt-newtab", "true");
const {r, g, b, a} = rgbaChannels;
if (!_isTextColorDark(r, g, b)) {
element.setAttribute("lwt-newtab-brighttext", "true");
/**
* Set a CSS variable to a given value
* @param {Element} elem The element where the CSS variable should be added.
* @param {string} variableName The CSS variable to set.
* @param {string} value The new value of the CSS variable.
*/
_setProperty(elem, variableName, value) {
if (value) {
elem.style.setProperty(variableName, value);
} else {
element.removeAttribute("lwt-newtab-brighttext");
elem.style.removeProperty(variableName);
}
return `rgba(${r}, ${g}, ${b}, ${a})`;
},
}],
["--lwt-sidebar-background-color", {
lwtProperty: "sidebar",
processColor(rgbaChannels) {
if (!rgbaChannels) {
return null;
/**
* Apply theme data to an element
* @param {Element} root The element where the properties should be applied.
* @param {Object} themeData The theme data.
*/
_setProperties(elem, themeData) {
for (let [cssVarName, definition] of inContentVariableMap) {
const { lwtProperty, processColor } = definition;
let value = themeData[lwtProperty];
if (processColor) {
value = processColor(value, elem);
} else if (value) {
const { r, g, b, a } = value;
value = `rgba(${r}, ${g}, ${b}, ${a})`;
}
this._setProperty(elem, cssVarName, value);
}
const {r, g, b} = rgbaChannels;
// Drop alpha channel
return `rgb(${r}, ${g}, ${b})`;
},
}],
["--lwt-sidebar-text-color", {
lwtProperty: "sidebar_text",
processColor(rgbaChannels, element) {
if (!rgbaChannels) {
element.removeAttribute("lwt-sidebar");
element.removeAttribute("lwt-sidebar-brighttext");
return null;
}
element.setAttribute("lwt-sidebar", "true");
const {r, g, b, a} = rgbaChannels;
if (!_isTextColorDark(r, g, b)) {
element.setAttribute("lwt-sidebar-brighttext", "true");
} else {
element.removeAttribute("lwt-sidebar-brighttext");
}
return `rgba(${r}, ${g}, ${b}, ${a})`;
},
}],
["--lwt-sidebar-highlight-background-color", {
lwtProperty: "sidebar_highlight",
}],
["--lwt-sidebar-highlight-text-color", {
lwtProperty: "sidebar_highlight_text",
processColor(rgbaChannels, element) {
if (!rgbaChannels) {
element.removeAttribute("lwt-sidebar-highlight");
return null;
}
element.setAttribute("lwt-sidebar-highlight", "true");
const {r, g, b, a} = rgbaChannels;
return `rgba(${r}, ${g}, ${b}, ${a})`;
},
}],
];
/**
* ContentThemeController handles theme updates sent by the frame script.
* To be able to use ContentThemeController, you must add your page to the whitelist
* in LightweightThemeChildListener.jsm
*/
const ContentThemeController = {
/**
* Tell the frame script that the page supports theming, and watch for updates
* from the frame script.
*/
init() {
addEventListener("LightweightTheme:Set", this);
},
/**
* Handle theme updates from the frame script.
* @param {Object} event object containing the theme update.
*/
handleEvent({ type, detail }) {
if (type == "LightweightTheme:Set") {
let {data} = detail;
if (!data) {
data = {};
}
// XUL documents don't have a body
const element = document.body ? document.body : document.documentElement;
this._setProperties(element, data);
}
},
/**
* Set a CSS variable to a given value
* @param {Element} elem The element where the CSS variable should be added.
* @param {string} variableName The CSS variable to set.
* @param {string} value The new value of the CSS variable.
*/
_setProperty(elem, variableName, value) {
if (value) {
elem.style.setProperty(variableName, value);
} else {
elem.style.removeProperty(variableName);
}
},
/**
* Apply theme data to an element
* @param {Element} root The element where the properties should be applied.
* @param {Object} themeData The theme data.
*/
_setProperties(elem, themeData) {
for (let [cssVarName, definition] of inContentVariableMap) {
const {
lwtProperty,
processColor,
} = definition;
let value = themeData[lwtProperty];
if (processColor) {
value = processColor(value, elem);
} else if (value) {
const {r, g, b, a} = value;
value = `rgba(${r}, ${g}, ${b}, ${a})`;
}
this._setProperty(elem, cssVarName, value);
}
},
};
ContentThemeController.init();
};
ContentThemeController.init();
}

Просмотреть файл

@ -2,7 +2,10 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm", {});
const { Services } = ChromeUtils.import(
"resource://gre/modules/Services.jsm",
{}
);
function init() {
document.querySelector("button").addEventListener("command", () => {

Просмотреть файл

@ -28,7 +28,7 @@ async function requestFlowMetrics() {
let requestURL = new URL(await endpoint);
requestURL.pathname = "metrics-flow";
appendParams(requestURL, {
"form_type": "email",
form_type: "email",
});
let response = await fetch(requestURL, { credentials: "omit" });
@ -49,11 +49,11 @@ async function submitForm(event) {
let requestURL = new URL(await endpoint);
appendParams(requestURL, {
"action": "email",
"utm_campaign": CAMPAIGN,
"email": input.value,
"flow_id": flowId,
"flow_begin_time": flowBeginTime,
action: "email",
utm_campaign: CAMPAIGN,
email: input.value,
flow_id: flowId,
flow_begin_time: flowBeginTime,
});
window.open(requestURL, "_blank", "noopener");
@ -65,6 +65,10 @@ const endpoint = RPMGetFxAccountsEndpoint(ENTRYPOINT);
// This must come before the CSP is set or it will be blocked.
const metrics = requestFlowMetrics();
document.addEventListener("DOMContentLoaded", () => {
document.getElementById("sync").addEventListener("submit", submitForm);
}, { once: true });
document.addEventListener(
"DOMContentLoaded",
() => {
document.getElementById("sync").addEventListener("submit", submitForm);
},
{ once: true }
);

Просмотреть файл

@ -9,47 +9,76 @@ let delayedStartupTimeoutId = null;
function OpenBrowserWindowFromDockMenu(options) {
let win = OpenBrowserWindow(options);
win.addEventListener("load", function() {
let dockSupport = Cc["@mozilla.org/widget/macdocksupport;1"]
.getService(Ci.nsIMacDockSupport);
dockSupport.activateApplication(true);
}, { once: true });
win.addEventListener(
"load",
function() {
let dockSupport = Cc["@mozilla.org/widget/macdocksupport;1"].getService(
Ci.nsIMacDockSupport
);
dockSupport.activateApplication(true);
},
{ once: true }
);
return win;
}
function nonBrowserWindowStartup() {
// Disable inappropriate commands / submenus
var disabledItems = ["Browser:SavePage",
"Browser:SendLink", "cmd_pageSetup", "cmd_print", "cmd_find", "cmd_findAgain",
"viewToolbarsMenu", "viewSidebarMenuMenu", "Browser:Reload",
"viewFullZoomMenu", "pageStyleMenu", "charsetMenu", "View:PageSource", "View:FullScreen",
"viewHistorySidebar", "Browser:AddBookmarkAs", "Browser:BookmarkAllTabs",
"View:PageInfo", "History:UndoCloseTab"];
var disabledItems = [
"Browser:SavePage",
"Browser:SendLink",
"cmd_pageSetup",
"cmd_print",
"cmd_find",
"cmd_findAgain",
"viewToolbarsMenu",
"viewSidebarMenuMenu",
"Browser:Reload",
"viewFullZoomMenu",
"pageStyleMenu",
"charsetMenu",
"View:PageSource",
"View:FullScreen",
"viewHistorySidebar",
"Browser:AddBookmarkAs",
"Browser:BookmarkAllTabs",
"View:PageInfo",
"History:UndoCloseTab",
];
var element;
for (let disabledItem of disabledItems) {
element = document.getElementById(disabledItem);
if (element)
if (element) {
element.setAttribute("disabled", "true");
}
}
// Show menus that are only visible in non-browser windows
let shownItems = ["menu_openLocation"];
for (let shownItem of shownItems) {
element = document.getElementById(shownItem);
if (element)
if (element) {
element.removeAttribute("hidden");
}
}
// If no windows are active (i.e. we're the hidden window), disable the close, minimize
// and zoom menu commands as well
if (window.location.href == "chrome://browser/content/hiddenWindowMac.xhtml") {
var hiddenWindowDisabledItems = ["cmd_close", "minimizeWindow", "zoomWindow"];
if (
window.location.href == "chrome://browser/content/hiddenWindowMac.xhtml"
) {
var hiddenWindowDisabledItems = [
"cmd_close",
"minimizeWindow",
"zoomWindow",
];
for (let hiddenWindowDisabledItem of hiddenWindowDisabledItems) {
element = document.getElementById(hiddenWindowDisabledItem);
if (element)
if (element) {
element.setAttribute("disabled", "true");
}
}
// also hide the window-list separator
@ -59,17 +88,18 @@ function nonBrowserWindowStartup() {
// Setup the dock menu.
let dockMenuElement = document.getElementById("menu_mac_dockmenu");
if (dockMenuElement != null) {
let nativeMenu = Cc["@mozilla.org/widget/standalonenativemenu;1"]
.createInstance(Ci.nsIStandaloneNativeMenu);
let nativeMenu = Cc[
"@mozilla.org/widget/standalonenativemenu;1"
].createInstance(Ci.nsIStandaloneNativeMenu);
try {
nativeMenu.init(dockMenuElement);
let dockSupport = Cc["@mozilla.org/widget/macdocksupport;1"]
.getService(Ci.nsIMacDockSupport);
let dockSupport = Cc["@mozilla.org/widget/macdocksupport;1"].getService(
Ci.nsIMacDockSupport
);
dockSupport.dockMenu = nativeMenu;
} catch (e) {
}
} catch (e) {}
}
}
@ -96,9 +126,12 @@ function nonBrowserWindowDelayedStartup() {
function nonBrowserWindowShutdown() {
// If this is the hidden window being closed, release our reference to
// the dock menu element to prevent leaks on shutdown
if (window.location.href == "chrome://browser/content/hiddenWindowMac.xhtml") {
let dockSupport = Cc["@mozilla.org/widget/macdocksupport;1"]
.getService(Ci.nsIMacDockSupport);
if (
window.location.href == "chrome://browser/content/hiddenWindowMac.xhtml"
) {
let dockSupport = Cc["@mozilla.org/widget/macdocksupport;1"].getService(
Ci.nsIMacDockSupport
);
dockSupport.dockMenu = null;
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -4,7 +4,9 @@
/* import-globals-from pageInfo.js */
const {SitePermissions} = ChromeUtils.import("resource:///modules/SitePermissions.jsm");
const { SitePermissions } = ChromeUtils.import(
"resource:///modules/SitePermissions.jsm"
);
var gPermPrincipal;
var gUsageRequest;
@ -22,8 +24,11 @@ var permissionObserver = {
observe(aSubject, aTopic, aData) {
if (aTopic == "perm-changed") {
var permission = aSubject.QueryInterface(Ci.nsIPermission);
if (permission.matches(gPermPrincipal, true) && gPermissions.includes(permission.type)) {
initRow(permission.type);
if (
permission.matches(gPermPrincipal, true) &&
gPermissions.includes(permission.type)
) {
initRow(permission.type);
}
}
},
@ -60,14 +65,20 @@ function initRow(aPartId) {
createRow(aPartId);
var checkbox = document.getElementById(aPartId + "Def");
var command = document.getElementById("cmd_" + aPartId + "Toggle");
var {state, scope} = SitePermissions.getForPrincipal(gPermPrincipal, aPartId);
var command = document.getElementById("cmd_" + aPartId + "Toggle");
var { state, scope } = SitePermissions.getForPrincipal(
gPermPrincipal,
aPartId
);
let defaultState = SitePermissions.getDefault(aPartId);
// Since cookies preferences have many different possible configuration states
// we don't consider any permission except "no permission" to be default.
if (aPartId == "cookie") {
state = Services.perms.testPermissionFromPrincipal(gPermPrincipal, "cookie");
state = Services.perms.testPermissionFromPrincipal(
gPermPrincipal,
"cookie"
);
if (state == SitePermissions.UNKNOWN) {
checkbox.checked = true;
@ -93,7 +104,9 @@ function initRow(aPartId) {
command.setAttribute("disabled", "true");
}
if ([SitePermissions.SCOPE_POLICY, SitePermissions.SCOPE_GLOBAL].includes(scope)) {
if (
[SitePermissions.SCOPE_POLICY, SitePermissions.SCOPE_GLOBAL].includes(scope)
) {
checkbox.setAttribute("disabled", "true");
command.setAttribute("disabled", "true");
}
@ -103,8 +116,9 @@ function initRow(aPartId) {
function createRow(aPartId) {
let rowId = "perm-" + aPartId + "-row";
if (document.getElementById(rowId))
if (document.getElementById(rowId)) {
return;
}
let commandId = "cmd_" + aPartId + "Toggle";
let labelId = "perm-" + aPartId + "-label";
@ -146,7 +160,10 @@ function createRow(aPartId) {
for (let state of SitePermissions.getAvailableStates(aPartId)) {
let radio = document.createXULElement("radio");
radio.setAttribute("id", aPartId + "#" + state);
radio.setAttribute("label", SitePermissions.getMultichoiceStateLabel(aPartId, state));
radio.setAttribute(
"label",
SitePermissions.getMultichoiceStateLabel(aPartId, state)
);
radio.setAttribute("command", commandId);
radiogroup.appendChild(radio);
}
@ -158,7 +175,7 @@ function createRow(aPartId) {
}
function onCheckboxClick(aPartId) {
var command = document.getElementById("cmd_" + aPartId + "Toggle");
var command = document.getElementById("cmd_" + aPartId + "Toggle");
var checkbox = document.getElementById(aPartId + "Def");
if (checkbox.checked) {
SitePermissions.removeFromPrincipal(gPermPrincipal, aPartId);

Просмотреть файл

@ -3,15 +3,25 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const {SiteDataManager} = ChromeUtils.import("resource:///modules/SiteDataManager.jsm");
const {DownloadUtils} = ChromeUtils.import("resource://gre/modules/DownloadUtils.jsm");
const { SiteDataManager } = ChromeUtils.import(
"resource:///modules/SiteDataManager.jsm"
);
const { DownloadUtils } = ChromeUtils.import(
"resource://gre/modules/DownloadUtils.jsm"
);
/* import-globals-from pageInfo.js */
ChromeUtils.defineModuleGetter(this, "LoginHelper",
"resource://gre/modules/LoginHelper.jsm");
ChromeUtils.defineModuleGetter(this, "PluralForm",
"resource://gre/modules/PluralForm.jsm");
ChromeUtils.defineModuleGetter(
this,
"LoginHelper",
"resource://gre/modules/LoginHelper.jsm"
);
ChromeUtils.defineModuleGetter(
this,
"PluralForm",
"resource://gre/modules/PluralForm.jsm"
);
var security = {
init(uri, windowInfo) {
@ -28,24 +38,24 @@ var security = {
_getSecurityInfo() {
// We don't have separate info for a frame, return null until further notice
// (see bug 138479)
if (!this.windowInfo.isTopWindow)
if (!this.windowInfo.isTopWindow) {
return null;
}
var hostName = this.windowInfo.hostName;
var ui = security._getSecurityUI();
if (!ui)
if (!ui) {
return null;
}
var isBroken =
(ui.state & Ci.nsIWebProgressListener.STATE_IS_BROKEN);
var isBroken = ui.state & Ci.nsIWebProgressListener.STATE_IS_BROKEN;
var isMixed =
(ui.state & (Ci.nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT |
Ci.nsIWebProgressListener.STATE_LOADED_MIXED_DISPLAY_CONTENT));
var isInsecure =
(ui.state & Ci.nsIWebProgressListener.STATE_IS_INSECURE);
var isEV =
(ui.state & Ci.nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL);
ui.state &
(Ci.nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT |
Ci.nsIWebProgressListener.STATE_LOADED_MIXED_DISPLAY_CONTENT);
var isInsecure = ui.state & Ci.nsIWebProgressListener.STATE_IS_INSECURE;
var isEV = ui.state & Ci.nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL;
var secInfo = ui.secInfo;
if (!isInsecure && secInfo) {
@ -70,8 +80,7 @@ var security = {
retval.encryptionAlgorithm = secInfo.cipherName;
retval.encryptionStrength = secInfo.secretKeyLength;
version = secInfo.protocolVersion;
} catch (e) {
}
} catch (e) {}
switch (version) {
case Ci.nsITransportSecurityInfo.SSL_VERSION_3:
@ -96,16 +105,16 @@ var security = {
// we must not complain on policy discompliance (it might be viewed
// as a security issue by the user).
switch (secInfo.certificateTransparencyStatus) {
case Ci.nsITransportSecurityInfo.
CERTIFICATE_TRANSPARENCY_NOT_APPLICABLE:
case Ci.nsITransportSecurityInfo.
CERTIFICATE_TRANSPARENCY_POLICY_NOT_ENOUGH_SCTS:
case Ci.nsITransportSecurityInfo.
CERTIFICATE_TRANSPARENCY_POLICY_NOT_DIVERSE_SCTS:
case Ci.nsITransportSecurityInfo
.CERTIFICATE_TRANSPARENCY_NOT_APPLICABLE:
case Ci.nsITransportSecurityInfo
.CERTIFICATE_TRANSPARENCY_POLICY_NOT_ENOUGH_SCTS:
case Ci.nsITransportSecurityInfo
.CERTIFICATE_TRANSPARENCY_POLICY_NOT_DIVERSE_SCTS:
retval.certificateTransparency = null;
break;
case Ci.nsITransportSecurityInfo.
CERTIFICATE_TRANSPARENCY_POLICY_COMPLIANT:
case Ci.nsITransportSecurityInfo
.CERTIFICATE_TRANSPARENCY_POLICY_COMPLIANT:
retval.certificateTransparency = "Compliant";
break;
}
@ -128,18 +137,24 @@ var security = {
// Find the secureBrowserUI object (if present)
_getSecurityUI() {
if (window.opener.gBrowser)
if (window.opener.gBrowser) {
return window.opener.gBrowser.securityUI;
}
return null;
},
async _updateSiteDataInfo() {
// Save site data info for deleting.
this.siteData = await SiteDataManager.getSites(
SiteDataManager.getBaseDomainFromHost(this.uri.host));
SiteDataManager.getBaseDomainFromHost(this.uri.host)
);
let clearSiteDataButton = document.getElementById("security-clear-sitedata");
let siteDataLabel = document.getElementById("security-privacy-sitedata-value");
let clearSiteDataButton = document.getElementById(
"security-clear-sitedata"
);
let siteDataLabel = document.getElementById(
"security-privacy-sitedata-value"
);
if (!this.siteData.length) {
document.l10n.setAttributes(siteDataLabel, "security-site-data-no");
@ -152,13 +167,23 @@ var security = {
let size = DownloadUtils.convertByteUnits(usage);
let hasCookies = this.siteData.some(site => site.cookies.length > 0);
if (hasCookies) {
document.l10n.setAttributes(siteDataLabel, "security-site-data-cookies", {"value": size[0], "unit": size[1]});
document.l10n.setAttributes(
siteDataLabel,
"security-site-data-cookies",
{ value: size[0], unit: size[1] }
);
} else {
document.l10n.setAttributes(siteDataLabel, "security-site-data-only", {"value": size[0], "unit": size[1]});
document.l10n.setAttributes(siteDataLabel, "security-site-data-only", {
value: size[0],
unit: size[1],
});
}
} else {
// We're storing cookies, else the list would have been empty.
document.l10n.setAttributes(siteDataLabel, "security-site-data-cookies-only");
document.l10n.setAttributes(
siteDataLabel,
"security-site-data-cookies-only"
);
}
clearSiteDataButton.removeAttribute("disabled");
@ -193,7 +218,10 @@ function securityOnLoad(uri, windowInfo) {
security.init(uri, windowInfo);
var info = security._getSecurityInfo();
if (!info || (uri.scheme === "about" && !uri.spec.startsWith("about:certerror"))) {
if (
!info ||
(uri.scheme === "about" && !uri.spec.startsWith("about:certerror"))
) {
document.getElementById("securityTab").hidden = true;
return;
}
@ -218,16 +246,25 @@ function securityOnLoad(uri, windowInfo) {
// way to tell those apart, and no policy way to establish which organization
// vetting standards are good enough (that's what EV is for) so we default to
// treating these certs as domain-validated only.
document.l10n.setAttributes(document.getElementById("security-identity-owner-value"),
"security-no-owner");
setText("security-identity-verifier-value", info.cAName || info.cert.issuerCommonName || info.cert.issuerName);
document.l10n.setAttributes(
document.getElementById("security-identity-owner-value"),
"security-no-owner"
);
setText(
"security-identity-verifier-value",
info.cAName || info.cert.issuerCommonName || info.cert.issuerName
);
}
} else {
// We don't have valid identity credentials.
document.l10n.setAttributes(document.getElementById("security-identity-owner-value"),
"security-no-owner");
document.l10n.setAttributes(document.getElementById("security-identity-verifier-value"),
"not-set-verified-by");
document.l10n.setAttributes(
document.getElementById("security-identity-owner-value"),
"security-no-owner"
);
document.l10n.setAttributes(
document.getElementById("security-identity-verifier-value"),
"not-set-verified-by"
);
}
if (validity) {
@ -255,15 +292,22 @@ function securityOnLoad(uri, windowInfo) {
}
if (realmHasPasswords(uri)) {
document.l10n.setAttributes(document.getElementById("security-privacy-passwords-value"),
"saved-passwords-yes");
document.l10n.setAttributes(
document.getElementById("security-privacy-passwords-value"),
"saved-passwords-yes"
);
} else {
document.l10n.setAttributes(document.getElementById("security-privacy-passwords-value"),
"saved-passwords-no");
document.l10n.setAttributes(
document.getElementById("security-privacy-passwords-value"),
"saved-passwords-no"
);
}
document.l10n.setAttributes(document.getElementById("security-privacy-history-value"),
"security-visits-number", {"visits": previousVisitCount(info.hostName)});
document.l10n.setAttributes(
document.getElementById("security-privacy-history-value"),
"security-visits-number",
{ visits: previousVisitCount(info.hostName) }
);
/* Set the Technical Detail section messages */
const pkiBundle = document.getElementById("pkiBundle");
@ -276,39 +320,45 @@ function securityOnLoad(uri, windowInfo) {
hdr = pkiBundle.getString("pageInfo_MixedContent");
msg1 = pkiBundle.getString("pageInfo_MixedContent2");
} else {
hdr = pkiBundle.getFormattedString("pageInfo_BrokenEncryption",
[info.encryptionAlgorithm,
info.encryptionStrength + "",
info.version]);
hdr = pkiBundle.getFormattedString("pageInfo_BrokenEncryption", [
info.encryptionAlgorithm,
info.encryptionStrength + "",
info.version,
]);
msg1 = pkiBundle.getString("pageInfo_WeakCipher");
}
msg2 = pkiBundle.getString("pageInfo_Privacy_None2");
} else if (info.encryptionStrength > 0) {
hdr = pkiBundle.getFormattedString("pageInfo_EncryptionWithBitsAndProtocol",
[info.encryptionAlgorithm,
info.encryptionStrength + "",
info.version]);
hdr = pkiBundle.getFormattedString(
"pageInfo_EncryptionWithBitsAndProtocol",
[info.encryptionAlgorithm, info.encryptionStrength + "", info.version]
);
msg1 = pkiBundle.getString("pageInfo_Privacy_Encrypted1");
msg2 = pkiBundle.getString("pageInfo_Privacy_Encrypted2");
security._cert = info.cert;
} else {
hdr = pkiBundle.getString("pageInfo_NoEncryption");
if (info.hostName != null)
msg1 = pkiBundle.getFormattedString("pageInfo_Privacy_None1", [info.hostName]);
else
if (info.hostName != null) {
msg1 = pkiBundle.getFormattedString("pageInfo_Privacy_None1", [
info.hostName,
]);
} else {
msg1 = pkiBundle.getString("pageInfo_Privacy_None4");
}
msg2 = pkiBundle.getString("pageInfo_Privacy_None2");
}
setText("security-technical-shortform", hdr);
setText("security-technical-longform1", msg1);
setText("security-technical-longform2", msg2);
const ctStatus =
document.getElementById("security-technical-certificate-transparency");
const ctStatus = document.getElementById(
"security-technical-certificate-transparency"
);
if (info.certificateTransparency) {
ctStatus.hidden = false;
ctStatus.value = pkiBundle.getString(
"pageInfo_CertificateTransparency_" + info.certificateTransparency);
"pageInfo_CertificateTransparency_" + info.certificateTransparency
);
} else {
ctStatus.hidden = true;
}
@ -316,20 +366,28 @@ function securityOnLoad(uri, windowInfo) {
function setText(id, value) {
var element = document.getElementById(id);
if (!element)
if (!element) {
return;
if (element.localName == "textbox" || element.localName == "label")
}
if (element.localName == "textbox" || element.localName == "label") {
element.value = value;
else
} else {
element.textContent = value;
}
}
function viewCertHelper(parent, cert) {
if (!cert)
if (!cert) {
return;
}
Services.ww.openWindow(parent, "chrome://pippki/content/certViewer.xul",
"_blank", "centerscreen,chrome", cert);
Services.ww.openWindow(
parent,
"chrome://pippki/content/certViewer.xul",
"_blank",
"centerscreen,chrome",
cert
);
}
/**
@ -346,11 +404,13 @@ function realmHasPasswords(uri) {
* @param host - the domain name to look for in history
*/
function previousVisitCount(host, endTimeReference) {
if (!host)
if (!host) {
return 0;
}
var historyService = Cc["@mozilla.org/browser/nav-history-service;1"]
.getService(Ci.nsINavHistoryService);
var historyService = Cc[
"@mozilla.org/browser/nav-history-service;1"
].getService(Ci.nsINavHistoryService);
var options = historyService.getNewQueryOptions();
options.resultType = options.RESULTS_AS_VISIT;

Просмотреть файл

@ -3,11 +3,13 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
const appStartup = Services.startup;
const {ResetProfile} = ChromeUtils.import("resource://gre/modules/ResetProfile.jsm");
const { ResetProfile } = ChromeUtils.import(
"resource://gre/modules/ResetProfile.jsm"
);
var defaultToReset = false;
@ -17,8 +19,9 @@ function restartApp() {
function resetProfile() {
// Set the reset profile environment variable.
let env = Cc["@mozilla.org/process/environment;1"]
.getService(Ci.nsIEnvironment);
let env = Cc["@mozilla.org/process/environment;1"].getService(
Ci.nsIEnvironment
);
env.set("MOZ_RESET_PROFILE_RESTART", "1");
}
@ -27,10 +30,15 @@ function showResetDialog() {
let retVals = {
reset: false,
};
window.openDialog("chrome://global/content/resetProfile.xul", null,
"chrome,modal,centerscreen,titlebar,dialog=yes", retVals);
if (!retVals.reset)
window.openDialog(
"chrome://global/content/resetProfile.xul",
null,
"chrome,modal,centerscreen,titlebar,dialog=yes",
retVals
);
if (!retVals.reset) {
return;
}
resetProfile();
restartApp();
}

Просмотреть файл

@ -5,8 +5,8 @@
/* import-globals-from ../../../toolkit/content/preferencesBindings.js */
var {Sanitizer} = ChromeUtils.import("resource:///modules/Sanitizer.jsm");
var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
var { Sanitizer } = ChromeUtils.import("resource:///modules/Sanitizer.jsm");
var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
Preferences.addAll([
{ id: "privacy.cpd.history", type: "bool" },
@ -21,7 +21,6 @@ Preferences.addAll([
]);
var gSanitizePromptDialog = {
get selectedTimespan() {
var durList = document.getElementById("sanitizeDurationChoice");
return parseInt(durList.value);
@ -38,18 +37,26 @@ var gSanitizePromptDialog = {
let OKButton = document.documentElement.getButton("accept");
document.l10n.setAttributes(OKButton, "sanitize-button-ok");
document.addEventListener("dialogaccept", function(e) { gSanitizePromptDialog.sanitize(e); });
document.addEventListener("dialogaccept", function(e) {
gSanitizePromptDialog.sanitize(e);
});
if (this.selectedTimespan === Sanitizer.TIMESPAN_EVERYTHING) {
this.prepareWarning();
this.warningBox.hidden = false;
document.l10n.setAttributes(document.documentElement, "dialog-title-everything");
document.l10n.setAttributes(
document.documentElement,
"dialog-title-everything"
);
let warningDesc = document.getElementById("sanitizeEverythingWarning");
// Ensure we've translated and sized the warning.
document.mozSubdialogReady =
document.l10n.translateFragment(warningDesc).then(() => {
document.mozSubdialogReady = document.l10n
.translateFragment(warningDesc)
.then(() => {
// And then ensure we've run layout.
let rootWin = window.docShell.rootTreeItem.QueryInterface(Ci.nsIDocShell).domWindow;
let rootWin = window.docShell.rootTreeItem.QueryInterface(
Ci.nsIDocShell
).domWindow;
return rootWin.promiseDocumentFlushed(() => {});
});
} else {
@ -69,8 +76,9 @@ var gSanitizePromptDialog = {
selectByTimespan() {
// This method is the onselect handler for the duration dropdown. As a
// result it's called a couple of times before onload calls init().
if (!this._inited)
if (!this._inited) {
return;
}
var warningBox = this.warningBox;
@ -81,7 +89,10 @@ var gSanitizePromptDialog = {
warningBox.hidden = false;
window.resizeBy(0, warningBox.getBoundingClientRect().height);
}
document.l10n.setAttributes(document.documentElement, "dialog-title-everything");
document.l10n.setAttributes(
document.documentElement,
"dialog-title-everything"
);
return;
}
@ -145,7 +156,9 @@ var gSanitizePromptDialog = {
* of history. The only pref this excludes is privacy.sanitize.timeSpan.
*/
_getItemPrefs() {
return Preferences.getAll().filter(p => p.id !== "privacy.sanitize.timeSpan");
return Preferences.getAll().filter(
p => p.id !== "privacy.sanitize.timeSpan"
);
},
/**
@ -155,11 +168,13 @@ var gSanitizePromptDialog = {
onReadGeneric() {
// Find any other pref that's checked and enabled (except for
// privacy.sanitize.timeSpan, which doesn't affect the button's status).
var found = this._getItemPrefs().some(pref => !!pref.value && !pref.disabled);
var found = this._getItemPrefs().some(
pref => !!pref.value && !pref.disabled
);
try {
document.documentElement.getButton("accept").disabled = !found;
} catch (e) { }
} catch (e) {}
// Update the warning prompt if needed
this.prepareWarning();
@ -178,8 +193,9 @@ var gSanitizePromptDialog = {
Services.prefs.setIntPref(Sanitizer.PREF_TIMESPAN, this.selectedTimespan);
// Keep the pref for the download history in sync with the history pref.
Preferences.get("privacy.cpd.downloads").value =
Preferences.get("privacy.cpd.history").value;
Preferences.get("privacy.cpd.downloads").value = Preferences.get(
"privacy.cpd.history"
).value;
// Now manually set the prefs from their corresponding preference
// elements.
@ -197,8 +213,9 @@ var gSanitizePromptDialog = {
let checkboxes = document.querySelectorAll("checkbox[preference]");
for (let i = 0; i < checkboxes.length; ++i) {
let pref = Preferences.get(checkboxes[i].getAttribute("preference"));
if (!pref.value)
if (!pref.value) {
return true;
}
}
return false;
},

Просмотреть файл

@ -7,14 +7,22 @@
/* eslint-env mozilla/frame-script */
var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.defineModuleGetter(this, "E10SUtils",
"resource://gre/modules/E10SUtils.jsm");
ChromeUtils.defineModuleGetter(this, "BrowserUtils",
"resource://gre/modules/BrowserUtils.jsm");
ChromeUtils.defineModuleGetter(
this,
"E10SUtils",
"resource://gre/modules/E10SUtils.jsm"
);
ChromeUtils.defineModuleGetter(
this,
"BrowserUtils",
"resource://gre/modules/BrowserUtils.jsm"
);
var {ActorManagerChild} = ChromeUtils.import("resource://gre/modules/ActorManagerChild.jsm");
var { ActorManagerChild } = ChromeUtils.import(
"resource://gre/modules/ActorManagerChild.jsm"
);
ActorManagerChild.attach(this, "browsers");
@ -24,19 +32,41 @@ var global = this;
// Keep a reference to the translation content handler to avoid it it being GC'ed.
var trHandler = null;
if (Services.prefs.getBoolPref("browser.translation.detectLanguage")) {
var {TranslationContentHandler} = ChromeUtils.import("resource:///modules/translation/TranslationContentHandler.jsm");
var { TranslationContentHandler } = ChromeUtils.import(
"resource:///modules/translation/TranslationContentHandler.jsm"
);
trHandler = new TranslationContentHandler(global, docShell);
}
var WebBrowserChrome = {
onBeforeLinkTraversal(originalTarget, linkURI, linkNode, isAppTab) {
return BrowserUtils.onBeforeLinkTraversal(originalTarget, linkURI, linkNode, isAppTab);
return BrowserUtils.onBeforeLinkTraversal(
originalTarget,
linkURI,
linkNode,
isAppTab
);
},
// Check whether this URI should load in the current process
shouldLoadURI(aDocShell, aURI, aReferrer, aHasPostData, aTriggeringPrincipal, aCsp) {
shouldLoadURI(
aDocShell,
aURI,
aReferrer,
aHasPostData,
aTriggeringPrincipal,
aCsp
) {
if (!E10SUtils.shouldLoadURI(aDocShell, aURI, aReferrer, aHasPostData)) {
E10SUtils.redirectLoad(aDocShell, aURI, aReferrer, aTriggeringPrincipal, false, null, aCsp);
E10SUtils.redirectLoad(
aDocShell,
aURI,
aReferrer,
aTriggeringPrincipal,
false,
null,
aCsp
);
return false;
}
@ -44,20 +74,37 @@ var WebBrowserChrome = {
},
shouldLoadURIInThisProcess(aURI) {
let remoteSubframes = docShell.QueryInterface(Ci.nsILoadContext).useRemoteSubframes;
let remoteSubframes = docShell.QueryInterface(Ci.nsILoadContext)
.useRemoteSubframes;
return E10SUtils.shouldLoadURIInThisProcess(aURI, remoteSubframes);
},
// Try to reload the currently active or currently loading page in a new process.
reloadInFreshProcess(aDocShell, aURI, aReferrer, aTriggeringPrincipal, aLoadFlags, aCsp) {
E10SUtils.redirectLoad(aDocShell, aURI, aReferrer, aTriggeringPrincipal, true, aLoadFlags, aCsp);
reloadInFreshProcess(
aDocShell,
aURI,
aReferrer,
aTriggeringPrincipal,
aLoadFlags,
aCsp
) {
E10SUtils.redirectLoad(
aDocShell,
aURI,
aReferrer,
aTriggeringPrincipal,
true,
aLoadFlags,
aCsp
);
return true;
},
};
if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT) {
let tabchild = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIBrowserChild);
let tabchild = docShell
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIBrowserChild);
tabchild.webBrowserChrome = WebBrowserChrome;
}
@ -65,8 +112,9 @@ Services.obs.notifyObservers(this, "tab-content-frameloader-created");
// Remove this once bug 1397365 is fixed.
addEventListener("MozAfterPaint", function onFirstNonBlankPaint() {
if (content.document.documentURI == "about:blank" && !content.opener)
if (content.document.documentURI == "about:blank" && !content.opener) {
return;
}
removeEventListener("MozAfterPaint", onFirstNonBlankPaint);
sendAsyncMessage("Browser:FirstNonBlankPaint");
});

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -9,31 +9,48 @@ const GOOD_PAGE = "https://example.com/";
const GOOD_PAGE_2 = "https://example.org/";
const BAD_CERT = "https://expired.example.com/";
const UNKNOWN_ISSUER = "https://self-signed.example.com ";
const BAD_STS_CERT = "https://badchain.include-subdomains.pinning.example.com:443";
const {TabStateFlusher} = ChromeUtils.import("resource:///modules/sessionstore/TabStateFlusher.jsm");
const BAD_STS_CERT =
"https://badchain.include-subdomains.pinning.example.com:443";
const { TabStateFlusher } = ChromeUtils.import(
"resource:///modules/sessionstore/TabStateFlusher.jsm"
);
add_task(async function checkReturnToAboutHome() {
info("Loading a bad cert page directly and making sure 'return to previous page' goes to about:home");
info(
"Loading a bad cert page directly and making sure 'return to previous page' goes to about:home"
);
for (let useFrame of [false, true]) {
let tab = await openErrorPage(BAD_CERT, useFrame);
let browser = tab.linkedBrowser;
is(browser.webNavigation.canGoBack, false, "!webNavigation.canGoBack");
is(browser.webNavigation.canGoForward, false, "!webNavigation.canGoForward");
is(
browser.webNavigation.canGoForward,
false,
"!webNavigation.canGoForward"
);
// Populate the shistory entries manually, since it happens asynchronously
// and the following tests will be too soon otherwise.
await TabStateFlusher.flush(browser);
let {entries} = JSON.parse(SessionStore.getTabState(tab));
let { entries } = JSON.parse(SessionStore.getTabState(tab));
is(entries.length, 1, "there is one shistory entry");
info("Clicking the go back button on about:certerror");
await ContentTask.spawn(browser, {frame: useFrame}, async function({frame}) {
let doc = frame ? content.document.querySelector("iframe").contentDocument : content.document;
await ContentTask.spawn(browser, { frame: useFrame }, async function({
frame,
}) {
let doc = frame
? content.document.querySelector("iframe").contentDocument
: content.document;
let returnButton = doc.getElementById("returnButton");
if (!frame) {
is(returnButton.getAttribute("autofocus"), "true", "returnButton has autofocus");
is(
returnButton.getAttribute("autofocus"),
"true",
"returnButton has autofocus"
);
}
// Note that going back to about:newtab might cause a process flip, if
// the browser is configured to run about:newtab in its own special
@ -44,7 +61,11 @@ add_task(async function checkReturnToAboutHome() {
await BrowserTestUtils.waitForLocationChange(gBrowser, "about:home");
is(browser.webNavigation.canGoBack, true, "webNavigation.canGoBack");
is(browser.webNavigation.canGoForward, false, "!webNavigation.canGoForward");
is(
browser.webNavigation.canGoForward,
false,
"!webNavigation.canGoForward"
);
is(gBrowser.currentURI.spec, "about:home", "Went back");
BrowserTestUtils.removeTab(gBrowser.selectedTab);
@ -52,7 +73,9 @@ add_task(async function checkReturnToAboutHome() {
});
add_task(async function checkReturnToPreviousPage() {
info("Loading a bad cert page and making sure 'return to previous page' goes back");
info(
"Loading a bad cert page and making sure 'return to previous page' goes back"
);
for (let useFrame of [false, true]) {
let tab;
let browser;
@ -74,17 +97,25 @@ add_task(async function checkReturnToPreviousPage() {
}
is(browser.webNavigation.canGoBack, true, "webNavigation.canGoBack");
is(browser.webNavigation.canGoForward, false, "!webNavigation.canGoForward");
is(
browser.webNavigation.canGoForward,
false,
"!webNavigation.canGoForward"
);
// Populate the shistory entries manually, since it happens asynchronously
// and the following tests will be too soon otherwise.
await TabStateFlusher.flush(browser);
let {entries} = JSON.parse(SessionStore.getTabState(tab));
let { entries } = JSON.parse(SessionStore.getTabState(tab));
is(entries.length, 2, "there are two shistory entries");
info("Clicking the go back button on about:certerror");
await ContentTask.spawn(browser, {frame: useFrame}, async function({frame}) {
let doc = frame ? content.document.querySelector("iframe").contentDocument : content.document;
await ContentTask.spawn(browser, { frame: useFrame }, async function({
frame,
}) {
let doc = frame
? content.document.querySelector("iframe").contentDocument
: content.document;
let returnButton = doc.getElementById("returnButton");
returnButton.click();
@ -113,67 +144,96 @@ add_task(async function checkAppBuildIDIsDate() {
});
add_task(async function checkAdvancedDetails() {
info("Loading a bad cert page and verifying the main error and advanced details section");
info(
"Loading a bad cert page and verifying the main error and advanced details section"
);
for (let useFrame of [false, true]) {
let tab = await openErrorPage(BAD_CERT, useFrame);
let browser = tab.linkedBrowser;
let message = await ContentTask.spawn(browser, {frame: useFrame}, async function({frame}) {
let doc = frame ? content.document.querySelector("iframe").contentDocument : content.document;
let message = await ContentTask.spawn(
browser,
{ frame: useFrame },
async function({ frame }) {
let doc = frame
? content.document.querySelector("iframe").contentDocument
: content.document;
let shortDescText = doc.getElementById("errorShortDescText");
info("Main error text: " + shortDescText.textContent);
ok(shortDescText.textContent.includes("expired.example.com"),
"Should list hostname in error message.");
let shortDescText = doc.getElementById("errorShortDescText");
info("Main error text: " + shortDescText.textContent);
ok(
shortDescText.textContent.includes("expired.example.com"),
"Should list hostname in error message."
);
let exceptionButton = doc.getElementById("exceptionDialogButton");
ok(!exceptionButton.disabled, "Exception button is not disabled by default.");
let exceptionButton = doc.getElementById("exceptionDialogButton");
ok(
!exceptionButton.disabled,
"Exception button is not disabled by default."
);
let advancedButton = doc.getElementById("advancedButton");
advancedButton.click();
let advancedButton = doc.getElementById("advancedButton");
advancedButton.click();
// Wait until fluent sets the errorCode inner text.
let el;
await ContentTaskUtils.waitForCondition(() => {
el = doc.getElementById("errorCode");
return el.textContent != "";
}, "error code has been set inside the advanced button panel");
// Wait until fluent sets the errorCode inner text.
let el;
await ContentTaskUtils.waitForCondition(() => {
el = doc.getElementById("errorCode");
return el.textContent != "";
}, "error code has been set inside the advanced button panel");
return { textContent: el.textContent, tagName: el.tagName };
});
is(message.textContent, "SEC_ERROR_EXPIRED_CERTIFICATE",
"Correct error message found");
return { textContent: el.textContent, tagName: el.tagName };
}
);
is(
message.textContent,
"SEC_ERROR_EXPIRED_CERTIFICATE",
"Correct error message found"
);
is(message.tagName, "a", "Error message is a link");
message = await ContentTask.spawn(browser, {frame: useFrame}, async function({frame}) {
let win = frame ? content.document.querySelector("iframe").contentWindow : content;
let doc = win.document;
message = await ContentTask.spawn(
browser,
{ frame: useFrame },
async function({ frame }) {
let win = frame
? content.document.querySelector("iframe").contentWindow
: content;
let doc = win.document;
let errorCode = doc.getElementById("errorCode");
errorCode.click();
let div = doc.getElementById("certificateErrorDebugInformation");
let text = doc.getElementById("certificateErrorText");
let errorCode = doc.getElementById("errorCode");
errorCode.click();
let div = doc.getElementById("certificateErrorDebugInformation");
let text = doc.getElementById("certificateErrorText");
let serhelper = Cc["@mozilla.org/network/serialization-helper;1"]
.getService(Ci.nsISerializationHelper);
let serializable = win.docShell.failedChannel.securityInfo
.QueryInterface(Ci.nsITransportSecurityInfo)
.QueryInterface(Ci.nsISerializable);
let serializedSecurityInfo = serhelper.serializeToString(serializable);
return {
divDisplay: content.getComputedStyle(div).display,
text: text.textContent,
securityInfoAsString: serializedSecurityInfo,
};
});
let serhelper = Cc[
"@mozilla.org/network/serialization-helper;1"
].getService(Ci.nsISerializationHelper);
let serializable = win.docShell.failedChannel.securityInfo
.QueryInterface(Ci.nsITransportSecurityInfo)
.QueryInterface(Ci.nsISerializable);
let serializedSecurityInfo = serhelper.serializeToString(serializable);
return {
divDisplay: content.getComputedStyle(div).display,
text: text.textContent,
securityInfoAsString: serializedSecurityInfo,
};
}
);
isnot(message.divDisplay, "none", "Debug information is visible");
ok(message.text.includes(BAD_CERT), "Correct URL found");
ok(message.text.includes("Certificate has expired"),
"Correct error message found");
ok(message.text.includes("HTTP Strict Transport Security: false"),
"Correct HSTS value found");
ok(message.text.includes("HTTP Public Key Pinning: false"),
"Correct HPKP value found");
ok(
message.text.includes("Certificate has expired"),
"Correct error message found"
);
ok(
message.text.includes("HTTP Strict Transport Security: false"),
"Correct HSTS value found"
);
ok(
message.text.includes("HTTP Public Key Pinning: false"),
"Correct HPKP value found"
);
let certChain = getCertChain(message.securityInfoAsString);
ok(message.text.includes(certChain), "Found certificate chain");
@ -182,71 +242,96 @@ add_task(async function checkAdvancedDetails() {
});
add_task(async function checkAdvancedDetailsForHSTS() {
info("Loading a bad STS cert page and verifying the advanced details section");
info(
"Loading a bad STS cert page and verifying the advanced details section"
);
for (let useFrame of [false, true]) {
let tab = await openErrorPage(BAD_STS_CERT, useFrame);
let browser = tab.linkedBrowser;
let message = await ContentTask.spawn(browser, {frame: useFrame}, async function({frame}) {
let doc = frame ? content.document.querySelector("iframe").contentDocument : content.document;
let message = await ContentTask.spawn(
browser,
{ frame: useFrame },
async function({ frame }) {
let doc = frame
? content.document.querySelector("iframe").contentDocument
: content.document;
let advancedButton = doc.getElementById("advancedButton");
advancedButton.click();
let advancedButton = doc.getElementById("advancedButton");
advancedButton.click();
// Wait until fluent sets the errorCode inner text.
let ec;
await ContentTaskUtils.waitForCondition(() => {
ec = doc.getElementById("errorCode");
return ec.textContent != "";
}, "error code has been set inside the advanced button panel");
// Wait until fluent sets the errorCode inner text.
let ec;
await ContentTaskUtils.waitForCondition(() => {
ec = doc.getElementById("errorCode");
return ec.textContent != "";
}, "error code has been set inside the advanced button panel");
let cdl = doc.getElementById("cert_domain_link");
return {
ecTextContent: ec.textContent,
ecTagName: ec.tagName,
cdlTextContent: cdl.textContent,
cdlTagName: cdl.tagName,
};
});
let cdl = doc.getElementById("cert_domain_link");
return {
ecTextContent: ec.textContent,
ecTagName: ec.tagName,
cdlTextContent: cdl.textContent,
cdlTagName: cdl.tagName,
};
}
);
const badStsUri = Services.io.newURI(BAD_STS_CERT);
is(message.ecTextContent, "SSL_ERROR_BAD_CERT_DOMAIN",
"Correct error message found");
is(
message.ecTextContent,
"SSL_ERROR_BAD_CERT_DOMAIN",
"Correct error message found"
);
is(message.ecTagName, "a", "Error message is a link");
const url = badStsUri.prePath.slice(badStsUri.prePath.indexOf(".") + 1);
is(message.cdlTextContent, url,
"Correct cert_domain_link contents found");
is(message.cdlTextContent, url, "Correct cert_domain_link contents found");
is(message.cdlTagName, "a", "cert_domain_link is a link");
message = await ContentTask.spawn(browser, {frame: useFrame}, async function({frame}) {
let win = frame ? content.document.querySelector("iframe").contentWindow : content;
let doc = win.document;
message = await ContentTask.spawn(
browser,
{ frame: useFrame },
async function({ frame }) {
let win = frame
? content.document.querySelector("iframe").contentWindow
: content;
let doc = win.document;
let errorCode = doc.getElementById("errorCode");
errorCode.click();
let div = doc.getElementById("certificateErrorDebugInformation");
let text = doc.getElementById("certificateErrorText");
let errorCode = doc.getElementById("errorCode");
errorCode.click();
let div = doc.getElementById("certificateErrorDebugInformation");
let text = doc.getElementById("certificateErrorText");
let serhelper = Cc["@mozilla.org/network/serialization-helper;1"]
.getService(Ci.nsISerializationHelper);
let serializable = win.docShell.failedChannel.securityInfo
.QueryInterface(Ci.nsITransportSecurityInfo)
.QueryInterface(Ci.nsISerializable);
let serializedSecurityInfo = serhelper.serializeToString(serializable);
return {
divDisplay: content.getComputedStyle(div).display,
text: text.textContent,
securityInfoAsString: serializedSecurityInfo,
};
});
let serhelper = Cc[
"@mozilla.org/network/serialization-helper;1"
].getService(Ci.nsISerializationHelper);
let serializable = win.docShell.failedChannel.securityInfo
.QueryInterface(Ci.nsITransportSecurityInfo)
.QueryInterface(Ci.nsISerializable);
let serializedSecurityInfo = serhelper.serializeToString(serializable);
return {
divDisplay: content.getComputedStyle(div).display,
text: text.textContent,
securityInfoAsString: serializedSecurityInfo,
};
}
);
isnot(message.divDisplay, "none", "Debug information is visible");
ok(message.text.includes(badStsUri.spec), "Correct URL found");
ok(message.text.includes("requested domain name does not match the server\u2019s certificate"),
"Correct error message found");
ok(message.text.includes("HTTP Strict Transport Security: false"),
"Correct HSTS value found");
ok(message.text.includes("HTTP Public Key Pinning: true"),
"Correct HPKP value found");
ok(
message.text.includes(
"requested domain name does not match the server\u2019s certificate"
),
"Correct error message found"
);
ok(
message.text.includes("HTTP Strict Transport Security: false"),
"Correct HSTS value found"
);
ok(
message.text.includes("HTTP Public Key Pinning: true"),
"Correct HPKP value found"
);
let certChain = getCertChain(message.securityInfoAsString);
ok(message.text.includes(certChain), "Found certificate chain");
@ -255,16 +340,24 @@ add_task(async function checkAdvancedDetailsForHSTS() {
});
add_task(async function checkUnknownIssuerLearnMoreLink() {
info("Loading a cert error for self-signed pages and checking the correct link is shown");
info(
"Loading a cert error for self-signed pages and checking the correct link is shown"
);
for (let useFrame of [false, true]) {
let tab = await openErrorPage(UNKNOWN_ISSUER, useFrame);
let browser = tab.linkedBrowser;
let href = await ContentTask.spawn(browser, {frame: useFrame}, async function({frame}) {
let doc = frame ? content.document.querySelector("iframe").contentDocument : content.document;
let learnMoreLink = doc.getElementById("learnMoreLink");
return learnMoreLink.href;
});
let href = await ContentTask.spawn(
browser,
{ frame: useFrame },
async function({ frame }) {
let doc = frame
? content.document.querySelector("iframe").contentDocument
: content.document;
let learnMoreLink = doc.getElementById("learnMoreLink");
return learnMoreLink.href;
}
);
ok(href.endsWith("security-error"), "security-error in the Learn More URL");
BrowserTestUtils.removeTab(gBrowser.selectedTab);
@ -277,9 +370,17 @@ add_task(async function checkCautionClass() {
let tab = await openErrorPage(UNKNOWN_ISSUER, useFrame);
let browser = tab.linkedBrowser;
await ContentTask.spawn(browser, {frame: useFrame}, async function({frame}) {
let doc = frame ? content.document.querySelector("iframe").contentDocument : content.document;
is(doc.body.classList.contains("caution"), !frame, `Cert error body has ${frame ? "no" : ""} caution class`);
await ContentTask.spawn(browser, { frame: useFrame }, async function({
frame,
}) {
let doc = frame
? content.document.querySelector("iframe").contentDocument
: content.document;
is(
doc.body.classList.contains("caution"),
!frame,
`Cert error body has ${frame ? "no" : ""} caution class`
);
});
BrowserTestUtils.removeTab(gBrowser.selectedTab);
@ -287,9 +388,16 @@ add_task(async function checkCautionClass() {
tab = await openErrorPage(BAD_STS_CERT, useFrame);
browser = tab.linkedBrowser;
await ContentTask.spawn(browser, {frame: useFrame}, async function({frame}) {
let doc = frame ? content.document.querySelector("iframe").contentDocument : content.document;
ok(!doc.body.classList.contains("caution"), "Cert error body has no caution class");
await ContentTask.spawn(browser, { frame: useFrame }, async function({
frame,
}) {
let doc = frame
? content.document.querySelector("iframe").contentDocument
: content.document;
ok(
!doc.body.classList.contains("caution"),
"Cert error body has no caution class"
);
});
BrowserTestUtils.removeTab(gBrowser.selectedTab);
@ -304,18 +412,28 @@ add_task(async function checkViewCertificate() {
let dialogOpened = BrowserTestUtils.domWindowOpened();
await ContentTask.spawn(browser, {frame: useFrame}, async function({frame}) {
let doc = frame ? content.document.querySelector("iframe").contentDocument : content.document;
await ContentTask.spawn(browser, { frame: useFrame }, async function({
frame,
}) {
let doc = frame
? content.document.querySelector("iframe").contentDocument
: content.document;
let viewCertificate = doc.getElementById("viewCertificate");
viewCertificate.click();
});
let win = await dialogOpened;
await BrowserTestUtils.waitForEvent(win, "load");
is(win.document.documentURI, "chrome://pippki/content/certViewer.xul",
"Opened the cert viewer dialog");
is(win.document.getElementById("commonname").value, "self-signed.example.com",
"Shows the correct certificate in the dialog");
is(
win.document.documentURI,
"chrome://pippki/content/certViewer.xul",
"Opened the cert viewer dialog"
);
is(
win.document.getElementById("commonname").value,
"self-signed.example.com",
"Shows the correct certificate in the dialog"
);
win.close();
BrowserTestUtils.removeTab(gBrowser.selectedTab);
@ -323,20 +441,34 @@ add_task(async function checkViewCertificate() {
});
add_task(async function checkBadStsCertHeadline() {
info("Loading a bad sts cert error page and checking that the correct headline is shown");
info(
"Loading a bad sts cert error page and checking that the correct headline is shown"
);
for (let useFrame of [false, true]) {
let tab = await openErrorPage(BAD_CERT, useFrame);
let browser = tab.linkedBrowser;
let titleContent = await ContentTask.spawn(browser, {frame: useFrame}, async function({frame}) {
let doc = frame ? content.document.querySelector("iframe").contentDocument : content.document;
let titleText = doc.querySelector(".title-text");
return titleText.textContent;
});
let titleContent = await ContentTask.spawn(
browser,
{ frame: useFrame },
async function({ frame }) {
let doc = frame
? content.document.querySelector("iframe").contentDocument
: content.document;
let titleText = doc.querySelector(".title-text");
return titleText.textContent;
}
);
if (useFrame) {
ok(titleContent.endsWith("Security Issue"), "Did Not Connect: Potential Security Issue");
ok(
titleContent.endsWith("Security Issue"),
"Did Not Connect: Potential Security Issue"
);
} else {
ok(titleContent.endsWith("Risk Ahead"), "Warning: Potential Security Risk Ahead");
ok(
titleContent.endsWith("Risk Ahead"),
"Warning: Potential Security Risk Ahead"
);
}
BrowserTestUtils.removeTab(gBrowser.selectedTab);
}

Просмотреть файл

@ -3,18 +3,27 @@
"use strict";
const PREF_SERVICES_SETTINGS_CLOCK_SKEW_SECONDS = "services.settings.clock_skew_seconds";
const PREF_SERVICES_SETTINGS_LAST_FETCHED = "services.settings.last_update_seconds";
const PREF_SERVICES_SETTINGS_CLOCK_SKEW_SECONDS =
"services.settings.clock_skew_seconds";
const PREF_SERVICES_SETTINGS_LAST_FETCHED =
"services.settings.last_update_seconds";
add_task(async function checkWrongSystemTimeWarning() {
async function setUpPage() {
let browser;
let certErrorLoaded;
await BrowserTestUtils.openNewForegroundTab(gBrowser, () => {
gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, "https://expired.example.com/");
browser = gBrowser.selectedBrowser;
certErrorLoaded = BrowserTestUtils.waitForErrorPage(browser);
}, false);
await BrowserTestUtils.openNewForegroundTab(
gBrowser,
() => {
gBrowser.selectedTab = BrowserTestUtils.addTab(
gBrowser,
"https://expired.example.com/"
);
browser = gBrowser.selectedBrowser;
certErrorLoaded = BrowserTestUtils.waitForErrorPage(browser);
},
false
);
info("Loading and waiting for the cert error");
await certErrorLoaded;
@ -25,8 +34,10 @@ add_task(async function checkWrongSystemTimeWarning() {
let systemDateDiv = doc.getElementById("wrongSystemTime_systemDate1");
let learnMoreLink = doc.getElementById("learnMoreLink");
await ContentTaskUtils.waitForCondition(() => div.textContent.includes("update your computer clock"),
"Correct error message found");
await ContentTaskUtils.waitForCondition(
() => div.textContent.includes("update your computer clock"),
"Correct error message found"
);
return {
divDisplay: content.getComputedStyle(div).display,
@ -38,7 +49,10 @@ add_task(async function checkWrongSystemTimeWarning() {
}
// Pretend that we recently updated our kinto clock skew pref
Services.prefs.setIntPref(PREF_SERVICES_SETTINGS_LAST_FETCHED, Math.floor(Date.now() / 1000));
Services.prefs.setIntPref(
PREF_SERVICES_SETTINGS_LAST_FETCHED,
Math.floor(Date.now() / 1000)
);
let formatter = new Intl.DateTimeFormat("default");
@ -64,12 +78,24 @@ add_task(async function checkWrongSystemTimeWarning() {
info("Loading a bad cert page with a skewed clock");
let message = await setUpPage();
isnot(message.divDisplay, "none", "Wrong time message information is visible");
ok(message.text.includes("update your computer clock"),
"Correct error message found");
ok(message.text.includes("expired.example.com"), "URL found in error message");
isnot(
message.divDisplay,
"none",
"Wrong time message information is visible"
);
ok(
message.text.includes("update your computer clock"),
"Correct error message found"
);
ok(
message.text.includes("expired.example.com"),
"URL found in error message"
);
ok(message.systemDate.includes(localDateFmt), "Correct local date displayed");
ok(message.learnMoreLink.includes("time-errors"), "time-errors in the Learn More URL");
ok(
message.learnMoreLink.includes("time-errors"),
"time-errors in the Learn More URL"
);
BrowserTestUtils.removeTab(gBrowser.selectedTab);

Просмотреть файл

@ -4,11 +4,14 @@
"use strict";
const BAD_CERT = "https://expired.example.com/";
const BAD_STS_CERT = "https://badchain.include-subdomains.pinning.example.com:443";
const BAD_STS_CERT =
"https://badchain.include-subdomains.pinning.example.com:443";
const PREF_PERMANENT_OVERRIDE = "security.certerrors.permanentOverride";
add_task(async function checkExceptionDialogButton() {
info("Loading a bad cert page and making sure the exceptionDialogButton directly adds an exception");
info(
"Loading a bad cert page and making sure the exceptionDialogButton directly adds an exception"
);
let tab = await openErrorPage(BAD_CERT);
let browser = tab.linkedBrowser;
let loaded = BrowserTestUtils.browserLoaded(browser, false, BAD_CERT);
@ -24,17 +27,23 @@ add_task(async function checkExceptionDialogButton() {
await ContentTask.spawn(browser, null, async function() {
let doc = content.document;
ok(!doc.documentURI.startsWith("about:certerror"), "Exception has been added");
ok(
!doc.documentURI.startsWith("about:certerror"),
"Exception has been added"
);
});
let certOverrideService = Cc["@mozilla.org/security/certoverride;1"]
.getService(Ci.nsICertOverrideService);
let certOverrideService = Cc[
"@mozilla.org/security/certoverride;1"
].getService(Ci.nsICertOverrideService);
certOverrideService.clearValidityOverride("expired.example.com", -1);
BrowserTestUtils.removeTab(gBrowser.selectedTab);
});
add_task(async function checkPermanentExceptionPref() {
info("Loading a bad cert page and making sure the permanent state of exceptions can be controlled via pref");
info(
"Loading a bad cert page and making sure the permanent state of exceptions can be controlled via pref"
);
for (let permanentOverride of [false, true]) {
Services.prefs.setBoolPref(PREF_PERMANENT_OVERRIDE, permanentOverride);
@ -43,36 +52,55 @@ add_task(async function checkPermanentExceptionPref() {
let browser = tab.linkedBrowser;
let loaded = BrowserTestUtils.browserLoaded(browser, false, BAD_CERT);
info("Clicking the exceptionDialogButton in advanced panel");
let securityInfoAsString = await ContentTask.spawn(browser, null, async function() {
let doc = content.document;
let exceptionButton = doc.getElementById("exceptionDialogButton");
exceptionButton.click();
let serhelper = Cc["@mozilla.org/network/serialization-helper;1"]
.getService(Ci.nsISerializationHelper);
let serializable = content.docShell.failedChannel.securityInfo
.QueryInterface(Ci.nsITransportSecurityInfo)
.QueryInterface(Ci.nsISerializable);
return serhelper.serializeToString(serializable);
});
let securityInfoAsString = await ContentTask.spawn(
browser,
null,
async function() {
let doc = content.document;
let exceptionButton = doc.getElementById("exceptionDialogButton");
exceptionButton.click();
let serhelper = Cc[
"@mozilla.org/network/serialization-helper;1"
].getService(Ci.nsISerializationHelper);
let serializable = content.docShell.failedChannel.securityInfo
.QueryInterface(Ci.nsITransportSecurityInfo)
.QueryInterface(Ci.nsISerializable);
return serhelper.serializeToString(serializable);
}
);
info("Loading the url after adding exception");
await loaded;
await ContentTask.spawn(browser, null, async function() {
let doc = content.document;
ok(!doc.documentURI.startsWith("about:certerror"), "Exception has been added");
ok(
!doc.documentURI.startsWith("about:certerror"),
"Exception has been added"
);
});
let certOverrideService = Cc["@mozilla.org/security/certoverride;1"]
.getService(Ci.nsICertOverrideService);
let certOverrideService = Cc[
"@mozilla.org/security/certoverride;1"
].getService(Ci.nsICertOverrideService);
let isTemporary = {};
let cert = getSecurityInfo(securityInfoAsString).serverCert;
let hasException =
certOverrideService.hasMatchingOverride("expired.example.com", -1, cert, {}, isTemporary);
let hasException = certOverrideService.hasMatchingOverride(
"expired.example.com",
-1,
cert,
{},
isTemporary
);
ok(hasException, "Has stored an exception for the page.");
is(isTemporary.value, !permanentOverride,
`Has stored a ${permanentOverride ? "permanent" : "temporary"} exception for the page.`);
is(
isTemporary.value,
!permanentOverride,
`Has stored a ${
permanentOverride ? "permanent" : "temporary"
} exception for the page.`
);
certOverrideService.clearValidityOverride("expired.example.com", -1);
BrowserTestUtils.removeTab(gBrowser.selectedTab);
@ -88,40 +116,76 @@ add_task(async function checkBadStsCert() {
let tab = await openErrorPage(BAD_STS_CERT, useFrame);
let browser = tab.linkedBrowser;
await ContentTask.spawn(browser, {frame: useFrame}, async function({frame}) {
let doc = frame ? content.document.querySelector("iframe").contentDocument : content.document;
await ContentTask.spawn(browser, { frame: useFrame }, async function({
frame,
}) {
let doc = frame
? content.document.querySelector("iframe").contentDocument
: content.document;
let exceptionButton = doc.getElementById("exceptionDialogButton");
ok(ContentTaskUtils.is_hidden(exceptionButton), "Exception button is hidden.");
ok(
ContentTaskUtils.is_hidden(exceptionButton),
"Exception button is hidden."
);
});
let message = await ContentTask.spawn(browser, {frame: useFrame}, async function({frame}) {
let doc = frame ? content.document.querySelector("iframe").contentDocument : content.document;
let advancedButton = doc.getElementById("advancedButton");
advancedButton.click();
return doc.getElementById("badCertTechnicalInfo").textContent;
});
ok(message.includes("SSL_ERROR_BAD_CERT_DOMAIN"), "Didn't find SSL_ERROR_BAD_CERT_DOMAIN.");
ok(message.includes("The certificate is only valid for"), "Didn't find error message.");
ok(message.includes("a certificate that is not valid for"), "Didn't find error message.");
ok(message.includes("badchain.include-subdomains.pinning.example.com"), "Didn't find domain in error message.");
let message = await ContentTask.spawn(
browser,
{ frame: useFrame },
async function({ frame }) {
let doc = frame
? content.document.querySelector("iframe").contentDocument
: content.document;
let advancedButton = doc.getElementById("advancedButton");
advancedButton.click();
return doc.getElementById("badCertTechnicalInfo").textContent;
}
);
ok(
message.includes("SSL_ERROR_BAD_CERT_DOMAIN"),
"Didn't find SSL_ERROR_BAD_CERT_DOMAIN."
);
ok(
message.includes("The certificate is only valid for"),
"Didn't find error message."
);
ok(
message.includes("a certificate that is not valid for"),
"Didn't find error message."
);
ok(
message.includes("badchain.include-subdomains.pinning.example.com"),
"Didn't find domain in error message."
);
BrowserTestUtils.removeTab(gBrowser.selectedTab);
}
});
add_task(async function checkhideAddExceptionButtonViaPref() {
info("Loading a bad cert page and verifying the pref security.certerror.hideAddException");
info(
"Loading a bad cert page and verifying the pref security.certerror.hideAddException"
);
Services.prefs.setBoolPref("security.certerror.hideAddException", true);
for (let useFrame of [false, true]) {
let tab = await openErrorPage(BAD_CERT, useFrame);
let browser = tab.linkedBrowser;
await ContentTask.spawn(browser, {frame: useFrame}, async function({frame}) {
let doc = frame ? content.document.querySelector("iframe").contentDocument : content.document;
await ContentTask.spawn(browser, { frame: useFrame }, async function({
frame,
}) {
let doc = frame
? content.document.querySelector("iframe").contentDocument
: content.document;
let exceptionButton = doc.querySelector(".exceptionDialogButtonContainer");
ok(ContentTaskUtils.is_hidden(exceptionButton), "Exception button is hidden.");
let exceptionButton = doc.querySelector(
".exceptionDialogButtonContainer"
);
ok(
ContentTaskUtils.is_hidden(exceptionButton),
"Exception button is hidden."
);
});
BrowserTestUtils.removeTab(gBrowser.selectedTab);
@ -138,7 +202,10 @@ add_task(async function checkhideAddExceptionButtonInFrames() {
await ContentTask.spawn(browser, null, async function() {
let doc = content.document.querySelector("iframe").contentDocument;
let exceptionButton = doc.getElementById("exceptionDialogButton");
ok(ContentTaskUtils.is_hidden(exceptionButton), "Exception button is hidden.");
ok(
ContentTaskUtils.is_hidden(exceptionButton),
"Exception button is hidden."
);
});
BrowserTestUtils.removeTab(gBrowser.selectedTab);

Просмотреть файл

@ -6,25 +6,32 @@
const PREF_MITM_PRIMING = "security.certerrors.mitm.priming.enabled";
const PREF_MITM_PRIMING_ENDPOINT = "security.certerrors.mitm.priming.endpoint";
const PREF_MITM_CANARY_ISSUER = "security.pki.mitm_canary_issuer";
const PREF_MITM_AUTO_ENABLE_ENTERPRISE_ROOTS = "security.certerrors.mitm.auto_enable_enterprise_roots";
const PREF_MITM_AUTO_ENABLE_ENTERPRISE_ROOTS =
"security.certerrors.mitm.auto_enable_enterprise_roots";
const PREF_ENTERPRISE_ROOTS = "security.enterprise_roots.enabled";
const UNKNOWN_ISSUER = "https://untrusted.example.com";
// Check that basic MitM priming works and the MitM error page is displayed successfully.
add_task(async function checkMitmPriming() {
await SpecialPowers.pushPrefEnv({"set": [
[PREF_MITM_PRIMING, true],
[PREF_MITM_PRIMING_ENDPOINT, UNKNOWN_ISSUER],
]});
await SpecialPowers.pushPrefEnv({
set: [
[PREF_MITM_PRIMING, true],
[PREF_MITM_PRIMING_ENDPOINT, UNKNOWN_ISSUER],
],
});
let browser;
let certErrorLoaded;
await BrowserTestUtils.openNewForegroundTab(gBrowser, () => {
gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, UNKNOWN_ISSUER);
browser = gBrowser.selectedBrowser;
certErrorLoaded = BrowserTestUtils.waitForErrorPage(browser);
}, false);
await BrowserTestUtils.openNewForegroundTab(
gBrowser,
() => {
gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, UNKNOWN_ISSUER);
browser = gBrowser.selectedBrowser;
certErrorLoaded = BrowserTestUtils.waitForErrorPage(browser);
},
false
);
await certErrorLoaded;
@ -32,21 +39,38 @@ add_task(async function checkMitmPriming() {
// wait until we're seeing the dedicated MitM page.
await TestUtils.waitForCondition(function() {
return ContentTask.spawn(browser, {}, () => {
return content.document.body.getAttribute("code") == "MOZILLA_PKIX_ERROR_MITM_DETECTED";
return (
content.document.body.getAttribute("code") ==
"MOZILLA_PKIX_ERROR_MITM_DETECTED"
);
});
}, "Loads the MitM error page.");
ok(true, "Successfully loaded the MitM error page.");
is(Services.prefs.getStringPref(PREF_MITM_CANARY_ISSUER), "CN=Unknown CA", "Stored the correct issuer");
is(
Services.prefs.getStringPref(PREF_MITM_CANARY_ISSUER),
"CN=Unknown CA",
"Stored the correct issuer"
);
await ContentTask.spawn(browser, {}, () => {
let mitmName1 = content.document.querySelector("#errorShortDescText .mitm-name");
ok(ContentTaskUtils.is_visible(mitmName1), "Potential man in the middle is displayed");
let mitmName1 = content.document.querySelector(
"#errorShortDescText .mitm-name"
);
ok(
ContentTaskUtils.is_visible(mitmName1),
"Potential man in the middle is displayed"
);
is(mitmName1.textContent, "Unknown CA", "Shows the name of the issuer.");
let mitmName2 = content.document.querySelector("#errorWhatToDoText .mitm-name");
ok(ContentTaskUtils.is_visible(mitmName2), "Potential man in the middle is displayed");
let mitmName2 = content.document.querySelector(
"#errorWhatToDoText .mitm-name"
);
ok(
ContentTaskUtils.is_visible(mitmName2),
"Potential man in the middle is displayed"
);
is(mitmName2.textContent, "Unknown CA", "Shows the name of the issuer.");
});
@ -57,22 +81,31 @@ add_task(async function checkMitmPriming() {
// Check that we set the enterprise roots pref correctly on MitM
add_task(async function checkMitmAutoEnableEnterpriseRoots() {
await SpecialPowers.pushPrefEnv({"set": [
[PREF_MITM_PRIMING, true],
[PREF_MITM_PRIMING_ENDPOINT, UNKNOWN_ISSUER],
[PREF_MITM_AUTO_ENABLE_ENTERPRISE_ROOTS, true],
[PREF_ENTERPRISE_ROOTS, false],
]});
await SpecialPowers.pushPrefEnv({
set: [
[PREF_MITM_PRIMING, true],
[PREF_MITM_PRIMING_ENDPOINT, UNKNOWN_ISSUER],
[PREF_MITM_AUTO_ENABLE_ENTERPRISE_ROOTS, true],
[PREF_ENTERPRISE_ROOTS, false],
],
});
let browser;
let certErrorLoaded;
let prefChanged = TestUtils.waitForPrefChange(PREF_ENTERPRISE_ROOTS, value => value === true);
await BrowserTestUtils.openNewForegroundTab(gBrowser, () => {
gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, UNKNOWN_ISSUER);
browser = gBrowser.selectedBrowser;
certErrorLoaded = BrowserTestUtils.waitForErrorPage(browser);
}, false);
let prefChanged = TestUtils.waitForPrefChange(
PREF_ENTERPRISE_ROOTS,
value => value === true
);
await BrowserTestUtils.openNewForegroundTab(
gBrowser,
() => {
gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, UNKNOWN_ISSUER);
browser = gBrowser.selectedBrowser;
certErrorLoaded = BrowserTestUtils.waitForErrorPage(browser);
},
false
);
await certErrorLoaded;
await prefChanged;
@ -81,13 +114,19 @@ add_task(async function checkMitmAutoEnableEnterpriseRoots() {
// wait until we're seeing the dedicated MitM page.
await TestUtils.waitForCondition(function() {
return ContentTask.spawn(browser, {}, () => {
return content.document.body.getAttribute("code") == "MOZILLA_PKIX_ERROR_MITM_DETECTED";
return (
content.document.body.getAttribute("code") ==
"MOZILLA_PKIX_ERROR_MITM_DETECTED"
);
});
}, "Loads the MitM error page.");
ok(true, "Successfully loaded the MitM error page.");
ok(!Services.prefs.prefHasUserValue(PREF_ENTERPRISE_ROOTS), "Flipped the enterprise roots pref back");
ok(
!Services.prefs.prefHasUserValue(PREF_ENTERPRISE_ROOTS),
"Flipped the enterprise roots pref back"
);
BrowserTestUtils.removeTab(gBrowser.selectedTab);

Просмотреть файл

@ -3,7 +3,9 @@
"use strict";
const BROWSER_NAME = document.getElementById("bundle_brand").getString("brandShortName");
const BROWSER_NAME = document
.getElementById("bundle_brand")
.getString("brandShortName");
const UNKNOWN_ISSUER = "https://no-subject-alt-name.example.com:443";
const checkAdvancedAndGetTechnicalInfoText = async () => {
@ -11,7 +13,11 @@ const checkAdvancedAndGetTechnicalInfoText = async () => {
let advancedButton = doc.getElementById("advancedButton");
ok(advancedButton, "advancedButton found");
is(advancedButton.hasAttribute("disabled"), false, "advancedButton should be clickable");
is(
advancedButton.hasAttribute("disabled"),
false,
"advancedButton should be clickable"
);
advancedButton.click();
let badCertAdvancedPanel = doc.getElementById("badCertAdvancedPanel");
@ -32,24 +38,30 @@ const checkAdvancedAndGetTechnicalInfoText = async () => {
return badCertTechnicalInfo.innerHTML;
};
const checkCorrectMessages = (message) => {
let isCorrectMessage =
message.includes("Websites prove their identity via certificates. "
+ BROWSER_NAME + " does not trust this site because it uses a certificate that is"
+ " not valid for no-subject-alt-name.example.com");
const checkCorrectMessages = message => {
let isCorrectMessage = message.includes(
"Websites prove their identity via certificates. " +
BROWSER_NAME +
" does not trust this site because it uses a certificate that is" +
" not valid for no-subject-alt-name.example.com"
);
is(isCorrectMessage, true, "That message should appear");
let isWrongMessage =
message.includes("The certificate is only valid for ");
let isWrongMessage = message.includes("The certificate is only valid for ");
is(isWrongMessage, false, "That message shouldn't appear");
};
add_task(async function checkUntrustedCertError() {
info(`Loading ${UNKNOWN_ISSUER} which does not have a subject specified in the certificate`);
info(
`Loading ${UNKNOWN_ISSUER} which does not have a subject specified in the certificate`
);
let tab = await openErrorPage(UNKNOWN_ISSUER);
let browser = tab.linkedBrowser;
info("Clicking the exceptionDialogButton in advanced panel");
let badCertTechnicalInfoText =
await ContentTask.spawn(browser, null, checkAdvancedAndGetTechnicalInfoText);
let badCertTechnicalInfoText = await ContentTask.spawn(
browser,
null,
checkAdvancedAndGetTechnicalInfoText
);
checkCorrectMessages(badCertTechnicalInfoText, browser);
BrowserTestUtils.removeTab(gBrowser.selectedTab);
});

Просмотреть файл

@ -6,7 +6,8 @@
requestLongerTimeout(2);
const BAD_CERT = "https://expired.example.com/";
const BAD_STS_CERT = "https://badchain.include-subdomains.pinning.example.com:443";
const BAD_STS_CERT =
"https://badchain.include-subdomains.pinning.example.com:443";
add_task(async function checkTelemetryClickEvents() {
info("Loading a bad cert page and verifying telemetry click events arrive.");
@ -33,7 +34,9 @@ add_task(async function checkTelemetryClickEvents() {
Services.telemetry.clearEvents();
await TestUtils.waitForCondition(() => {
let events = Services.telemetry.snapshotEvents(
Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS, true).content;
Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS,
true
).content;
return !events || !events.length;
});
@ -64,40 +67,76 @@ add_task(async function checkTelemetryClickEvents() {
let loadEvents = await TestUtils.waitForCondition(() => {
let events = Services.telemetry.snapshotEvents(
Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS, true).parent;
Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS,
true
).parent;
if (events && events.length) {
events = events.filter(e => e[1] == "security.ui.certerror" && e[2] == "load");
if (events.length == 1 && events[0][5].is_frame == useFrame.toString()) {
events = events.filter(
e => e[1] == "security.ui.certerror" && e[2] == "load"
);
if (
events.length == 1 &&
events[0][5].is_frame == useFrame.toString()
) {
return events;
}
}
return null;
}, "recorded telemetry for the load");
is(loadEvents.length, 1, `recorded telemetry for the load testing ${object}, useFrame: ${useFrame}`);
is(
loadEvents.length,
1,
`recorded telemetry for the load testing ${object}, useFrame: ${useFrame}`
);
await ContentTask.spawn(browser, {frame: useFrame, objectId: object}, async function({frame, objectId}) {
let doc = frame ? content.document.querySelector("iframe").contentDocument : content.document;
await ContentTask.spawn(
browser,
{ frame: useFrame, objectId: object },
async function({ frame, objectId }) {
let doc = frame
? content.document.querySelector("iframe").contentDocument
: content.document;
await ContentTaskUtils.waitForCondition(() => doc.body.classList.contains("certerror"), "Wait for certerror to be loaded");
await ContentTaskUtils.waitForCondition(
() => doc.body.classList.contains("certerror"),
"Wait for certerror to be loaded"
);
let domElement = doc.querySelector(`[data-telemetry-id='${objectId}']`);
domElement.click();
});
let domElement = doc.querySelector(
`[data-telemetry-id='${objectId}']`
);
domElement.click();
}
);
let clickEvents = await TestUtils.waitForCondition(() => {
let events = Services.telemetry.snapshotEvents(
Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS, true).content;
Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS,
true
).content;
if (events && events.length) {
events = events.filter(e => e[1] == "security.ui.certerror" && e[2] == "click" && e[3] == object);
if (events.length == 1 && events[0][5].is_frame == useFrame.toString()) {
events = events.filter(
e =>
e[1] == "security.ui.certerror" &&
e[2] == "click" &&
e[3] == object
);
if (
events.length == 1 &&
events[0][5].is_frame == useFrame.toString()
) {
return events;
}
}
return null;
}, "Has captured telemetry events.");
is(clickEvents.length, 1, `recorded telemetry for the click on ${object}, useFrame: ${useFrame}`);
is(
clickEvents.length,
1,
`recorded telemetry for the click on ${object}, useFrame: ${useFrame}`
);
// We opened an extra tab for the SUMO page, need to close it.
if (object == "learn_more_link") {
@ -105,8 +144,9 @@ add_task(async function checkTelemetryClickEvents() {
}
if (object == "exception_button") {
let certOverrideService = Cc["@mozilla.org/security/certoverride;1"]
.getService(Ci.nsICertOverrideService);
let certOverrideService = Cc[
"@mozilla.org/security/certoverride;1"
].getService(Ci.nsICertOverrideService);
certOverrideService.clearValidityOverride("expired.example.com", -1);
}
@ -114,8 +154,11 @@ add_task(async function checkTelemetryClickEvents() {
}
}
let enableCertErrorUITelemetry =
Services.prefs.getBoolPref("security.certerrors.recordEventTelemetry");
Services.telemetry.setEventRecordingEnabled("security.ui.certerror",
enableCertErrorUITelemetry);
let enableCertErrorUITelemetry = Services.prefs.getBoolPref(
"security.certerrors.recordEventTelemetry"
);
Services.telemetry.setEventRecordingEnabled(
"security.ui.certerror",
enableCertErrorUITelemetry
);
});

Просмотреть файл

@ -7,26 +7,39 @@ ignoreAllUncaughtExceptions();
add_task(async function() {
info("Check POST search engine support");
await BrowserTestUtils.withNewTab({ gBrowser, url: "about:home" }, function(browser) {
await BrowserTestUtils.withNewTab({ gBrowser, url: "about:home" }, function(
browser
) {
return new Promise(resolve => {
let searchObserver = async function search_observer(subject, topic, data) {
let searchObserver = async function search_observer(
subject,
topic,
data
) {
let currEngine = await Services.search.getDefault();
let engine = subject.QueryInterface(Ci.nsISearchEngine);
info("Observer: " + data + " for " + engine.name);
if (data != "engine-added")
if (data != "engine-added") {
return;
}
if (engine.name != "POST Search")
if (engine.name != "POST Search") {
return;
}
Services.obs.removeObserver(searchObserver, "browser-search-engine-modified");
Services.obs.removeObserver(
searchObserver,
"browser-search-engine-modified"
);
// Ready to execute the tests!
let needle = "Search for something awesome.";
await Promise.all([promiseContentSearchChange(browser, engine.name),
Services.search.setDefault(engine)]);
await Promise.all([
promiseContentSearchChange(browser, engine.name),
Services.search.setDefault(engine),
]);
let promise = BrowserTestUtils.browserLoaded(browser);
await ContentTask.spawn(browser, { needle }, async function(args) {
let doc = content.document;
@ -41,8 +54,11 @@ add_task(async function() {
await ContentTask.spawn(browser, { needle }, async function(args) {
let loadedText = content.document.body.textContent;
ok(loadedText, "search page loaded");
is(loadedText, "searchterms=" + escape(args.needle.replace(/\s/g, "+")),
"Search text should arrive correctly");
is(
loadedText,
"searchterms=" + escape(args.needle.replace(/\s/g, "+")),
"Search text should arrive correctly"
);
});
await Services.search.setDefault(currEngine);
@ -51,9 +67,15 @@ add_task(async function() {
} catch (ex) {}
resolve();
};
Services.obs.addObserver(searchObserver, "browser-search-engine-modified");
Services.search.addEngine("http://test:80/browser/browser/base/content/test/about/POSTSearchEngine.xml",
null, false);
Services.obs.addObserver(
searchObserver,
"browser-search-engine-modified"
);
Services.search.addEngine(
"http://test:80/browser/browser/base/content/test/about/POSTSearchEngine.xml",
null,
false
);
});
});
});

Просмотреть файл

@ -7,93 +7,119 @@ ignoreAllUncaughtExceptions();
add_task(async function() {
info("Clicking suggestion list while composing");
await BrowserTestUtils.withNewTab({ gBrowser, url: "about:home" }, async function(browser) {
// Add a test engine that provides suggestions and switch to it.
let currEngine = await Services.search.getDefault();
let engine = await promiseNewEngine("searchSuggestionEngine.xml");
let p = promiseContentSearchChange(browser, engine.name);
await Services.search.setDefault(engine);
await p;
await BrowserTestUtils.withNewTab(
{ gBrowser, url: "about:home" },
async function(browser) {
// Add a test engine that provides suggestions and switch to it.
let currEngine = await Services.search.getDefault();
let engine = await promiseNewEngine("searchSuggestionEngine.xml");
let p = promiseContentSearchChange(browser, engine.name);
await Services.search.setDefault(engine);
await p;
// Clear any search history results
await new Promise((resolve, reject) => {
FormHistory.update({op: "remove"}, {
handleError(error) {
reject(error);
},
handleCompletion(reason) {
if (!reason) {
resolve();
} else {
reject();
// Clear any search history results
await new Promise((resolve, reject) => {
FormHistory.update(
{ op: "remove" },
{
handleError(error) {
reject(error);
},
handleCompletion(reason) {
if (!reason) {
resolve();
} else {
reject();
}
},
}
},
});
});
await ContentTask.spawn(browser, null, async function() {
// Start composition and type "x"
let input = content.document.querySelector(["#searchText", "#newtab-search-text"]);
input.focus();
});
info("Setting up the mutation observer before synthesizing composition");
let mutationPromise = ContentTask.spawn(browser, null, async function() {
let searchController = content.wrappedJSObject.gContentSearchController;
// Wait for the search suggestions to become visible.
let table = searchController._suggestionsList;
let input = content.document.querySelector(["#searchText", "#newtab-search-text"]);
await new Promise(resolve => {
let observer = new content.MutationObserver(() => {
if (input.getAttribute("aria-expanded") == "true") {
observer.disconnect();
ok(!table.hidden, "Search suggestion table unhidden");
resolve();
}
});
observer.observe(input, {
attributes: true,
attributeFilter: ["aria-expanded"],
});
);
});
let row = table.children[1];
row.setAttribute("id", "TEMPID");
await ContentTask.spawn(browser, null, async function() {
// Start composition and type "x"
let input = content.document.querySelector([
"#searchText",
"#newtab-search-text",
]);
input.focus();
});
// ContentSearchUIController looks at the current selectedIndex when
// performing a search. Synthesizing the mouse event on the suggestion
// doesn't actually mouseover the suggestion and trigger it to be flagged
// as selected, so we manually select it first.
searchController.selectedIndex = 1;
});
info("Setting up the mutation observer before synthesizing composition");
let mutationPromise = ContentTask.spawn(browser, null, async function() {
let searchController = content.wrappedJSObject.gContentSearchController;
// FYI: "compositionstart" will be dispatched automatically.
await BrowserTestUtils.synthesizeCompositionChange({
composition: {
string: "x",
clauses: [
{ length: 1, attr: Ci.nsITextInputProcessor.ATTR_RAW_CLAUSE },
],
},
caret: { start: 1, length: 0 },
}, browser);
// Wait for the search suggestions to become visible.
let table = searchController._suggestionsList;
let input = content.document.querySelector([
"#searchText",
"#newtab-search-text",
]);
info("Waiting for search suggestion table unhidden");
await mutationPromise;
await new Promise(resolve => {
let observer = new content.MutationObserver(() => {
if (input.getAttribute("aria-expanded") == "true") {
observer.disconnect();
ok(!table.hidden, "Search suggestion table unhidden");
resolve();
}
});
observer.observe(input, {
attributes: true,
attributeFilter: ["aria-expanded"],
});
});
// Click the second suggestion.
let expectedURL = (await Services.search.getDefault()).getSubmission("xbar", null, "homepage").uri.spec;
let loadPromise = BrowserTestUtils.waitForDocLoadAndStopIt(expectedURL, gBrowser.selectedBrowser);
await BrowserTestUtils.synthesizeMouseAtCenter("#TEMPID", {
button: 0,
}, browser);
await loadPromise;
let row = table.children[1];
row.setAttribute("id", "TEMPID");
Services.search.setDefault(currEngine);
try {
await Services.search.removeEngine(engine);
} catch (ex) { }
});
// ContentSearchUIController looks at the current selectedIndex when
// performing a search. Synthesizing the mouse event on the suggestion
// doesn't actually mouseover the suggestion and trigger it to be flagged
// as selected, so we manually select it first.
searchController.selectedIndex = 1;
});
// FYI: "compositionstart" will be dispatched automatically.
await BrowserTestUtils.synthesizeCompositionChange(
{
composition: {
string: "x",
clauses: [
{ length: 1, attr: Ci.nsITextInputProcessor.ATTR_RAW_CLAUSE },
],
},
caret: { start: 1, length: 0 },
},
browser
);
info("Waiting for search suggestion table unhidden");
await mutationPromise;
// Click the second suggestion.
let expectedURL = (await Services.search.getDefault()).getSubmission(
"xbar",
null,
"homepage"
).uri.spec;
let loadPromise = BrowserTestUtils.waitForDocLoadAndStopIt(
expectedURL,
gBrowser.selectedBrowser
);
await BrowserTestUtils.synthesizeMouseAtCenter(
"#TEMPID",
{
button: 0,
},
browser
);
await loadPromise;
Services.search.setDefault(currEngine);
try {
await Services.search.removeEngine(engine);
} catch (ex) {}
}
);
});

Просмотреть файл

@ -2,7 +2,10 @@
* http://creativecommons.org/publicdomain/zero/1.0/
*/
ChromeUtils.import("resource://testing-common/CustomizableUITestUtils.jsm", this);
ChromeUtils.import(
"resource://testing-common/CustomizableUITestUtils.jsm",
this
);
let gCUITestUtils = new CustomizableUITestUtils(window);
ignoreAllUncaughtExceptions();
@ -17,15 +20,26 @@ add_task(async function test_setup() {
add_task(async function() {
info("Cmd+k should focus the search box in the toolbar when it's present");
await BrowserTestUtils.withNewTab({ gBrowser, url: "about:home" }, async function(browser) {
await BrowserTestUtils.synthesizeMouseAtCenter("#brandLogo", {}, browser);
await BrowserTestUtils.withNewTab(
{ gBrowser, url: "about:home" },
async function(browser) {
await BrowserTestUtils.synthesizeMouseAtCenter("#brandLogo", {}, browser);
let doc = window.document;
let searchInput = BrowserSearch.searchBar.textbox.inputField;
isnot(searchInput, doc.activeElement, "Search bar should not be the active element.");
let doc = window.document;
let searchInput = BrowserSearch.searchBar.textbox.inputField;
isnot(
searchInput,
doc.activeElement,
"Search bar should not be the active element."
);
EventUtils.synthesizeKey("k", { accelKey: true });
await TestUtils.waitForCondition(() => doc.activeElement === searchInput);
is(searchInput, doc.activeElement, "Search bar should be the active element.");
});
EventUtils.synthesizeKey("k", { accelKey: true });
await TestUtils.waitForCondition(() => doc.activeElement === searchInput);
is(
searchInput,
doc.activeElement,
"Search bar should be the active element."
);
}
);
});

Просмотреть файл

@ -8,54 +8,67 @@ add_task(async function() {
// See browser_contentSearchUI.js for comprehensive content search UI tests.
info("Search suggestion smoke test");
await BrowserTestUtils.withNewTab({ gBrowser, url: "about:home" }, async function(browser) {
// Add a test engine that provides suggestions and switch to it.
let currEngine = await Services.search.getDefault();
let engine = await promiseNewEngine("searchSuggestionEngine.xml");
await Promise.all([promiseContentSearchChange(browser, engine.name),
Services.search.setDefault(engine)]);
await BrowserTestUtils.withNewTab(
{ gBrowser, url: "about:home" },
async function(browser) {
// Add a test engine that provides suggestions and switch to it.
let currEngine = await Services.search.getDefault();
let engine = await promiseNewEngine("searchSuggestionEngine.xml");
await Promise.all([
promiseContentSearchChange(browser, engine.name),
Services.search.setDefault(engine),
]);
await ContentTask.spawn(browser, null, async function() {
// Type an X in the search input.
let input = content.document.querySelector(["#searchText", "#newtab-search-text"]);
input.focus();
});
await ContentTask.spawn(browser, null, async function() {
// Type an X in the search input.
let input = content.document.querySelector([
"#searchText",
"#newtab-search-text",
]);
input.focus();
});
await BrowserTestUtils.synthesizeKey("x", {}, browser);
await BrowserTestUtils.synthesizeKey("x", {}, browser);
await ContentTask.spawn(browser, null, async function() {
// Wait for the search suggestions to become visible.
let table = content.document.getElementById("searchSuggestionTable");
let input = content.document.querySelector(["#searchText", "#newtab-search-text"]);
await ContentTask.spawn(browser, null, async function() {
// Wait for the search suggestions to become visible.
let table = content.document.getElementById("searchSuggestionTable");
let input = content.document.querySelector([
"#searchText",
"#newtab-search-text",
]);
await new Promise(resolve => {
let observer = new content.MutationObserver(() => {
if (input.getAttribute("aria-expanded") == "true") {
observer.disconnect();
ok(!table.hidden, "Search suggestion table unhidden");
resolve();
}
});
observer.observe(input, {
attributes: true,
attributeFilter: ["aria-expanded"],
await new Promise(resolve => {
let observer = new content.MutationObserver(() => {
if (input.getAttribute("aria-expanded") == "true") {
observer.disconnect();
ok(!table.hidden, "Search suggestion table unhidden");
resolve();
}
});
observer.observe(input, {
attributes: true,
attributeFilter: ["aria-expanded"],
});
});
});
});
// Empty the search input, causing the suggestions to be hidden.
await BrowserTestUtils.synthesizeKey("a", { accelKey: true }, browser);
await BrowserTestUtils.synthesizeKey("VK_DELETE", {}, browser);
// Empty the search input, causing the suggestions to be hidden.
await BrowserTestUtils.synthesizeKey("a", { accelKey: true }, browser);
await BrowserTestUtils.synthesizeKey("VK_DELETE", {}, browser);
await ContentTask.spawn(browser, null, async function() {
let table = content.document.getElementById("searchSuggestionTable");
await ContentTaskUtils.waitForCondition(() => table.hidden,
"Search suggestion table hidden");
});
await ContentTask.spawn(browser, null, async function() {
let table = content.document.getElementById("searchSuggestionTable");
await ContentTaskUtils.waitForCondition(
() => table.hidden,
"Search suggestion table hidden"
);
});
await Services.search.setDefault(currEngine);
try {
await Services.search.removeEngine(engine);
} catch (ex) { }
});
await Services.search.setDefault(currEngine);
try {
await Services.search.removeEngine(engine);
} catch (ex) {}
}
);
});

Просмотреть файл

@ -5,60 +5,91 @@
ignoreAllUncaughtExceptions();
add_task(async function() {
info("Check that performing a search fires a search event and records to Telemetry.");
info(
"Check that performing a search fires a search event and records to Telemetry."
);
await BrowserTestUtils.withNewTab({ gBrowser, url: "about:home" }, async function(browser) {
let currEngine = await Services.search.getDefault();
let engine = await promiseNewEngine("searchSuggestionEngine.xml");
// Make this actually work in healthreport by giving it an ID:
Object.defineProperty(engine.wrappedJSObject, "identifier",
{ value: "org.mozilla.testsearchsuggestions" });
await BrowserTestUtils.withNewTab(
{ gBrowser, url: "about:home" },
async function(browser) {
let currEngine = await Services.search.getDefault();
let engine = await promiseNewEngine("searchSuggestionEngine.xml");
// Make this actually work in healthreport by giving it an ID:
Object.defineProperty(engine.wrappedJSObject, "identifier", {
value: "org.mozilla.testsearchsuggestions",
});
await Promise.all([promiseContentSearchChange(browser, engine.name),
Services.search.setDefault(engine)]);
await Promise.all([
promiseContentSearchChange(browser, engine.name),
Services.search.setDefault(engine),
]);
await ContentTask.spawn(browser, { expectedName: engine.name }, async function(args) {
let engineName = content.wrappedJSObject.gContentSearchController.defaultEngine.name;
is(engineName, args.expectedName, "Engine name in DOM should match engine we just added");
});
await ContentTask.spawn(
browser,
{ expectedName: engine.name },
async function(args) {
let engineName =
content.wrappedJSObject.gContentSearchController.defaultEngine.name;
is(
engineName,
args.expectedName,
"Engine name in DOM should match engine we just added"
);
}
);
let numSearchesBefore = 0;
// Get the current number of recorded searches.
let histogramKey = engine.identifier + ".abouthome";
try {
let hs = Services.telemetry.getKeyedHistogramById("SEARCH_COUNTS").snapshot();
if (histogramKey in hs) {
numSearchesBefore = hs[histogramKey].sum;
let numSearchesBefore = 0;
// Get the current number of recorded searches.
let histogramKey = engine.identifier + ".abouthome";
try {
let hs = Services.telemetry
.getKeyedHistogramById("SEARCH_COUNTS")
.snapshot();
if (histogramKey in hs) {
numSearchesBefore = hs[histogramKey].sum;
}
} catch (ex) {
// No searches performed yet, not a problem, |numSearchesBefore| is 0.
}
} catch (ex) {
// No searches performed yet, not a problem, |numSearchesBefore| is 0.
let searchStr = "a search";
let expectedURL = (await Services.search.getDefault()).getSubmission(
searchStr,
null,
"homepage"
).uri.spec;
let promise = BrowserTestUtils.waitForDocLoadAndStopIt(
expectedURL,
browser
);
// Perform a search to increase the SEARCH_COUNT histogram.
await ContentTask.spawn(browser, { searchStr }, async function(args) {
let doc = content.document;
info("Perform a search.");
let el = doc.querySelector(["#searchText", "#newtab-search-text"]);
el.value = args.searchStr;
doc.getElementById("searchSubmit").click();
});
await promise;
// Make sure the SEARCH_COUNTS histogram has the right key and count.
let hs = Services.telemetry
.getKeyedHistogramById("SEARCH_COUNTS")
.snapshot();
Assert.ok(histogramKey in hs, "histogram with key should be recorded");
Assert.equal(
hs[histogramKey].sum,
numSearchesBefore + 1,
"histogram sum should be incremented"
);
await Services.search.setDefault(currEngine);
try {
await Services.search.removeEngine(engine);
} catch (ex) {}
}
let searchStr = "a search";
let expectedURL = (await Services.search.getDefault()).getSubmission(searchStr, null, "homepage").uri.spec;
let promise = BrowserTestUtils.waitForDocLoadAndStopIt(expectedURL, browser);
// Perform a search to increase the SEARCH_COUNT histogram.
await ContentTask.spawn(browser, { searchStr }, async function(args) {
let doc = content.document;
info("Perform a search.");
let el = doc.querySelector(["#searchText", "#newtab-search-text"]);
el.value = args.searchStr;
doc.getElementById("searchSubmit").click();
});
await promise;
// Make sure the SEARCH_COUNTS histogram has the right key and count.
let hs = Services.telemetry.getKeyedHistogramById("SEARCH_COUNTS").snapshot();
Assert.ok(histogramKey in hs, "histogram with key should be recorded");
Assert.equal(hs[histogramKey].sum, numSearchesBefore + 1,
"histogram sum should be incremented");
await Services.search.setDefault(currEngine);
try {
await Services.search.removeEngine(engine);
} catch (ex) {}
});
);
});

Просмотреть файл

@ -6,7 +6,9 @@
const LOW_TLS_VERSION = "https://tls1.example.com/";
add_task(async function checkReturnToPreviousPage() {
info("Loading a TLS page that isn't supported, ensure we have a fix button and clicking it then loads the page");
info(
"Loading a TLS page that isn't supported, ensure we have a fix button and clicking it then loads the page"
);
// Set ourselves up for TLS error
Services.prefs.setIntPref("security.tls.version.max", 3);
@ -14,11 +16,15 @@ add_task(async function checkReturnToPreviousPage() {
let browser;
let pageLoaded;
await BrowserTestUtils.openNewForegroundTab(gBrowser, () => {
gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, LOW_TLS_VERSION);
browser = gBrowser.selectedBrowser;
pageLoaded = BrowserTestUtils.waitForErrorPage(browser);
}, false);
await BrowserTestUtils.openNewForegroundTab(
gBrowser,
() => {
gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, LOW_TLS_VERSION);
browser = gBrowser.selectedBrowser;
pageLoaded = BrowserTestUtils.waitForErrorPage(browser);
},
false
);
info("Loading and waiting for the net error");
await pageLoaded;
@ -26,27 +32,45 @@ add_task(async function checkReturnToPreviousPage() {
// NB: This code assumes that the error page and the test page load in the
// same process. If this test starts to fail, it could be because they load
// in different processes.
await ContentTask.spawn(browser, LOW_TLS_VERSION, async function(LOW_TLS_VERSION_) {
ok(content.document.getElementById("prefResetButton").getBoundingClientRect().left >= 0,
"Should have a visible button");
await ContentTask.spawn(browser, LOW_TLS_VERSION, async function(
LOW_TLS_VERSION_
) {
ok(
content.document.getElementById("prefResetButton").getBoundingClientRect()
.left >= 0,
"Should have a visible button"
);
ok(content.document.documentURI.startsWith("about:neterror"), "Should be showing error page");
ok(
content.document.documentURI.startsWith("about:neterror"),
"Should be showing error page"
);
let doc = content.document;
let prefResetButton = doc.getElementById("prefResetButton");
is(prefResetButton.getAttribute("autofocus"), "true", "prefResetButton has autofocus");
is(
prefResetButton.getAttribute("autofocus"),
"true",
"prefResetButton has autofocus"
);
prefResetButton.click();
await ContentTaskUtils.waitForEvent(this, "pageshow", true);
is(content.document.documentURI, LOW_TLS_VERSION_, "Should not be showing page");
is(
content.document.documentURI,
LOW_TLS_VERSION_,
"Should not be showing page"
);
});
BrowserTestUtils.removeTab(gBrowser.selectedTab);
});
add_task(async function checkLearnMoreLink() {
info("Loading a TLS page that isn't supported and checking the learn more link");
info(
"Loading a TLS page that isn't supported and checking the learn more link"
);
// Set ourselves up for TLS error
Services.prefs.setIntPref("security.tls.version.max", 3);
@ -54,11 +78,15 @@ add_task(async function checkLearnMoreLink() {
let browser;
let pageLoaded;
await BrowserTestUtils.openNewForegroundTab(gBrowser, () => {
gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, LOW_TLS_VERSION);
browser = gBrowser.selectedBrowser;
pageLoaded = BrowserTestUtils.waitForErrorPage(browser);
}, false);
await BrowserTestUtils.openNewForegroundTab(
gBrowser,
() => {
gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, LOW_TLS_VERSION);
browser = gBrowser.selectedBrowser;
pageLoaded = BrowserTestUtils.waitForErrorPage(browser);
},
false
);
info("Loading and waiting for the net error");
await pageLoaded;
@ -66,11 +94,17 @@ add_task(async function checkLearnMoreLink() {
let baseURL = Services.urlFormatter.formatURLPref("app.support.baseURL");
await ContentTask.spawn(browser, baseURL, function(_baseURL) {
ok(content.document.documentURI.startsWith("about:neterror"), "Should be showing error page");
ok(
content.document.documentURI.startsWith("about:neterror"),
"Should be showing error page"
);
let doc = content.document;
let learnMoreLink = doc.getElementById("learnMoreLink");
ok(ContentTaskUtils.is_visible(learnMoreLink), "Learn More link is visible");
ok(
ContentTaskUtils.is_visible(learnMoreLink),
"Learn More link is visible"
);
is(learnMoreLink.getAttribute("href"), _baseURL + "connection-not-secure");
});

Просмотреть файл

@ -3,86 +3,129 @@ async function waitForNoAnimation(elt) {
}
async function getAnimatePromise(elt) {
return BrowserTestUtils.waitForAttribute("animate", elt)
.then(() => Assert.ok(true, `${elt.id} should animate`));
return BrowserTestUtils.waitForAttribute("animate", elt).then(() =>
Assert.ok(true, `${elt.id} should animate`)
);
}
function stopReloadMutationCallback() {
Assert.ok(false, "stop-reload's animate attribute should not have been mutated");
Assert.ok(
false,
"stop-reload's animate attribute should not have been mutated"
);
}
add_task(async function checkDontShowStopOnNewTab() {
let stopReloadContainer = document.getElementById("stop-reload-button");
let stopReloadContainerObserver = new MutationObserver(stopReloadMutationCallback);
let stopReloadContainerObserver = new MutationObserver(
stopReloadMutationCallback
);
await waitForNoAnimation(stopReloadContainer);
stopReloadContainerObserver.observe(stopReloadContainer, { attributeFilter: ["animate"]});
let tab = await BrowserTestUtils.openNewForegroundTab({gBrowser,
opening: "about:robots",
waitForStateStop: true});
stopReloadContainerObserver.observe(stopReloadContainer, {
attributeFilter: ["animate"],
});
let tab = await BrowserTestUtils.openNewForegroundTab({
gBrowser,
opening: "about:robots",
waitForStateStop: true,
});
BrowserTestUtils.removeTab(tab);
Assert.ok(true, "Test finished: stop-reload does not animate when navigating to local URI on new tab");
Assert.ok(
true,
"Test finished: stop-reload does not animate when navigating to local URI on new tab"
);
stopReloadContainerObserver.disconnect();
});
add_task(async function checkDontShowStopFromLocalURI() {
let stopReloadContainer = document.getElementById("stop-reload-button");
let stopReloadContainerObserver = new MutationObserver(stopReloadMutationCallback);
let stopReloadContainerObserver = new MutationObserver(
stopReloadMutationCallback
);
let tab = await BrowserTestUtils.openNewForegroundTab({gBrowser,
opening: "about:robots",
waitForStateStop: true});
let tab = await BrowserTestUtils.openNewForegroundTab({
gBrowser,
opening: "about:robots",
waitForStateStop: true,
});
await waitForNoAnimation(stopReloadContainer);
stopReloadContainerObserver.observe(stopReloadContainer, { attributeFilter: ["animate"]});
stopReloadContainerObserver.observe(stopReloadContainer, {
attributeFilter: ["animate"],
});
await BrowserTestUtils.loadURI(tab.linkedBrowser, "about:mozilla");
BrowserTestUtils.removeTab(tab);
Assert.ok(true, "Test finished: stop-reload does not animate when navigating between local URIs");
Assert.ok(
true,
"Test finished: stop-reload does not animate when navigating between local URIs"
);
stopReloadContainerObserver.disconnect();
});
add_task(async function checkDontShowStopFromNonLocalURI() {
let stopReloadContainer = document.getElementById("stop-reload-button");
let stopReloadContainerObserver = new MutationObserver(stopReloadMutationCallback);
let stopReloadContainerObserver = new MutationObserver(
stopReloadMutationCallback
);
let tab = await BrowserTestUtils.openNewForegroundTab({gBrowser,
opening: "https://example.com",
waitForStateStop: true});
let tab = await BrowserTestUtils.openNewForegroundTab({
gBrowser,
opening: "https://example.com",
waitForStateStop: true,
});
await waitForNoAnimation(stopReloadContainer);
stopReloadContainerObserver.observe(stopReloadContainer, { attributeFilter: ["animate"]});
stopReloadContainerObserver.observe(stopReloadContainer, {
attributeFilter: ["animate"],
});
await BrowserTestUtils.loadURI(tab.linkedBrowser, "about:mozilla");
BrowserTestUtils.removeTab(tab);
Assert.ok(true, "Test finished: stop-reload does not animate when navigating to local URI from non-local URI");
Assert.ok(
true,
"Test finished: stop-reload does not animate when navigating to local URI from non-local URI"
);
stopReloadContainerObserver.disconnect();
});
add_task(async function checkDoShowStopOnNewTab() {
let stopReloadContainer = document.getElementById("stop-reload-button");
let reloadButton = document.getElementById("reload-button");
let stopPromise = BrowserTestUtils.waitForAttribute("displaystop", reloadButton);
let stopPromise = BrowserTestUtils.waitForAttribute(
"displaystop",
reloadButton
);
await waitForNoAnimation(stopReloadContainer);
let tab = await BrowserTestUtils.openNewForegroundTab({gBrowser,
opening: "https://example.com",
waitForStateStop: true});
let tab = await BrowserTestUtils.openNewForegroundTab({
gBrowser,
opening: "https://example.com",
waitForStateStop: true,
});
await stopPromise;
await waitForNoAnimation(stopReloadContainer);
BrowserTestUtils.removeTab(tab);
info("Test finished: stop-reload shows stop when navigating to non-local URI during tab opening");
info(
"Test finished: stop-reload shows stop when navigating to non-local URI during tab opening"
);
});
add_task(async function checkAnimateStopOnTabAfterTabFinishesOpening() {
let stopReloadContainer = document.getElementById("stop-reload-button");
await waitForNoAnimation(stopReloadContainer);
let tab = await BrowserTestUtils.openNewForegroundTab({gBrowser,
waitForStateStop: true});
let tab = await BrowserTestUtils.openNewForegroundTab({
gBrowser,
waitForStateStop: true,
});
await BrowserTestUtils.waitForCondition(() => {
info("Waiting for tabAnimationsInProgress to equal 0, currently " + gBrowser.tabAnimationsInProgress);
info(
"Waiting for tabAnimationsInProgress to equal 0, currently " +
gBrowser.tabAnimationsInProgress
);
return !gBrowser.tabAnimationsInProgress;
});
let animatePromise = getAnimatePromise(stopReloadContainer);
@ -90,18 +133,25 @@ add_task(async function checkAnimateStopOnTabAfterTabFinishesOpening() {
await animatePromise;
BrowserTestUtils.removeTab(tab);
info("Test finished: stop-reload animates when navigating to non-local URI on new tab after tab has opened");
info(
"Test finished: stop-reload animates when navigating to non-local URI on new tab after tab has opened"
);
});
add_task(async function checkDoShowStopFromLocalURI() {
let stopReloadContainer = document.getElementById("stop-reload-button");
await waitForNoAnimation(stopReloadContainer);
let tab = await BrowserTestUtils.openNewForegroundTab({gBrowser,
opening: "about:robots",
waitForStateStop: true});
let tab = await BrowserTestUtils.openNewForegroundTab({
gBrowser,
opening: "about:robots",
waitForStateStop: true,
});
await BrowserTestUtils.waitForCondition(() => {
info("Waiting for tabAnimationsInProgress to equal 0, currently " + gBrowser.tabAnimationsInProgress);
info(
"Waiting for tabAnimationsInProgress to equal 0, currently " +
gBrowser.tabAnimationsInProgress
);
return !gBrowser.tabAnimationsInProgress;
});
let animatePromise = getAnimatePromise(stopReloadContainer);
@ -110,5 +160,7 @@ add_task(async function checkDoShowStopFromLocalURI() {
await waitForNoAnimation(stopReloadContainer);
BrowserTestUtils.removeTab(tab);
info("Test finished: stop-reload animates when navigating to non-local URI from local URI");
info(
"Test finished: stop-reload animates when navigating to non-local URI from local URI"
);
});

Просмотреть файл

@ -4,30 +4,60 @@
"use strict";
add_task(async function() {
await BrowserTestUtils.withNewTab({ gBrowser, url: "about:support" }, async function(browser) {
let keyLocationServiceGoogleStatus = await ContentTask.spawn(browser, null, async function() {
let textBox = content.document.getElementById("key-location-service-google-box");
await ContentTaskUtils.waitForCondition(() => content.document.l10n.getAttributes(textBox).id,
"Google location service API key status loaded");
return content.document.l10n.getAttributes(textBox).id;
});
ok(keyLocationServiceGoogleStatus, "Google location service API key status shown");
await BrowserTestUtils.withNewTab(
{ gBrowser, url: "about:support" },
async function(browser) {
let keyLocationServiceGoogleStatus = await ContentTask.spawn(
browser,
null,
async function() {
let textBox = content.document.getElementById(
"key-location-service-google-box"
);
await ContentTaskUtils.waitForCondition(
() => content.document.l10n.getAttributes(textBox).id,
"Google location service API key status loaded"
);
return content.document.l10n.getAttributes(textBox).id;
}
);
ok(
keyLocationServiceGoogleStatus,
"Google location service API key status shown"
);
let keySafebrowsingGoogleStatus = await ContentTask.spawn(browser, null, async function() {
let textBox = content.document.getElementById("key-safebrowsing-google-box");
await ContentTaskUtils.waitForCondition(() => content.document.l10n.getAttributes(textBox).id,
"Google Safebrowsing API key status loaded");
return content.document.l10n.getAttributes(textBox).id;
});
ok(keySafebrowsingGoogleStatus, "Google Safebrowsing API key status shown");
let keySafebrowsingGoogleStatus = await ContentTask.spawn(
browser,
null,
async function() {
let textBox = content.document.getElementById(
"key-safebrowsing-google-box"
);
await ContentTaskUtils.waitForCondition(
() => content.document.l10n.getAttributes(textBox).id,
"Google Safebrowsing API key status loaded"
);
return content.document.l10n.getAttributes(textBox).id;
}
);
ok(
keySafebrowsingGoogleStatus,
"Google Safebrowsing API key status shown"
);
let keyMozillaStatus = await ContentTask.spawn(browser, null, async function() {
let textBox = content.document.getElementById("key-mozilla-box");
await ContentTaskUtils.waitForCondition(() => content.document.l10n.getAttributes(textBox).id,
"Mozilla API key status loaded");
return content.document.l10n.getAttributes(textBox).id;
});
ok(keyMozillaStatus, "Mozilla API key status shown");
});
let keyMozillaStatus = await ContentTask.spawn(
browser,
null,
async function() {
let textBox = content.document.getElementById("key-mozilla-box");
await ContentTaskUtils.waitForCondition(
() => content.document.l10n.getAttributes(textBox).id,
"Mozilla API key status loaded"
);
return content.document.l10n.getAttributes(textBox).id;
}
);
ok(keyMozillaStatus, "Mozilla API key status shown");
}
);
});

Просмотреть файл

@ -17,4 +17,3 @@ add_task(async function checkIdentityOfAboutSupport() {
is(identityBox.className, "chromeUI", "Should know that we're chrome.");
gBrowser.removeTab(tab);
});

Просмотреть файл

@ -10,11 +10,13 @@ add_task(async function checkSwitchPageToOnlineMode() {
// Tests always connect to localhost, and per bug 87717, localhost is now
// reachable in offline mode. To avoid this, disable any proxy.
let proxyPrefValue = SpecialPowers.getIntPref("network.proxy.type");
await SpecialPowers.pushPrefEnv({"set": [
["network.proxy.type", 0],
["browser.cache.disk.enable", false],
["browser.cache.memory.enable", false],
]});
await SpecialPowers.pushPrefEnv({
set: [
["network.proxy.type", 0],
["browser.cache.disk.enable", false],
["browser.cache.memory.enable", false],
],
});
await BrowserTestUtils.withNewTab("about:blank", async function(browser) {
let netErrorLoaded = BrowserTestUtils.waitForErrorPage(browser);
@ -24,17 +26,29 @@ add_task(async function checkSwitchPageToOnlineMode() {
// Re-enable the proxy so example.com is resolved to localhost, rather than
// the actual example.com.
await SpecialPowers.pushPrefEnv({"set": [["network.proxy.type", proxyPrefValue]]});
let changeObserved = TestUtils.topicObserved("network:offline-status-changed");
await SpecialPowers.pushPrefEnv({
set: [["network.proxy.type", proxyPrefValue]],
});
let changeObserved = TestUtils.topicObserved(
"network:offline-status-changed"
);
// Click on the 'Try again' button.
await ContentTask.spawn(browser, null, async function() {
ok(content.document.documentURI.startsWith("about:neterror?e=netOffline"), "Should be showing error page");
content.document.querySelector("#netErrorButtonContainer > .try-again").click();
ok(
content.document.documentURI.startsWith("about:neterror?e=netOffline"),
"Should be showing error page"
);
content.document
.querySelector("#netErrorButtonContainer > .try-again")
.click();
});
await changeObserved;
ok(!Services.io.offline, "After clicking the 'Try Again' button, we're back online.");
ok(
!Services.io.offline,
"After clicking the 'Try Again' button, we're back online."
);
});
});

Просмотреть файл

@ -5,8 +5,9 @@ XPCOMUtils.defineLazyModuleGetters(this, {
});
function getSecurityInfo(securityInfoAsString) {
const serhelper = Cc["@mozilla.org/network/serialization-helper;1"]
.getService(Ci.nsISerializationHelper);
const serhelper = Cc[
"@mozilla.org/network/serialization-helper;1"
].getService(Ci.nsISerializationHelper);
let securityInfo = serhelper.deserializeObject(securityInfoAsString);
securityInfo.QueryInterface(Ci.nsITransportSecurityInfo);
return securityInfo;
@ -35,28 +36,42 @@ function getPEMString(cert) {
// Wrap the Base64 string into lines of 64 characters,
// with CRLF line breaks (as specified in RFC 1421).
var wrapped = derb64.replace(/(\S{64}(?!$))/g, "$1\r\n");
return "-----BEGIN CERTIFICATE-----\r\n"
+ wrapped
+ "\r\n-----END CERTIFICATE-----\r\n";
return (
"-----BEGIN CERTIFICATE-----\r\n" +
wrapped +
"\r\n-----END CERTIFICATE-----\r\n"
);
}
function injectErrorPageFrame(tab, src) {
return ContentTask.spawn(tab.linkedBrowser, {frameSrc: src}, async function({frameSrc}) {
let loaded = ContentTaskUtils.waitForEvent(content.wrappedJSObject, "DOMFrameContentLoaded");
let iframe = content.document.createElement("iframe");
iframe.src = frameSrc;
content.document.body.appendChild(iframe);
await loaded;
// We will have race conditions when accessing the frame content after setting a src,
// so we can't wait for AboutNetErrorLoad. Let's wait for the certerror class to
// appear instead (which should happen at the same time as AboutNetErrorLoad).
await ContentTaskUtils.waitForCondition(() =>
iframe.contentDocument.body.classList.contains("certerror"));
});
return ContentTask.spawn(
tab.linkedBrowser,
{ frameSrc: src },
async function({ frameSrc }) {
let loaded = ContentTaskUtils.waitForEvent(
content.wrappedJSObject,
"DOMFrameContentLoaded"
);
let iframe = content.document.createElement("iframe");
iframe.src = frameSrc;
content.document.body.appendChild(iframe);
await loaded;
// We will have race conditions when accessing the frame content after setting a src,
// so we can't wait for AboutNetErrorLoad. Let's wait for the certerror class to
// appear instead (which should happen at the same time as AboutNetErrorLoad).
await ContentTaskUtils.waitForCondition(() =>
iframe.contentDocument.body.classList.contains("certerror")
);
}
);
}
async function openErrorPage(src, useFrame) {
let dummyPage = getRootDirectory(gTestPath).replace("chrome://mochitests/content", "https://example.com") + "dummy_page.html";
let dummyPage =
getRootDirectory(gTestPath).replace(
"chrome://mochitests/content",
"https://example.com"
) + "dummy_page.html";
let tab;
if (useFrame) {
@ -65,11 +80,15 @@ async function openErrorPage(src, useFrame) {
await injectErrorPageFrame(tab, src);
} else {
let certErrorLoaded;
tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, () => {
gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, src);
let browser = gBrowser.selectedBrowser;
certErrorLoaded = BrowserTestUtils.waitForErrorPage(browser);
}, false);
tab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
() => {
gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, src);
let browser = gBrowser.selectedBrowser;
certErrorLoaded = BrowserTestUtils.waitForErrorPage(browser);
},
false
);
info("Loading and waiting for the cert error");
await certErrorLoaded;
}
@ -97,7 +116,10 @@ function waitForCondition(condition, nextTest, errorMsg, retryTimes) {
}
tries++;
}, 100);
var moveOn = function() { clearInterval(interval); nextTest(); };
var moveOn = function() {
clearInterval(interval);
nextTest();
};
}
function whenTabLoaded(aTab, aCallback) {
@ -137,8 +159,9 @@ function promiseTabLoadEvent(tab, url) {
let loaded = BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, handle);
if (url)
if (url) {
BrowserTestUtils.loadURI(tab.linkedBrowser, url);
}
return loaded;
}
@ -149,9 +172,14 @@ function promiseTabLoadEvent(tab, url) {
function promiseContentSearchChange(browser, newEngineName) {
return ContentTask.spawn(browser, { newEngineName }, async function(args) {
return new Promise(resolve => {
content.addEventListener("ContentSearchService", function listener(aEvent) {
if (aEvent.detail.type == "CurrentState" &&
content.wrappedJSObject.gContentSearchController.defaultEngine.name == args.newEngineName) {
content.addEventListener("ContentSearchService", function listener(
aEvent
) {
if (
aEvent.detail.type == "CurrentState" &&
content.wrappedJSObject.gContentSearchController.defaultEngine.name ==
args.newEngineName
) {
content.removeEventListener("ContentSearchService", listener);
resolve();
}
@ -178,7 +206,9 @@ async function promiseNewEngine(basename) {
registerCleanupFunction(async () => {
try {
await Services.search.removeEngine(engine);
} catch (ex) { /* Can't remove the engine more than once */ }
} catch (ex) {
/* Can't remove the engine more than once */
}
});
return engine;

Просмотреть файл

@ -1,9 +1,11 @@
"use strict";
const {PlacesTestUtils} =
ChromeUtils.import("resource://testing-common/PlacesTestUtils.jsm");
const { PlacesTestUtils } = ChromeUtils.import(
"resource://testing-common/PlacesTestUtils.jsm"
);
let notificationURL = "http://example.org/browser/browser/base/content/test/alerts/file_dom_notifications.html";
let notificationURL =
"http://example.org/browser/browser/base/content/test/alerts/file_dom_notifications.html";
let oldShowFavicons;
add_task(async function test_notificationClose() {
@ -15,52 +17,83 @@ add_task(async function test_notificationClose() {
await PlacesTestUtils.addVisits(notificationURI);
let faviconURI = await new Promise(resolve => {
let uri =
makeURI("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVQI12P4//8/AAX+Av7czFnnAAAAAElFTkSuQmCC");
PlacesUtils.favicons.setAndFetchFaviconForPage(notificationURI, uri,
true, PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE,
(uriResult) => resolve(uriResult),
Services.scriptSecurityManager.getSystemPrincipal());
let uri = makeURI(
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVQI12P4//8/AAX+Av7czFnnAAAAAElFTkSuQmCC"
);
PlacesUtils.favicons.setAndFetchFaviconForPage(
notificationURI,
uri,
true,
PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE,
uriResult => resolve(uriResult),
Services.scriptSecurityManager.getSystemPrincipal()
);
});
await BrowserTestUtils.withNewTab({
gBrowser,
url: notificationURL,
}, async function dummyTabTask(aBrowser) {
await openNotification(aBrowser, "showNotification2");
await BrowserTestUtils.withNewTab(
{
gBrowser,
url: notificationURL,
},
async function dummyTabTask(aBrowser) {
await openNotification(aBrowser, "showNotification2");
info("Notification alert showing");
info("Notification alert showing");
let alertWindow = Services.wm.getMostRecentWindow("alert:alert");
if (!alertWindow) {
ok(true, "Notifications don't use XUL windows on all platforms.");
await closeNotification(aBrowser);
return;
let alertWindow = Services.wm.getMostRecentWindow("alert:alert");
if (!alertWindow) {
ok(true, "Notifications don't use XUL windows on all platforms.");
await closeNotification(aBrowser);
return;
}
let alertTitleLabel = alertWindow.document.getElementById(
"alertTitleLabel"
);
is(
alertTitleLabel.value,
"Test title",
"Title text of notification should be present"
);
let alertTextLabel = alertWindow.document.getElementById(
"alertTextLabel"
);
is(
alertTextLabel.textContent,
"Test body 2",
"Body text of notification should be present"
);
let alertIcon = alertWindow.document.getElementById("alertIcon");
is(
alertIcon.src,
faviconURI.spec,
"Icon of notification should be present"
);
let alertCloseButton = alertWindow.document.querySelector(".close-icon");
is(alertCloseButton.localName, "toolbarbutton", "close button found");
let promiseBeforeUnloadEvent = BrowserTestUtils.waitForEvent(
alertWindow,
"beforeunload"
);
let closedTime = alertWindow.Date.now();
alertCloseButton.click();
info("Clicked on close button");
await promiseBeforeUnloadEvent;
ok(true, "Alert should close when the close button is clicked");
let currentTime = alertWindow.Date.now();
// The notification will self-close at 12 seconds, so this checks
// that the notification closed before the timeout.
ok(
currentTime - closedTime < 5000,
"Close requested at " +
closedTime +
", actually closed at " +
currentTime
);
}
let alertTitleLabel = alertWindow.document.getElementById("alertTitleLabel");
is(alertTitleLabel.value, "Test title", "Title text of notification should be present");
let alertTextLabel = alertWindow.document.getElementById("alertTextLabel");
is(alertTextLabel.textContent, "Test body 2", "Body text of notification should be present");
let alertIcon = alertWindow.document.getElementById("alertIcon");
is(alertIcon.src, faviconURI.spec, "Icon of notification should be present");
let alertCloseButton = alertWindow.document.querySelector(".close-icon");
is(alertCloseButton.localName, "toolbarbutton", "close button found");
let promiseBeforeUnloadEvent =
BrowserTestUtils.waitForEvent(alertWindow, "beforeunload");
let closedTime = alertWindow.Date.now();
alertCloseButton.click();
info("Clicked on close button");
await promiseBeforeUnloadEvent;
ok(true, "Alert should close when the close button is clicked");
let currentTime = alertWindow.Date.now();
// The notification will self-close at 12 seconds, so this checks
// that the notification closed before the timeout.
ok(currentTime - closedTime < 5000,
"Close requested at " + closedTime + ", actually closed at " + currentTime);
});
);
});
add_task(async function cleanup() {

Просмотреть файл

@ -1,11 +1,12 @@
"use strict";
var tab;
var notificationURL = "http://example.org/browser/browser/base/content/test/alerts/file_dom_notifications.html";
var notificationURL =
"http://example.org/browser/browser/base/content/test/alerts/file_dom_notifications.html";
const ALERT_SERVICE = Cc["@mozilla.org/alerts-service;1"]
.getService(Ci.nsIAlertsService)
.QueryInterface(Ci.nsIAlertsDoNotDisturb);
.getService(Ci.nsIAlertsService)
.QueryInterface(Ci.nsIAlertsDoNotDisturb);
function test() {
waitForExplicitFinish();
@ -16,7 +17,10 @@ function test() {
ALERT_SERVICE.manualDoNotDisturb;
ok(true, "Alert service implements do-not-disturb interface");
} catch (e) {
ok(true, "Alert service doesn't implement do-not-disturb interface, exiting test");
ok(
true,
"Alert service doesn't implement do-not-disturb interface, exiting test"
);
finish();
return;
}
@ -27,9 +31,11 @@ function test() {
window.restore();
});
// Make sure that do-not-disturb is not enabled.
ok(!ALERT_SERVICE.manualDoNotDisturb, "Alert service should not be disabled when test starts");
ok(
!ALERT_SERVICE.manualDoNotDisturb,
"Alert service should not be disabled when test starts"
);
ALERT_SERVICE.manualDoNotDisturb = false;
addNotificationPermission(notificationURL).then(function openTab() {
@ -52,7 +58,9 @@ function onAlertShowing() {
closeNotification(tab.linkedBrowser).then(finish);
return;
}
let doNotDisturbMenuItem = alertWindow.document.getElementById("doNotDisturbMenuItem");
let doNotDisturbMenuItem = alertWindow.document.getElementById(
"doNotDisturbMenuItem"
);
is(doNotDisturbMenuItem.localName, "menuitem", "menuitem found");
alertWindow.addEventListener("beforeunload", onAlertClosing);
doNotDisturbMenuItem.click();
@ -62,14 +70,19 @@ function onAlertShowing() {
function onAlertClosing(event) {
event.target.removeEventListener("beforeunload", onAlertClosing);
ok(ALERT_SERVICE.manualDoNotDisturb, "Alert service should be disabled after clicking menuitem");
ok(
ALERT_SERVICE.manualDoNotDisturb,
"Alert service should be disabled after clicking menuitem"
);
// The notification should not appear, but there is
// no way from the client-side to know that it was
// blocked, except for waiting some time and realizing
// that the "onshow" event never fired.
openNotification(tab.linkedBrowser, "showNotification2", 2000)
.then(onAlert2Showing, finish);
openNotification(tab.linkedBrowser, "showNotification2", 2000).then(
onAlert2Showing,
finish
);
}
function onAlert2Showing() {

Просмотреть файл

@ -1,60 +1,80 @@
"use strict";
var notificationURL = "http://example.org/browser/browser/base/content/test/alerts/file_dom_notifications.html";
var notificationURL =
"http://example.org/browser/browser/base/content/test/alerts/file_dom_notifications.html";
var expectedURL = "about:preferences#privacy";
add_task(async function test_settingsOpen_observer() {
info("Opening a dummy tab so openPreferences=>switchToTabHavingURI doesn't use the blank tab.");
await BrowserTestUtils.withNewTab({
gBrowser,
url: "about:robots",
}, async function dummyTabTask(aBrowser) {
// Ensure preferences is loaded before removing the tab.
let syncPaneLoadedPromise = TestUtils.topicObserved("sync-pane-loaded", () => true);
let tabPromise = BrowserTestUtils.waitForNewTab(gBrowser, expectedURL);
info("simulate a notifications-open-settings notification");
let uri = NetUtil.newURI("https://example.com");
let principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {});
Services.obs.notifyObservers(principal, "notifications-open-settings");
let tab = await tabPromise;
ok(tab, "The notification settings tab opened");
await syncPaneLoadedPromise;
BrowserTestUtils.removeTab(tab);
});
info(
"Opening a dummy tab so openPreferences=>switchToTabHavingURI doesn't use the blank tab."
);
await BrowserTestUtils.withNewTab(
{
gBrowser,
url: "about:robots",
},
async function dummyTabTask(aBrowser) {
// Ensure preferences is loaded before removing the tab.
let syncPaneLoadedPromise = TestUtils.topicObserved(
"sync-pane-loaded",
() => true
);
let tabPromise = BrowserTestUtils.waitForNewTab(gBrowser, expectedURL);
info("simulate a notifications-open-settings notification");
let uri = NetUtil.newURI("https://example.com");
let principal = Services.scriptSecurityManager.createCodebasePrincipal(
uri,
{}
);
Services.obs.notifyObservers(principal, "notifications-open-settings");
let tab = await tabPromise;
ok(tab, "The notification settings tab opened");
await syncPaneLoadedPromise;
BrowserTestUtils.removeTab(tab);
}
);
});
add_task(async function test_settingsOpen_button() {
info("Adding notification permission");
await addNotificationPermission(notificationURL);
await BrowserTestUtils.withNewTab({
gBrowser,
url: notificationURL,
}, async function tabTask(aBrowser) {
// Ensure preferences is loaded before removing the tab.
let syncPaneLoadedPromise = TestUtils.topicObserved("sync-pane-loaded", () => true);
await BrowserTestUtils.withNewTab(
{
gBrowser,
url: notificationURL,
},
async function tabTask(aBrowser) {
// Ensure preferences is loaded before removing the tab.
let syncPaneLoadedPromise = TestUtils.topicObserved(
"sync-pane-loaded",
() => true
);
info("Waiting for notification");
await openNotification(aBrowser, "showNotification2");
info("Waiting for notification");
await openNotification(aBrowser, "showNotification2");
let alertWindow = Services.wm.getMostRecentWindow("alert:alert");
if (!alertWindow) {
ok(true, "Notifications don't use XUL windows on all platforms.");
await closeNotification(aBrowser);
return;
let alertWindow = Services.wm.getMostRecentWindow("alert:alert");
if (!alertWindow) {
ok(true, "Notifications don't use XUL windows on all platforms.");
await closeNotification(aBrowser);
return;
}
let closePromise = promiseWindowClosed(alertWindow);
let tabPromise = BrowserTestUtils.waitForNewTab(gBrowser, expectedURL);
let openSettingsMenuItem = alertWindow.document.getElementById(
"openSettingsMenuItem"
);
openSettingsMenuItem.click();
info("Waiting for notification settings tab");
let tab = await tabPromise;
ok(tab, "The notification settings tab opened");
await syncPaneLoadedPromise;
await closePromise;
BrowserTestUtils.removeTab(tab);
}
let closePromise = promiseWindowClosed(alertWindow);
let tabPromise = BrowserTestUtils.waitForNewTab(gBrowser, expectedURL);
let openSettingsMenuItem = alertWindow.document.getElementById("openSettingsMenuItem");
openSettingsMenuItem.click();
info("Waiting for notification settings tab");
let tab = await tabPromise;
ok(tab, "The notification settings tab opened");
await syncPaneLoadedPromise;
await closePromise;
BrowserTestUtils.removeTab(tab);
});
);
});

Просмотреть файл

@ -1,7 +1,8 @@
"use strict";
var tab;
var notificationURL = "http://example.org/browser/browser/base/content/test/alerts/file_dom_notifications.html";
var notificationURL =
"http://example.org/browser/browser/base/content/test/alerts/file_dom_notifications.html";
var alertWindowClosed = false;
var permRemoved = false;
@ -33,9 +34,16 @@ function onAlertShowing() {
closeNotification(tab.linkedBrowser).then(finish);
return;
}
ok(Services.perms.testExactPermission(makeURI(notificationURL), "desktop-notification"),
"Permission should exist prior to removal");
let disableForOriginMenuItem = alertWindow.document.getElementById("disableForOriginMenuItem");
ok(
Services.perms.testExactPermission(
makeURI(notificationURL),
"desktop-notification"
),
"Permission should exist prior to removal"
);
let disableForOriginMenuItem = alertWindow.document.getElementById(
"disableForOriginMenuItem"
);
is(disableForOriginMenuItem.localName, "menuitem", "menuitem found");
Services.obs.addObserver(permObserver, "perm-changed");
alertWindow.addEventListener("beforeunload", onAlertClosing);
@ -49,7 +57,11 @@ function permObserver(subject, topic, data) {
}
let permission = subject.QueryInterface(Ci.nsIPermission);
is(permission.type, "desktop-notification", "desktop-notification permission changed");
is(
permission.type,
"desktop-notification",
"desktop-notification permission changed"
);
is(data, "deleted", "desktop-notification permission deleted");
Services.obs.removeObserver(permObserver, "perm-changed");

Просмотреть файл

@ -1,33 +1,65 @@
"use strict";
let notificationURL = "http://example.org/browser/browser/base/content/test/alerts/file_dom_notifications.html";
let notificationURL =
"http://example.org/browser/browser/base/content/test/alerts/file_dom_notifications.html";
add_task(async function test_notificationReplace() {
await addNotificationPermission(notificationURL);
await BrowserTestUtils.withNewTab({
gBrowser,
url: notificationURL,
}, async function dummyTabTask(aBrowser) {
await ContentTask.spawn(aBrowser, {}, async function() {
let win = content.window.wrappedJSObject;
let notification = win.showNotification1();
let promiseCloseEvent = ContentTaskUtils.waitForEvent(notification, "close");
await BrowserTestUtils.withNewTab(
{
gBrowser,
url: notificationURL,
},
async function dummyTabTask(aBrowser) {
await ContentTask.spawn(aBrowser, {}, async function() {
let win = content.window.wrappedJSObject;
let notification = win.showNotification1();
let promiseCloseEvent = ContentTaskUtils.waitForEvent(
notification,
"close"
);
let showEvent = await ContentTaskUtils.waitForEvent(notification, "show");
Assert.equal(showEvent.target.body, "Test body 1", "Showed tagged notification");
let showEvent = await ContentTaskUtils.waitForEvent(
notification,
"show"
);
Assert.equal(
showEvent.target.body,
"Test body 1",
"Showed tagged notification"
);
let newNotification = win.showNotification2();
let newShowEvent = await ContentTaskUtils.waitForEvent(newNotification, "show");
Assert.equal(newShowEvent.target.body, "Test body 2", "Showed new notification with same tag");
let newNotification = win.showNotification2();
let newShowEvent = await ContentTaskUtils.waitForEvent(
newNotification,
"show"
);
Assert.equal(
newShowEvent.target.body,
"Test body 2",
"Showed new notification with same tag"
);
let closeEvent = await promiseCloseEvent;
Assert.equal(closeEvent.target.body, "Test body 1", "Closed previous tagged notification");
let closeEvent = await promiseCloseEvent;
Assert.equal(
closeEvent.target.body,
"Test body 1",
"Closed previous tagged notification"
);
let promiseNewCloseEvent = ContentTaskUtils.waitForEvent(newNotification, "close");
newNotification.close();
let newCloseEvent = await promiseNewCloseEvent;
Assert.equal(newCloseEvent.target.body, "Test body 2", "Closed new notification");
});
});
let promiseNewCloseEvent = ContentTaskUtils.waitForEvent(
newNotification,
"close"
);
newNotification.close();
let newCloseEvent = await promiseNewCloseEvent;
Assert.equal(
newCloseEvent.target.body,
"Test body 2",
"Closed new notification"
);
});
}
);
});

Просмотреть файл

@ -6,71 +6,101 @@
var tab;
var notification;
var notificationURL = "http://example.org/browser/browser/base/content/test/alerts/file_dom_notifications.html";
var notificationURL =
"http://example.org/browser/browser/base/content/test/alerts/file_dom_notifications.html";
var newWindowOpenedFromTab;
add_task(async function test_notificationPreventDefaultAndSwitchTabs() {
await addNotificationPermission(notificationURL);
let originalTab = gBrowser.selectedTab;
await BrowserTestUtils.withNewTab({
gBrowser,
url: notificationURL,
}, async function dummyTabTask(aBrowser) {
// Put new tab in background so it is obvious when it is re-focused.
await BrowserTestUtils.switchTab(gBrowser, originalTab);
isnot(gBrowser.selectedBrowser, aBrowser, "Notification page loaded as a background tab");
await BrowserTestUtils.withNewTab(
{
gBrowser,
url: notificationURL,
},
async function dummyTabTask(aBrowser) {
// Put new tab in background so it is obvious when it is re-focused.
await BrowserTestUtils.switchTab(gBrowser, originalTab);
isnot(
gBrowser.selectedBrowser,
aBrowser,
"Notification page loaded as a background tab"
);
// First, show a notification that will be have the tab-switching prevented.
function promiseNotificationEvent(evt) {
return ContentTask.spawn(aBrowser, evt, async function(contentEvt) {
return new Promise(resolve => {
let contentNotification = content.wrappedJSObject._notification;
contentNotification.addEventListener(contentEvt, function(event) {
resolve({ defaultPrevented: event.defaultPrevented });
}, {once: true});
// First, show a notification that will be have the tab-switching prevented.
function promiseNotificationEvent(evt) {
return ContentTask.spawn(aBrowser, evt, async function(contentEvt) {
return new Promise(resolve => {
let contentNotification = content.wrappedJSObject._notification;
contentNotification.addEventListener(
contentEvt,
function(event) {
resolve({ defaultPrevented: event.defaultPrevented });
},
{ once: true }
);
});
});
}
await openNotification(aBrowser, "showNotification1");
info("Notification alert showing");
let alertWindow = Services.wm.getMostRecentWindow("alert:alert");
if (!alertWindow) {
ok(true, "Notifications don't use XUL windows on all platforms.");
await closeNotification(aBrowser);
return;
}
info("Clicking on notification");
let promiseClickEvent = promiseNotificationEvent("click");
// NB: This executeSoon is needed to allow the non-e10s runs of this test
// a chance to set the event listener on the page. Otherwise, we
// synchronously fire the click event before we listen for the event.
executeSoon(() => {
EventUtils.synthesizeMouseAtCenter(
alertWindow.document.getElementById("alertTitleLabel"),
{},
alertWindow
);
});
}
await openNotification(aBrowser, "showNotification1");
info("Notification alert showing");
let alertWindow = Services.wm.getMostRecentWindow("alert:alert");
if (!alertWindow) {
ok(true, "Notifications don't use XUL windows on all platforms.");
let clickEvent = await promiseClickEvent;
ok(
clickEvent.defaultPrevented,
"The event handler for the first notification cancels the event"
);
isnot(
gBrowser.selectedBrowser,
aBrowser,
"Notification page still a background tab"
);
let notificationClosed = promiseNotificationEvent("close");
await closeNotification(aBrowser);
return;
await notificationClosed;
// Second, show a notification that will cause the tab to get switched.
await openNotification(aBrowser, "showNotification2");
alertWindow = Services.wm.getMostRecentWindow("alert:alert");
let promiseTabSelect = BrowserTestUtils.waitForEvent(
gBrowser.tabContainer,
"TabSelect"
);
EventUtils.synthesizeMouseAtCenter(
alertWindow.document.getElementById("alertTitleLabel"),
{},
alertWindow
);
await promiseTabSelect;
is(
gBrowser.selectedBrowser.currentURI.spec,
notificationURL,
"Clicking on the second notification should select its originating tab"
);
notificationClosed = promiseNotificationEvent("close");
await closeNotification(aBrowser);
await notificationClosed;
}
info("Clicking on notification");
let promiseClickEvent = promiseNotificationEvent("click");
// NB: This executeSoon is needed to allow the non-e10s runs of this test
// a chance to set the event listener on the page. Otherwise, we
// synchronously fire the click event before we listen for the event.
executeSoon(() => {
EventUtils.synthesizeMouseAtCenter(alertWindow.document.getElementById("alertTitleLabel"),
{}, alertWindow);
});
let clickEvent = await promiseClickEvent;
ok(clickEvent.defaultPrevented, "The event handler for the first notification cancels the event");
isnot(gBrowser.selectedBrowser, aBrowser, "Notification page still a background tab");
let notificationClosed = promiseNotificationEvent("close");
await closeNotification(aBrowser);
await notificationClosed;
// Second, show a notification that will cause the tab to get switched.
await openNotification(aBrowser, "showNotification2");
alertWindow = Services.wm.getMostRecentWindow("alert:alert");
let promiseTabSelect = BrowserTestUtils.waitForEvent(gBrowser.tabContainer, "TabSelect");
EventUtils.synthesizeMouseAtCenter(alertWindow.document.getElementById("alertTitleLabel"),
{},
alertWindow);
await promiseTabSelect;
is(gBrowser.selectedBrowser.currentURI.spec, notificationURL,
"Clicking on the second notification should select its originating tab");
notificationClosed = promiseNotificationEvent("close");
await closeNotification(aBrowser);
await notificationClosed;
});
);
});
add_task(async function cleanup() {

Просмотреть файл

@ -1,10 +1,15 @@
async function addNotificationPermission(originString) {
return new Promise(resolve => {
SpecialPowers.pushPermissions([{
type: "desktop-notification",
allow: true,
context: originString,
}], resolve);
SpecialPowers.pushPermissions(
[
{
type: "desktop-notification",
allow: true,
context: originString,
},
],
resolve
);
});
}
@ -33,7 +38,10 @@ function promiseWindowClosed(window) {
*/
function openNotification(aBrowser, fn, timeout) {
info(`openNotification: ${fn}`);
return ContentTask.spawn(aBrowser, [fn, timeout], async function([contentFn, contentTimeout]) {
return ContentTask.spawn(aBrowser, [fn, timeout], async function([
contentFn,
contentTimeout,
]) {
await new Promise((resolve, reject) => {
let win = content.wrappedJSObject;
let notification = win[contentFn]();

Просмотреть файл

@ -43,28 +43,30 @@ add_task(async function test_deserialize_principal_with_csp() {
let serializedPrincipalsFromFirefox = [
{
"input": "ZT4OTT7kRfqycpfCC8AeuAAAAAAAAAAAwAAAAAAAAEYB3pRy0IA0EdOTmQAQS6D9QJIHOlRteE8wkTq4cYEyCMYAAAAC/////wAAAbsBAAAAHmh0dHBzOi8vd3d3Lm1vemlsbGEub3JnL2VuLVVTLwAAAAAAAAAFAAAACAAAAA8AAAAA/////wAAAAD/////AAAACAAAAA8AAAAXAAAABwAAABcAAAAHAAAAFwAAAAcAAAAeAAAAAAAAAAD/////AAAAAP////8AAAAA/////wAAAAD/////AQAAAAAAAAAAAAAAAQnZ7Rrl1EAEv+Anzrkj2ayzxMCuvV5MrYfgjSENuz+fAd6UctCANBHTk5kAEEug/UCSBzpUbXhPMJE6uHGBMgjGAAAAAv////8AAAG7AQAAAB5odHRwczovL3d3dy5tb3ppbGxhLm9yZy9lbi1VUy8AAAAAAAAABQAAAAgAAAAPAAAAAP////8AAAAA/////wAAAAgAAAAPAAAAFwAAAAcAAAAXAAAABwAAABcAAAAHAAAAHgAAAAAAAAAA/////wAAAAD/////AAAAAP////8AAAAA/////wEAAAAAAAAAAAABAAAFtgBzAGMAcgBpAHAAdAAtAHMAcgBjACAAJwBzAGUAbABmACcAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBuAGUAdAAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AYwBvAG0AIAAnAHUAbgBzAGEAZgBlAC0AaQBuAGwAaQBuAGUAJwAgACcAdQBuAHMAYQBmAGUALQBlAHYAYQBsACcAIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgBnAG8AbwBnAGwAZQB0AGEAZwBtAGEAbgBhAGcAZQByAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgBnAG8AbwBnAGwAZQAtAGEAbgBhAGwAeQB0AGkAYwBzAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdABhAGcAbQBhAG4AYQBnAGUAcgAuAGcAbwBvAGcAbABlAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgB5AG8AdQB0AHUAYgBlAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AcwAuAHkAdABpAG0AZwAuAGMAbwBtADsAIABpAG0AZwAtAHMAcgBjACAAJwBzAGUAbABmACcAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBuAGUAdAAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AYwBvAG0AIABkAGEAdABhADoAIABoAHQAdABwAHMAOgAvAC8AbQBvAHoAaQBsAGwAYQAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUAdABhAGcAbQBhAG4AYQBnAGUAcgAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUALQBhAG4AYQBsAHkAdABpAGMAcwAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAGEAZABzAGUAcgB2AGkAYwBlAC4AZwBvAG8AZwBsAGUALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwBhAGQAcwBlAHIAdgBpAGMAZQAuAGcAbwBvAGcAbABlAC4AZABlACAAaAB0AHQAcABzADoALwAvAGEAZABzAGUAcgB2AGkAYwBlAC4AZwBvAG8AZwBsAGUALgBkAGsAIABoAHQAdABwAHMAOgAvAC8AYwByAGUAYQB0AGkAdgBlAGMAbwBtAG0AbwBuAHMALgBvAHIAZwAgAGgAdAB0AHAAcwA6AC8ALwBhAGQALgBkAG8AdQBiAGwAZQBjAGwAaQBjAGsALgBuAGUAdAA7ACAAZABlAGYAYQB1AGwAdAAtAHMAcgBjACAAJwBzAGUAbABmACcAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBuAGUAdAAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AYwBvAG0AOwAgAGYAcgBhAG0AZQAtAHMAcgBjACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUAdABhAGcAbQBhAG4AYQBnAGUAcgAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUALQBhAG4AYQBsAHkAdABpAGMAcwAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AeQBvAHUAdAB1AGIAZQAtAG4AbwBjAG8AbwBrAGkAZQAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHQAcgBhAGMAawBlAHIAdABlAHMAdAAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AcwB1AHIAdgBlAHkAZwBpAHoAbQBvAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AYQBjAGMAbwB1AG4AdABzAC4AZgBpAHIAZQBmAG8AeAAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAGEAYwBjAG8AdQBuAHQAcwAuAGYAaQByAGUAZgBvAHgALgBjAG8AbQAuAGMAbgAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAHkAbwB1AHQAdQBiAGUALgBjAG8AbQA7ACAAcwB0AHkAbABlAC0AcwByAGMAIAAnAHMAZQBsAGYAJwAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAG4AZQB0ACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AbwByAGcAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBjAG8AbQAgACcAdQBuAHMAYQBmAGUALQBpAG4AbABpAG4AZQAnADsAIABjAG8AbgBuAGUAYwB0AC0AcwByAGMAIAAnAHMAZQBsAGYAJwAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAG4AZQB0ACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AbwByAGcAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAGcAbwBvAGcAbABlAHQAYQBnAG0AYQBuAGEAZwBlAHIALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAGcAbwBvAGcAbABlAC0AYQBuAGEAbAB5AHQAaQBjAHMALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwBhAGMAYwBvAHUAbgB0AHMALgBmAGkAcgBlAGYAbwB4AC4AYwBvAG0ALwAgAGgAdAB0AHAAcwA6AC8ALwBhAGMAYwBvAHUAbgB0AHMALgBmAGkAcgBlAGYAbwB4AC4AYwBvAG0ALgBjAG4ALwA7ACAAYwBoAGkAbABkAC0AcwByAGMAIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgBnAG8AbwBnAGwAZQB0AGEAZwBtAGEAbgBhAGcAZQByAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgBnAG8AbwBnAGwAZQAtAGEAbgBhAGwAeQB0AGkAYwBzAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgB5AG8AdQB0AHUAYgBlAC0AbgBvAGMAbwBvAGsAaQBlAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdAByAGEAYwBrAGUAcgB0AGUAcwB0AC4AbwByAGcAIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgBzAHUAcgB2AGUAeQBnAGkAegBtAG8ALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwBhAGMAYwBvAHUAbgB0AHMALgBmAGkAcgBlAGYAbwB4AC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AYQBjAGMAbwB1AG4AdABzAC4AZgBpAHIAZQBmAG8AeAAuAGMAbwBtAC4AYwBuACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AeQBvAHUAdAB1AGIAZQAuAGMAbwBtAAA=",
"output": {
input:
"ZT4OTT7kRfqycpfCC8AeuAAAAAAAAAAAwAAAAAAAAEYB3pRy0IA0EdOTmQAQS6D9QJIHOlRteE8wkTq4cYEyCMYAAAAC/////wAAAbsBAAAAHmh0dHBzOi8vd3d3Lm1vemlsbGEub3JnL2VuLVVTLwAAAAAAAAAFAAAACAAAAA8AAAAA/////wAAAAD/////AAAACAAAAA8AAAAXAAAABwAAABcAAAAHAAAAFwAAAAcAAAAeAAAAAAAAAAD/////AAAAAP////8AAAAA/////wAAAAD/////AQAAAAAAAAAAAAAAAQnZ7Rrl1EAEv+Anzrkj2ayzxMCuvV5MrYfgjSENuz+fAd6UctCANBHTk5kAEEug/UCSBzpUbXhPMJE6uHGBMgjGAAAAAv////8AAAG7AQAAAB5odHRwczovL3d3dy5tb3ppbGxhLm9yZy9lbi1VUy8AAAAAAAAABQAAAAgAAAAPAAAAAP////8AAAAA/////wAAAAgAAAAPAAAAFwAAAAcAAAAXAAAABwAAABcAAAAHAAAAHgAAAAAAAAAA/////wAAAAD/////AAAAAP////8AAAAA/////wEAAAAAAAAAAAABAAAFtgBzAGMAcgBpAHAAdAAtAHMAcgBjACAAJwBzAGUAbABmACcAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBuAGUAdAAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AYwBvAG0AIAAnAHUAbgBzAGEAZgBlAC0AaQBuAGwAaQBuAGUAJwAgACcAdQBuAHMAYQBmAGUALQBlAHYAYQBsACcAIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgBnAG8AbwBnAGwAZQB0AGEAZwBtAGEAbgBhAGcAZQByAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgBnAG8AbwBnAGwAZQAtAGEAbgBhAGwAeQB0AGkAYwBzAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdABhAGcAbQBhAG4AYQBnAGUAcgAuAGcAbwBvAGcAbABlAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgB5AG8AdQB0AHUAYgBlAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AcwAuAHkAdABpAG0AZwAuAGMAbwBtADsAIABpAG0AZwAtAHMAcgBjACAAJwBzAGUAbABmACcAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBuAGUAdAAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AYwBvAG0AIABkAGEAdABhADoAIABoAHQAdABwAHMAOgAvAC8AbQBvAHoAaQBsAGwAYQAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUAdABhAGcAbQBhAG4AYQBnAGUAcgAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUALQBhAG4AYQBsAHkAdABpAGMAcwAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAGEAZABzAGUAcgB2AGkAYwBlAC4AZwBvAG8AZwBsAGUALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwBhAGQAcwBlAHIAdgBpAGMAZQAuAGcAbwBvAGcAbABlAC4AZABlACAAaAB0AHQAcABzADoALwAvAGEAZABzAGUAcgB2AGkAYwBlAC4AZwBvAG8AZwBsAGUALgBkAGsAIABoAHQAdABwAHMAOgAvAC8AYwByAGUAYQB0AGkAdgBlAGMAbwBtAG0AbwBuAHMALgBvAHIAZwAgAGgAdAB0AHAAcwA6AC8ALwBhAGQALgBkAG8AdQBiAGwAZQBjAGwAaQBjAGsALgBuAGUAdAA7ACAAZABlAGYAYQB1AGwAdAAtAHMAcgBjACAAJwBzAGUAbABmACcAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBuAGUAdAAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AYwBvAG0AOwAgAGYAcgBhAG0AZQAtAHMAcgBjACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUAdABhAGcAbQBhAG4AYQBnAGUAcgAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUALQBhAG4AYQBsAHkAdABpAGMAcwAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AeQBvAHUAdAB1AGIAZQAtAG4AbwBjAG8AbwBrAGkAZQAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHQAcgBhAGMAawBlAHIAdABlAHMAdAAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AcwB1AHIAdgBlAHkAZwBpAHoAbQBvAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AYQBjAGMAbwB1AG4AdABzAC4AZgBpAHIAZQBmAG8AeAAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAGEAYwBjAG8AdQBuAHQAcwAuAGYAaQByAGUAZgBvAHgALgBjAG8AbQAuAGMAbgAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAHkAbwB1AHQAdQBiAGUALgBjAG8AbQA7ACAAcwB0AHkAbABlAC0AcwByAGMAIAAnAHMAZQBsAGYAJwAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAG4AZQB0ACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AbwByAGcAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBjAG8AbQAgACcAdQBuAHMAYQBmAGUALQBpAG4AbABpAG4AZQAnADsAIABjAG8AbgBuAGUAYwB0AC0AcwByAGMAIAAnAHMAZQBsAGYAJwAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAG4AZQB0ACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AbwByAGcAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAGcAbwBvAGcAbABlAHQAYQBnAG0AYQBuAGEAZwBlAHIALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAGcAbwBvAGcAbABlAC0AYQBuAGEAbAB5AHQAaQBjAHMALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwBhAGMAYwBvAHUAbgB0AHMALgBmAGkAcgBlAGYAbwB4AC4AYwBvAG0ALwAgAGgAdAB0AHAAcwA6AC8ALwBhAGMAYwBvAHUAbgB0AHMALgBmAGkAcgBlAGYAbwB4AC4AYwBvAG0ALgBjAG4ALwA7ACAAYwBoAGkAbABkAC0AcwByAGMAIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgBnAG8AbwBnAGwAZQB0AGEAZwBtAGEAbgBhAGcAZQByAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgBnAG8AbwBnAGwAZQAtAGEAbgBhAGwAeQB0AGkAYwBzAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgB5AG8AdQB0AHUAYgBlAC0AbgBvAGMAbwBvAGsAaQBlAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdAByAGEAYwBrAGUAcgB0AGUAcwB0AC4AbwByAGcAIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgBzAHUAcgB2AGUAeQBnAGkAegBtAG8ALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwBhAGMAYwBvAHUAbgB0AHMALgBmAGkAcgBlAGYAbwB4AC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AYQBjAGMAbwB1AG4AdABzAC4AZgBpAHIAZQBmAG8AeAAuAGMAbwBtAC4AYwBuACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AeQBvAHUAdAB1AGIAZQAuAGMAbwBtAAA=",
output: {
// Within Bug 965637 we removed CSP from Principals. Already serialized Principals however should still deserialize correctly (just without the CSP).
// "cspJSON": "{\"csp-policies\":[{\"child-src\":[\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://www.youtube-nocookie.com\",\"https://trackertest.org\",\"https://www.surveygizmo.com\",\"https://accounts.firefox.com\",\"https://accounts.firefox.com.cn\",\"https://www.youtube.com\"],\"connect-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://accounts.firefox.com/\",\"https://accounts.firefox.com.cn/\"],\"default-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\"],\"frame-src\":[\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://www.youtube-nocookie.com\",\"https://trackertest.org\",\"https://www.surveygizmo.com\",\"https://accounts.firefox.com\",\"https://accounts.firefox.com.cn\",\"https://www.youtube.com\"],\"img-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"data:\",\"https://mozilla.org\",\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://adservice.google.com\",\"https://adservice.google.de\",\"https://adservice.google.dk\",\"https://creativecommons.org\",\"https://ad.doubleclick.net\"],\"report-only\":false,\"script-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"'unsafe-inline'\",\"'unsafe-eval'\",\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://tagmanager.google.com\",\"https://www.youtube.com\",\"https://s.ytimg.com\"],\"style-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"'unsafe-inline'\"]}]}",
"URISpec": "https://www.mozilla.org/en-US/",
"originAttributes": {
"firstPartyDomain": "",
"inIsolatedMozBrowser": false,
"privateBrowsingId": 0,
"userContextId": 0,
URISpec: "https://www.mozilla.org/en-US/",
originAttributes: {
firstPartyDomain: "",
inIsolatedMozBrowser: false,
privateBrowsingId: 0,
userContextId: 0,
},
},
},
{
"input": "ZT4OTT7kRfqycpfCC8AeuAAAAAAAAAAAwAAAAAAAAEYB3pRy0IA0EdOTmQAQS6D9QJIHOlRteE8wkTq4cYEyCMYAAAAC/////wAAAbsBAAAAL2h0dHBzOi8vd3d3Lm1vemlsbGEub3JnL2VuLVVTL2ZpcmVmb3gvYWNjb3VudHMvAAAAAAAAAAUAAAAIAAAADwAAAAj/////AAAACP////8AAAAIAAAADwAAABcAAAAYAAAAFwAAABgAAAAXAAAAGAAAAC8AAAAAAAAAL/////8AAAAA/////wAAABf/////AAAAF/////8BAAAAAAAAAAAAAAABCdntGuXUQAS/4CfOuSPZrLPEwK69Xkyth+CNIQ27P58B3pRy0IA0EdOTmQAQS6D9QJIHOlRteE8wkTq4cYEyCMYAAAAC/////wAAAbsBAAAAL2h0dHBzOi8vd3d3Lm1vemlsbGEub3JnL2VuLVVTL2ZpcmVmb3gvYWNjb3VudHMvAAAAAAAAAAUAAAAIAAAADwAAAAj/////AAAACP////8AAAAIAAAADwAAABcAAAAYAAAAFwAAABgAAAAXAAAAGAAAAC8AAAAAAAAAL/////8AAAAA/////wAAABf/////AAAAF/////8BAAAAAAAAAAAAAQAABbYAcwBjAHIAaQBwAHQALQBzAHIAYwAgACcAcwBlAGwAZgAnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AbgBlAHQAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBvAHIAZwAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAGMAbwBtACAAJwB1AG4AcwBhAGYAZQAtAGkAbgBsAGkAbgBlACcAIAAnAHUAbgBzAGEAZgBlAC0AZQB2AGEAbAAnACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUAdABhAGcAbQBhAG4AYQBnAGUAcgAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUALQBhAG4AYQBsAHkAdABpAGMAcwAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHQAYQBnAG0AYQBuAGEAZwBlAHIALgBnAG8AbwBnAGwAZQAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AeQBvAHUAdAB1AGIAZQAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHMALgB5AHQAaQBtAGcALgBjAG8AbQA7ACAAaQBtAGcALQBzAHIAYwAgACcAcwBlAGwAZgAnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AbgBlAHQAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBvAHIAZwAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAGMAbwBtACAAZABhAHQAYQA6ACAAaAB0AHQAcABzADoALwAvAG0AbwB6AGkAbABsAGEALgBvAHIAZwAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAGcAbwBvAGcAbABlAHQAYQBnAG0AYQBuAGEAZwBlAHIALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAGcAbwBvAGcAbABlAC0AYQBuAGEAbAB5AHQAaQBjAHMALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwBhAGQAcwBlAHIAdgBpAGMAZQAuAGcAbwBvAGcAbABlAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AYQBkAHMAZQByAHYAaQBjAGUALgBnAG8AbwBnAGwAZQAuAGQAZQAgAGgAdAB0AHAAcwA6AC8ALwBhAGQAcwBlAHIAdgBpAGMAZQAuAGcAbwBvAGcAbABlAC4AZABrACAAaAB0AHQAcABzADoALwAvAGMAcgBlAGEAdABpAHYAZQBjAG8AbQBtAG8AbgBzAC4AbwByAGcAIABoAHQAdABwAHMAOgAvAC8AYQBkAC4AZABvAHUAYgBsAGUAYwBsAGkAYwBrAC4AbgBlAHQAOwAgAGQAZQBmAGEAdQBsAHQALQBzAHIAYwAgACcAcwBlAGwAZgAnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AbgBlAHQAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBvAHIAZwAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAGMAbwBtADsAIABmAHIAYQBtAGUALQBzAHIAYwAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAGcAbwBvAGcAbABlAHQAYQBnAG0AYQBuAGEAZwBlAHIALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAGcAbwBvAGcAbABlAC0AYQBuAGEAbAB5AHQAaQBjAHMALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAHkAbwB1AHQAdQBiAGUALQBuAG8AYwBvAG8AawBpAGUALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwB0AHIAYQBjAGsAZQByAHQAZQBzAHQALgBvAHIAZwAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAHMAdQByAHYAZQB5AGcAaQB6AG0AbwAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAGEAYwBjAG8AdQBuAHQAcwAuAGYAaQByAGUAZgBvAHgALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwBhAGMAYwBvAHUAbgB0AHMALgBmAGkAcgBlAGYAbwB4AC4AYwBvAG0ALgBjAG4AIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgB5AG8AdQB0AHUAYgBlAC4AYwBvAG0AOwAgAHMAdAB5AGwAZQAtAHMAcgBjACAAJwBzAGUAbABmACcAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBuAGUAdAAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AYwBvAG0AIAAnAHUAbgBzAGEAZgBlAC0AaQBuAGwAaQBuAGUAJwA7ACAAYwBvAG4AbgBlAGMAdAAtAHMAcgBjACAAJwBzAGUAbABmACcAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBuAGUAdAAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgBnAG8AbwBnAGwAZQB0AGEAZwBtAGEAbgBhAGcAZQByAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgBnAG8AbwBnAGwAZQAtAGEAbgBhAGwAeQB0AGkAYwBzAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AYQBjAGMAbwB1AG4AdABzAC4AZgBpAHIAZQBmAG8AeAAuAGMAbwBtAC8AIABoAHQAdABwAHMAOgAvAC8AYQBjAGMAbwB1AG4AdABzAC4AZgBpAHIAZQBmAG8AeAAuAGMAbwBtAC4AYwBuAC8AOwAgAGMAaABpAGwAZAAtAHMAcgBjACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUAdABhAGcAbQBhAG4AYQBnAGUAcgAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUALQBhAG4AYQBsAHkAdABpAGMAcwAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AeQBvAHUAdAB1AGIAZQAtAG4AbwBjAG8AbwBrAGkAZQAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHQAcgBhAGMAawBlAHIAdABlAHMAdAAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AcwB1AHIAdgBlAHkAZwBpAHoAbQBvAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AYQBjAGMAbwB1AG4AdABzAC4AZgBpAHIAZQBmAG8AeAAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAGEAYwBjAG8AdQBuAHQAcwAuAGYAaQByAGUAZgBvAHgALgBjAG8AbQAuAGMAbgAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAHkAbwB1AHQAdQBiAGUALgBjAG8AbQAA",
"output": {
"URISpec": "https://www.mozilla.org/en-US/firefox/accounts/",
"originAttributes": {
"firstPartyDomain": "",
"inIsolatedMozBrowser": false,
"privateBrowsingId": 0,
"userContextId": 0,
input:
"ZT4OTT7kRfqycpfCC8AeuAAAAAAAAAAAwAAAAAAAAEYB3pRy0IA0EdOTmQAQS6D9QJIHOlRteE8wkTq4cYEyCMYAAAAC/////wAAAbsBAAAAL2h0dHBzOi8vd3d3Lm1vemlsbGEub3JnL2VuLVVTL2ZpcmVmb3gvYWNjb3VudHMvAAAAAAAAAAUAAAAIAAAADwAAAAj/////AAAACP////8AAAAIAAAADwAAABcAAAAYAAAAFwAAABgAAAAXAAAAGAAAAC8AAAAAAAAAL/////8AAAAA/////wAAABf/////AAAAF/////8BAAAAAAAAAAAAAAABCdntGuXUQAS/4CfOuSPZrLPEwK69Xkyth+CNIQ27P58B3pRy0IA0EdOTmQAQS6D9QJIHOlRteE8wkTq4cYEyCMYAAAAC/////wAAAbsBAAAAL2h0dHBzOi8vd3d3Lm1vemlsbGEub3JnL2VuLVVTL2ZpcmVmb3gvYWNjb3VudHMvAAAAAAAAAAUAAAAIAAAADwAAAAj/////AAAACP////8AAAAIAAAADwAAABcAAAAYAAAAFwAAABgAAAAXAAAAGAAAAC8AAAAAAAAAL/////8AAAAA/////wAAABf/////AAAAF/////8BAAAAAAAAAAAAAQAABbYAcwBjAHIAaQBwAHQALQBzAHIAYwAgACcAcwBlAGwAZgAnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AbgBlAHQAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBvAHIAZwAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAGMAbwBtACAAJwB1AG4AcwBhAGYAZQAtAGkAbgBsAGkAbgBlACcAIAAnAHUAbgBzAGEAZgBlAC0AZQB2AGEAbAAnACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUAdABhAGcAbQBhAG4AYQBnAGUAcgAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUALQBhAG4AYQBsAHkAdABpAGMAcwAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHQAYQBnAG0AYQBuAGEAZwBlAHIALgBnAG8AbwBnAGwAZQAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AeQBvAHUAdAB1AGIAZQAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHMALgB5AHQAaQBtAGcALgBjAG8AbQA7ACAAaQBtAGcALQBzAHIAYwAgACcAcwBlAGwAZgAnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AbgBlAHQAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBvAHIAZwAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAGMAbwBtACAAZABhAHQAYQA6ACAAaAB0AHQAcABzADoALwAvAG0AbwB6AGkAbABsAGEALgBvAHIAZwAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAGcAbwBvAGcAbABlAHQAYQBnAG0AYQBuAGEAZwBlAHIALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAGcAbwBvAGcAbABlAC0AYQBuAGEAbAB5AHQAaQBjAHMALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwBhAGQAcwBlAHIAdgBpAGMAZQAuAGcAbwBvAGcAbABlAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AYQBkAHMAZQByAHYAaQBjAGUALgBnAG8AbwBnAGwAZQAuAGQAZQAgAGgAdAB0AHAAcwA6AC8ALwBhAGQAcwBlAHIAdgBpAGMAZQAuAGcAbwBvAGcAbABlAC4AZABrACAAaAB0AHQAcABzADoALwAvAGMAcgBlAGEAdABpAHYAZQBjAG8AbQBtAG8AbgBzAC4AbwByAGcAIABoAHQAdABwAHMAOgAvAC8AYQBkAC4AZABvAHUAYgBsAGUAYwBsAGkAYwBrAC4AbgBlAHQAOwAgAGQAZQBmAGEAdQBsAHQALQBzAHIAYwAgACcAcwBlAGwAZgAnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AbgBlAHQAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBvAHIAZwAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAGMAbwBtADsAIABmAHIAYQBtAGUALQBzAHIAYwAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAGcAbwBvAGcAbABlAHQAYQBnAG0AYQBuAGEAZwBlAHIALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAGcAbwBvAGcAbABlAC0AYQBuAGEAbAB5AHQAaQBjAHMALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAHkAbwB1AHQAdQBiAGUALQBuAG8AYwBvAG8AawBpAGUALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwB0AHIAYQBjAGsAZQByAHQAZQBzAHQALgBvAHIAZwAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAHMAdQByAHYAZQB5AGcAaQB6AG0AbwAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAGEAYwBjAG8AdQBuAHQAcwAuAGYAaQByAGUAZgBvAHgALgBjAG8AbQAgAGgAdAB0AHAAcwA6AC8ALwBhAGMAYwBvAHUAbgB0AHMALgBmAGkAcgBlAGYAbwB4AC4AYwBvAG0ALgBjAG4AIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgB5AG8AdQB0AHUAYgBlAC4AYwBvAG0AOwAgAHMAdAB5AGwAZQAtAHMAcgBjACAAJwBzAGUAbABmACcAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBuAGUAdAAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AYwBvAG0AIAAnAHUAbgBzAGEAZgBlAC0AaQBuAGwAaQBuAGUAJwA7ACAAYwBvAG4AbgBlAGMAdAAtAHMAcgBjACAAJwBzAGUAbABmACcAIABoAHQAdABwAHMAOgAvAC8AKgAuAG0AbwB6AGkAbABsAGEALgBuAGUAdAAgAGgAdAB0AHAAcwA6AC8ALwAqAC4AbQBvAHoAaQBsAGwAYQAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvACoALgBtAG8AegBpAGwAbABhAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgBnAG8AbwBnAGwAZQB0AGEAZwBtAGEAbgBhAGcAZQByAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AdwB3AHcALgBnAG8AbwBnAGwAZQAtAGEAbgBhAGwAeQB0AGkAYwBzAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AYQBjAGMAbwB1AG4AdABzAC4AZgBpAHIAZQBmAG8AeAAuAGMAbwBtAC8AIABoAHQAdABwAHMAOgAvAC8AYQBjAGMAbwB1AG4AdABzAC4AZgBpAHIAZQBmAG8AeAAuAGMAbwBtAC4AYwBuAC8AOwAgAGMAaABpAGwAZAAtAHMAcgBjACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUAdABhAGcAbQBhAG4AYQBnAGUAcgAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUALQBhAG4AYQBsAHkAdABpAGMAcwAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AeQBvAHUAdAB1AGIAZQAtAG4AbwBjAG8AbwBrAGkAZQAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAHQAcgBhAGMAawBlAHIAdABlAHMAdAAuAG8AcgBnACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AcwB1AHIAdgBlAHkAZwBpAHoAbQBvAC4AYwBvAG0AIABoAHQAdABwAHMAOgAvAC8AYQBjAGMAbwB1AG4AdABzAC4AZgBpAHIAZQBmAG8AeAAuAGMAbwBtACAAaAB0AHQAcABzADoALwAvAGEAYwBjAG8AdQBuAHQAcwAuAGYAaQByAGUAZgBvAHgALgBjAG8AbQAuAGMAbgAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAHkAbwB1AHQAdQBiAGUALgBjAG8AbQAA",
output: {
URISpec: "https://www.mozilla.org/en-US/firefox/accounts/",
originAttributes: {
firstPartyDomain: "",
inIsolatedMozBrowser: false,
privateBrowsingId: 0,
userContextId: 0,
},
// Within Bug 965637 we removed CSP from Principals. Already serialized Principals however should still deserialize correctly (just without the CSP).
// "cspJSON": "{\"csp-policies\":[{\"child-src\":[\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://www.youtube-nocookie.com\",\"https://trackertest.org\",\"https://www.surveygizmo.com\",\"https://accounts.firefox.com\",\"https://accounts.firefox.com.cn\",\"https://www.youtube.com\"],\"connect-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://accounts.firefox.com/\",\"https://accounts.firefox.com.cn/\"],\"default-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\"],\"frame-src\":[\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://www.youtube-nocookie.com\",\"https://trackertest.org\",\"https://www.surveygizmo.com\",\"https://accounts.firefox.com\",\"https://accounts.firefox.com.cn\",\"https://www.youtube.com\"],\"img-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"data:\",\"https://mozilla.org\",\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://adservice.google.com\",\"https://adservice.google.de\",\"https://adservice.google.dk\",\"https://creativecommons.org\",\"https://ad.doubleclick.net\"],\"report-only\":false,\"script-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"'unsafe-inline'\",\"'unsafe-eval'\",\"https://www.googletagmanager.com\",\"https://www.google-analytics.com\",\"https://tagmanager.google.com\",\"https://www.youtube.com\",\"https://s.ytimg.com\"],\"style-src\":[\"'self'\",\"https://*.mozilla.net\",\"https://*.mozilla.org\",\"https://*.mozilla.com\",\"'unsafe-inline'\"]}]}",
@ -76,13 +78,21 @@ add_task(async function test_deserialize_principal_with_csp() {
let principal = E10SUtils.deserializePrincipal(test.input);
for (let key in principal.originAttributes) {
is(principal.originAttributes[key], test.output.originAttributes[key], `Ensure value of ${key} is ${test.output.originAttributes[key]}`);
is(
principal.originAttributes[key],
test.output.originAttributes[key],
`Ensure value of ${key} is ${test.output.originAttributes[key]}`
);
}
if ("URI" in test.output && test.output.URI === false) {
is(principal.URI, null, "Should have not have a URI for system");
} else {
is(principal.URI.spec, test.output.URISpec, `Should have spec ${test.output.URISpec}`);
is(
principal.URI.spec,
test.output.URISpec,
`Should have spec ${test.output.URISpec}`
);
}
}
});

Просмотреть файл

@ -3,7 +3,6 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
/*
This test file exists to ensure whenever changes to principal serialization happens,
we guarantee that the data can be restored and generated into a new principal.
@ -26,27 +25,27 @@ add_task(async function test_nullPrincipal() {
*/
let tests = [
{
input: {OA: {}},
input: { OA: {} },
expected: `{"${nullId}":{"${uri}":"${NULL_REPLACE}"}}`,
},
{
input: {OA: {}},
input: { OA: {} },
expected: `{"${nullId}":{"${uri}":"${NULL_REPLACE}"}}`,
},
{
input: {OA: { userContextId: 0 }},
input: { OA: { userContextId: 0 } },
expected: `{"${nullId}":{"${uri}":"${NULL_REPLACE}"}}`,
},
{
input: {OA: { userContextId: 2 }},
input: { OA: { userContextId: 2 } },
expected: `{"${nullId}":{"${uri}":"${NULL_REPLACE}","${suffix}":"^userContextId=2"}}`,
},
{
input: {OA: { privateBrowsingId: 1 }},
input: { OA: { privateBrowsingId: 1 } },
expected: `{"${nullId}":{"${uri}":"${NULL_REPLACE}","${suffix}":"^privateBrowsingId=1"}}`,
},
{
input: {OA: { privateBrowsingId: 0 }},
input: { OA: { privateBrowsingId: 0 } },
expected: `{"${nullId}":{"${uri}":"${NULL_REPLACE}"}}`,
},
];
@ -56,12 +55,20 @@ add_task(async function test_nullPrincipal() {
let sp = E10SUtils.serializePrincipal(p);
// Not sure why cppjson is adding a \n here
let spr = atob(sp).replace(nullReplaceRegex, NULL_REPLACE);
is(test.expected, spr, "Expected serialized object for " + JSON.stringify(test.input));
is(
test.expected,
spr,
"Expected serialized object for " + JSON.stringify(test.input)
);
let dp = E10SUtils.deserializePrincipal(sp);
// Check all the origin attributes
for (let key in test.input.OA) {
is(dp.originAttributes[key], test.input.OA[key], "Ensure value of " + key + " is " + test.input.OA[key]);
is(
dp.originAttributes[key],
test.input.OA[key],
"Ensure value of " + key + " is " + test.input.OA[key]
);
}
}
});
@ -80,43 +87,58 @@ add_task(async function test_contentPrincipal() {
*/
let tests = [
{
input: {uri: "http://example.com/", OA: {}},
input: { uri: "http://example.com/", OA: {} },
expected: `{"${contentId}":{"${codebase}":"http://example.com/"}}`,
},
{
input: {uri: "http://mozilla1.com/", OA: {}},
input: { uri: "http://mozilla1.com/", OA: {} },
expected: `{"${contentId}":{"${codebase}":"http://mozilla1.com/"}}`,
},
{
input: {uri: "http://mozilla2.com/", OA: { userContextId: 0 }},
input: { uri: "http://mozilla2.com/", OA: { userContextId: 0 } },
expected: `{"${contentId}":{"${codebase}":"http://mozilla2.com/"}}`,
},
{
input: {uri: "http://mozilla3.com/", OA: { userContextId: 2 }},
input: { uri: "http://mozilla3.com/", OA: { userContextId: 2 } },
expected: `{"${contentId}":{"${codebase}":"http://mozilla3.com/","${suffix}":"^userContextId=2"}}`,
},
{
input: {uri: "http://mozilla4.com/", OA: { privateBrowsingId: 1 }},
input: { uri: "http://mozilla4.com/", OA: { privateBrowsingId: 1 } },
expected: `{"${contentId}":{"${codebase}":"http://mozilla4.com/","${suffix}":"^privateBrowsingId=1"}}`,
},
{
input: {uri: "http://mozilla5.com/", OA: { privateBrowsingId: 0 }},
input: { uri: "http://mozilla5.com/", OA: { privateBrowsingId: 0 } },
expected: `{"${contentId}":{"${codebase}":"http://mozilla5.com/"}}`,
},
];
for (let test of tests) {
let uri = Services.io.newURI(test.input.uri);
let p = Services.scriptSecurityManager.createCodebasePrincipal(uri, test.input.OA);
let p = Services.scriptSecurityManager.createCodebasePrincipal(
uri,
test.input.OA
);
let sp = E10SUtils.serializePrincipal(p);
is(test.expected, atob(sp), "Expected serialized object for " + test.input.uri);
is(btoa(test.expected), sp, "Expected serialized string for " + test.input.uri);
is(
test.expected,
atob(sp),
"Expected serialized object for " + test.input.uri
);
is(
btoa(test.expected),
sp,
"Expected serialized string for " + test.input.uri
);
let dp = E10SUtils.deserializePrincipal(sp);
is(dp.URI.spec, test.input.uri, "Ensure spec is the same");
// Check all the origin attributes
for (let key in test.input.OA) {
is(dp.originAttributes[key], test.input.OA[key], "Ensure value of " + key + " is " + test.input.OA[key]);
is(
dp.originAttributes[key],
test.input.OA[key],
"Ensure value of " + key + " is " + test.input.OA[key]
);
}
}
});
@ -134,6 +156,9 @@ add_task(async function test_systemPrincipal() {
is(expected, atob(sp), "Expected serialized object for system principal");
is(btoa(expected), sp, "Expected serialized string for system principal");
let dp = E10SUtils.deserializePrincipal(sp);
is(dp, Services.scriptSecurityManager.getSystemPrincipal(), "Deserialized the system principal");
is(
dp,
Services.scriptSecurityManager.getSystemPrincipal(),
"Deserialized the system principal"
);
});

Просмотреть файл

@ -3,7 +3,6 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
/*
This test file exists to ensure whenever changes to principal serialization happens,
we guarantee that the data can be restored and generated into a new principal.
@ -19,12 +18,24 @@ add_task(function test_nullPrincipal() {
This test should be resilient to changes in versioning, however it should also be duplicated for a new serialization change.
*/
// Principal created with: E10SUtils.serializePrincipal(Services.scriptSecurityManager.createNullPrincipal({ }));
let p = E10SUtils.deserializePrincipal("vQZuXxRvRHKDMXv9BbHtkAAAAAAAAAAAwAAAAAAAAEYAAAA4bW96LW51bGxwcmluY2lwYWw6ezU2Y2FjNTQwLTg2NGQtNDdlNy04ZTI1LTE2MTRlYWI1MTU1ZX0AAAAA");
is("moz-nullprincipal:{56cac540-864d-47e7-8e25-1614eab5155e}", p.URI.spec, "Deserialized principal doesn't have the correct URI");
let p = E10SUtils.deserializePrincipal(
"vQZuXxRvRHKDMXv9BbHtkAAAAAAAAAAAwAAAAAAAAEYAAAA4bW96LW51bGxwcmluY2lwYWw6ezU2Y2FjNTQwLTg2NGQtNDdlNy04ZTI1LTE2MTRlYWI1MTU1ZX0AAAAA"
);
is(
"moz-nullprincipal:{56cac540-864d-47e7-8e25-1614eab5155e}",
p.URI.spec,
"Deserialized principal doesn't have the correct URI"
);
// Principal created with: E10SUtils.serializePrincipal(Services.scriptSecurityManager.createNullPrincipal({ userContextId: 2 }));
let p2 = E10SUtils.deserializePrincipal("vQZuXxRvRHKDMXv9BbHtkAAAAAAAAAAAwAAAAAAAAEYAAAA4bW96LW51bGxwcmluY2lwYWw6ezA1ZjllN2JhLWIwODMtNDJhMi1iNDdkLTZiODRmNmYwYTM3OX0AAAAQXnVzZXJDb250ZXh0SWQ9Mg==");
is("moz-nullprincipal:{05f9e7ba-b083-42a2-b47d-6b84f6f0a379}", p2.URI.spec, "Deserialized principal doesn't have the correct URI");
let p2 = E10SUtils.deserializePrincipal(
"vQZuXxRvRHKDMXv9BbHtkAAAAAAAAAAAwAAAAAAAAEYAAAA4bW96LW51bGxwcmluY2lwYWw6ezA1ZjllN2JhLWIwODMtNDJhMi1iNDdkLTZiODRmNmYwYTM3OX0AAAAQXnVzZXJDb250ZXh0SWQ9Mg=="
);
is(
"moz-nullprincipal:{05f9e7ba-b083-42a2-b47d-6b84f6f0a379}",
p2.URI.spec,
"Deserialized principal doesn't have the correct URI"
);
is(p2.originAttributes.userContextId, 2, "Expected a userContextId of 2");
});
@ -60,50 +71,53 @@ add_task(async function test_realHistoryCheck() {
let serializedPrincipalsFromFirefox = [
{
"input": "SmIS26zLEdO3ZQBgsLbOywAAAAAAAAAAwAAAAAAAAEY=",
"output": {
"URI": false,
"originAttributes": {
"firstPartyDomain": "",
"inIsolatedMozBrowser": false,
"privateBrowsingId": 0,
"userContextId": 0,
input: "SmIS26zLEdO3ZQBgsLbOywAAAAAAAAAAwAAAAAAAAEY=",
output: {
URI: false,
originAttributes: {
firstPartyDomain: "",
inIsolatedMozBrowser: false,
privateBrowsingId: 0,
userContextId: 0,
},
},
},
{
"input": "ZT4OTT7kRfqycpfCC8AeuAAAAAAAAAAAwAAAAAAAAEYB3pRy0IA0EdOTmQAQS6D9QJIHOlRteE8wkTq4cYEyCMYAAAAC/////wAAAbsBAAAAe2h0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTLz91dG1fc291cmNlPXd3dy5tb3ppbGxhLm9yZyZ1dG1fbWVkaXVtPXJlZmVycmFsJnV0bV9jYW1wYWlnbj1uYXYmdXRtX2NvbnRlbnQ9ZGV2ZWxvcGVycwAAAAAAAAAFAAAACAAAABUAAAAA/////wAAAAD/////AAAACAAAABUAAAAdAAAAXgAAAB0AAAAHAAAAHQAAAAcAAAAkAAAAAAAAAAD/////AAAAAP////8AAAAlAAAAVgAAAAD/////AQAAAAAAAAAAAAAAAA==",
"output": {
"URISpec": "https://developer.mozilla.org/en-US/?utm_source=www.mozilla.org&utm_medium=referral&utm_campaign=nav&utm_content=developers",
"originAttributes": {
"firstPartyDomain": "",
"inIsolatedMozBrowser": false,
"privateBrowsingId": 0,
"userContextId": 0,
input:
"ZT4OTT7kRfqycpfCC8AeuAAAAAAAAAAAwAAAAAAAAEYB3pRy0IA0EdOTmQAQS6D9QJIHOlRteE8wkTq4cYEyCMYAAAAC/////wAAAbsBAAAAe2h0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTLz91dG1fc291cmNlPXd3dy5tb3ppbGxhLm9yZyZ1dG1fbWVkaXVtPXJlZmVycmFsJnV0bV9jYW1wYWlnbj1uYXYmdXRtX2NvbnRlbnQ9ZGV2ZWxvcGVycwAAAAAAAAAFAAAACAAAABUAAAAA/////wAAAAD/////AAAACAAAABUAAAAdAAAAXgAAAB0AAAAHAAAAHQAAAAcAAAAkAAAAAAAAAAD/////AAAAAP////8AAAAlAAAAVgAAAAD/////AQAAAAAAAAAAAAAAAA==",
output: {
URISpec:
"https://developer.mozilla.org/en-US/?utm_source=www.mozilla.org&utm_medium=referral&utm_campaign=nav&utm_content=developers",
originAttributes: {
firstPartyDomain: "",
inIsolatedMozBrowser: false,
privateBrowsingId: 0,
userContextId: 0,
},
},
},
{
"input": "SmIS26zLEdO3ZQBgsLbOywAAAAAAAAAAwAAAAAAAAEY=",
"output": {
"URI": false,
"originAttributes": {
"firstPartyDomain": "",
"inIsolatedMozBrowser": false,
"privateBrowsingId": 0,
"userContextId": 0,
input: "SmIS26zLEdO3ZQBgsLbOywAAAAAAAAAAwAAAAAAAAEY=",
output: {
URI: false,
originAttributes: {
firstPartyDomain: "",
inIsolatedMozBrowser: false,
privateBrowsingId: 0,
userContextId: 0,
},
},
},
{
"input": "vQZuXxRvRHKDMXv9BbHtkAAAAAAAAAAAwAAAAAAAAEYAAAA4bW96LW51bGxwcmluY2lwYWw6ezA0NWNhMThkLTQzNmMtNDc0NC1iYmI2LWIxYTE1MzY2ZGY3OX0AAAAA",
"output": {
"URISpec": "moz-nullprincipal:{045ca18d-436c-4744-bbb6-b1a15366df79}",
"originAttributes": {
"firstPartyDomain": "",
"inIsolatedMozBrowser": false,
"privateBrowsingId": 0,
"userContextId": 0,
input:
"vQZuXxRvRHKDMXv9BbHtkAAAAAAAAAAAwAAAAAAAAEYAAAA4bW96LW51bGxwcmluY2lwYWw6ezA0NWNhMThkLTQzNmMtNDc0NC1iYmI2LWIxYTE1MzY2ZGY3OX0AAAAA",
output: {
URISpec: "moz-nullprincipal:{045ca18d-436c-4744-bbb6-b1a15366df79}",
originAttributes: {
firstPartyDomain: "",
inIsolatedMozBrowser: false,
privateBrowsingId: 0,
userContextId: 0,
},
},
},
@ -113,13 +127,21 @@ add_task(async function test_realHistoryCheck() {
let principal = E10SUtils.deserializePrincipal(test.input);
for (let key in principal.originAttributes) {
is(principal.originAttributes[key], test.output.originAttributes[key], `Ensure value of ${key} is ${test.output.originAttributes[key]}`);
is(
principal.originAttributes[key],
test.output.originAttributes[key],
`Ensure value of ${key} is ${test.output.originAttributes[key]}`
);
}
if ("URI" in test.output && test.output.URI === false) {
is(principal.URI, null, "Should have not have a URI for system");
} else {
is(principal.URI.spec, test.output.URISpec, `Should have spec ${test.output.URISpec}`);
is(
principal.URI.spec,
test.output.URISpec,
`Should have spec ${test.output.URISpec}`
);
}
}
});

Просмотреть файл

@ -14,8 +14,11 @@ let testcases = [
await portalDetected();
let win = await focusWindowAndWaitForPortalUI();
let browser = win.gBrowser.selectedTab.linkedBrowser;
let loadPromise =
BrowserTestUtils.browserLoaded(browser, false, CANONICAL_URL_REDIRECTED);
let loadPromise = BrowserTestUtils.browserLoaded(
browser,
false,
CANONICAL_URL_REDIRECTED
);
BrowserTestUtils.loadURI(browser, CANONICAL_URL_REDIRECTED);
await loadPromise;
await freePortal(true);
@ -37,7 +40,11 @@ let testcases = [
testShowLoginPageButtonVisibility(notification, "visible");
function testPortalTabSelectedAndButtonNotVisible() {
is(win.gBrowser.selectedTab, tab, "The captive portal tab should be selected.");
is(
win.gBrowser.selectedTab,
tab,
"The captive portal tab should be selected."
);
testShowLoginPageButtonVisibility(notification, "hidden");
}
@ -46,7 +53,11 @@ let testcases = [
let p = BrowserTestUtils.waitForNewTab(win.gBrowser, CANONICAL_URL);
button.click();
let tab = await p;
is(win.gBrowser.selectedTab, tab, "The captive portal tab should be selected.");
is(
win.gBrowser.selectedTab,
tab,
"The captive portal tab should be selected."
);
return tab;
}
@ -69,7 +80,11 @@ let testcases = [
let anotherTab = await BrowserTestUtils.openNewForegroundTab(win.gBrowser);
testShowLoginPageButtonVisibility(notification, "visible");
button.click();
is(win.gBrowser.selectedTab, tab, "The captive portal tab should be selected.");
is(
win.gBrowser.selectedTab,
tab,
"The captive portal tab should be selected."
);
// Close the portal tab and select the arbitrary tab. The button should become
// visible and when it's clicked, a new portal tab should be opened.

Просмотреть файл

@ -9,47 +9,75 @@ const BAD_CERT_PAGE = "https://expired.example.com/";
add_task(async function checkCaptivePortalCertErrorUI() {
await SpecialPowers.pushPrefEnv({
set: [["captivedetect.canonicalURL", CANONICAL_URL],
["captivedetect.canonicalContent", CANONICAL_CONTENT]],
set: [
["captivedetect.canonicalURL", CANONICAL_URL],
["captivedetect.canonicalContent", CANONICAL_CONTENT],
],
});
let captivePortalStatePropagated = TestUtils.topicObserved("ipc:network:captive-portal-set-state");
let captivePortalStatePropagated = TestUtils.topicObserved(
"ipc:network:captive-portal-set-state"
);
info("Checking that the alternate about:certerror UI is shown when we are behind a captive portal.");
info(
"Checking that the alternate about:certerror UI is shown when we are behind a captive portal."
);
Services.obs.notifyObservers(null, "captive-portal-login");
info("Waiting for captive portal state to be propagated to the content process.");
info(
"Waiting for captive portal state to be propagated to the content process."
);
await captivePortalStatePropagated;
// Open a page with a cert error.
let browser;
let certErrorLoaded;
let errorTab = await BrowserTestUtils.openNewForegroundTab(gBrowser, () => {
let tab = BrowserTestUtils.addTab(gBrowser, BAD_CERT_PAGE);
gBrowser.selectedTab = tab;
browser = gBrowser.selectedBrowser;
certErrorLoaded = BrowserTestUtils.waitForContentEvent(browser, "DOMContentLoaded");
return tab;
}, false);
let errorTab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
() => {
let tab = BrowserTestUtils.addTab(gBrowser, BAD_CERT_PAGE);
gBrowser.selectedTab = tab;
browser = gBrowser.selectedBrowser;
certErrorLoaded = BrowserTestUtils.waitForContentEvent(
browser,
"DOMContentLoaded"
);
return tab;
},
false
);
info("Waiting for cert error page to load.");
await certErrorLoaded;
let portalTabPromise = BrowserTestUtils.waitForNewTab(gBrowser, CANONICAL_URL);
let portalTabPromise = BrowserTestUtils.waitForNewTab(
gBrowser,
CANONICAL_URL
);
await ContentTask.spawn(browser, null, () => {
let doc = content.document;
ok(doc.body.classList.contains("captiveportal"),
"Captive portal error page UI is visible.");
ok(
doc.body.classList.contains("captiveportal"),
"Captive portal error page UI is visible."
);
info("Clicking the Open Login Page button.");
let loginButton = doc.getElementById("openPortalLoginPageButton");
is(loginButton.getAttribute("autofocus"), "true", "openPortalLoginPageButton has autofocus");
is(
loginButton.getAttribute("autofocus"),
"true",
"openPortalLoginPageButton has autofocus"
);
loginButton.click();
});
let portalTab = await portalTabPromise;
is(gBrowser.selectedTab, portalTab, "Login page should be open in a new foreground tab.");
is(
gBrowser.selectedTab,
portalTab,
"Login page should be open in a new foreground tab."
);
// Make sure clicking the "Open Login Page" button again focuses the existing portal tab.
await BrowserTestUtils.switchTab(gBrowser, errorTab);
@ -70,12 +98,16 @@ add_task(async function checkCaptivePortalCertErrorUI() {
Services.obs.notifyObservers(null, "captive-portal-login-success");
await portalTabClosing;
info("Waiting for error tab to be reloaded after the captive portal was freed.");
info(
"Waiting for error tab to be reloaded after the captive portal was freed."
);
await errorTabReloaded;
await ContentTask.spawn(browser, null, () => {
let doc = content.document;
ok(!doc.body.classList.contains("captiveportal"),
"Captive portal error page UI is not visible.");
ok(
!doc.body.classList.contains("captiveportal"),
"Captive portal error page UI is not visible."
);
});
BrowserTestUtils.removeTab(errorTab);

Просмотреть файл

@ -1,11 +1,19 @@
var {BrowserWindowTracker} = ChromeUtils.import("resource:///modules/BrowserWindowTracker.jsm");
var { BrowserWindowTracker } = ChromeUtils.import(
"resource:///modules/BrowserWindowTracker.jsm"
);
ChromeUtils.defineModuleGetter(this, "CaptivePortalWatcher",
"resource:///modules/CaptivePortalWatcher.jsm");
ChromeUtils.defineModuleGetter(
this,
"CaptivePortalWatcher",
"resource:///modules/CaptivePortalWatcher.jsm"
);
XPCOMUtils.defineLazyServiceGetter(this, "cps",
"@mozilla.org/network/captive-portal-service;1",
"nsICaptivePortalService");
XPCOMUtils.defineLazyServiceGetter(
this,
"cps",
"@mozilla.org/network/captive-portal-service;1",
"nsICaptivePortalService"
);
const CANONICAL_CONTENT = "success";
const CANONICAL_URL = "data:text/plain;charset=utf-8," + CANONICAL_CONTENT;
@ -14,8 +22,10 @@ const PORTAL_NOTIFICATION_VALUE = "captive-portal-detected";
async function setupPrefsAndRecentWindowBehavior() {
await SpecialPowers.pushPrefEnv({
set: [["captivedetect.canonicalURL", CANONICAL_URL],
["captivedetect.canonicalContent", CANONICAL_CONTENT]],
set: [
["captivedetect.canonicalURL", CANONICAL_URL],
["captivedetect.canonicalContent", CANONICAL_CONTENT],
],
});
// We need to test behavior when a portal is detected when there is no browser
// window, but we can't close the default window opened by the test harness.
@ -38,8 +48,10 @@ async function portalDetected() {
}
async function freePortal(aSuccess) {
Services.obs.notifyObservers(null,
"captive-portal-login-" + (aSuccess ? "success" : "abort"));
Services.obs.notifyObservers(
null,
"captive-portal-login-" + (aSuccess ? "success" : "abort")
);
await BrowserTestUtils.waitForCondition(() => {
return cps.state != cps.LOCKED_PORTAL;
}, "Waiting for Captive Portal Service to update state after portal freed.");
@ -55,7 +67,10 @@ async function focusWindowAndWaitForPortalUI(aLongRecheck, win) {
// so use a delay threshold of -1 to simulate a long recheck (so that any
// amount of time is considered excessive), and a very large threshold to
// simulate a short recheck.
Services.prefs.setIntPref("captivedetect.portalRecheckDelayMS", aLongRecheck ? -1 : 1000000);
Services.prefs.setIntPref(
"captivedetect.portalRecheckDelayMS",
aLongRecheck ? -1 : 1000000
);
if (!win) {
win = await BrowserTestUtils.openNewBrowserWindow();
@ -84,8 +99,11 @@ async function focusWindowAndWaitForPortalUI(aLongRecheck, win) {
// The tab should load the canonical URL, wait for it.
await BrowserTestUtils.waitForLocationChange(win.gBrowser, CANONICAL_URL);
}
is(win.gBrowser.selectedTab, tab,
"The captive portal tab should be open and selected in the new window.");
is(
win.gBrowser.selectedTab,
tab,
"The captive portal tab should be open and selected in the new window."
);
testShowLoginPageButtonVisibility(notification, "hidden");
return win;
}
@ -93,37 +111,56 @@ async function focusWindowAndWaitForPortalUI(aLongRecheck, win) {
function ensurePortalTab(win) {
// For the tests that call this function, it's enough to ensure there
// are two tabs in the window - the default tab and the portal tab.
is(win.gBrowser.tabs.length, 2,
"There should be a captive portal tab in the window.");
is(
win.gBrowser.tabs.length,
2,
"There should be a captive portal tab in the window."
);
}
function ensurePortalNotification(win) {
let notification = win.gHighPriorityNotificationBox.getNotificationWithValue(
PORTAL_NOTIFICATION_VALUE);
isnot(notification, null,
"There should be a captive portal notification in the window.");
PORTAL_NOTIFICATION_VALUE
);
isnot(
notification,
null,
"There should be a captive portal notification in the window."
);
return notification;
}
// Helper to test whether the "Show Login Page" is visible in the captive portal
// notification (it should be hidden when the portal tab is selected).
function testShowLoginPageButtonVisibility(notification, visibility) {
let showLoginPageButton = notification.querySelector("button.notification-button");
let showLoginPageButton = notification.querySelector(
"button.notification-button"
);
// If the visibility property was never changed from default, it will be
// an empty string, so we pretend it's "visible" (effectively the same).
is(showLoginPageButton.style.visibility || "visible", visibility,
"The \"Show Login Page\" button should be " + visibility + ".");
is(
showLoginPageButton.style.visibility || "visible",
visibility,
'The "Show Login Page" button should be ' + visibility + "."
);
}
function ensureNoPortalTab(win) {
is(win.gBrowser.tabs.length, 1,
"There should be no captive portal tab in the window.");
is(
win.gBrowser.tabs.length,
1,
"There should be no captive portal tab in the window."
);
}
function ensureNoPortalNotification(win) {
is(win.gHighPriorityNotificationBox
.getNotificationWithValue(PORTAL_NOTIFICATION_VALUE), null,
"There should be no captive portal notification in the window.");
is(
win.gHighPriorityNotificationBox.getNotificationWithValue(
PORTAL_NOTIFICATION_VALUE
),
null,
"There should be no captive portal notification in the window."
);
}
/**
@ -140,9 +177,13 @@ function waitForBrowserWindowActive(win) {
if (Services.focus.activeWindow == win) {
resolve();
} else {
win.addEventListener("activate", () => {
resolve();
}, { once: true });
win.addEventListener(
"activate",
() => {
resolve();
},
{ once: true }
);
}
});
}
@ -150,8 +191,10 @@ function waitForBrowserWindowActive(win) {
async function closeWindowAndWaitForWindowActivate(win) {
let activationPromises = [];
for (let w of BrowserWindowTracker.orderedWindows) {
if (w != win &&
!win.document.documentElement.getAttribute("ignorecaptiveportal")) {
if (
w != win &&
!win.document.documentElement.getAttribute("ignorecaptiveportal")
) {
activationPromises.push(waitForBrowserWindowActive(win));
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,22 +1,38 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
const gBaseURL = "https://example.com/browser/browser/base/content/test/contextMenu/";
const gBaseURL =
"https://example.com/browser/browser/base/content/test/contextMenu/";
add_task(async function() {
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, gBaseURL + "subtst_contextmenu.html");
let tab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
gBaseURL + "subtst_contextmenu.html"
);
let contextMenu = document.getElementById("contentAreaContextMenu");
// Get the point of the element with the page menu (test-pagemenu) and
// synthesize a right mouse click there.
let popupShownPromise = BrowserTestUtils.waitForEvent(contextMenu, "popupshown");
await BrowserTestUtils.synthesizeMouse("#test-pagemenu", 5, 5, { type: "contextmenu", button: 2 }, tab.linkedBrowser);
let popupShownPromise = BrowserTestUtils.waitForEvent(
contextMenu,
"popupshown"
);
await BrowserTestUtils.synthesizeMouse(
"#test-pagemenu",
5,
5,
{ type: "contextmenu", button: 2 },
tab.linkedBrowser
);
await popupShownPromise;
checkMenu(contextMenu);
let popupHiddenPromise = BrowserTestUtils.waitForEvent(contextMenu, "popuphidden");
let popupHiddenPromise = BrowserTestUtils.waitForEvent(
contextMenu,
"popuphidden"
);
contextMenu.hidePopup();
await popupHiddenPromise;
@ -38,17 +54,23 @@ function checkItems(menuitem, arr) {
is(menuitem.getAttribute("label"), str, str + " label");
is(menuitem.getAttribute("type"), details.type, str + " type");
is(menuitem.getAttribute("image"), details.icon ? gBaseURL + details.icon : "", str + " icon");
is(
menuitem.getAttribute("image"),
details.icon ? gBaseURL + details.icon : "",
str + " icon"
);
if (details.checked)
if (details.checked) {
is(menuitem.getAttribute("checked"), "true", str + " checked");
else
} else {
ok(!menuitem.hasAttribute("checked"), str + " checked");
}
if (details.disabled)
if (details.disabled) {
is(menuitem.getAttribute("disabled"), "true", str + " disabled");
else
} else {
ok(!menuitem.hasAttribute("disabled"), str + " disabled");
}
}
menuitem = menuitem.nextElementSibling;
@ -56,25 +78,48 @@ function checkItems(menuitem, arr) {
}
function checkMenu(contextMenu) {
let items = [ "Plain item", {type: "", icon: "", checked: false, disabled: false},
"Disabled item", {type: "", icon: "", checked: false, disabled: true},
"Item w/ textContent", {type: "", icon: "", checked: false, disabled: false},
"---", null,
"Checkbox", {type: "checkbox", icon: "", checked: true, disabled: false},
"---", null,
"Radio1", {type: "checkbox", icon: "", checked: true, disabled: false},
"Radio2", {type: "checkbox", icon: "", checked: false, disabled: false},
"Radio3", {type: "checkbox", icon: "", checked: false, disabled: false},
"---", null,
"Item w/ icon", {type: "", icon: "favicon.ico", checked: false, disabled: false},
"Item w/ bad icon", {type: "", icon: "", checked: false, disabled: false},
"---", null,
"Submenu", { children:
["Radio1", {type: "checkbox", icon: "", checked: false, disabled: false},
"Radio2", {type: "checkbox", icon: "", checked: true, disabled: false},
"Radio3", {type: "checkbox", icon: "", checked: false, disabled: false},
"---", null,
"Checkbox", {type: "checkbox", icon: "", checked: false, disabled: false}] },
];
let items = [
"Plain item",
{ type: "", icon: "", checked: false, disabled: false },
"Disabled item",
{ type: "", icon: "", checked: false, disabled: true },
"Item w/ textContent",
{ type: "", icon: "", checked: false, disabled: false },
"---",
null,
"Checkbox",
{ type: "checkbox", icon: "", checked: true, disabled: false },
"---",
null,
"Radio1",
{ type: "checkbox", icon: "", checked: true, disabled: false },
"Radio2",
{ type: "checkbox", icon: "", checked: false, disabled: false },
"Radio3",
{ type: "checkbox", icon: "", checked: false, disabled: false },
"---",
null,
"Item w/ icon",
{ type: "", icon: "favicon.ico", checked: false, disabled: false },
"Item w/ bad icon",
{ type: "", icon: "", checked: false, disabled: false },
"---",
null,
"Submenu",
{
children: [
"Radio1",
{ type: "checkbox", icon: "", checked: false, disabled: false },
"Radio2",
{ type: "checkbox", icon: "", checked: true, disabled: false },
"Radio3",
{ type: "checkbox", icon: "", checked: false, disabled: false },
"---",
null,
"Checkbox",
{ type: "checkbox", icon: "", checked: false, disabled: false },
],
},
];
checkItems(contextMenu.children[2], items);
}

Просмотреть файл

@ -4,37 +4,63 @@
"use strict";
const TEST_LINK = "https://example.com/";
const RESOURCE_LINK = getRootDirectory(gTestPath).replace("chrome://mochitests/content", "https://example.com") + "test_contextmenu_iframe.html";
const RESOURCE_LINK =
getRootDirectory(gTestPath).replace(
"chrome://mochitests/content",
"https://example.com"
) + "test_contextmenu_iframe.html";
/* This test checks that a context menu can open up
* a frame into it's own tab. */
add_task(async function test_open_iframe() {
let testTab = await BrowserTestUtils.openNewForegroundTab(gBrowser, RESOURCE_LINK);
let testTab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
RESOURCE_LINK
);
const selector = "#iframe";
const openPromise = BrowserTestUtils.waitForNewTab(gBrowser, TEST_LINK, false);
const openPromise = BrowserTestUtils.waitForNewTab(
gBrowser,
TEST_LINK,
false
);
const contextMenu = document.getElementById("contentAreaContextMenu");
is(contextMenu.state, "closed", "checking if popup is closed");
let awaitPopupShown = BrowserTestUtils.waitForEvent(contextMenu, "popupshown");
await BrowserTestUtils.synthesizeMouseAtCenter(selector, {
let awaitPopupShown = BrowserTestUtils.waitForEvent(
contextMenu,
"popupshown"
);
await BrowserTestUtils.synthesizeMouseAtCenter(
selector,
{
type: "contextmenu",
button: 2,
centered: true,
},
gBrowser.selectedBrowser);
gBrowser.selectedBrowser
);
await awaitPopupShown;
info("Popup Shown");
const awaitPopupHidden = BrowserTestUtils.waitForEvent(contextMenu, "popuphidden");
const awaitPopupHidden = BrowserTestUtils.waitForEvent(
contextMenu,
"popuphidden"
);
// Open frame submenu
const menuPopup = contextMenu.querySelector("#frame").menupopup;
const menuPopupPromise = BrowserTestUtils.waitForEvent(menuPopup, "popupshown");
const menuPopupPromise = BrowserTestUtils.waitForEvent(
menuPopup,
"popupshown"
);
menuPopup.openPopup();
await menuPopupPromise;
let domItem = contextMenu.querySelector("#context-openframeintab");
info("Going to click item " + domItem.id);
ok(BrowserTestUtils.is_visible(domItem), "DOM context menu item tab should be visible");
ok(
BrowserTestUtils.is_visible(domItem),
"DOM context menu item tab should be visible"
);
ok(!domItem.disabled, "DOM context menu item tab shouldn't be disabled");
domItem.click();

Просмотреть файл

@ -4,255 +4,467 @@ let contextMenu;
let hasPocket = Services.prefs.getBoolPref("extensions.pocket.enabled");
add_task(async function test_setup() {
const example_base = "http://example.com/browser/browser/base/content/test/contextMenu/";
const example_base =
"http://example.com/browser/browser/base/content/test/contextMenu/";
const url = example_base + "subtst_contextmenu_input.html";
await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
const chrome_base = "chrome://mochitests/content/browser/browser/base/content/test/contextMenu/";
const chrome_base =
"chrome://mochitests/content/browser/browser/base/content/test/contextMenu/";
const contextmenu_common = chrome_base + "contextmenu_common.js";
/* import-globals-from contextmenu_common.js */
Services.scriptloader.loadSubScript(contextmenu_common, this);
// Ensure screenshots is really disabled (bug 1498738)
const addon = await AddonManager.getAddonByID("screenshots@mozilla.org");
await addon.disable({allowSystemAddons: true});
await addon.disable({ allowSystemAddons: true });
});
add_task(async function test_text_input() {
await test_contextmenu("#input_text",
["context-undo", false,
"---", null,
"context-cut", true,
"context-copy", true,
"context-paste", null, // ignore clipboard state
"context-delete", false,
"---", null,
"context-selectall", false,
"---", null,
"spell-check-enabled", true]);
await test_contextmenu("#input_text", [
"context-undo",
false,
"---",
null,
"context-cut",
true,
"context-copy",
true,
"context-paste",
null, // ignore clipboard state
"context-delete",
false,
"---",
null,
"context-selectall",
false,
"---",
null,
"spell-check-enabled",
true,
]);
});
add_task(async function test_text_input_spellcheck() {
await test_contextmenu("#input_spellcheck_no_value",
["context-undo", false,
"---", null,
"context-cut", true,
"context-copy", true,
"context-paste", null, // ignore clipboard state
"context-delete", false,
"---", null,
"context-selectall", false,
"---", null,
"spell-check-enabled", true,
"spell-dictionaries", true,
["spell-check-dictionary-en-US", true,
"---", null,
"spell-add-dictionaries", true], null],
await test_contextmenu(
"#input_spellcheck_no_value",
[
"context-undo",
false,
"---",
null,
"context-cut",
true,
"context-copy",
true,
"context-paste",
null, // ignore clipboard state
"context-delete",
false,
"---",
null,
"context-selectall",
false,
"---",
null,
"spell-check-enabled",
true,
"spell-dictionaries",
true,
[
"spell-check-dictionary-en-US",
true,
"---",
null,
"spell-add-dictionaries",
true,
],
null,
],
{
waitForSpellCheck: true,
// Need to dynamically add/remove the "password" type or LoginManager
// will think that the form inputs on the page are part of a login
// and will add fill-login context menu items.
async preCheckContextMenuFn() {
await ContentTask.spawn(gBrowser.selectedBrowser, null, async function() {
let doc = content.document;
let input = doc.getElementById("input_spellcheck_no_value");
input.setAttribute("spellcheck", "true");
input.clientTop; // force layout flush
});
await ContentTask.spawn(
gBrowser.selectedBrowser,
null,
async function() {
let doc = content.document;
let input = doc.getElementById("input_spellcheck_no_value");
input.setAttribute("spellcheck", "true");
input.clientTop; // force layout flush
}
);
},
}
);
});
add_task(async function test_text_input_spellcheckwrong() {
await test_contextmenu("#input_spellcheck_incorrect",
["*prodigality", true, // spelling suggestion
"spell-add-to-dictionary", true,
"---", null,
"context-undo", false,
"---", null,
"context-cut", true,
"context-copy", true,
"context-paste", null, // ignore clipboard state
"context-delete", false,
"---", null,
"context-selectall", true,
"---", null,
"spell-check-enabled", true,
"spell-dictionaries", true,
["spell-check-dictionary-en-US", true,
"---", null,
"spell-add-dictionaries", true], null],
{waitForSpellCheck: true}
);
await test_contextmenu(
"#input_spellcheck_incorrect",
[
"*prodigality",
true, // spelling suggestion
"spell-add-to-dictionary",
true,
"---",
null,
"context-undo",
false,
"---",
null,
"context-cut",
true,
"context-copy",
true,
"context-paste",
null, // ignore clipboard state
"context-delete",
false,
"---",
null,
"context-selectall",
true,
"---",
null,
"spell-check-enabled",
true,
"spell-dictionaries",
true,
[
"spell-check-dictionary-en-US",
true,
"---",
null,
"spell-add-dictionaries",
true,
],
null,
],
{ waitForSpellCheck: true }
);
});
add_task(async function test_text_input_spellcheckcorrect() {
await test_contextmenu("#input_spellcheck_correct",
["context-undo", false,
"---", null,
"context-cut", true,
"context-copy", true,
"context-paste", null, // ignore clipboard state
"context-delete", false,
"---", null,
"context-selectall", true,
"---", null,
"spell-check-enabled", true,
"spell-dictionaries", true,
["spell-check-dictionary-en-US", true,
"---", null,
"spell-add-dictionaries", true], null],
{waitForSpellCheck: true}
await test_contextmenu(
"#input_spellcheck_correct",
[
"context-undo",
false,
"---",
null,
"context-cut",
true,
"context-copy",
true,
"context-paste",
null, // ignore clipboard state
"context-delete",
false,
"---",
null,
"context-selectall",
true,
"---",
null,
"spell-check-enabled",
true,
"spell-dictionaries",
true,
[
"spell-check-dictionary-en-US",
true,
"---",
null,
"spell-add-dictionaries",
true,
],
null,
],
{ waitForSpellCheck: true }
);
});
add_task(async function test_text_input_disabled() {
await test_contextmenu("#input_disabled",
["context-undo", false,
"---", null,
"context-cut", true,
"context-copy", true,
"context-paste", null, // ignore clipboard state
"context-delete", false,
"---", null,
"context-selectall", true,
"---", null,
"spell-check-enabled", true],
{skipFocusChange: true}
await test_contextmenu(
"#input_disabled",
[
"context-undo",
false,
"---",
null,
"context-cut",
true,
"context-copy",
true,
"context-paste",
null, // ignore clipboard state
"context-delete",
false,
"---",
null,
"context-selectall",
true,
"---",
null,
"spell-check-enabled",
true,
],
{ skipFocusChange: true }
);
});
add_task(async function test_password_input() {
todo(false, "context-selectall is enabled on osx-e10s, and windows when" +
" it should be disabled");
await test_contextmenu("#input_password",
["context-undo", false,
"---", null,
"context-cut", true,
"context-copy", true,
"context-paste", null, // ignore clipboard state
"context-delete", false,
"---", null,
"context-selectall", null,
"---", null,
"fill-login", null,
["fill-login-no-logins", false,
"---", null,
"fill-login-saved-passwords", true], null],
todo(
false,
"context-selectall is enabled on osx-e10s, and windows when" +
" it should be disabled"
);
await test_contextmenu(
"#input_password",
[
"context-undo",
false,
"---",
null,
"context-cut",
true,
"context-copy",
true,
"context-paste",
null, // ignore clipboard state
"context-delete",
false,
"---",
null,
"context-selectall",
null,
"---",
null,
"fill-login",
null,
[
"fill-login-no-logins",
false,
"---",
null,
"fill-login-saved-passwords",
true,
],
null,
],
{
skipFocusChange: true,
// Need to dynamically add/remove the "password" type or LoginManager
// will think that the form inputs on the page are part of a login
// and will add fill-login context menu items.
async preCheckContextMenuFn() {
await ContentTask.spawn(gBrowser.selectedBrowser, null, async function() {
let doc = content.document;
let input = doc.getElementById("input_password");
input.type = "password";
input.clientTop; // force layout flush
});
await ContentTask.spawn(
gBrowser.selectedBrowser,
null,
async function() {
let doc = content.document;
let input = doc.getElementById("input_password");
input.type = "password";
input.clientTop; // force layout flush
}
);
},
async postCheckContextMenuFn() {
await ContentTask.spawn(gBrowser.selectedBrowser, null, async function() {
let doc = content.document;
let input = doc.getElementById("input_password");
input.type = "text";
input.clientTop; // force layout flush
});
await ContentTask.spawn(
gBrowser.selectedBrowser,
null,
async function() {
let doc = content.document;
let input = doc.getElementById("input_password");
input.type = "text";
input.clientTop; // force layout flush
}
);
},
}
);
});
add_task(async function test_tel_email_url_number_input() {
todo(false, "context-selectall is enabled on osx-e10s, and windows when" +
" it should be disabled");
for (let selector of ["#input_email", "#input_url", "#input_tel", "#input_number"]) {
await test_contextmenu(selector,
["context-undo", false,
"---", null,
"context-cut", true,
"context-copy", true,
"context-paste", null, // ignore clipboard state
"context-delete", false,
"---", null,
"context-selectall", null], {
skipFocusChange: true,
});
todo(
false,
"context-selectall is enabled on osx-e10s, and windows when" +
" it should be disabled"
);
for (let selector of [
"#input_email",
"#input_url",
"#input_tel",
"#input_number",
]) {
await test_contextmenu(
selector,
[
"context-undo",
false,
"---",
null,
"context-cut",
true,
"context-copy",
true,
"context-paste",
null, // ignore clipboard state
"context-delete",
false,
"---",
null,
"context-selectall",
null,
],
{
skipFocusChange: true,
}
);
}
});
add_task(async function test_date_time_color_range_month_week_datetimelocal_input() {
for (let selector of ["#input_date", "#input_time", "#input_color",
"#input_range", "#input_month", "#input_week",
"#input_datetime-local"]) {
await test_contextmenu(selector,
["context-navigation", null,
["context-back", false,
"context-forward", false,
"context-reload", true,
"context-bookmarkpage", true], null,
"---", null,
"context-savepage", true,
...(hasPocket ? ["context-pocket", true] : []),
"---", null,
"context-sendpagetodevice", null, [], null,
"---", null,
"context-viewbgimage", false,
"context-selectall", null,
"---", null,
"context-viewsource", true,
"context-viewinfo", true], {
add_task(
async function test_date_time_color_range_month_week_datetimelocal_input() {
for (let selector of [
"#input_date",
"#input_time",
"#input_color",
"#input_range",
"#input_month",
"#input_week",
"#input_datetime-local",
]) {
await test_contextmenu(
selector,
[
"context-navigation",
null,
[
"context-back",
false,
"context-forward",
false,
"context-reload",
true,
"context-bookmarkpage",
true,
],
null,
"---",
null,
"context-savepage",
true,
...(hasPocket ? ["context-pocket", true] : []),
"---",
null,
"context-sendpagetodevice",
null,
[],
null,
"---",
null,
"context-viewbgimage",
false,
"context-selectall",
null,
"---",
null,
"context-viewsource",
true,
"context-viewinfo",
true,
],
{
// XXX Bug 1345081. Currently the Screenshots menu option is shown for
// various text elements even though it is set to type "page". That bug
// should remove the need for next line.
maybeScreenshotsPresent: true,
skipFocusChange: true,
}
);
}
}
);
add_task(async function test_search_input() {
todo(
false,
"context-selectall is enabled on osx-e10s, and windows when" +
" it should be disabled"
);
await test_contextmenu(
"#input_search",
[
"context-undo",
false,
"---",
null,
"context-cut",
true,
"context-copy",
true,
"context-paste",
null, // ignore clipboard state
"context-delete",
false,
"---",
null,
"context-selectall",
null,
"---",
null,
"spell-check-enabled",
true,
],
{ skipFocusChange: true }
);
});
add_task(async function test_text_input_readonly() {
todo(
false,
"context-selectall is enabled on osx-e10s, and windows when" +
" it should be disabled"
);
todo(
false,
"spell-check should not be enabled for input[readonly]. see bug 1246296"
);
await test_contextmenu(
"#input_readonly",
[
"context-undo",
false,
"---",
null,
"context-cut",
true,
"context-copy",
true,
"context-paste",
null, // ignore clipboard state
"context-delete",
false,
"---",
null,
"context-selectall",
null,
],
{
// XXX Bug 1345081. Currently the Screenshots menu option is shown for
// various text elements even though it is set to type "page". That bug
// should remove the need for next line.
maybeScreenshotsPresent: true,
skipFocusChange: true,
});
}
});
add_task(async function test_search_input() {
todo(false, "context-selectall is enabled on osx-e10s, and windows when" +
" it should be disabled");
await test_contextmenu("#input_search",
["context-undo", false,
"---", null,
"context-cut", true,
"context-copy", true,
"context-paste", null, // ignore clipboard state
"context-delete", false,
"---", null,
"context-selectall", null,
"---", null,
"spell-check-enabled", true],
{skipFocusChange: true}
}
);
});
add_task(async function test_text_input_readonly() {
todo(false, "context-selectall is enabled on osx-e10s, and windows when" +
" it should be disabled");
todo(false, "spell-check should not be enabled for input[readonly]. see bug 1246296");
await test_contextmenu("#input_readonly",
["context-undo", false,
"---", null,
"context-cut", true,
"context-copy", true,
"context-paste", null, // ignore clipboard state
"context-delete", false,
"---", null,
"context-selectall", null], {
// XXX Bug 1345081. Currently the Screenshots menu option is shown for
// various text elements even though it is set to type "page". That bug
// should remove the need for next line.
maybeScreenshotsPresent: true,
skipFocusChange: true,
});
});
add_task(async function test_cleanup() {
BrowserTestUtils.removeTab(gBrowser.selectedTab);
});

Просмотреть файл

@ -4,7 +4,11 @@
"use strict";
const TEST_LINK = "https://example.com/";
const RESOURCE_LINK = getRootDirectory(gTestPath).replace("chrome://mochitests/content", "https://example.com") + "test_contextmenu_links.html";
const RESOURCE_LINK =
getRootDirectory(gTestPath).replace(
"chrome://mochitests/content",
"https://example.com"
) + "test_contextmenu_links.html";
async function activateContextAndWaitFor(selector, where) {
info("Starting test for " + where);
@ -15,42 +19,69 @@ async function activateContextAndWaitFor(selector, where) {
case "tab":
contextMenuItem += "intab";
openPromise = BrowserTestUtils.waitForNewTab(gBrowser, TEST_LINK, false);
closeMethod = async (tab) => BrowserTestUtils.removeTab(tab);
closeMethod = async tab => BrowserTestUtils.removeTab(tab);
break;
case "privatewindow":
contextMenuItem += "private";
openPromise = BrowserTestUtils.waitForNewWindow({url: TEST_LINK}).then(win => {
ok(PrivateBrowsingUtils.isWindowPrivate(win), "Should have opened a private window.");
return win;
});
closeMethod = async (win) => BrowserTestUtils.closeWindow(win);
openPromise = BrowserTestUtils.waitForNewWindow({ url: TEST_LINK }).then(
win => {
ok(
PrivateBrowsingUtils.isWindowPrivate(win),
"Should have opened a private window."
);
return win;
}
);
closeMethod = async win => BrowserTestUtils.closeWindow(win);
break;
case "window":
// No contextMenuItem suffix for normal new windows;
openPromise = BrowserTestUtils.waitForNewWindow({url: TEST_LINK}).then(win => {
ok(!PrivateBrowsingUtils.isWindowPrivate(win), "Should have opened a normal window.");
return win;
});
closeMethod = async (win) => BrowserTestUtils.closeWindow(win);
openPromise = BrowserTestUtils.waitForNewWindow({ url: TEST_LINK }).then(
win => {
ok(
!PrivateBrowsingUtils.isWindowPrivate(win),
"Should have opened a normal window."
);
return win;
}
);
closeMethod = async win => BrowserTestUtils.closeWindow(win);
break;
}
let contextMenu = document.getElementById("contentAreaContextMenu");
is(contextMenu.state, "closed", "checking if popup is closed");
let awaitPopupShown = BrowserTestUtils.waitForEvent(contextMenu, "popupshown");
await BrowserTestUtils.synthesizeMouse(selector, 0, 0, {
let awaitPopupShown = BrowserTestUtils.waitForEvent(
contextMenu,
"popupshown"
);
await BrowserTestUtils.synthesizeMouse(
selector,
0,
0,
{
type: "contextmenu",
button: 2,
centered: true,
},
gBrowser.selectedBrowser);
gBrowser.selectedBrowser
);
await awaitPopupShown;
info("Popup Shown");
let awaitPopupHidden = BrowserTestUtils.waitForEvent(contextMenu, "popuphidden");
let awaitPopupHidden = BrowserTestUtils.waitForEvent(
contextMenu,
"popuphidden"
);
let domItem = contextMenu.querySelector("#context-" + contextMenuItem);
info("Going to click item " + domItem.id);
let bounds = domItem.getBoundingClientRect();
ok(bounds.height && bounds.width, "DOM context menu item " + where + " should be visible");
ok(!domItem.disabled, "DOM context menu item " + where + " shouldn't be disabled");
ok(
bounds.height && bounds.width,
"DOM context menu item " + where + " should be visible"
);
ok(
!domItem.disabled,
"DOM context menu item " + where + " shouldn't be disabled"
);
domItem.click();
contextMenu.hidePopup();
await awaitPopupHidden;
@ -62,8 +93,16 @@ async function activateContextAndWaitFor(selector, where) {
}
add_task(async function test_select_text_link() {
let testTab = await BrowserTestUtils.openNewForegroundTab(gBrowser, RESOURCE_LINK);
for (let elementID of ["test-link", "test-image-link", "svg-with-link", "svg-with-relative-link"]) {
let testTab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
RESOURCE_LINK
);
for (let elementID of [
"test-link",
"test-image-link",
"svg-with-link",
"svg-with-relative-link",
]) {
for (let where of ["tab", "window", "privatewindow"]) {
await activateContextAndWaitFor("#" + elementID, where);
}

Просмотреть файл

@ -13,16 +13,23 @@ async function openAndCheckContextMenu(contextMenu, target) {
await popupshown;
is(contextMenu.state, "open", "Context menu is open.");
is(contextMenu.getAttribute("touchmode"), "true", "Context menu is in touchmode.");
is(
contextMenu.getAttribute("touchmode"),
"true",
"Context menu is in touchmode."
);
contextMenu.hidePopup();
popupshown = BrowserTestUtils.waitForEvent(contextMenu, "popupshown");
EventUtils.synthesizeMouseAtCenter(target, {type: "contextmenu"});
EventUtils.synthesizeMouseAtCenter(target, { type: "contextmenu" });
await popupshown;
is(contextMenu.state, "open", "Context menu is open.");
ok(!contextMenu.hasAttribute("touchmode"), "Context menu is not in touchmode.");
ok(
!contextMenu.hasAttribute("touchmode"),
"Context menu is not in touchmode."
);
contextMenu.hidePopup();
}
@ -31,9 +38,7 @@ async function openAndCheckContextMenu(contextMenu, target) {
add_task(async function setup() {
let isWindows = AppConstants.isPlatformAndVersionAtLeast("win", "10.0");
await SpecialPowers.pushPrefEnv({
set: [
["apz.test.fails_with_native_injection", isWindows],
],
set: [["apz.test.fails_with_native_injection", isWindows]],
});
});
@ -47,18 +52,23 @@ add_task(async function test_contentarea_contextmenu_touch() {
// Test the back and forward buttons.
add_task(async function test_back_forward_button_contextmenu_touch() {
await BrowserTestUtils.withNewTab("http://example.com", async function(browser) {
await BrowserTestUtils.withNewTab("http://example.com", async function(
browser
) {
let contextMenu = document.getElementById("backForwardMenu");
let backbutton = document.getElementById("back-button");
let notDisabled = BrowserTestUtils.waitForCondition(() => !backbutton.hasAttribute("disabled"));
let notDisabled = BrowserTestUtils.waitForCondition(
() => !backbutton.hasAttribute("disabled")
);
BrowserTestUtils.loadURI(browser, "http://example.org");
await notDisabled;
await openAndCheckContextMenu(contextMenu, backbutton);
let forwardbutton = document.getElementById("forward-button");
notDisabled = BrowserTestUtils.waitForCondition(() => !forwardbutton.hasAttribute("disabled"));
notDisabled = BrowserTestUtils.waitForCondition(
() => !forwardbutton.hasAttribute("disabled")
);
backbutton.click();
await notDisabled;
await openAndCheckContextMenu(contextMenu, forwardbutton);
@ -75,8 +85,11 @@ add_task(async function test_toolbar_contextmenu_touch() {
// Test the urlbar input context menu.
add_task(async function test_urlbar_contextmenu_touch() {
let urlbar = document.getElementById("urlbar");
let textBox = document.getAnonymousElementByAttribute(urlbar,
"anonid", "moz-input-box");
let textBox = document.getAnonymousElementByAttribute(
urlbar,
"anonid",
"moz-input-box"
);
let menu = textBox.menupopup;
await openAndCheckContextMenu(menu, textBox);
});

Просмотреть файл

@ -40,7 +40,7 @@ function test_eventMatchesKey() {
key.setAttribute("key", "t");
key.setAttribute("modifiers", "accel");
keyset.appendChild(key);
EventUtils.synthesizeKey("t", {accelKey: true});
EventUtils.synthesizeKey("t", { accelKey: true });
is(eventMatchResult, true, "eventMatchesKey: one modifier");
keyset.removeChild(key);
@ -48,7 +48,7 @@ function test_eventMatchesKey() {
key.setAttribute("key", "g");
key.setAttribute("modifiers", "accel,shift");
keyset.appendChild(key);
EventUtils.synthesizeKey("g", {accelKey: true, shiftKey: true});
EventUtils.synthesizeKey("g", { accelKey: true, shiftKey: true });
is(eventMatchResult, true, "eventMatchesKey: combination modifiers");
keyset.removeChild(key);
@ -56,14 +56,14 @@ function test_eventMatchesKey() {
key.setAttribute("key", "w");
key.setAttribute("modifiers", "accel");
keyset.appendChild(key);
EventUtils.synthesizeKey("f", {accelKey: true});
EventUtils.synthesizeKey("f", { accelKey: true });
is(eventMatchResult, false, "eventMatchesKey: mismatch keys");
keyset.removeChild(key);
key = document.createXULElement("key");
key.setAttribute("keycode", "VK_DELETE");
keyset.appendChild(key);
EventUtils.synthesizeKey("VK_DELETE", {accelKey: true});
EventUtils.synthesizeKey("VK_DELETE", { accelKey: true });
is(eventMatchResult, false, "eventMatchesKey: mismatch modifiers");
keyset.removeChild(key);
} finally {
@ -81,22 +81,37 @@ function test_getTopWin() {
}
function test_openNewTabWith() {
openNewTabWith("http://example.com/", null, {triggeringPrincipal: Services.scriptSecurityManager.createNullPrincipal({})});
let tab = gBrowser.selectedTab = gBrowser.tabs[1];
openNewTabWith("http://example.com/", null, {
triggeringPrincipal: Services.scriptSecurityManager.createNullPrincipal({}),
});
let tab = (gBrowser.selectedTab = gBrowser.tabs[1]);
BrowserTestUtils.browserLoaded(tab.linkedBrowser).then(() => {
is(tab.linkedBrowser.currentURI.spec, "http://example.com/", "example.com loaded");
is(
tab.linkedBrowser.currentURI.spec,
"http://example.com/",
"example.com loaded"
);
gBrowser.removeCurrentTab();
runNextTest();
});
}
function test_openUILink() {
let tab = gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, "about:blank");
let tab = (gBrowser.selectedTab = BrowserTestUtils.addTab(
gBrowser,
"about:blank"
));
BrowserTestUtils.browserLoaded(tab.linkedBrowser).then(() => {
is(tab.linkedBrowser.currentURI.spec, "http://example.org/", "example.org loaded");
is(
tab.linkedBrowser.currentURI.spec,
"http://example.org/",
"example.org loaded"
);
gBrowser.removeCurrentTab();
runNextTest();
});
openUILink("http://example.org/", null, {triggeringPrincipal: Services.scriptSecurityManager.createNullPrincipal({})}); // defaults to "current"
openUILink("http://example.org/", null, {
triggeringPrincipal: Services.scriptSecurityManager.createNullPrincipal({}),
}); // defaults to "current"
}

Просмотреть файл

@ -2,9 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const gTests = [
test_openUILink_checkPrincipal,
];
const gTests = [test_openUILink_checkPrincipal];
function test() {
waitForExplicitFinish();
@ -22,9 +20,16 @@ function runNextTest() {
}
function test_openUILink_checkPrincipal() {
let tab = gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, "http://example.com/"); // remote tab
let tab = (gBrowser.selectedTab = BrowserTestUtils.addTab(
gBrowser,
"http://example.com/"
)); // remote tab
BrowserTestUtils.browserLoaded(tab.linkedBrowser).then(async function() {
is(tab.linkedBrowser.currentURI.spec, "http://example.com/", "example.com loaded");
is(
tab.linkedBrowser.currentURI.spec,
"http://example.com/",
"example.com loaded"
);
await ContentTask.spawn(tab.linkedBrowser, null, function() {
let channel = content.docShell.currentDocumentChannel;
@ -32,14 +37,24 @@ function test_openUILink_checkPrincipal() {
const loadingPrincipal = channel.loadInfo.loadingPrincipal;
is(loadingPrincipal, null, "sanity: correct loadingPrincipal");
const triggeringPrincipal = channel.loadInfo.triggeringPrincipal;
ok(triggeringPrincipal.isSystemPrincipal,
"sanity: correct triggeringPrincipal");
ok(
triggeringPrincipal.isSystemPrincipal,
"sanity: correct triggeringPrincipal"
);
const principalToInherit = channel.loadInfo.principalToInherit;
ok(principalToInherit.isNullPrincipal, "sanity: correct principalToInherit");
ok(content.document.nodePrincipal.isCodebasePrincipal,
"sanity: correct doc.nodePrincipal");
is(content.document.nodePrincipal.URI.asciiSpec, "http://example.com/",
"sanity: correct doc.nodePrincipal URL");
ok(
principalToInherit.isNullPrincipal,
"sanity: correct principalToInherit"
);
ok(
content.document.nodePrincipal.isCodebasePrincipal,
"sanity: correct doc.nodePrincipal"
);
is(
content.document.nodePrincipal.URI.asciiSpec,
"http://example.com/",
"sanity: correct doc.nodePrincipal URL"
);
});
gBrowser.removeCurrentTab();

Просмотреть файл

@ -5,180 +5,246 @@ var lastElement;
const FRAME_OS_PID = "context-frameOsPid";
function openContextMenuFor(element, shiftkey, waitForSpellCheck) {
// Context menu should be closed before we open it again.
is(SpecialPowers.wrap(contextMenu).state, "closed", "checking if popup is closed");
// Context menu should be closed before we open it again.
is(
SpecialPowers.wrap(contextMenu).state,
"closed",
"checking if popup is closed"
);
if (lastElement)
lastElement.blur();
element.focus();
if (lastElement) {
lastElement.blur();
}
element.focus();
// Some elements need time to focus and spellcheck before any tests are
// run on them.
function actuallyOpenContextMenuFor() {
lastElement = element;
var eventDetails = { type: "contextmenu", button: 2, shiftKey: shiftkey };
synthesizeMouse(element, 2, 2, eventDetails, element.ownerGlobal);
}
// Some elements need time to focus and spellcheck before any tests are
// run on them.
function actuallyOpenContextMenuFor() {
lastElement = element;
var eventDetails = { type: "contextmenu", button: 2, shiftKey: shiftkey };
synthesizeMouse(element, 2, 2, eventDetails, element.ownerGlobal);
}
if (waitForSpellCheck) {
var { onSpellCheck } =
SpecialPowers.Cu.import(
"resource://testing-common/AsyncSpellCheckTestHelper.jsm", {});
onSpellCheck(element, actuallyOpenContextMenuFor);
} else {
actuallyOpenContextMenuFor();
}
if (waitForSpellCheck) {
var { onSpellCheck } = SpecialPowers.Cu.import(
"resource://testing-common/AsyncSpellCheckTestHelper.jsm",
{}
);
onSpellCheck(element, actuallyOpenContextMenuFor);
} else {
actuallyOpenContextMenuFor();
}
}
function closeContextMenu() {
contextMenu.hidePopup();
contextMenu.hidePopup();
}
function getVisibleMenuItems(aMenu, aData) {
var items = [];
var accessKeys = {};
for (var i = 0; i < aMenu.children.length; i++) {
var item = aMenu.children[i];
if (item.hidden)
continue;
var key = item.accessKey;
if (key)
key = key.toLowerCase();
var isPageMenuItem = item.hasAttribute("generateditemid");
if (item.nodeName == "menuitem") {
var isGenerated = item.classList.contains("spell-suggestion")
|| item.classList.contains("sendtab-target");
if (isGenerated) {
is(item.id, "", "child menuitem #" + i + " is generated");
} else if (isPageMenuItem) {
is(item.id, "", "child menuitem #" + i + " is a generated page menu item");
} else {
ok(item.id, "child menuitem #" + i + " has an ID");
}
var label = item.getAttribute("label");
ok(label.length, "menuitem " + item.id + " has a label");
if (isGenerated) {
is(key, "", "Generated items shouldn't have an access key");
items.push("*" + label);
} else if (isPageMenuItem) {
items.push("+" + label);
} else if (item.id.indexOf("spell-check-dictionary-") != 0 &&
item.id != "spell-no-suggestions" &&
item.id != "spell-add-dictionaries-main" &&
item.id != "context-savelinktopocket" &&
item.id != "fill-login-saved-passwords" &&
item.id != "fill-login-no-logins" &&
// XXX Screenshots doesn't have an access key. This needs
// at least bug 1320462 fixing first.
item.id != "screenshots_mozilla_org-menuitem-_create-screenshot") {
if (item.id != FRAME_OS_PID) {
ok(key, "menuitem " + item.id + " has an access key");
}
if (accessKeys[key])
ok(false, "menuitem " + item.id + " has same accesskey as " + accessKeys[key]);
else
accessKeys[key] = item.id;
}
if (!isGenerated && !isPageMenuItem) {
items.push(item.id);
}
if (isPageMenuItem) {
var p = {};
p.type = item.getAttribute("type");
p.icon = item.getAttribute("image");
p.checked = item.hasAttribute("checked");
p.disabled = item.hasAttribute("disabled");
items.push(p);
} else {
items.push(!item.disabled);
}
} else if (item.nodeName == "menuseparator") {
ok(true, "--- seperator id is " + item.id);
items.push("---");
items.push(null);
} else if (item.nodeName == "menu") {
if (isPageMenuItem) {
item.id = "generated-submenu-" + aData.generatedSubmenuId++;
}
ok(item.id, "child menu #" + i + " has an ID");
if (!isPageMenuItem) {
ok(key, "menu has an access key");
if (accessKeys[key])
ok(false, "menu " + item.id + " has same accesskey as " + accessKeys[key]);
else
accessKeys[key] = item.id;
}
items.push(item.id);
items.push(!item.disabled);
// Add a dummy item so that the indexes in checkMenu are the same
// for expectedItems and actualItems.
items.push([]);
items.push(null);
} else if (item.nodeName == "menugroup") {
ok(item.id, "child menugroup #" + i + " has an ID");
items.push(item.id);
items.push(!item.disabled);
var menugroupChildren = [];
for (var child of item.children) {
if (child.hidden)
continue;
menugroupChildren.push([child.id, !child.disabled]);
}
items.push(menugroupChildren);
items.push(null);
} else {
ok(false, "child #" + i + " of menu ID " + aMenu.id +
" has an unknown type (" + item.nodeName + ")");
}
var items = [];
var accessKeys = {};
for (var i = 0; i < aMenu.children.length; i++) {
var item = aMenu.children[i];
if (item.hidden) {
continue;
}
return items;
var key = item.accessKey;
if (key) {
key = key.toLowerCase();
}
var isPageMenuItem = item.hasAttribute("generateditemid");
if (item.nodeName == "menuitem") {
var isGenerated =
item.classList.contains("spell-suggestion") ||
item.classList.contains("sendtab-target");
if (isGenerated) {
is(item.id, "", "child menuitem #" + i + " is generated");
} else if (isPageMenuItem) {
is(
item.id,
"",
"child menuitem #" + i + " is a generated page menu item"
);
} else {
ok(item.id, "child menuitem #" + i + " has an ID");
}
var label = item.getAttribute("label");
ok(label.length, "menuitem " + item.id + " has a label");
if (isGenerated) {
is(key, "", "Generated items shouldn't have an access key");
items.push("*" + label);
} else if (isPageMenuItem) {
items.push("+" + label);
} else if (
item.id.indexOf("spell-check-dictionary-") != 0 &&
item.id != "spell-no-suggestions" &&
item.id != "spell-add-dictionaries-main" &&
item.id != "context-savelinktopocket" &&
item.id != "fill-login-saved-passwords" &&
item.id != "fill-login-no-logins" &&
// XXX Screenshots doesn't have an access key. This needs
// at least bug 1320462 fixing first.
item.id != "screenshots_mozilla_org-menuitem-_create-screenshot"
) {
if (item.id != FRAME_OS_PID) {
ok(key, "menuitem " + item.id + " has an access key");
}
if (accessKeys[key]) {
ok(
false,
"menuitem " + item.id + " has same accesskey as " + accessKeys[key]
);
} else {
accessKeys[key] = item.id;
}
}
if (!isGenerated && !isPageMenuItem) {
items.push(item.id);
}
if (isPageMenuItem) {
var p = {};
p.type = item.getAttribute("type");
p.icon = item.getAttribute("image");
p.checked = item.hasAttribute("checked");
p.disabled = item.hasAttribute("disabled");
items.push(p);
} else {
items.push(!item.disabled);
}
} else if (item.nodeName == "menuseparator") {
ok(true, "--- seperator id is " + item.id);
items.push("---");
items.push(null);
} else if (item.nodeName == "menu") {
if (isPageMenuItem) {
item.id = "generated-submenu-" + aData.generatedSubmenuId++;
}
ok(item.id, "child menu #" + i + " has an ID");
if (!isPageMenuItem) {
ok(key, "menu has an access key");
if (accessKeys[key]) {
ok(
false,
"menu " + item.id + " has same accesskey as " + accessKeys[key]
);
} else {
accessKeys[key] = item.id;
}
}
items.push(item.id);
items.push(!item.disabled);
// Add a dummy item so that the indexes in checkMenu are the same
// for expectedItems and actualItems.
items.push([]);
items.push(null);
} else if (item.nodeName == "menugroup") {
ok(item.id, "child menugroup #" + i + " has an ID");
items.push(item.id);
items.push(!item.disabled);
var menugroupChildren = [];
for (var child of item.children) {
if (child.hidden) {
continue;
}
menugroupChildren.push([child.id, !child.disabled]);
}
items.push(menugroupChildren);
items.push(null);
} else {
ok(
false,
"child #" +
i +
" of menu ID " +
aMenu.id +
" has an unknown type (" +
item.nodeName +
")"
);
}
}
return items;
}
function checkContextMenu(expectedItems) {
is(contextMenu.state, "open", "checking if popup is open");
var data = { generatedSubmenuId: 1 };
checkMenu(contextMenu, expectedItems, data);
is(contextMenu.state, "open", "checking if popup is open");
var data = { generatedSubmenuId: 1 };
checkMenu(contextMenu, expectedItems, data);
}
function checkMenuItem(actualItem, actualEnabled, expectedItem, expectedEnabled, index) {
is(actualItem, expectedItem,
"checking item #" + index / 2 + " (" + expectedItem + ") name");
function checkMenuItem(
actualItem,
actualEnabled,
expectedItem,
expectedEnabled,
index
) {
is(
actualItem,
expectedItem,
"checking item #" + index / 2 + " (" + expectedItem + ") name"
);
if (typeof expectedEnabled == "object" && expectedEnabled != null ||
typeof actualEnabled == "object" && actualEnabled != null) {
ok(!(actualEnabled == null), "actualEnabled is not null");
ok(!(expectedEnabled == null), "expectedEnabled is not null");
is(typeof actualEnabled, typeof expectedEnabled, "checking types");
if (
(typeof expectedEnabled == "object" && expectedEnabled != null) ||
(typeof actualEnabled == "object" && actualEnabled != null)
) {
ok(!(actualEnabled == null), "actualEnabled is not null");
ok(!(expectedEnabled == null), "expectedEnabled is not null");
is(typeof actualEnabled, typeof expectedEnabled, "checking types");
if (typeof actualEnabled != typeof expectedEnabled ||
actualEnabled == null || expectedEnabled == null)
return;
is(actualEnabled.type, expectedEnabled.type,
"checking item #" + index / 2 + " (" + expectedItem + ") type attr value");
var icon = actualEnabled.icon;
if (icon) {
var tmp = "";
var j = icon.length - 1;
while (j && icon[j] != "/") {
tmp = icon[j--] + tmp;
}
icon = tmp;
}
is(icon, expectedEnabled.icon,
"checking item #" + index / 2 + " (" + expectedItem + ") icon attr value");
is(actualEnabled.checked, expectedEnabled.checked,
"checking item #" + index / 2 + " (" + expectedItem + ") has checked attr");
is(actualEnabled.disabled, expectedEnabled.disabled,
"checking item #" + index / 2 + " (" + expectedItem + ") has disabled attr");
} else if (expectedEnabled != null) {
is(actualEnabled, expectedEnabled,
"checking item #" + index / 2 + " (" + expectedItem + ") enabled state");
if (
typeof actualEnabled != typeof expectedEnabled ||
actualEnabled == null ||
expectedEnabled == null
) {
return;
}
is(
actualEnabled.type,
expectedEnabled.type,
"checking item #" + index / 2 + " (" + expectedItem + ") type attr value"
);
var icon = actualEnabled.icon;
if (icon) {
var tmp = "";
var j = icon.length - 1;
while (j && icon[j] != "/") {
tmp = icon[j--] + tmp;
}
icon = tmp;
}
is(
icon,
expectedEnabled.icon,
"checking item #" + index / 2 + " (" + expectedItem + ") icon attr value"
);
is(
actualEnabled.checked,
expectedEnabled.checked,
"checking item #" + index / 2 + " (" + expectedItem + ") has checked attr"
);
is(
actualEnabled.disabled,
expectedEnabled.disabled,
"checking item #" +
index / 2 +
" (" +
expectedItem +
") has disabled attr"
);
} else if (expectedEnabled != null) {
is(
actualEnabled,
expectedEnabled,
"checking item #" + index / 2 + " (" + expectedItem + ") enabled state"
);
}
}
/*
@ -195,38 +261,63 @@ function checkMenuItem(actualItem, actualEnabled, expectedItem, expectedEnabled,
*
*/
function checkMenu(menu, expectedItems, data) {
var actualItems = getVisibleMenuItems(menu, data);
// ok(false, "Items are: " + actualItems);
for (var i = 0; i < expectedItems.length; i += 2) {
var actualItem = actualItems[i];
var actualEnabled = actualItems[i + 1];
var expectedItem = expectedItems[i];
var expectedEnabled = expectedItems[i + 1];
if (expectedItem instanceof Array) {
ok(true, "Checking submenu/menugroup...");
var previousId = expectedItems[i - 2]; // The last item was the menu ID.
var previousItem = menu.getElementsByAttribute("id", previousId)[0];
ok(previousItem, (previousItem ? previousItem.nodeName : "item") + " with previous id (" + previousId + ") found");
if (previousItem && previousItem.nodeName == "menu") {
ok(previousItem, "got a submenu element of id='" + previousId + "'");
is(previousItem.nodeName, "menu", "submenu element of id='" + previousId +
"' has expected nodeName");
checkMenu(previousItem.menupopup, expectedItem, data, i);
} else if (previousItem && previousItem.nodeName == "menugroup") {
ok(expectedItem.length, "menugroup must not be empty");
for (var j = 0; j < expectedItem.length / 2; j++) {
checkMenuItem(actualItems[i][j][0], actualItems[i][j][1], expectedItem[j * 2], expectedItem[j * 2 + 1], i + j * 2);
}
i += j;
} else {
ok(false, "previous item is not a menu or menugroup");
}
} else {
checkMenuItem(actualItem, actualEnabled, expectedItem, expectedEnabled, i);
var actualItems = getVisibleMenuItems(menu, data);
// ok(false, "Items are: " + actualItems);
for (var i = 0; i < expectedItems.length; i += 2) {
var actualItem = actualItems[i];
var actualEnabled = actualItems[i + 1];
var expectedItem = expectedItems[i];
var expectedEnabled = expectedItems[i + 1];
if (expectedItem instanceof Array) {
ok(true, "Checking submenu/menugroup...");
var previousId = expectedItems[i - 2]; // The last item was the menu ID.
var previousItem = menu.getElementsByAttribute("id", previousId)[0];
ok(
previousItem,
(previousItem ? previousItem.nodeName : "item") +
" with previous id (" +
previousId +
") found"
);
if (previousItem && previousItem.nodeName == "menu") {
ok(previousItem, "got a submenu element of id='" + previousId + "'");
is(
previousItem.nodeName,
"menu",
"submenu element of id='" + previousId + "' has expected nodeName"
);
checkMenu(previousItem.menupopup, expectedItem, data, i);
} else if (previousItem && previousItem.nodeName == "menugroup") {
ok(expectedItem.length, "menugroup must not be empty");
for (var j = 0; j < expectedItem.length / 2; j++) {
checkMenuItem(
actualItems[i][j][0],
actualItems[i][j][1],
expectedItem[j * 2],
expectedItem[j * 2 + 1],
i + j * 2
);
}
i += j;
} else {
ok(false, "previous item is not a menu or menugroup");
}
} else {
checkMenuItem(
actualItem,
actualEnabled,
expectedItem,
expectedEnabled,
i
);
}
// Could find unexpected extra items at the end...
is(actualItems.length, expectedItems.length, "checking expected number of menu entries");
}
// Could find unexpected extra items at the end...
is(
actualItems.length,
expectedItems.length,
"checking expected number of menu entries"
);
}
let lastElementSelector = null;
@ -270,16 +361,20 @@ async function test_contextmenu(selector, menuItems, options = {}) {
}
if (!options.skipFocusChange) {
await ContentTask.spawn(gBrowser.selectedBrowser,
[lastElementSelector, selector],
async function([contentLastElementSelector, contentSelector]) {
if (contentLastElementSelector) {
let contentLastElement = content.document.querySelector(contentLastElementSelector);
contentLastElement.blur();
await ContentTask.spawn(
gBrowser.selectedBrowser,
[lastElementSelector, selector],
async function([contentLastElementSelector, contentSelector]) {
if (contentLastElementSelector) {
let contentLastElement = content.document.querySelector(
contentLastElementSelector
);
contentLastElement.blur();
}
let element = content.document.querySelector(contentSelector);
element.focus();
}
let element = content.document.querySelector(contentSelector);
element.focus();
});
);
lastElementSelector = selector;
info(`Moved focus to ${selector}`);
}
@ -291,23 +386,34 @@ async function test_contextmenu(selector, menuItems, options = {}) {
if (options.waitForSpellCheck) {
info("Waiting for spell check");
await ContentTask.spawn(gBrowser.selectedBrowser, selector, async function(contentSelector) {
let {onSpellCheck} =
ChromeUtils.import("resource://testing-common/AsyncSpellCheckTestHelper.jsm");
await ContentTask.spawn(gBrowser.selectedBrowser, selector, async function(
contentSelector
) {
let { onSpellCheck } = ChromeUtils.import(
"resource://testing-common/AsyncSpellCheckTestHelper.jsm"
);
let element = content.document.querySelector(contentSelector);
await new Promise(resolve => onSpellCheck(element, resolve));
info("Spell check running");
});
}
let awaitPopupShown = BrowserTestUtils.waitForEvent(contextMenu, "popupshown");
await BrowserTestUtils.synthesizeMouse(selector, options.offsetX || 0, options.offsetY || 0, {
let awaitPopupShown = BrowserTestUtils.waitForEvent(
contextMenu,
"popupshown"
);
await BrowserTestUtils.synthesizeMouse(
selector,
options.offsetX || 0,
options.offsetY || 0,
{
type: "contextmenu",
button: 2,
shiftkey: options.shiftkey,
centered: options.centered,
},
gBrowser.selectedBrowser);
gBrowser.selectedBrowser
);
await awaitPopupShown;
info("Popup Shown");
@ -318,22 +424,27 @@ async function test_contextmenu(selector, menuItems, options = {}) {
if (menuItems) {
if (Services.prefs.getBoolPref("devtools.inspector.enabled", true)) {
let inspectItems = ["---", null,
"context-inspect", true];
let inspectItems = ["---", null, "context-inspect", true];
menuItems = menuItems.concat(inspectItems);
}
if (Services.prefs.getBoolPref("devtools.accessibility.enabled", true) &&
Services.appinfo.accessibilityEnabled) {
if (
Services.prefs.getBoolPref("devtools.accessibility.enabled", true) &&
Services.appinfo.accessibilityEnabled
) {
let inspectA11YItems = ["context-inspect-a11y", true];
menuItems = menuItems.concat(inspectA11YItems);
}
if (options.maybeScreenshotsPresent &&
!Services.prefs.getBoolPref("extensions.screenshots.disabled", false)) {
if (
options.maybeScreenshotsPresent &&
!Services.prefs.getBoolPref("extensions.screenshots.disabled", false)
) {
let screenshotItems = [
"---", null,
"screenshots_mozilla_org-menuitem-_create-screenshot", true,
"---",
null,
"screenshots_mozilla_org-menuitem-_create-screenshot",
true,
];
menuItems = menuItems.concat(screenshotItems);
@ -342,7 +453,10 @@ async function test_contextmenu(selector, menuItems, options = {}) {
checkContextMenu(menuItems);
}
let awaitPopupHidden = BrowserTestUtils.waitForEvent(contextMenu, "popuphidden");
let awaitPopupHidden = BrowserTestUtils.waitForEvent(
contextMenu,
"popuphidden"
);
if (options.postCheckContextMenuFn) {
await options.postCheckContextMenuFn();

Просмотреть файл

@ -1,7 +1,8 @@
add_task(async function test() {
let testPath = getRootDirectory(gTestPath);
await BrowserTestUtils.withNewTab({ gBrowser, url: "about:blank" },
await BrowserTestUtils.withNewTab(
{ gBrowser, url: "about:blank" },
async function(tabBrowser) {
const URI = testPath + "file_with_favicon.html";
const expectedIcon = testPath + "file_generic_favicon.ico";
@ -28,6 +29,6 @@ add_task(async function test() {
} catch (e) {
ok(true, "Should have been able to cancel the promise.");
}
});
}
);
});

Просмотреть файл

@ -1,7 +1,8 @@
add_task(async function test() {
let testPath = getRootDirectory(gTestPath);
await BrowserTestUtils.withNewTab({ gBrowser, url: "about:blank" },
await BrowserTestUtils.withNewTab(
{ gBrowser, url: "about:blank" },
async function(tabBrowser) {
const URI = testPath + "file_with_favicon.html";
const expectedIcon = testPath + "file_generic_favicon.ico";
@ -29,5 +30,6 @@ add_task(async function test() {
} catch (e) {
ok(true, "Should have been able to cancel the promise.");
}
});
}
);
});

Просмотреть файл

@ -1,20 +1,30 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
const ROOT = getRootDirectory(gTestPath).replace("chrome://mochitest/content/", "http://mochi.test:8888/");
const ROOT = getRootDirectory(gTestPath).replace(
"chrome://mochitest/content/",
"http://mochi.test:8888/"
);
add_task(async () => {
await BrowserTestUtils.withNewTab({ gBrowser, url: "about:blank" }, async (browser) => {
let faviconPromise = waitForFaviconMessage(true, `${ROOT}accept.sjs`);
await BrowserTestUtils.withNewTab(
{ gBrowser, url: "about:blank" },
async browser => {
let faviconPromise = waitForFaviconMessage(true, `${ROOT}accept.sjs`);
BrowserTestUtils.loadURI(browser, ROOT + "accept.html");
await BrowserTestUtils.browserLoaded(browser);
BrowserTestUtils.loadURI(browser, ROOT + "accept.html");
await BrowserTestUtils.browserLoaded(browser);
try {
let result = await faviconPromise;
Assert.equal(result.iconURL, `${ROOT}accept.sjs`, "Should have seen the icon");
} catch (e) {
Assert.ok(false, "Favicon load failed.");
try {
let result = await faviconPromise;
Assert.equal(
result.iconURL,
`${ROOT}accept.sjs`,
"Should have seen the icon"
);
} catch (e) {
Assert.ok(false, "Favicon load failed.");
}
}
});
);
});

Просмотреть файл

@ -1,17 +1,27 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
const ROOT = getRootDirectory(gTestPath).replace("chrome://mochitests/content/", "http://mochi.test:8888/");
const ROOT = getRootDirectory(gTestPath).replace(
"chrome://mochitests/content/",
"http://mochi.test:8888/"
);
add_task(async () => {
await BrowserTestUtils.withNewTab({ gBrowser, url: "about:blank" }, async (browser) => {
let faviconPromise = waitForFaviconMessage(true, `${ROOT}auth_test.png`);
await BrowserTestUtils.withNewTab(
{ gBrowser, url: "about:blank" },
async browser => {
let faviconPromise = waitForFaviconMessage(true, `${ROOT}auth_test.png`);
BrowserTestUtils.loadURI(browser, `${ROOT}auth_test.html`);
await BrowserTestUtils.browserLoaded(browser);
BrowserTestUtils.loadURI(browser, `${ROOT}auth_test.html`);
await BrowserTestUtils.browserLoaded(browser);
await Assert.rejects(faviconPromise, result => {
return result.iconURL == `${ROOT}auth_test.png`;
}, "Should have failed to load the icon.");
});
await Assert.rejects(
faviconPromise,
result => {
return result.iconURL == `${ROOT}auth_test.png`;
},
"Should have failed to load the icon."
);
}
);
});

Просмотреть файл

@ -1,6 +1,8 @@
add_task(async () => {
const testPath = "http://example.com/browser/browser/base/content/test/favicons/cookie_favicon.html";
const resetPath = "http://example.com/browser/browser/base/content/test/favicons/cookie_favicon.sjs?reset";
const testPath =
"http://example.com/browser/browser/base/content/test/favicons/cookie_favicon.html";
const resetPath =
"http://example.com/browser/browser/base/content/test/favicons/cookie_favicon.sjs?reset";
let tab = BrowserTestUtils.addTab(gBrowser, testPath);
gBrowser.selectedTab = tab;
@ -9,7 +11,10 @@ add_task(async () => {
let faviconPromise = waitForLinkAvailable(browser);
await BrowserTestUtils.browserLoaded(browser);
await faviconPromise;
let cookies = Services.cookies.getCookiesFromHost("example.com", browser.contentPrincipal.originAttributes);
let cookies = Services.cookies.getCookiesFromHost(
"example.com",
browser.contentPrincipal.originAttributes
);
let seenCookie = false;
for (let cookie of cookies) {
if (cookie.name == "faviconCookie") {
@ -23,7 +28,10 @@ add_task(async () => {
BrowserTestUtils.loadURI(browser, testPath);
await BrowserTestUtils.browserLoaded(browser);
await faviconPromise;
cookies = Services.cookies.getCookiesFromHost("example.com", browser.contentPrincipal.originAttributes);
cookies = Services.cookies.getCookiesFromHost(
"example.com",
browser.contentPrincipal.originAttributes
);
seenCookie = false;
for (let cookie of cookies) {
if (cookie.name == "faviconCookie") {

Просмотреть файл

@ -3,12 +3,16 @@
"use strict";
const TEST_ROOT = "http://mochi.test:8888/browser/browser/base/content/test/favicons/";
const TEST_ROOT =
"http://mochi.test:8888/browser/browser/base/content/test/favicons/";
const TEST_URL = TEST_ROOT + "file_favicon_change.html";
add_task(async function() {
let extraTab = gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
let haveChanged = waitForFavicon(extraTab.linkedBrowser, TEST_ROOT + "file_bug970276_favicon1.ico");
let extraTab = (gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser));
let haveChanged = waitForFavicon(
extraTab.linkedBrowser,
TEST_ROOT + "file_bug970276_favicon1.ico"
);
BrowserTestUtils.loadURI(extraTab.linkedBrowser, TEST_URL);
await BrowserTestUtils.browserLoaded(extraTab.linkedBrowser);
@ -27,4 +31,3 @@ add_task(async function() {
gBrowser.removeTab(extraTab);
});

Просмотреть файл

@ -1,6 +1,7 @@
"use strict";
const TEST_ROOT = "http://mochi.test:8888/browser/browser/base/content/test/favicons/";
const TEST_ROOT =
"http://mochi.test:8888/browser/browser/base/content/test/favicons/";
const TEST_URL = TEST_ROOT + "file_favicon_change_not_in_document.html";
/*
@ -16,13 +17,21 @@ const TEST_URL = TEST_ROOT + "file_favicon_change_not_in_document.html";
* event after its href gets updated later.
*/
add_task(async function() {
let extraTab = gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
let extraTab = (gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser));
let domLinkAddedFired = 0;
let domLinkChangedFired = 0;
const linkAddedHandler = event => domLinkAddedFired++;
const linkChangedhandler = event => domLinkChangedFired++;
BrowserTestUtils.addContentEventListener(gBrowser.selectedBrowser, "DOMLinkAdded", linkAddedHandler);
BrowserTestUtils.addContentEventListener(gBrowser.selectedBrowser, "DOMLinkChanged", linkChangedhandler);
BrowserTestUtils.addContentEventListener(
gBrowser.selectedBrowser,
"DOMLinkAdded",
linkAddedHandler
);
BrowserTestUtils.addContentEventListener(
gBrowser.selectedBrowser,
"DOMLinkChanged",
linkChangedhandler
);
let expectedFavicon = TEST_ROOT + "file_generic_favicon.ico";
let faviconPromise = waitForFavicon(extraTab.linkedBrowser, expectedFavicon);
@ -32,7 +41,11 @@ add_task(async function() {
await faviconPromise;
is(domLinkAddedFired, 2, "Should fire the correct number of DOMLinkAdded event.");
is(
domLinkAddedFired,
2,
"Should fire the correct number of DOMLinkAdded event."
);
is(domLinkChangedFired, 0, "Should not fire any DOMLinkChanged event.");
gBrowser.removeTab(extraTab);

Просмотреть файл

@ -14,20 +14,27 @@ const TEST_PAGE =
const FAVICON_URI =
TEST_SITE + "/browser/browser/base/content/test/favicons/file_favicon.png";
const TEST_THIRD_PARTY_PAGE =
TEST_SITE + "/browser/browser/base/content/test/favicons/file_favicon_thirdParty.html";
TEST_SITE +
"/browser/browser/base/content/test/favicons/file_favicon_thirdParty.html";
const THIRD_PARTY_FAVICON_URI =
TEST_THIRD_PARTY_SITE + "/browser/browser/base/content/test/favicons/file_favicon.png";
TEST_THIRD_PARTY_SITE +
"/browser/browser/base/content/test/favicons/file_favicon.png";
ChromeUtils.defineModuleGetter(this, "PromiseUtils",
"resource://gre/modules/PromiseUtils.jsm");
ChromeUtils.defineModuleGetter(this, "PlacesTestUtils",
"resource://testing-common/PlacesTestUtils.jsm");
ChromeUtils.defineModuleGetter(
this,
"PromiseUtils",
"resource://gre/modules/PromiseUtils.jsm"
);
ChromeUtils.defineModuleGetter(
this,
"PlacesTestUtils",
"resource://testing-common/PlacesTestUtils.jsm"
);
let systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal();
function clearAllImageCaches() {
var tools = Cc["@mozilla.org/image/tools;1"]
.getService(Ci.imgITools);
var tools = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools);
var imageCache = tools.getImgCacheForDocument(window.document);
imageCache.clearCache(true); // true=chrome
imageCache.clearCache(false); // false=content
@ -94,9 +101,11 @@ FaviconObserver.prototype = {
function waitOnFaviconLoaded(aFaviconURL) {
return PlacesTestUtils.waitForNotification(
"onPageChanged",
(uri, attr, value, id) => attr === Ci.nsINavHistoryObserver.ATTRIBUTE_FAVICON &&
value === aFaviconURL,
"history");
(uri, attr, value, id) =>
attr === Ci.nsINavHistoryObserver.ATTRIBUTE_FAVICON &&
value === aFaviconURL,
"history"
);
}
async function doTest(aTestPage, aFaviconURL, aTailingEnabled) {
@ -124,9 +133,9 @@ async function doTest(aTestPage, aFaviconURL, aTailingEnabled) {
}
async function setupTailingPreference(aTailingEnabled) {
await SpecialPowers.pushPrefEnv({"set": [
["network.http.tailing.enabled", aTailingEnabled],
]});
await SpecialPowers.pushPrefEnv({
set: [["network.http.tailing.enabled", aTailingEnabled]],
});
}
async function cleanup() {

Просмотреть файл

@ -3,57 +3,72 @@
/* eslint-disable mozilla/no-arbitrary-setTimeout */
const ROOTURI = "http://mochi.test:8888/browser/browser/base/content/test/favicons/";
const ROOTURI =
"http://mochi.test:8888/browser/browser/base/content/test/favicons/";
const ICON = "moz.png";
const DATAURL = "data:image/x-icon;base64,AAABAAEAEBAAAAAAAABoBQAAFgAAACgAAAAQAAAAIAAAAAEACAAAAAAAAAEAAAAAAAAAAAAAAAEAAAABAAAAAAAAAACAAACAAAAAgIAAgAAAAIAAgACAgAAAwMDAAMDcwADwyqYABAQEAAgICAAMDAwAERERABYWFgAcHBwAIiIiACkpKQBVVVUATU1NAEJCQgA5OTkAgHz/AFBQ/wCTANYA/+zMAMbW7wDW5+cAkKmtAAAAMwAAAGYAAACZAAAAzAAAMwAAADMzAAAzZgAAM5kAADPMAAAz/wAAZgAAAGYzAABmZgAAZpkAAGbMAABm/wAAmQAAAJkzAACZZgAAmZkAAJnMAACZ/wAAzAAAAMwzAADMZgAAzJkAAMzMAADM/wAA/2YAAP+ZAAD/zAAzAAAAMwAzADMAZgAzAJkAMwDMADMA/wAzMwAAMzMzADMzZgAzM5kAMzPMADMz/wAzZgAAM2YzADNmZgAzZpkAM2bMADNm/wAzmQAAM5kzADOZZgAzmZkAM5nMADOZ/wAzzAAAM8wzADPMZgAzzJkAM8zMADPM/wAz/zMAM/9mADP/mQAz/8wAM///AGYAAABmADMAZgBmAGYAmQBmAMwAZgD/AGYzAABmMzMAZjNmAGYzmQBmM8wAZjP/AGZmAABmZjMAZmZmAGZmmQBmZswAZpkAAGaZMwBmmWYAZpmZAGaZzABmmf8AZswAAGbMMwBmzJkAZszMAGbM/wBm/wAAZv8zAGb/mQBm/8wAzAD/AP8AzACZmQAAmTOZAJkAmQCZAMwAmQAAAJkzMwCZAGYAmTPMAJkA/wCZZgAAmWYzAJkzZgCZZpkAmWbMAJkz/wCZmTMAmZlmAJmZmQCZmcwAmZn/AJnMAACZzDMAZsxmAJnMmQCZzMwAmcz/AJn/AACZ/zMAmcxmAJn/mQCZ/8wAmf//AMwAAACZADMAzABmAMwAmQDMAMwAmTMAAMwzMwDMM2YAzDOZAMwzzADMM/8AzGYAAMxmMwCZZmYAzGaZAMxmzACZZv8AzJkAAMyZMwDMmWYAzJmZAMyZzADMmf8AzMwAAMzMMwDMzGYAzMyZAMzMzADMzP8AzP8AAMz/MwCZ/2YAzP+ZAMz/zADM//8AzAAzAP8AZgD/AJkAzDMAAP8zMwD/M2YA/zOZAP8zzAD/M/8A/2YAAP9mMwDMZmYA/2aZAP9mzADMZv8A/5kAAP+ZMwD/mWYA/5mZAP+ZzAD/mf8A/8wAAP/MMwD/zGYA/8yZAP/MzAD/zP8A//8zAMz/ZgD//5kA///MAGZm/wBm/2YAZv//AP9mZgD/Zv8A//9mACEApQBfX18Ad3d3AIaGhgCWlpYAy8vLALKysgDX19cA3d3dAOPj4wDq6uoA8fHxAPj4+ADw+/8ApKCgAICAgAAAAP8AAP8AAAD//wD/AAAA/wD/AP//AAD///8ACgoKCgoKCgoKCgoKCgoKCgoKCgoHAQEMbQoKCgoKCgoAAAdDH/kgHRIAAAAAAAAAAADrHfn5ASQQAAAAAAAAAArsBx0B+fkgHesAAAAAAAD/Cgwf+fn5IA4dEus/IvcACgcMAfkg+QEB+SABHushbf8QHR/5HQH5+QEdHetEHx4K7B/5+QH5+fkdDBL5+SBE/wwdJfkf+fn5AR8g+fkfEArsCh/5+QEeJR/5+SAeBwAACgoe+SAlHwFAEhAfAAAAAPcKHh8eASYBHhAMAAAAAAAA9EMdIB8gHh0dBwAAAAAAAAAA7BAdQ+wHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//AADwfwAAwH8AAMB/AAAAPwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAQAAgAcAAIAPAADADwAA8D8AAP//AAA=";
const DATAURL =
"data:image/x-icon;base64,AAABAAEAEBAAAAAAAABoBQAAFgAAACgAAAAQAAAAIAAAAAEACAAAAAAAAAEAAAAAAAAAAAAAAAEAAAABAAAAAAAAAACAAACAAAAAgIAAgAAAAIAAgACAgAAAwMDAAMDcwADwyqYABAQEAAgICAAMDAwAERERABYWFgAcHBwAIiIiACkpKQBVVVUATU1NAEJCQgA5OTkAgHz/AFBQ/wCTANYA/+zMAMbW7wDW5+cAkKmtAAAAMwAAAGYAAACZAAAAzAAAMwAAADMzAAAzZgAAM5kAADPMAAAz/wAAZgAAAGYzAABmZgAAZpkAAGbMAABm/wAAmQAAAJkzAACZZgAAmZkAAJnMAACZ/wAAzAAAAMwzAADMZgAAzJkAAMzMAADM/wAA/2YAAP+ZAAD/zAAzAAAAMwAzADMAZgAzAJkAMwDMADMA/wAzMwAAMzMzADMzZgAzM5kAMzPMADMz/wAzZgAAM2YzADNmZgAzZpkAM2bMADNm/wAzmQAAM5kzADOZZgAzmZkAM5nMADOZ/wAzzAAAM8wzADPMZgAzzJkAM8zMADPM/wAz/zMAM/9mADP/mQAz/8wAM///AGYAAABmADMAZgBmAGYAmQBmAMwAZgD/AGYzAABmMzMAZjNmAGYzmQBmM8wAZjP/AGZmAABmZjMAZmZmAGZmmQBmZswAZpkAAGaZMwBmmWYAZpmZAGaZzABmmf8AZswAAGbMMwBmzJkAZszMAGbM/wBm/wAAZv8zAGb/mQBm/8wAzAD/AP8AzACZmQAAmTOZAJkAmQCZAMwAmQAAAJkzMwCZAGYAmTPMAJkA/wCZZgAAmWYzAJkzZgCZZpkAmWbMAJkz/wCZmTMAmZlmAJmZmQCZmcwAmZn/AJnMAACZzDMAZsxmAJnMmQCZzMwAmcz/AJn/AACZ/zMAmcxmAJn/mQCZ/8wAmf//AMwAAACZADMAzABmAMwAmQDMAMwAmTMAAMwzMwDMM2YAzDOZAMwzzADMM/8AzGYAAMxmMwCZZmYAzGaZAMxmzACZZv8AzJkAAMyZMwDMmWYAzJmZAMyZzADMmf8AzMwAAMzMMwDMzGYAzMyZAMzMzADMzP8AzP8AAMz/MwCZ/2YAzP+ZAMz/zADM//8AzAAzAP8AZgD/AJkAzDMAAP8zMwD/M2YA/zOZAP8zzAD/M/8A/2YAAP9mMwDMZmYA/2aZAP9mzADMZv8A/5kAAP+ZMwD/mWYA/5mZAP+ZzAD/mf8A/8wAAP/MMwD/zGYA/8yZAP/MzAD/zP8A//8zAMz/ZgD//5kA///MAGZm/wBm/2YAZv//AP9mZgD/Zv8A//9mACEApQBfX18Ad3d3AIaGhgCWlpYAy8vLALKysgDX19cA3d3dAOPj4wDq6uoA8fHxAPj4+ADw+/8ApKCgAICAgAAAAP8AAP8AAAD//wD/AAAA/wD/AP//AAD///8ACgoKCgoKCgoKCgoKCgoKCgoKCgoHAQEMbQoKCgoKCgoAAAdDH/kgHRIAAAAAAAAAAADrHfn5ASQQAAAAAAAAAArsBx0B+fkgHesAAAAAAAD/Cgwf+fn5IA4dEus/IvcACgcMAfkg+QEB+SABHushbf8QHR/5HQH5+QEdHetEHx4K7B/5+QH5+fkdDBL5+SBE/wwdJfkf+fn5AR8g+fkfEArsCh/5+QEeJR/5+SAeBwAACgoe+SAlHwFAEhAfAAAAAPcKHh8eASYBHhAMAAAAAAAA9EMdIB8gHh0dBwAAAAAAAAAA7BAdQ+wHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//AADwfwAAwH8AAMB/AAAAPwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAQAAgAcAAIAPAADADwAA8D8AAP//AAA=";
let iconDiscoveryTests = [
{
text: "rel icon discovered",
icons: [{}],
}, {
},
{
text: "rel may contain additional rels separated by spaces",
icons: [{ rel: "abcdefg icon qwerty" }],
}, {
},
{
text: "rel is case insensitive",
icons: [{ rel: "ICON" }],
}, {
},
{
text: "rel shortcut-icon not discovered",
expectedIcon: ROOTURI + ICON,
icons: [ // We will prefer the later icon if detected
{ },
icons: [
// We will prefer the later icon if detected
{},
{ rel: "shortcut-icon", href: "nothere.png" },
],
}, {
},
{
text: "relative href works",
icons: [{ href: "moz.png" }],
}, {
},
{
text: "404'd icon is removed properly",
pass: false,
icons: [{ href: "notthere.png" }],
}, {
},
{
text: "data: URIs work",
icons: [{ href: DATAURL, type: "image/x-icon" }],
}, {
},
{
text: "type may have optional parameters (RFC2046)",
icons: [{ type: "image/png; charset=utf-8" }],
}, {
},
{
text: "apple-touch-icon discovered",
richIcon: true,
icons: [{ rel: "apple-touch-icon" }],
}, {
},
{
text: "apple-touch-icon-precomposed discovered",
richIcon: true,
icons: [{ rel: "apple-touch-icon-precomposed" }],
}, {
},
{
text: "fluid-icon discovered",
richIcon: true,
icons: [{ rel: "fluid-icon" }],
}, {
},
{
text: "unknown icon not discovered",
expectedIcon: ROOTURI + ICON,
richIcon: true,
icons: [ // We will prefer the larger icon if detected
icons: [
// We will prefer the larger icon if detected
{ rel: "apple-touch-icon", sizes: "32x32" },
{ rel: "unknown-icon", sizes: "128x128", href: "notthere.png" },
],
@ -67,8 +82,9 @@ add_task(async function() {
for (let testCase of iconDiscoveryTests) {
info(`Running test "${testCase.text}"`);
if (testCase.pass === undefined)
if (testCase.pass === undefined) {
testCase.pass = true;
}
if (testCase.icons.length > 1 && !testCase.expectedIcon) {
ok(false, "Invalid test data, missing expectedIcon");
@ -76,25 +92,29 @@ add_task(async function() {
}
let expectedIcon = testCase.expectedIcon || testCase.icons[0].href || ICON;
expectedIcon = (new URL(expectedIcon, ROOTURI)).href;
expectedIcon = new URL(expectedIcon, ROOTURI).href;
let iconPromise = waitForFaviconMessage(!testCase.richIcon, expectedIcon);
await ContentTask.spawn(gBrowser.selectedBrowser, [testCase.icons, ROOTURI + ICON], ([icons, defaultIcon]) => {
let doc = content.document;
let head = doc.head;
await ContentTask.spawn(
gBrowser.selectedBrowser,
[testCase.icons, ROOTURI + ICON],
([icons, defaultIcon]) => {
let doc = content.document;
let head = doc.head;
for (let icon of icons) {
let link = doc.createElement("link");
link.rel = icon.rel || "icon";
link.href = icon.href || defaultIcon;
link.type = icon.type || "image/png";
if (icon.sizes) {
link.sizes = icon.sizes;
for (let icon of icons) {
let link = doc.createElement("link");
link.rel = icon.rel || "icon";
link.href = icon.href || defaultIcon;
link.type = icon.type || "image/png";
if (icon.sizes) {
link.sizes = icon.sizes;
}
head.appendChild(link);
}
head.appendChild(link);
}
});
);
try {
let { iconURL } = await iconPromise;

Просмотреть файл

@ -2,16 +2,23 @@
* http://creativecommons.org/publicdomain/zero/1.0/ */
add_task(async () => {
const testPath = "http://example.com/browser/browser/base/content/test/favicons/";
const testPath =
"http://example.com/browser/browser/base/content/test/favicons/";
const expectedIcon = "http://example.com/favicon.ico";
await BrowserTestUtils.withNewTab({ gBrowser, url: "about:blank" }, async (browser) => {
let faviconPromise = waitForLinkAvailable(browser);
BrowserTestUtils.loadURI(browser, testPath + "file_invalid_href.html");
await BrowserTestUtils.browserLoaded(browser);
await BrowserTestUtils.withNewTab(
{ gBrowser, url: "about:blank" },
async browser => {
let faviconPromise = waitForLinkAvailable(browser);
BrowserTestUtils.loadURI(browser, testPath + "file_invalid_href.html");
await BrowserTestUtils.browserLoaded(browser);
let iconURI = await faviconPromise;
Assert.equal(iconURI, expectedIcon,
"Should have fallen back to the default site favicon for an invalid href attribute");
});
let iconURI = await faviconPromise;
Assert.equal(
iconURI,
expectedIcon,
"Should have fallen back to the default site favicon for an invalid href attribute"
);
}
);
});

Просмотреть файл

@ -7,20 +7,27 @@ add_task(async () => {
Services.prefs.setBoolPref("browser.chrome.guess_favicon", true);
});
await BrowserTestUtils.withNewTab({ gBrowser, url: "about:blank" }, async (browser) => {
const expectedIcon = testPath + "file_generic_favicon.ico";
let faviconPromise = waitForLinkAvailable(browser);
await BrowserTestUtils.withNewTab(
{ gBrowser, url: "about:blank" },
async browser => {
const expectedIcon = testPath + "file_generic_favicon.ico";
let faviconPromise = waitForLinkAvailable(browser);
BrowserTestUtils.loadURI(browser, testPath + "file_with_favicon.html");
await BrowserTestUtils.browserLoaded(browser);
BrowserTestUtils.loadURI(browser, testPath + "file_with_favicon.html");
await BrowserTestUtils.browserLoaded(browser);
let iconURI = await faviconPromise;
is(iconURI, expectedIcon, "Got correct icon.");
let iconURI = await faviconPromise;
is(iconURI, expectedIcon, "Got correct icon.");
BrowserTestUtils.loadURI(browser, testPath + "blank.html");
await BrowserTestUtils.browserLoaded(browser);
BrowserTestUtils.loadURI(browser, testPath + "blank.html");
await BrowserTestUtils.browserLoaded(browser);
is(browser.mIconURL, null, "Should have blanked the icon.");
is(gBrowser.getTabForBrowser(browser).getAttribute("image"), "", "Should have blanked the tab icon.");
});
is(browser.mIconURL, null, "Should have blanked the icon.");
is(
gBrowser.getTabForBrowser(browser).getAttribute("image"),
"",
"Should have blanked the tab icon."
);
}
);
});

Просмотреть файл

@ -1,6 +1,8 @@
add_task(async () => {
const testPath = "https://example.com/browser/browser/base/content/test/favicons/file_insecure_favicon.html";
const expectedIcon = "http://example.com/browser/browser/base/content/test/favicons/file_favicon.png";
const testPath =
"https://example.com/browser/browser/base/content/test/favicons/file_insecure_favicon.html";
const expectedIcon =
"http://example.com/browser/browser/base/content/test/favicons/file_favicon.png";
let tab = BrowserTestUtils.addTab(gBrowser, testPath);
gBrowser.selectedTab = tab;
@ -11,7 +13,10 @@ add_task(async () => {
let iconURI = await faviconPromise;
is(iconURI, expectedIcon, "Got correct icon.");
ok(gIdentityHandler._isMixedPassiveContentLoaded, "Should have seen mixed content.");
ok(
gIdentityHandler._isMixedPassiveContentLoaded,
"Should have seen mixed content."
);
BrowserTestUtils.removeTab(tab);
});

Просмотреть файл

@ -2,10 +2,14 @@
* http://creativecommons.org/publicdomain/zero/1.0/ */
add_task(async function() {
const ROOT = "http://mochi.test:8888/browser/browser/base/content/test/favicons/";
const ROOT =
"http://mochi.test:8888/browser/browser/base/content/test/favicons/";
const URL = ROOT + "discovery.html";
let iconPromise = waitForFaviconMessage(true, "http://mochi.test:8888/favicon.ico");
let iconPromise = waitForFaviconMessage(
true,
"http://mochi.test:8888/favicon.ico"
);
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, URL);
let icon = await iconPromise;
@ -23,7 +27,11 @@ add_task(async function() {
});
icon = await waitForFaviconMessage();
Assert.equal(icon.iconURL, ROOT + "rich_moz_2.png", "The expected icon has been set");
Assert.equal(
icon.iconURL,
ROOT + "rich_moz_2.png",
"The expected icon has been set"
);
BrowserTestUtils.removeTab(tab);
});

Просмотреть файл

@ -1,17 +1,25 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
const ROOT = "http://mochi.test:8888/browser/browser/base/content/test/favicons/";
const ROOT =
"http://mochi.test:8888/browser/browser/base/content/test/favicons/";
add_task(async () => {
await BrowserTestUtils.withNewTab({ gBrowser, url: "about:blank" }, async (browser) => {
let faviconPromise = waitForFaviconMessage(true, `${ROOT}large.png`);
await BrowserTestUtils.withNewTab(
{ gBrowser, url: "about:blank" },
async browser => {
let faviconPromise = waitForFaviconMessage(true, `${ROOT}large.png`);
BrowserTestUtils.loadURI(browser, ROOT + "large_favicon.html");
await BrowserTestUtils.browserLoaded(browser);
BrowserTestUtils.loadURI(browser, ROOT + "large_favicon.html");
await BrowserTestUtils.browserLoaded(browser);
await Assert.rejects(faviconPromise, result => {
return result.iconURL == `${ROOT}large.png`;
}, "Should have failed to load the large icon.");
});
await Assert.rejects(
faviconPromise,
result => {
return result.iconURL == `${ROOT}large.png`;
},
"Should have failed to load the large icon."
);
}
);
});

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше