зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
55d8d8e0e0
Коммит
f9f5914039
|
@ -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."
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче