Merge mozilla-central to mozilla-inbound

--HG--
rename : testing/web-platform/tests/storage/interfaces.html => testing/web-platform/tests/storage/interfaces.https.html
This commit is contained in:
Carsten "Tomcat" Book 2017-03-23 13:57:16 +01:00
Родитель 9d5f980afa 492970c342
Коммит 332688962a
773 изменённых файлов: 24621 добавлений и 7317 удалений

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

@ -22,4 +22,4 @@
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more.
Bug 1346967 - Generate metadata for all three ISimpleDOM interfaces via a single combined run of MIDL
Bug 1343682 - backing out a previous version didn't stop the failures from it, so it appears to need a clobber both out and in

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

@ -38,6 +38,7 @@ pref("extensions.minCompatibleAppVersion", "4.0");
pref("extensions.checkCompatibility.temporaryThemeOverride_minAppVersion", "29.0a1");
pref("xpinstall.customConfirmationUI", true);
pref("extensions.webextPermissionPrompts", true);
// Preferences for AMO integration
pref("extensions.getAddons.cache.enabled", true);

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

@ -96,7 +96,7 @@
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});
const event = new CustomEvent("AboutNetErrorResetPreferences", {bubbles: true});
document.dispatchEvent(event);
});
addAutofocus("prefResetButton", "beforeend");
@ -127,7 +127,7 @@
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);
}
});
@ -292,7 +292,7 @@
}
}, true, true);
var event = new CustomEvent("AboutNetErrorLoad", {bubbles:true});
var event = new CustomEvent("AboutNetErrorLoad", {bubbles: true});
document.dispatchEvent(event);
if (err == "inadequateSecurityError") {
@ -315,7 +315,7 @@
document.getElementById("openPortalLoginPageButton")
.addEventListener("click", () => {
let event = new CustomEvent("AboutNetErrorOpenCaptivePortal", {bubbles:true});
let event = new CustomEvent("AboutNetErrorOpenCaptivePortal", {bubbles: true});
document.dispatchEvent(event);
});
@ -362,7 +362,7 @@
}
}, true, true);
let event = new CustomEvent("AboutNetErrorLoad", {bubbles:true});
let event = new CustomEvent("AboutNetErrorLoad", {bubbles: true});
document.getElementById("advancedButton").dispatchEvent(event);
addDomainErrorLinks();

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

@ -105,7 +105,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);
sendAsyncMessage("Load");
@ -202,7 +202,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);
},

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

@ -53,7 +53,7 @@ window.addEventListener("pageshow", function() {
window.addEventListener("resize", fitToWidth);
// Ask chrome to update snippets.
var event = new CustomEvent("AboutHomeLoad", {bubbles:true});
var event = new CustomEvent("AboutHomeLoad", {bubbles: true});
document.dispatchEvent(event);
});
@ -241,7 +241,7 @@ function setupSearch() {
* Inform the test harness that we're done loading the page.
*/
function loadCompleted() {
var event = new CustomEvent("AboutHomeLoadSnippetsCompleted", {bubbles:true});
var event = new CustomEvent("AboutHomeLoadSnippetsCompleted", {bubbles: true});
document.dispatchEvent(event);
}
@ -254,7 +254,7 @@ function loadSnippets() {
throw new Error("Snippets map has not properly been initialized");
// Allow tests to modify the snippets map before using it.
var event = new CustomEvent("AboutHomeLoadSnippets", {bubbles:true});
var event = new CustomEvent("AboutHomeLoadSnippets", {bubbles: true});
document.dispatchEvent(event);
// Check cached snippets version.

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

@ -135,7 +135,7 @@
}
// Inform the test harness that we're done loading the page
var event = new CustomEvent("AboutBlockedLoaded", {bubbles:true});
var event = new CustomEvent("AboutBlockedLoaded", {bubbles: true});
document.dispatchEvent(event);
}
]]></script>

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

@ -798,13 +798,13 @@ var gPopupBlockerObserver = {
} catch (e) { }
var bundlePreferences = document.getElementById("bundle_preferences");
var params = { blockVisible : false,
sessionVisible : false,
allowVisible : true,
prefilledHost : prefillValue,
permissionType : "popup",
windowTitle : bundlePreferences.getString("popuppermissionstitle"),
introText : bundlePreferences.getString("popuppermissionstext") };
var params = { blockVisible: false,
sessionVisible: false,
allowVisible: true,
prefilledHost: prefillValue,
permissionType: "popup",
windowTitle: bundlePreferences.getString("popuppermissionstitle"),
introText: bundlePreferences.getString("popuppermissionstext") };
var existingWindow = Services.wm.getMostRecentWindow("Browser:Permissions");
if (existingWindow) {
existingWindow.initWithParams(params);
@ -3056,7 +3056,7 @@ var BrowserOnClick = {
securityInfo = getSecurityInfo(securityInfoAsString);
let sslStatus = securityInfo.QueryInterface(Ci.nsISSLStatusProvider)
.SSLStatus;
let params = { exceptionAdded : false,
let params = { exceptionAdded: false,
sslStatus };
try {
@ -3611,7 +3611,7 @@ function openHomeDialog(aURL) {
var pressedVal = Services.prompt.confirmEx(window, promptTitle, promptMsg,
Services.prompt.STD_YES_NO_BUTTONS,
null, null, null, null, {value:0});
null, null, null, null, {value: 0});
if (pressedVal == 0) {
try {
@ -6232,7 +6232,7 @@ var OfflineApps = {
let options = {
persistent: true,
hideClose: true,
controlledItems : [[Cu.getWeakReference(browser), docId, uri]]
controlledItems: [[Cu.getWeakReference(browser), docId, uri]]
};
notification = PopupNotifications.show(browser, notificationID, message,
anchorID, mainAction,

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

@ -1258,8 +1258,10 @@ var PageInfoListener = {
try {
// Note: makeURLAbsolute will throw if either the baseURI is not a valid URI
// or the URI formed from the baseURI and the URL is not a valid URI.
let href = makeURLAbsolute(elem.baseURI, elem.href.baseVal);
addImage(href, strings.mediaImg, "", elem, false);
if (elem.href.baseVal) {
let href = Services.io.newURI(elem.href.baseVal, null, Services.io.newURI(elem.baseURI)).spec;
addImage(href, strings.mediaImg, "", elem, false);
}
} catch (e) { }
} else if (elem instanceof content.HTMLVideoElement) {
addImage(elem.currentSrc, strings.mediaVideo, "", elem, false);

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

@ -1002,12 +1002,9 @@ function formatDate(datestr, unknown) {
if (!date.valueOf())
return unknown;
const locale = Components.classes["@mozilla.org/chrome/chrome-registry;1"]
.getService(Components.interfaces.nsIXULChromeRegistry)
.getSelectedLocale("global", true);
const dtOptions = { year: "numeric", month: "long", day: "numeric",
hour: "numeric", minute: "numeric", second: "numeric" };
return date.toLocaleString(locale, dtOptions);
return date.toLocaleString(undefined, dtOptions);
}
function doCopy() {

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

@ -55,15 +55,15 @@ var security = {
var retval = {
hostName,
cAName : issuerName,
encryptionAlgorithm : undefined,
encryptionStrength : undefined,
cAName: issuerName,
encryptionAlgorithm: undefined,
encryptionStrength: undefined,
version: undefined,
isBroken,
isMixed,
isEV,
cert,
certificateTransparency : undefined
certificateTransparency: undefined
};
var version;
@ -111,15 +111,15 @@ var security = {
}
return {
hostName,
cAName : "",
encryptionAlgorithm : "",
encryptionStrength : 0,
cAName: "",
encryptionAlgorithm: "",
encryptionStrength: 0,
version: "",
isBroken,
isMixed,
isEV,
cert : null,
certificateTransparency : null
cert: null,
certificateTransparency: null
};
},
@ -165,7 +165,7 @@ var security = {
win.focus();
} else
window.openDialog("chrome://browser/content/preferences/cookies.xul",
"Browser:Cookies", "", {filterString : eTLD});
"Browser:Cookies", "", {filterString: eTLD});
},
/**
@ -175,7 +175,7 @@ var security = {
LoginHelper.openPasswordManager(window, this._getSecurityInfo().hostName);
},
_cert : null
_cert: null
};
function securityOnLoad(uri, windowInfo) {

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

@ -189,8 +189,8 @@ Sanitizer.prototype = {
// and can optionally specify a specific range. If timespan is not ignored,
// and range is not set, sanitize() will use the value of the timespan
// pref to determine a range
ignoreTimespan : true,
range : null,
ignoreTimespan: true,
range: null,
items: {
cache: {

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

@ -2552,6 +2552,23 @@
<parameter name="aParams"/>
<body>
<![CDATA[
// We collect Telemetry on how long it takes to close a tab.
// Sometimes, tabs animate closed, and sometimes they don't, and
// it doesn't really make sense to put timings for both cases in the
// same bucket.
//
// We decide later on whether or not we're actually going to animate
// the tab closed. In order to capture as much of the time we care
// about with these stopwatches, but also in order to avoid any
// unnecessary work (since calculating whether or not we're going
// to do the animation might involved a style flush), we start
// stopwatches for both the animating and non-animating case. When
// we decide that we're animating, we cancel the non-animating case,
// and vice-versa. Then, in _endRemoveTab, we "finish" both
// stopwatches, which is a no-op for cancelled stopwatches.
TelemetryStopwatch.start("FX_TAB_CLOSE_TIME_ANIM_MS", aTab);
TelemetryStopwatch.start("FX_TAB_CLOSE_TIME_NO_ANIM_MS", aTab);
if (aParams) {
var animate = aParams.animate;
var byMouse = aParams.byMouse;
@ -2570,8 +2587,11 @@
var isLastTab = (this.tabs.length - this._removingTabs.length == 1);
if (!this._beginRemoveTab(aTab, null, null, true, skipPermitUnload))
if (!this._beginRemoveTab(aTab, null, null, true, skipPermitUnload)) {
TelemetryStopwatch.cancel("FX_TAB_CLOSE_TIME_ANIM_MS", aTab);
TelemetryStopwatch.cancel("FX_TAB_CLOSE_TIME_NO_ANIM_MS", aTab);
return;
}
if (!aTab.pinned && !aTab.hidden && aTab._fullyOpen && byMouse)
this.tabContainer._lockTabSizing(aTab);
@ -2586,10 +2606,15 @@
aTab.getAttribute("fadein") != "true" /* fade-in transition hasn't been triggered yet */ ||
window.getComputedStyle(aTab).maxWidth == "0.1px" /* fade-in transition hasn't moved yet */ ||
!Services.prefs.getBoolPref("browser.tabs.animate")) {
// We're not animating, so we can cancel the animation stopwatch.
TelemetryStopwatch.cancel("FX_TAB_CLOSE_TIME_ANIM_MS", aTab);
this._endRemoveTab(aTab);
return;
}
// We're animating, so we can cancel the non-animation stopwatch.
TelemetryStopwatch.cancel("FX_TAB_CLOSE_TIME_NO_ANIM_MS", aTab);
this.tabContainer._handleTabTelemetryStart(aTab);
this._blurTab(aTab);
@ -2634,9 +2659,15 @@
// We need to block while calling permitUnload() because it
// processes the event queue and may lead to another removeTab()
// call before permitUnload() returns.
TelemetryStopwatch.start("FX_TAB_CLOSE_PERMIT_UNLOAD_TIME_MS", aTab);
aTab._pendingPermitUnload = true;
let {permitUnload, timedOut} = browser.permitUnload();
delete aTab._pendingPermitUnload;
TelemetryStopwatch.finish("FX_TAB_CLOSE_PERMIT_UNLOAD_TIME_MS", aTab);
// If we were closed during onbeforeunload, we return false now
// so we don't (try to) close the same tab again. Of course, we
// also stop if the unload was cancelled by the user:
@ -2846,6 +2877,14 @@
panel.remove();
// closeWindow might wait an arbitrary length of time if we're supposed
// to warn about closing the window, so we'll just stop the tab close
// stopwatches here instead.
TelemetryStopwatch.finish("FX_TAB_CLOSE_TIME_ANIM_MS", aTab,
true /* aCanceledOkay */);
TelemetryStopwatch.finish("FX_TAB_CLOSE_TIME_NO_ANIM_MS", aTab,
true /* aCanceledOkay */);
if (aCloseWindow)
this._windowIsClosing = closeWindow(true, window.warnAboutClosingWindow);
]]>

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

@ -64,7 +64,7 @@ add_task(function* checkCaptivePortalCertErrorUI() {
let portalTab2 = yield portalTabPromise;
is(portalTab2, portalTab, "The existing portal tab should be focused.");
let portalTabRemoved = BrowserTestUtils.removeTab(portalTab, {dontRemove: true});
let portalTabRemoved = BrowserTestUtils.tabRemoved(portalTab);
let errorTabReloaded = BrowserTestUtils.waitForErrorPage(browser);
Services.obs.notifyObservers(null, "captive-portal-login-success", null);

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

@ -46,7 +46,7 @@ add_task(function*() {
});
yield BrowserTestUtils.synthesizeMouseAtCenter(`#${id} > input`,
{ type : "contextmenu", button : 2 },
{ type: "contextmenu", button: 2 },
tab.linkedBrowser);
let target = yield contextMenuPromise;

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

@ -7,7 +7,7 @@ add_task(function*() {
var tab = gBrowser.selectedTab;
gPrefService.setBoolPref("browser.tabs.closeWindowWithLastTab", false);
let tabClosedPromise = BrowserTestUtils.removeTab(tab, {dontRemove: true});
let tabClosedPromise = BrowserTestUtils.tabRemoved(tab);
EventUtils.synthesizeKey("w", { accelKey: true });
yield tabClosedPromise;

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

@ -34,6 +34,8 @@ function getObserverTopic(aNotificationId) {
topic = "addon-install-started";
else if (topic == "addon-install-restart")
topic = "addon-install-complete";
else if (topic == "addon-installed")
topic = "webextension-install-notify";
return topic;
}
@ -441,14 +443,9 @@ function test_restartless() {
yield progressPromise;
let installDialog = yield dialogPromise;
let notificationPromise = waitForNotification("addon-install-complete");
let notificationPromise = waitForNotification("addon-installed");
acceptInstallDialog(installDialog);
let panel = yield notificationPromise;
let notification = panel.childNodes[0];
is(notification.getAttribute("label"),
"XPI Test has been installed successfully.",
"Should have seen the right message");
yield notificationPromise;
let installs = yield getInstalls();
is(installs.length, 0, "Should be no pending installs");
@ -574,7 +571,7 @@ function test_allUnverified() {
is(container.childNodes[0].firstChild.getAttribute("value"), "XPI Test", "Should have the right add-on");
is(container.childNodes[0].childNodes.length, 1, "Shouldn't have the unverified marker");
let notificationPromise = waitForNotification("addon-install-complete");
let notificationPromise = waitForNotification("addon-installed");
acceptInstallDialog(installDialog);
yield notificationPromise;
@ -1024,7 +1021,7 @@ var gTestStart = null;
var XPInstallObserver = {
observe(aSubject, aTopic, aData) {
var installInfo = aSubject.QueryInterface(Components.interfaces.amIWebInstallInfo);
var installInfo = aSubject.wrappedJSObject;
info("Observed " + aTopic + " for " + installInfo.installs.length + " installs");
installInfo.installs.forEach(function(aInstall) {
info("Install of " + aInstall.sourceURI.spec + " was in state " + aInstall.state);
@ -1043,7 +1040,6 @@ add_task(function* () {
Services.obs.addObserver(XPInstallObserver, "addon-install-started", false);
Services.obs.addObserver(XPInstallObserver, "addon-install-blocked", false);
Services.obs.addObserver(XPInstallObserver, "addon-install-failed", false);
Services.obs.addObserver(XPInstallObserver, "addon-install-complete", false);
registerCleanupFunction(function() {
// Make sure no more test parts run in case we were timed out
@ -1063,7 +1059,6 @@ add_task(function* () {
Services.obs.removeObserver(XPInstallObserver, "addon-install-started");
Services.obs.removeObserver(XPInstallObserver, "addon-install-blocked");
Services.obs.removeObserver(XPInstallObserver, "addon-install-failed");
Services.obs.removeObserver(XPInstallObserver, "addon-install-complete");
});
for (let i = 0; i < TESTS.length; ++i) {

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

@ -13,7 +13,7 @@ function checkPopupHide() {
}
var gObserver = {
QueryInterface : XPCOMUtils.generateQI([Ci.nsIFormSubmitObserver]),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIFormSubmitObserver]),
notifyInvalidSubmit(aFormElement, aInvalidElements) {
}

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

@ -11,7 +11,7 @@ add_task(function *() {
// 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");
yield BrowserTestUtils.synthesizeMouse("#test-pagemenu", 5, 5, { type : "contextmenu", button : 2 }, tab.linkedBrowser);
yield BrowserTestUtils.synthesizeMouse("#test-pagemenu", 5, 5, { type: "contextmenu", button: 2 }, tab.linkedBrowser);
yield popupShownPromise;
checkMenu(contextMenu);

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

@ -46,7 +46,7 @@ function* expectFocusOnF6(backward, expectedDocument, expectedElement, onContent
if (!contentExpectedElement) {
sendSyncMessage("BrowserTest:FocusChanged",
{ details : "expected element " + arg.expectedElementId + " not found" });
{ details: "expected element " + arg.expectedElementId + " not found" });
return;
}

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

@ -11,14 +11,14 @@ function test() {
var urlString = value + "\n" + content.document.title;
var htmlString = "<a href=\"" + value + "\">" + value + "</a>";
var expected = [ [
{ type : "text/x-moz-url",
data : urlString },
{ type : "text/uri-list",
data : value },
{ type : "text/plain",
data : value },
{ type : "text/html",
data : htmlString }
{ type: "text/x-moz-url",
data: urlString },
{ type: "text/uri-list",
data: value },
{ type: "text/plain",
data: value },
{ type: "text/html",
data: htmlString }
] ];
// set the valid attribute so dropping is allowed
var oldstate = gURLBar.getAttribute("pageproxystate");

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

@ -519,41 +519,41 @@ function* setupFormHistory() {
op: "remove"
},
{
op : "add",
fieldname : "10minutes",
value : "10m"
op: "add",
fieldname: "10minutes",
value: "10m"
}, {
op : "add",
fieldname : "1hour",
value : "1h"
op: "add",
fieldname: "1hour",
value: "1h"
}, {
op : "add",
fieldname : "1hour10minutes",
value : "1h10m"
op: "add",
fieldname: "1hour10minutes",
value: "1h10m"
}, {
op : "add",
fieldname : "2hour",
value : "2h"
op: "add",
fieldname: "2hour",
value: "2h"
}, {
op : "add",
fieldname : "2hour10minutes",
value : "2h10m"
op: "add",
fieldname: "2hour10minutes",
value: "2h10m"
}, {
op : "add",
fieldname : "4hour",
value : "4h"
op: "add",
fieldname: "4hour",
value: "4h"
}, {
op : "add",
fieldname : "4hour10minutes",
value : "4h10m"
op: "add",
fieldname: "4hour10minutes",
value: "4h10m"
}, {
op : "add",
fieldname : "today",
value : "1d"
op: "add",
fieldname: "today",
value: "1d"
}, {
op : "add",
fieldname : "b4today",
value : "1y"
op: "add",
fieldname: "b4today",
value: "1y"
}]);
// Artifically age the entries to the proper vintage.

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

@ -78,7 +78,7 @@ function focusInChild() {
id = getWindowDocId(event.originalTarget) + "-document";
else
id = event.originalTarget.id;
sendSyncMessage("Browser:FocusChanged", { details : event.type + ": " + id });
sendSyncMessage("Browser:FocusChanged", { details: event.type + ": " + id });
}
addEventListener("focus", eventListener, true);

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

@ -32,7 +32,7 @@ add_task(function*() {
yield secondTabLoadedPromise;
let closeBtn = document.getAnonymousElementByAttribute(secondTab, "anonid", "close-button");
let closePromise = BrowserTestUtils.removeTab(secondTab, {dontRemove: true});
let closePromise = BrowserTestUtils.tabRemoved(secondTab);
info("closing second tab (which will self-close in beforeunload)");
closeBtn.click();
ok(secondTab.closing, "Second tab should be marked as closing synchronously.");

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

@ -12,7 +12,7 @@ function openContextMenuFor(element, shiftkey, waitForSpellCheck) {
// run on them.
function actuallyOpenContextMenuFor() {
lastElement = element;
var eventDetails = { type : "contextmenu", button : 2, shiftKey : shiftkey };
var eventDetails = { type: "contextmenu", button: 2, shiftKey: shiftkey };
synthesizeMouse(element, 2, 2, eventDetails, element.ownerGlobal);
}

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

@ -6,3 +6,7 @@ support-files =
[browser_pageinfo_images.js]
[browser_pageinfo_image_info.js]
skip-if = (os == 'linux' && e10s) # bug 1161699
[browser_pageinfo_svg_image.js]
support-files =
svg_image.html
../general/title_test.svg

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

@ -0,0 +1,37 @@
function test() {
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function() {
var pageInfo = BrowserPageInfo(gBrowser.selectedBrowser.currentURI.spec,
"mediaTab");
pageInfo.addEventListener("load", function() {
pageInfo.onFinished.push(function() {
executeSoon(function() {
var imageTree = pageInfo.document.getElementById("imagetree");
var imageRowsNum = imageTree.view.rowCount;
ok(imageTree, "Image tree is null (media tab is broken)");
is(imageRowsNum, 1, "should have one image");
// Only bother running this if we've got the right number of rows.
if (imageRowsNum == 1) {
is(imageTree.view.getCellText(0, imageTree.columns[0]),
"https://example.com/browser/browser/base/content/test/pageinfo/title_test.svg",
"The URL should be the svg image.");
}
pageInfo.close();
gBrowser.removeCurrentTab();
finish();
});
});
}, {capture: true, once: true});
}, {capture: true, once: true});
content.location =
"https://example.com/browser/browser/base/content/test/pageinfo/svg_image.html";
}

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

@ -0,0 +1,11 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for page info svg images</title>
</head>
<body>
<svg width="20" height="20">
<image xlink:href="title_test.svg" width="20" height="20">
</svg>
</body>
</html>

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

@ -77,7 +77,7 @@ var corpus = [
url: "https://www.mozilla.org/",
// shortUrl: this.getShortURL(),
// og:image
previews:["https://www.mozilla.org/favicon.png"],
previews: ["https://www.mozilla.org/favicon.png"],
// og:site_name
siteName: ">My simple test page<"
}

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

@ -169,15 +169,6 @@ var whitelist = new Set([
platforms: ["linux"]},
// Bug 1348559
{file: "chrome://pippki/content/resetpassword.xul"},
// Bug 1348562
{file: "chrome://devtools/skin/images/debugging-devices.svg",
isFromDevTools: true},
{file: "chrome://devtools/skin/images/fast-forward.svg",
isFromDevTools: true},
{file: "chrome://devtools/skin/images/firebug/spinner.png",
isFromDevTools: true},
{file: "chrome://devtools/skin/images/noise.png",
isFromDevTools: true},
].filter(item =>
("isFromDevTools" in item) == isDevtools &&

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

@ -25,7 +25,7 @@ add_task(function* test_without_dump() {
let tab = gBrowser.getTabForBrowser(browser);
yield BrowserTestUtils.crashBrowser(browser);
let tabRemovedPromise = BrowserTestUtils.removeTab(tab, { dontRemove: true });
let tabRemovedPromise = BrowserTestUtils.tabRemoved(tab);
yield ContentTask.spawn(browser, null, function*() {
let doc = content.document;

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

@ -4,6 +4,7 @@ support-files =
[browser_abandonment_telemetry.js]
[browser_allow_process_switches_despite_related_browser.js]
[browser_tabCloseProbes.js]
[browser_tabSpinnerProbe.js]
skip-if = !e10s # Tab spinner is e10s only.
[browser_tabSpinnerTypeProbe.js]

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

@ -0,0 +1,77 @@
"use strict";
var gAnimHistogram = Services.telemetry
.getHistogramById("FX_TAB_CLOSE_TIME_ANIM_MS");
var gNoAnimHistogram = Services.telemetry
.getHistogramById("FX_TAB_CLOSE_TIME_NO_ANIM_MS");
/**
* Takes a Telemetry histogram snapshot and makes sure
* that the sum of all counts equals expectedCount.
*
* @param snapshot (Object)
* The Telemetry histogram snapshot to examine.
* @param expectedCount (int)
* What we expect the number of incremented counts to be. For example,
* If we expect this probe to have only had a single recording, this
* would be 1. If we expected it to have not recorded any data at all,
* this would be 0.
*/
function assertCount(snapshot, expectedCount) {
// Use Array.prototype.reduce to sum up all of the
// snapshot.count entries
Assert.equal(snapshot.counts.reduce((a, b) => a + b), expectedCount,
`Should only be ${expectedCount} collected value.`);
}
add_task(function* setup() {
// These probes are opt-in, meaning we only capture them if extended
// Telemetry recording is enabled.
yield SpecialPowers.pushPrefEnv({
set: [["toolkit.telemetry.enabled", true]]
});
let oldCanRecord = Services.telemetry.canRecordExtended;
Services.telemetry.canRecordExtended = true;
registerCleanupFunction(() => {
Services.telemetry.canRecordExtended = oldCanRecord;
});
});
/**
* Tests the FX_TAB_CLOSE_TIME_ANIM_MS probe by closing a tab with the tab
* close animation.
*/
add_task(function* test_close_time_anim_probe() {
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser);
gAnimHistogram.clear();
gNoAnimHistogram.clear();
yield BrowserTestUtils.removeTab(tab, { animate: true });
assertCount(gAnimHistogram.snapshot(), 1);
assertCount(gNoAnimHistogram.snapshot(), 0);
gAnimHistogram.clear();
gNoAnimHistogram.clear();
});
/**
* Tests the FX_TAB_CLOSE_TIME_NO_ANIM_MS probe by closing a tab without the
* tab close animation.
*/
add_task(function* test_close_time_no_anim_probe() {
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser);
gAnimHistogram.clear();
gNoAnimHistogram.clear();
yield BrowserTestUtils.removeTab(tab, { animate: false });
assertCount(gAnimHistogram.snapshot(), 0);
assertCount(gNoAnimHistogram.snapshot(), 1);
gAnimHistogram.clear();
gNoAnimHistogram.clear();
});

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

@ -66,7 +66,7 @@ function* runTest(aSourceWindow, aDestWindow, aExpectSwitch, aCallback) {
let awaitTabSwitch;
if (aExpectSwitch) {
awaitTabSwitch = BrowserTestUtils.removeTab(testTab, {dontRemove: true})
awaitTabSwitch = BrowserTestUtils.tabRemoved(testTab)
}
// Execute the selected action.

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

@ -81,11 +81,6 @@ function promiseSetDisabled(addon) {
let cleanup;
add_task(function* () {
// XXX remove this when prompts are enabled by default
yield SpecialPowers.pushPrefEnv({set: [
["extensions.webextPermissionPrompts", true],
]});
// ICON_URL wouldn't ever appear as an actual webextension icon, but
// we're just mocking out the addon here, so all we care about is that
// that it propagates correctly to the popup.

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

@ -35,9 +35,6 @@ add_task(function* setup() {
// We don't have pre-pinned certificates for the local mochitest server
["extensions.install.requireBuiltInCerts", false],
["extensions.update.requireBuiltInCerts", false],
// XXX remove this when prompts are enabled by default
["extensions.webextPermissionPrompts", true],
]});
// Navigate away from the initial page so that about:addons always

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

@ -7,9 +7,6 @@ add_task(async function test_unsigned() {
await SpecialPowers.pushPrefEnv({set: [
["extensions.webapi.testing", true],
["extensions.install.requireBuiltInCerts", false],
// XXX remove this when prompts are enabled by default
["extensions.webextPermissionPrompts", true],
]});
let testURI = makeURI("https://example.com/");

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

@ -8,9 +8,6 @@ add_task(function* setup() {
// We don't have pre-pinned certificates for the local mochitest server
["extensions.install.requireBuiltInCerts", false],
["extensions.update.requireBuiltInCerts", false],
// XXX remove this when prompts are enabled by default
["extensions.webextPermissionPrompts", true],
]});
});

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

@ -8,9 +8,6 @@ add_task(function* setup() {
// Point updates to the local mochitest server
["extensions.update.url", `${BASE}/browser_webext_update.json`],
// XXX remove this when prompts are enabled by default
["extensions.webextPermissionPrompts", true],
]});
});

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

@ -217,9 +217,6 @@ async function testInstallMethod(installFn, telemetryBase) {
await SpecialPowers.pushPrefEnv({set: [
["extensions.webapi.testing", true],
["extensions.install.requireBuiltInCerts", false],
// XXX remove this when prompts are enabled by default
["extensions.webextPermissionPrompts", true],
]});
if (telemetryBase !== undefined) {

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

@ -12,7 +12,7 @@ skip-if = (os == "linux" && debug) # linux: bug 976544
[browser_devices_get_user_media_multi_process.js]
skip-if = (e10s && debug) # bug 1347625
[browser_devices_get_user_media_screen.js]
skip-if = (e10s && debug) || (os == "linux") || (os == "win" && !debug) # bug 1320754 for e10s debug, and bug 1320994 for linux opt, bug 1338038 for windows and linux debug
skip-if = (os == "linux") || (os == "win" && !debug) # bug 1320994 for linux opt, bug 1338038 for windows and linux debug
[browser_devices_get_user_media_tear_off_tab.js]
[browser_devices_get_user_media_unprompted_access.js]
[browser_devices_get_user_media_unprompted_access_in_frame.js]

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

@ -790,7 +790,7 @@ function openPreferences(paneID, extraArgs) {
}
function openAdvancedPreferences(tabID) {
openPreferences("paneAdvanced", { "advancedTab" : tabID });
openPreferences("paneAdvanced", { "advancedTab": tabID });
}
/**

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

@ -13,6 +13,7 @@
#include "nsIScriptSecurityManager.h"
#include "nsIProtocolHandler.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/Preferences.h"
#include "nsServiceManagerUtils.h"
namespace mozilla {
@ -20,6 +21,8 @@ namespace browser {
NS_IMPL_ISUPPORTS(AboutRedirector, nsIAboutModule)
bool AboutRedirector::sUseOldPreferences = false;
struct RedirEntry {
const char* id;
const char* url;
@ -138,6 +141,13 @@ AboutRedirector::NewChannel(nsIURI* aURI,
nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv);
NS_ENSURE_SUCCESS(rv, rv);
static bool sPrefCacheInited = false;
if (!sPrefCacheInited) {
Preferences::AddBoolVarCache(&sUseOldPreferences,
"browser.preferences.useOldOrganization");
sPrefCacheInited = true;
}
for (auto & redir : kRedirMap) {
if (!strcmp(path.get(), redir.id)) {
nsAutoCString url;
@ -149,6 +159,8 @@ AboutRedirector::NewChannel(nsIURI* aURI,
NS_ENSURE_SUCCESS(rv, rv);
rv = aboutNewTabService->GetDefaultURL(url);
NS_ENSURE_SUCCESS(rv, rv);
} else if (path.EqualsLiteral("preferences") && sUseOldPreferences) {
url.AssignASCII("chrome://browser/content/preferences/in-content-old/preferences.xul");
}
// fall back to the specified url in the map
if (url.IsEmpty()) {

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

@ -24,6 +24,9 @@ public:
protected:
virtual ~AboutRedirector() {}
private:
static bool sUseOldPreferences;
};
} // namespace browser

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

@ -544,14 +544,8 @@ XPCOMUtils.defineConstant(this, "PanelUI", PanelUI);
/**
* Gets the currently selected locale for display.
* @return the selected locale or "en-US" if none is selected
* @return the selected locale
*/
function getLocale() {
try {
let chromeRegistry = Cc["@mozilla.org/chrome/chrome-registry;1"]
.getService(Ci.nsIXULChromeRegistry);
return chromeRegistry.getSelectedLocale("browser");
} catch (ex) {
return "en-US";
}
return Services.locale.getAppLocaleAsLangTag();
}

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

@ -240,6 +240,18 @@ var gMenuBuilder = {
info.modifiers.push("MacCtrl");
}
// Allow context menu's to open various actions supported in webext prior
// to notifying onclicked.
let actionFor = {
_execute_page_action: pageActionFor,
_execute_browser_action: browserActionFor,
_execute_sidebar_action: sidebarActionFor,
}[item.command];
if (actionFor) {
let win = event.target.ownerGlobal;
actionFor(item.extension).triggerAction(win);
}
item.extension.emit("webext-contextmenu-menuitem-click", info, tab);
});

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

@ -202,6 +202,11 @@
"type": "boolean",
"optional": true,
"description": "Whether this context menu item is enabled or disabled. Defaults to true."
},
"command": {
"type": "string",
"optional": true,
"description": "Specifies a command to issue for the context click. Currently supports internal commands _execute_page_action, _execute_browser_action and _execute_sidebar_action."
}
}
},

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

@ -50,6 +50,7 @@ support-files =
[browser_ext_contextMenus.js]
[browser_ext_contextMenus_checkboxes.js]
[browser_ext_contextMenus_chrome.js]
[browser_ext_contextMenus_commands.js]
[browser_ext_contextMenus_icons.js]
[browser_ext_contextMenus_onclick.js]
[browser_ext_contextMenus_radioGroups.js]

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

@ -0,0 +1,79 @@
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
add_task(function* () {
function background() {
browser.contextMenus.create({
title: "open_browser_action",
contexts: ["all"],
command: "_execute_browser_action",
});
browser.contextMenus.create({
title: "open_page_action",
contexts: ["all"],
command: "_execute_page_action",
});
browser.contextMenus.create({
title: "open_sidebar_action",
contexts: ["all"],
command: "_execute_sidebar_action",
});
browser.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
browser.pageAction.show(tabId);
});
browser.test.sendMessage("ready");
}
function testScript() {
window.onload = () => {
browser.test.sendMessage("test-opened", true);
};
}
let extension = ExtensionTestUtils.loadExtension({
manifest: {
"permissions": ["contextMenus", "activeTab", "tabs"],
"browser_action": {
"default_title": "Test BrowserAction",
"default_popup": "test.html",
"browser_style": true,
},
"page_action": {
"default_title": "Test PageAction",
"default_popup": "test.html",
"browser_style": true,
},
"sidebar_action": {
"default_title": "Test Sidebar",
"default_panel": "test.html",
},
},
background,
files: {
"test.html": `<!DOCTYPE html><meta charset="utf-8"><script src="test.js"></script>`,
"test.js": testScript,
},
});
function* testContext(id) {
const menu = yield openExtensionContextMenu();
const items = menu.getElementsByAttribute("label", id);
yield closeExtensionContextMenu(items[0]);
return extension.awaitMessage("test-opened");
}
yield extension.startup();
yield extension.awaitMessage("ready");
// open a page so page action works
const PAGE = "http://mochi.test:8888/browser/browser/components/extensions/test/browser/context.html?test=commands";
const tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, PAGE);
ok(yield testContext("open_sidebar_action"), "_execute_sidebar_action worked");
ok(yield testContext("open_browser_action"), "_execute_browser_action worked");
ok(yield testContext("open_page_action"), "_execute_page_action worked");
yield BrowserTestUtils.removeTab(tab);
yield extension.unload();
});

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

@ -4,7 +4,7 @@
add_task(function* () {
let tab1 = yield BrowserTestUtils.openNewForegroundTab(gBrowser,
"http://mochi.test:8888/browser/browser/components/extensions/test/browser/context.html");
"http://mochi.test:8888/browser/browser/components/extensions/test/browser/context.html?test=icons");
let encodedImageData = "iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAAC4klEQVRYhdWXLWzbQBSADQtDAwsHC1tUhUxqfL67lk2tdn+OJg0ODU0rLByqgqINBY6tmlbn7LMTJ5FaFVVBk1G0oUGjG2jT2Y7jxmmcbU/6iJ+f36fz+e5sGP9riCGm9hB37RG+scd4Yo/wsDXCZyIE2xuXsce4bY+wXkAsQtzYmExrfFgvkJkRbkzo1ehoxx5iXcgI/9iYUGt8WH9MqDXEcmNChmEYrRCf2SHWeYgQx3x0tLNRIeKQLTtEFyJEep4NTuhk8BC+yMrwEE3+iozo42d8gK7FAOkMsRiiN8QhW2ttSK5QTfRRV4QoymVeJMvPvDp7gCZigD613MN6yRFA3SWarow9QB9LCfG+NeF9qCtjAKOSQjCqVKhfVsiHEQ+grgx/lRGqUihAc1uL8EFD+KCRO+GrF4J61phcoRoPoEzkYhZYpykh5sMb7kOdIeY+jHKur4QI4Feh4AFX1nVeLxrAvQchGsBz5ls6wa2QdwcvIcE2863bTH79KOvsz/uUYJsp+J0pSzNlDckVqqVGUAF+n6uS7txcOl6wot4JVy70ufDLy4pWLUQVPE81pRI0mGe9oxLMHSeohHvMs/STUNaUK6vDPCvOyxMFDx4achehRDJmHnydnkPww5OFfLxrGIZBFDyYl4LpMzlTQFIP6AQx86w2UeYBccFpJrcKv5L9eGDtUAU6RIELqsB74uynjy/UBRF1gS5BTFxwQT1wTiXoUg9MH7m/3NZRRoi5IJytUbMgzv4Wc832+oQkiKgEehmyMkkpKsFkQV11QsRJL5rJYBLItQgRaUZEmnoZXsomz3vGiWw+I9KMF9SVFOqZEemZekli1jN3U/UOqhHHvC6oWWGElhfSpGdOk6+O9prdwvtLj5BjRsQxdRnot+Zeifpy/2/0stktKTRNLmbk0mwXyl8253fyojj+8rxOHNAhjjm5n0/5OOCGOKBzkrMO0Z75lvSAzKlrF32Z/3z8BqLAn+yMV7VhAAAAAElFTkSuQmCC";
const IMAGE_ARRAYBUFFER = imageBufferFromDataURI(encodedImageData);
@ -26,6 +26,7 @@ add_task(function* () {
title: "child-to-delete",
onclick: () => {
browser.contextMenus.remove(menuitemId);
browser.test.sendMessage("child-deleted");
},
});
@ -33,9 +34,6 @@ add_task(function* () {
title: "child",
});
browser.test.onMessage.addListener(() => {
browser.test.sendMessage("pong");
});
browser.test.notifyPass("contextmenus-icons");
},
});
@ -57,10 +55,7 @@ add_task(function* () {
let childToDelete = extensionMenu.getElementsByAttribute("label", "child-to-delete")[0];
yield closeExtensionContextMenu(childToDelete);
// Now perform a roundtrip to the extension process to make sure that the
// click event has had a chance to fire.
extension.sendMessage("ping");
yield extension.awaitMessage("pong");
yield extension.awaitMessage("child-deleted");
yield openExtensionContextMenu();

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

@ -189,12 +189,9 @@ FeedWriter.prototype = {
__dateFormatter: null,
get _dateFormatter() {
if (!this.__dateFormatter) {
const locale = Cc["@mozilla.org/chrome/chrome-registry;1"]
.getService(Ci.nsIXULChromeRegistry)
.getSelectedLocale("global", true);
const dtOptions = { year: "numeric", month: "long", day: "numeric",
hour: "numeric", minute: "numeric" };
this.__dateFormatter = new Intl.DateTimeFormat(locale, dtOptions);
this.__dateFormatter = new Intl.DateTimeFormat(undefined, dtOptions);
}
return this.__dateFormatter;
},

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

@ -638,10 +638,8 @@ const AutoMigrate = {
// Strip out any empty elements, so an empty pref doesn't
// lead to a an array with 1 empty string in it.
surveyLocales = new Set(surveyLocales.filter(str => !!str));
let chromeRegistry = Cc["@mozilla.org/chrome/chrome-registry;1"]
.getService(Ci.nsIXULChromeRegistry);
canDoSurveyInLocale =
surveyLocales.has(chromeRegistry.getSelectedLocale("global"));
surveyLocales.has(Services.locale.getAppLocaleAsLangTag());
} catch (ex) {
/* ignore exceptions and just don't do the survey. */
}

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

@ -222,7 +222,7 @@ add_task(function* test_datareporting_many() {
Assert.ok(ok, "callback should have been true");
checkDirectoryContains(targetDir, {
"datareporting" : {
"datareporting": {
"state.json": shouldBeCopied,
"session-state.json": shouldBeCopied,
}
@ -241,7 +241,7 @@ add_task(function* test_no_session_state() {
Assert.ok(ok, "callback should have been true");
checkDirectoryContains(targetDir, {
"datareporting" : {
"datareporting": {
"state.json": stateContent,
}
});
@ -259,7 +259,7 @@ add_task(function* test_no_state() {
Assert.ok(ok, "callback should have been true");
checkDirectoryContains(targetDir, {
"datareporting" : {
"datareporting": {
"session-state.json": sessionStateContent,
}
});

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

@ -283,7 +283,7 @@ nsBrowserContentHandler.prototype = {
/* helper functions */
mChromeURL : null,
mChromeURL: null,
get chromeURL() {
if (this.mChromeURL) {
@ -296,13 +296,13 @@ nsBrowserContentHandler.prototype = {
},
/* nsISupports */
QueryInterface : XPCOMUtils.generateQI([nsICommandLineHandler,
nsIBrowserHandler,
nsIContentHandler,
nsICommandLineValidator]),
QueryInterface: XPCOMUtils.generateQI([nsICommandLineHandler,
nsIBrowserHandler,
nsIContentHandler,
nsICommandLineValidator]),
/* nsICommandLineHandler */
handle : function bch_handle(cmdLine) {
handle: function bch_handle(cmdLine) {
if (cmdLine.handleFlag("browser", false)) {
// Passing defaultArgs, so use NO_EXTERNAL_URIS
openWindow(null, this.chromeURL, "_blank",
@ -558,9 +558,9 @@ nsBrowserContentHandler.prototype = {
return uri;
},
mFeatures : null,
mFeatures: null,
getFeatures : function bch_features(cmdLine) {
getFeatures: function bch_features(cmdLine) {
if (this.mFeatures === null) {
this.mFeatures = "";
@ -587,7 +587,7 @@ nsBrowserContentHandler.prototype = {
/* nsIContentHandler */
handleContent : function bch_handleContent(contentType, context, request) {
handleContent: function bch_handleContent(contentType, context, request) {
try {
var webNavInfo = Components.classes["@mozilla.org/webnavigation-info;1"]
.getService(nsIWebNavigationInfo);
@ -605,7 +605,7 @@ nsBrowserContentHandler.prototype = {
},
/* nsICommandLineValidator */
validate : function bch_validate(cmdLine) {
validate: function bch_validate(cmdLine) {
// Other handlers may use osint so only handle the osint flag if the url
// flag is also present and the command line is valid.
var osintFlagIdx = cmdLine.findFlag("osint", false);
@ -669,7 +669,7 @@ nsDefaultCommandLineHandler.prototype = {
classID: Components.ID("{47cd0651-b1be-4a0f-b5c4-10e5a573ef71}"),
/* nsISupports */
QueryInterface : function dch_QI(iid) {
QueryInterface: function dch_QI(iid) {
if (!iid.equals(nsISupports) &&
!iid.equals(nsICommandLineHandler))
throw Components.results.NS_ERROR_NO_INTERFACE;
@ -680,7 +680,7 @@ nsDefaultCommandLineHandler.prototype = {
_haveProfile: false,
/* nsICommandLineHandler */
handle : function dch_handle(cmdLine) {
handle: function dch_handle(cmdLine) {
var urilist = [];
if (AppConstants.platform == "win") {
@ -765,7 +765,7 @@ nsDefaultCommandLineHandler.prototype = {
}
},
helpInfo : "",
helpInfo: "",
};
var components = [nsBrowserContentHandler, nsDefaultCommandLineHandler];

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

@ -512,18 +512,18 @@ var BookmarkPropertiesPanel = {
var childTransactions = [];
if (this._description) {
let annoObj = { name : PlacesUIUtils.DESCRIPTION_ANNO,
type : Ci.nsIAnnotationService.TYPE_STRING,
flags : 0,
value : this._description,
let annoObj = { name: PlacesUIUtils.DESCRIPTION_ANNO,
type: Ci.nsIAnnotationService.TYPE_STRING,
flags: 0,
value: this._description,
expires: Ci.nsIAnnotationService.EXPIRE_NEVER };
let editItemTxn = new PlacesSetItemAnnotationTransaction(-1, annoObj);
childTransactions.push(editItemTxn);
}
if (this._loadInSidebar) {
let annoObj = { name : PlacesUIUtils.LOAD_IN_SIDEBAR_ANNO,
value : true };
let annoObj = { name: PlacesUIUtils.LOAD_IN_SIDEBAR_ANNO,
value: true };
let setLoadTxn = new PlacesSetItemAnnotationTransaction(-1, annoObj);
childTransactions.push(setLoadTxn);
}

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

@ -671,7 +671,7 @@ var gEditItemOverlay = {
if (!this.initialized || !this._paneInfo.isBookmark)
return;
let annotation = { name : PlacesUIUtils.LOAD_IN_SIDEBAR_ANNO };
let annotation = { name: PlacesUIUtils.LOAD_IN_SIDEBAR_ANNO };
if (this._loadInSidebarCheckbox.checked)
annotation.value = true;

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

@ -411,11 +411,8 @@ var PlacesOrganizer = {
populateRestoreMenu: function PO_populateRestoreMenu() {
let restorePopup = document.getElementById("fileRestorePopup");
const locale = Cc["@mozilla.org/chrome/chrome-registry;1"]
.getService(Ci.nsIXULChromeRegistry)
.getSelectedLocale("global", true);
const dtOptions = { year: "numeric", month: "long", day: "numeric" };
let dateFormatter = new Intl.DateTimeFormat(locale, dtOptions);
let dateFormatter = new Intl.DateTimeFormat(undefined, dtOptions);
// Remove existing menu items. Last item is the restoreFromFile item.
while (restorePopup.childNodes.length > 1)

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

@ -499,11 +499,8 @@ PlacesTreeView.prototype = {
__todayFormatter: null,
get _todayFormatter() {
if (!this.__todayFormatter) {
const locale = Cc["@mozilla.org/chrome/chrome-registry;1"]
.getService(Ci.nsIXULChromeRegistry)
.getSelectedLocale("global", true);
const dtOptions = { hour: "numeric", minute: "numeric" };
this.__todayFormatter = new Intl.DateTimeFormat(locale, dtOptions);
this.__todayFormatter = new Intl.DateTimeFormat(undefined, dtOptions);
}
return this.__todayFormatter;
},
@ -511,12 +508,9 @@ PlacesTreeView.prototype = {
__dateFormatter: null,
get _dateFormatter() {
if (!this.__dateFormatter) {
const locale = Cc["@mozilla.org/chrome/chrome-registry;1"]
.getService(Ci.nsIXULChromeRegistry)
.getSelectedLocale("global", true);
const dtOptions = { year: "numeric", month: "numeric", day: "numeric",
hour: "numeric", minute: "numeric" };
this.__dateFormatter = new Intl.DateTimeFormat(locale, dtOptions);
this.__dateFormatter = new Intl.DateTimeFormat(undefined, dtOptions);
}
return this.__dateFormatter;
},

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

@ -104,9 +104,6 @@
ok(rc >= 3, "Rows found");
let columns = tree.columns;
ok(columns.count > 0, "Columns found");
const locale = Cc["@mozilla.org/chrome/chrome-registry;1"]
.getService(Ci.nsIXULChromeRegistry)
.getSelectedLocale("global", true);
for (let r = 0; r < rc; r++) {
let node = treeView.nodeForTreeIndex(r);
ok(node, "Places node found");
@ -138,7 +135,7 @@
// a redirecting uri could be put in the tree while we test.
break;
}
let timeStr = timeObj.toLocaleString(locale, dtOptions);
let timeStr = timeObj.toLocaleString(undefined, dtOptions);
is(text, timeStr, "Date format is correct");
break;

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

@ -13,7 +13,7 @@ const UPDATE_TIME_PREF = "browser.safebrowsing.provider.mozilla.nextupdatetime";
var gBlocklistManager = {
_type: "",
_blockLists: [],
_brandShortName : null,
_brandShortName: null,
_bundle: null,
_tree: null,

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

@ -16,12 +16,12 @@ XPCOMUtils.defineLazyModuleGetter(this, "ContextualIdentityService",
"resource://gre/modules/ContextualIdentityService.jsm");
var gCookiesWindow = {
_cm : Components.classes["@mozilla.org/cookiemanager;1"]
.getService(Components.interfaces.nsICookieManager),
_hosts : {},
_hostOrder : [],
_tree : null,
_bundle : null,
_cm: Components.classes["@mozilla.org/cookiemanager;1"]
.getService(Components.interfaces.nsICookieManager),
_hosts: {},
_hostOrder: [],
_tree: null,
_bundle: null,
init() {
var os = Components.classes["@mozilla.org/observer-service;1"]
@ -194,12 +194,12 @@ var gCookiesWindow = {
},
_view: {
_filtered : false,
_filterSet : [],
_filtered: false,
_filterSet: [],
_filterValue: "",
_rowCount : 0,
_cacheValid : 0,
_cacheItems : [],
_rowCount: 0,
_cacheValid: 0,
_cacheItems: [],
get rowCount() {
return this._rowCount;
},
@ -225,7 +225,7 @@ var gCookiesWindow = {
return currHost;
hostIndex = count;
var cacheEntry = { "start" : i, "count" : count };
var cacheEntry = { "start": i, "count": count };
var cacheStart = count;
if (currHost.open) {
@ -446,11 +446,11 @@ var gCookiesWindow = {
_addCookie(aStrippedHost, aCookie, aHostCount) {
if (!(aStrippedHost in this._hosts) || !this._hosts[aStrippedHost]) {
this._hosts[aStrippedHost] = { cookies : [],
rawHost : aStrippedHost,
level : 0,
open : false,
container : true };
this._hosts[aStrippedHost] = { cookies: [],
rawHost: aStrippedHost,
level: 0,
open: false,
container: true };
this._hostOrder.push(aStrippedHost);
++aHostCount.value;
}
@ -460,16 +460,16 @@ var gCookiesWindow = {
},
_makeCookieObject(aStrippedHost, aCookie) {
var c = { name : aCookie.name,
value : aCookie.value,
isDomain : aCookie.isDomain,
host : aCookie.host,
rawHost : aStrippedHost,
path : aCookie.path,
isSecure : aCookie.isSecure,
expires : aCookie.expires,
level : 1,
container : false,
var c = { name: aCookie.name,
value: aCookie.value,
isDomain: aCookie.isDomain,
host: aCookie.host,
rawHost: aStrippedHost,
path: aCookie.path,
isSecure: aCookie.isSecure,
expires: aCookie.expires,
level: 1,
container: false,
originAttributes: aCookie.originAttributes };
return c;
},
@ -497,12 +497,9 @@ var gCookiesWindow = {
formatExpiresString(aExpires) {
if (aExpires) {
var date = new Date(1000 * aExpires);
const locale = Components.classes["@mozilla.org/chrome/chrome-registry;1"]
.getService(Components.interfaces.nsIXULChromeRegistry)
.getSelectedLocale("global", true);
const dtOptions = { year: "numeric", month: "long", day: "numeric",
hour: "numeric", minute: "numeric", second: "numeric" };
return date.toLocaleString(locale, dtOptions);
return date.toLocaleString(undefined, dtOptions);
}
return this._bundle.getString("expireAtEndOfSession");
},
@ -739,7 +736,7 @@ var gCookiesWindow = {
}
},
_lastSortProperty : "",
_lastSortProperty: "",
_lastSortAscending: false,
sort(aProperty) {
var ascending = (aProperty == this._lastSortProperty) ? !this._lastSortAscending : true;

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

@ -0,0 +1,798 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
/* import-globals-from preferences.js */
// Load DownloadUtils module for convertByteUnits
Components.utils.import("resource://gre/modules/DownloadUtils.jsm");
Components.utils.import("resource://gre/modules/LoadContextInfo.jsm");
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "SiteDataManager",
"resource:///modules/SiteDataManager.jsm");
const PREF_UPLOAD_ENABLED = "datareporting.healthreport.uploadEnabled";
var gAdvancedPane = {
_inited: false,
/**
* Brings the appropriate tab to the front and initializes various bits of UI.
*/
init() {
function setEventListener(aId, aEventType, aCallback) {
document.getElementById(aId)
.addEventListener(aEventType, aCallback.bind(gAdvancedPane));
}
this._inited = true;
var advancedPrefs = document.getElementById("advancedPrefs");
var preference = document.getElementById("browser.preferences.advanced.selectedTabIndex");
if (preference.value !== null)
advancedPrefs.selectedIndex = preference.value;
if (AppConstants.MOZ_UPDATER) {
let onUnload = function() {
window.removeEventListener("unload", onUnload);
Services.prefs.removeObserver("app.update.", this);
}.bind(this);
window.addEventListener("unload", onUnload);
Services.prefs.addObserver("app.update.", this, false);
this.updateReadPrefs();
}
this.updateOfflineApps();
if (AppConstants.MOZ_CRASHREPORTER) {
this.initSubmitCrashes();
}
this.initTelemetry();
if (AppConstants.MOZ_TELEMETRY_REPORTING) {
this.initSubmitHealthReport();
}
this.updateOnScreenKeyboardVisibility();
this.updateCacheSizeInputField();
this.updateActualCacheSize();
this.updateActualAppCacheSize();
if (Services.prefs.getBoolPref("browser.storageManager.enabled")) {
Services.obs.addObserver(this, "sitedatamanager:sites-updated", false);
let unload = () => {
window.removeEventListener("unload", unload);
Services.obs.removeObserver(this, "sitedatamanager:sites-updated");
};
window.addEventListener("unload", unload);
SiteDataManager.updateSites();
setEventListener("clearSiteDataButton", "command",
gAdvancedPane.clearSiteData);
setEventListener("siteDataSettings", "command",
gAdvancedPane.showSiteDataSettings);
let url = Services.urlFormatter.formatURLPref("app.support.baseURL") + "storage-permissions";
document.getElementById("siteDataLearnMoreLink").setAttribute("href", url);
}
setEventListener("layers.acceleration.disabled", "change",
gAdvancedPane.updateHardwareAcceleration);
setEventListener("advancedPrefs", "select",
gAdvancedPane.tabSelectionChanged);
if (AppConstants.MOZ_TELEMETRY_REPORTING) {
setEventListener("submitHealthReportBox", "command",
gAdvancedPane.updateSubmitHealthReport);
}
setEventListener("connectionSettings", "command",
gAdvancedPane.showConnections);
setEventListener("clearCacheButton", "command",
gAdvancedPane.clearCache);
setEventListener("clearOfflineAppCacheButton", "command",
gAdvancedPane.clearOfflineAppCache);
setEventListener("offlineNotifyExceptions", "command",
gAdvancedPane.showOfflineExceptions);
setEventListener("offlineAppsList", "select",
gAdvancedPane.offlineAppSelected);
let bundlePrefs = document.getElementById("bundlePreferences");
document.getElementById("offlineAppsList")
.style.height = bundlePrefs.getString("offlineAppsList.height");
setEventListener("offlineAppsListRemove", "command",
gAdvancedPane.removeOfflineApp);
if (AppConstants.MOZ_UPDATER) {
setEventListener("updateRadioGroup", "command",
gAdvancedPane.updateWritePrefs);
setEventListener("showUpdateHistory", "command",
gAdvancedPane.showUpdates);
}
setEventListener("viewCertificatesButton", "command",
gAdvancedPane.showCertificates);
setEventListener("viewSecurityDevicesButton", "command",
gAdvancedPane.showSecurityDevices);
setEventListener("cacheSize", "change",
gAdvancedPane.updateCacheSizePref);
if (AppConstants.MOZ_WIDGET_GTK) {
// GTK tabbox' allow the scroll wheel to change the selected tab,
// but we don't want this behavior for the in-content preferences.
let tabsElement = document.getElementById("tabsElement");
tabsElement.addEventListener("DOMMouseScroll", event => {
event.stopPropagation();
}, true);
}
},
/**
* Stores the identity of the current tab in preferences so that the selected
* tab can be persisted between openings of the preferences window.
*/
tabSelectionChanged() {
if (!this._inited)
return;
var advancedPrefs = document.getElementById("advancedPrefs");
var preference = document.getElementById("browser.preferences.advanced.selectedTabIndex");
// tabSelectionChanged gets called twice due to the selectedIndex being set
// by both the selectedItem and selectedPanel callstacks. This guard is used
// to prevent double-counting in Telemetry.
if (preference.valueFromPreferences != advancedPrefs.selectedIndex) {
Services.telemetry
.getHistogramById("FX_PREFERENCES_CATEGORY_OPENED")
.add(telemetryBucketForCategory("advanced"));
}
preference.valueFromPreferences = advancedPrefs.selectedIndex;
},
// GENERAL TAB
/*
* Preferences:
*
* accessibility.browsewithcaret
* - true enables keyboard navigation and selection within web pages using a
* visible caret, false uses normal keyboard navigation with no caret
* accessibility.typeaheadfind
* - when set to true, typing outside text areas and input boxes will
* automatically start searching for what's typed within the current
* document; when set to false, no search action happens
* ui.osk.enabled
* - when set to true, subject to other conditions, we may sometimes invoke
* an on-screen keyboard when a text input is focused.
* (Currently Windows-only, and depending on prefs, may be Windows-8-only)
* general.autoScroll
* - when set to true, clicking the scroll wheel on the mouse activates a
* mouse mode where moving the mouse down scrolls the document downward with
* speed correlated with the distance of the cursor from the original
* position at which the click occurred (and likewise with movement upward);
* if false, this behavior is disabled
* general.smoothScroll
* - set to true to enable finer page scrolling than line-by-line on page-up,
* page-down, and other such page movements
* layout.spellcheckDefault
* - an integer:
* 0 disables spellchecking
* 1 enables spellchecking, but only for multiline text fields
* 2 enables spellchecking for all text fields
*/
/**
* Stores the original value of the spellchecking preference to enable proper
* restoration if unchanged (since we're mapping a tristate onto a checkbox).
*/
_storedSpellCheck: 0,
/**
* Returns true if any spellchecking is enabled and false otherwise, caching
* the current value to enable proper pref restoration if the checkbox is
* never changed.
*/
readCheckSpelling() {
var pref = document.getElementById("layout.spellcheckDefault");
this._storedSpellCheck = pref.value;
return (pref.value != 0);
},
/**
* Returns the value of the spellchecking preference represented by UI,
* preserving the preference's "hidden" value if the preference is
* unchanged and represents a value not strictly allowed in UI.
*/
writeCheckSpelling() {
var checkbox = document.getElementById("checkSpelling");
if (checkbox.checked) {
if (this._storedSpellCheck == 2) {
return 2;
}
return 1;
}
return 0;
},
/**
* security.OCSP.enabled is an integer value for legacy reasons.
* A value of 1 means OCSP is enabled. Any other value means it is disabled.
*/
readEnableOCSP() {
var preference = document.getElementById("security.OCSP.enabled");
// This is the case if the preference is the default value.
if (preference.value === undefined) {
return true;
}
return preference.value == 1;
},
/**
* See documentation for readEnableOCSP.
*/
writeEnableOCSP() {
var checkbox = document.getElementById("enableOCSP");
return checkbox.checked ? 1 : 0;
},
/**
* When the user toggles the layers.acceleration.disabled pref,
* sync its new value to the gfx.direct2d.disabled pref too.
*/
updateHardwareAcceleration() {
if (AppConstants.platform == "win") {
var fromPref = document.getElementById("layers.acceleration.disabled");
var toPref = document.getElementById("gfx.direct2d.disabled");
toPref.value = fromPref.value;
}
},
// DATA CHOICES TAB
/**
* Set up or hide the Learn More links for various data collection options
*/
_setupLearnMoreLink(pref, element) {
// set up the Learn More link with the correct URL
let url = Services.prefs.getCharPref(pref);
let el = document.getElementById(element);
if (url) {
el.setAttribute("href", url);
} else {
el.setAttribute("hidden", "true");
}
},
/**
*
*/
initSubmitCrashes() {
this._setupLearnMoreLink("toolkit.crashreporter.infoURL",
"crashReporterLearnMore");
},
/**
* The preference/checkbox is configured in XUL.
*
* In all cases, set up the Learn More link sanely.
*/
initTelemetry() {
if (AppConstants.MOZ_TELEMETRY_REPORTING) {
this._setupLearnMoreLink("toolkit.telemetry.infoURL", "telemetryLearnMore");
}
},
/**
* Set the status of the telemetry controls based on the input argument.
* @param {Boolean} aEnabled False disables the controls, true enables them.
*/
setTelemetrySectionEnabled(aEnabled) {
if (AppConstants.MOZ_TELEMETRY_REPORTING) {
// If FHR is disabled, additional data sharing should be disabled as well.
let disabled = !aEnabled;
document.getElementById("submitTelemetryBox").disabled = disabled;
if (disabled) {
// If we disable FHR, untick the telemetry checkbox.
Services.prefs.setBoolPref("toolkit.telemetry.enabled", false);
}
document.getElementById("telemetryDataDesc").disabled = disabled;
}
},
/**
* Initialize the health report service reference and checkbox.
*/
initSubmitHealthReport() {
if (AppConstants.MOZ_TELEMETRY_REPORTING) {
this._setupLearnMoreLink("datareporting.healthreport.infoURL", "FHRLearnMore");
let checkbox = document.getElementById("submitHealthReportBox");
if (Services.prefs.prefIsLocked(PREF_UPLOAD_ENABLED)) {
checkbox.setAttribute("disabled", "true");
return;
}
checkbox.checked = Services.prefs.getBoolPref(PREF_UPLOAD_ENABLED);
this.setTelemetrySectionEnabled(checkbox.checked);
}
},
/**
* Update the health report preference with state from checkbox.
*/
updateSubmitHealthReport() {
if (AppConstants.MOZ_TELEMETRY_REPORTING) {
let checkbox = document.getElementById("submitHealthReportBox");
Services.prefs.setBoolPref(PREF_UPLOAD_ENABLED, checkbox.checked);
this.setTelemetrySectionEnabled(checkbox.checked);
}
},
updateOnScreenKeyboardVisibility() {
if (AppConstants.platform == "win") {
let minVersion = Services.prefs.getBoolPref("ui.osk.require_win10") ? 10 : 6.2;
if (Services.vc.compare(Services.sysinfo.getProperty("version"), minVersion) >= 0) {
document.getElementById("useOnScreenKeyboard").hidden = false;
}
}
},
// NETWORK TAB
/*
* Preferences:
*
* browser.cache.disk.capacity
* - the size of the browser cache in KB
* - Only used if browser.cache.disk.smart_size.enabled is disabled
*/
/**
* Displays a dialog in which proxy settings may be changed.
*/
showConnections() {
gSubDialog.open("chrome://browser/content/preferences/connection.xul");
},
showSiteDataSettings() {
gSubDialog.open("chrome://browser/content/preferences/siteDataSettings.xul");
},
updateTotalSiteDataSize() {
SiteDataManager.getTotalUsage()
.then(usage => {
let size = DownloadUtils.convertByteUnits(usage);
let prefStrBundle = document.getElementById("bundlePreferences");
let totalSiteDataSizeLabel = document.getElementById("totalSiteDataSize");
totalSiteDataSizeLabel.textContent = prefStrBundle.getFormattedString("totalSiteDataSize", size);
let siteDataGroup = document.getElementById("siteDataGroup");
siteDataGroup.hidden = false;
});
},
// Retrieves the amount of space currently used by disk cache
updateActualCacheSize() {
var actualSizeLabel = document.getElementById("actualDiskCacheSize");
var prefStrBundle = document.getElementById("bundlePreferences");
// Needs to root the observer since cache service keeps only a weak reference.
this.observer = {
onNetworkCacheDiskConsumption(consumption) {
var size = DownloadUtils.convertByteUnits(consumption);
// The XBL binding for the string bundle may have been destroyed if
// the page was closed before this callback was executed.
if (!prefStrBundle.getFormattedString) {
return;
}
actualSizeLabel.value = prefStrBundle.getFormattedString("actualDiskCacheSize", size);
},
QueryInterface: XPCOMUtils.generateQI([
Components.interfaces.nsICacheStorageConsumptionObserver,
Components.interfaces.nsISupportsWeakReference
])
};
actualSizeLabel.value = prefStrBundle.getString("actualDiskCacheSizeCalculated");
try {
var cacheService =
Components.classes["@mozilla.org/netwerk/cache-storage-service;1"]
.getService(Components.interfaces.nsICacheStorageService);
cacheService.asyncGetDiskConsumption(this.observer);
} catch (e) {}
},
// Retrieves the amount of space currently used by offline cache
updateActualAppCacheSize() {
var visitor = {
onCacheStorageInfo(aEntryCount, aConsumption, aCapacity, aDiskDirectory) {
var actualSizeLabel = document.getElementById("actualAppCacheSize");
var sizeStrings = DownloadUtils.convertByteUnits(aConsumption);
var prefStrBundle = document.getElementById("bundlePreferences");
// The XBL binding for the string bundle may have been destroyed if
// the page was closed before this callback was executed.
if (!prefStrBundle.getFormattedString) {
return;
}
var sizeStr = prefStrBundle.getFormattedString("actualAppCacheSize", sizeStrings);
actualSizeLabel.value = sizeStr;
}
};
try {
var cacheService =
Components.classes["@mozilla.org/netwerk/cache-storage-service;1"]
.getService(Components.interfaces.nsICacheStorageService);
var storage = cacheService.appCacheStorage(LoadContextInfo.default, null);
storage.asyncVisitStorage(visitor, false);
} catch (e) {}
},
updateCacheSizeUI(smartSizeEnabled) {
document.getElementById("useCacheBefore").disabled = smartSizeEnabled;
document.getElementById("cacheSize").disabled = smartSizeEnabled;
document.getElementById("useCacheAfter").disabled = smartSizeEnabled;
},
readSmartSizeEnabled() {
// The smart_size.enabled preference element is inverted="true", so its
// value is the opposite of the actual pref value
var disabled = document.getElementById("browser.cache.disk.smart_size.enabled").value;
this.updateCacheSizeUI(!disabled);
},
/**
* Converts the cache size from units of KB to units of MB and stores it in
* the textbox element.
*/
updateCacheSizeInputField() {
let cacheSizeElem = document.getElementById("cacheSize");
let cachePref = document.getElementById("browser.cache.disk.capacity");
cacheSizeElem.value = cachePref.value / 1024;
if (cachePref.locked)
cacheSizeElem.disabled = true;
},
/**
* Updates the cache size preference once user enters a new value.
* We intentionally do not set preference="browser.cache.disk.capacity"
* onto the textbox directly, as that would update the pref at each keypress
* not only after the final value is entered.
*/
updateCacheSizePref() {
let cacheSizeElem = document.getElementById("cacheSize");
let cachePref = document.getElementById("browser.cache.disk.capacity");
// Converts the cache size as specified in UI (in MB) to KB.
let intValue = parseInt(cacheSizeElem.value, 10);
cachePref.value = isNaN(intValue) ? 0 : intValue * 1024;
},
/**
* Clears the cache.
*/
clearCache() {
try {
var cache = Components.classes["@mozilla.org/netwerk/cache-storage-service;1"]
.getService(Components.interfaces.nsICacheStorageService);
cache.clear();
} catch (ex) {}
this.updateActualCacheSize();
},
/**
* Clears the application cache.
*/
clearOfflineAppCache() {
Components.utils.import("resource:///modules/offlineAppCache.jsm");
OfflineAppCacheHelper.clear();
this.updateActualAppCacheSize();
this.updateOfflineApps();
},
clearSiteData() {
let flags =
Services.prompt.BUTTON_TITLE_IS_STRING * Services.prompt.BUTTON_POS_0 +
Services.prompt.BUTTON_TITLE_CANCEL * Services.prompt.BUTTON_POS_1 +
Services.prompt.BUTTON_POS_0_DEFAULT;
let prefStrBundle = document.getElementById("bundlePreferences");
let title = prefStrBundle.getString("clearSiteDataPromptTitle");
let text = prefStrBundle.getString("clearSiteDataPromptText");
let btn0Label = prefStrBundle.getString("clearSiteDataNow");
let result = Services.prompt.confirmEx(
window, title, text, flags, btn0Label, null, null, null, {});
if (result == 0) {
SiteDataManager.removeAll();
}
},
readOfflineNotify() {
var pref = document.getElementById("browser.offline-apps.notify");
var button = document.getElementById("offlineNotifyExceptions");
button.disabled = !pref.value;
return pref.value;
},
showOfflineExceptions() {
var bundlePreferences = document.getElementById("bundlePreferences");
var params = { blockVisible: false,
sessionVisible: false,
allowVisible: false,
prefilledHost: "",
permissionType: "offline-app",
manageCapability: Components.interfaces.nsIPermissionManager.DENY_ACTION,
windowTitle: bundlePreferences.getString("offlinepermissionstitle"),
introText: bundlePreferences.getString("offlinepermissionstext") };
gSubDialog.open("chrome://browser/content/preferences/permissions.xul",
null, params);
},
// XXX: duplicated in browser.js
_getOfflineAppUsage(perm, groups) {
let cacheService = Cc["@mozilla.org/network/application-cache-service;1"].
getService(Ci.nsIApplicationCacheService);
if (!groups) {
try {
groups = cacheService.getGroups();
} catch (ex) {
return 0;
}
}
let usage = 0;
for (let group of groups) {
let uri = Services.io.newURI(group);
if (perm.matchesURI(uri, true)) {
let cache = cacheService.getActiveCache(group);
usage += cache.usage;
}
}
return usage;
},
/**
* Updates the list of offline applications
*/
updateOfflineApps() {
var pm = Components.classes["@mozilla.org/permissionmanager;1"]
.getService(Components.interfaces.nsIPermissionManager);
var list = document.getElementById("offlineAppsList");
while (list.firstChild) {
list.firstChild.remove();
}
var groups;
try {
var cacheService = Components.classes["@mozilla.org/network/application-cache-service;1"].
getService(Components.interfaces.nsIApplicationCacheService);
groups = cacheService.getGroups();
} catch (e) {
return;
}
var bundle = document.getElementById("bundlePreferences");
var enumerator = pm.enumerator;
while (enumerator.hasMoreElements()) {
var perm = enumerator.getNext().QueryInterface(Components.interfaces.nsIPermission);
if (perm.type == "offline-app" &&
perm.capability != Components.interfaces.nsIPermissionManager.DEFAULT_ACTION &&
perm.capability != Components.interfaces.nsIPermissionManager.DENY_ACTION) {
var row = document.createElement("listitem");
row.id = "";
row.className = "offlineapp";
row.setAttribute("origin", perm.principal.origin);
var converted = DownloadUtils.
convertByteUnits(this._getOfflineAppUsage(perm, groups));
row.setAttribute("usage",
bundle.getFormattedString("offlineAppUsage",
converted));
list.appendChild(row);
}
}
},
offlineAppSelected() {
var removeButton = document.getElementById("offlineAppsListRemove");
var list = document.getElementById("offlineAppsList");
if (list.selectedItem) {
removeButton.setAttribute("disabled", "false");
} else {
removeButton.setAttribute("disabled", "true");
}
},
removeOfflineApp() {
var list = document.getElementById("offlineAppsList");
var item = list.selectedItem;
var origin = item.getAttribute("origin");
var principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(origin);
var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
.getService(Components.interfaces.nsIPromptService);
var flags = prompts.BUTTON_TITLE_IS_STRING * prompts.BUTTON_POS_0 +
prompts.BUTTON_TITLE_CANCEL * prompts.BUTTON_POS_1;
var bundle = document.getElementById("bundlePreferences");
var title = bundle.getString("offlineAppRemoveTitle");
var prompt = bundle.getFormattedString("offlineAppRemovePrompt", [principal.URI.prePath]);
var confirm = bundle.getString("offlineAppRemoveConfirm");
var result = prompts.confirmEx(window, title, prompt, flags, confirm,
null, null, null, {});
if (result != 0)
return;
// get the permission
var pm = Components.classes["@mozilla.org/permissionmanager;1"]
.getService(Components.interfaces.nsIPermissionManager);
var perm = pm.getPermissionObject(principal, "offline-app", true);
if (perm) {
// clear offline cache entries
try {
var cacheService = Components.classes["@mozilla.org/network/application-cache-service;1"].
getService(Components.interfaces.nsIApplicationCacheService);
var groups = cacheService.getGroups();
for (var i = 0; i < groups.length; i++) {
var uri = Services.io.newURI(groups[i]);
if (perm.matchesURI(uri, true)) {
var cache = cacheService.getActiveCache(groups[i]);
cache.discard();
}
}
} catch (e) {}
pm.removePermission(perm);
}
list.removeChild(item);
gAdvancedPane.offlineAppSelected();
this.updateActualAppCacheSize();
},
// UPDATE TAB
/*
* Preferences:
*
* app.update.enabled
* - true if updates to the application are enabled, false otherwise
* app.update.auto
* - true if updates should be automatically downloaded and installed and
* false if the user should be asked what he wants to do when an update is
* available
* extensions.update.enabled
* - true if updates to extensions and themes are enabled, false otherwise
* browser.search.update
* - true if updates to search engines are enabled, false otherwise
*/
/**
* Selects the item of the radiogroup based on the pref values and locked
* states.
*
* UI state matrix for update preference conditions
*
* UI Components: Preferences
* Radiogroup i = app.update.enabled
* ii = app.update.auto
*
* Disabled states:
* Element pref value locked disabled
* radiogroup i t/f f false
* i t/f *t* *true*
* ii t/f f false
* ii t/f *t* *true*
*/
updateReadPrefs() {
if (AppConstants.MOZ_UPDATER) {
var enabledPref = document.getElementById("app.update.enabled");
var autoPref = document.getElementById("app.update.auto");
var radiogroup = document.getElementById("updateRadioGroup");
if (!enabledPref.value) // Don't care for autoPref.value in this case.
radiogroup.value = "manual"; // 3. Never check for updates.
else if (autoPref.value) // enabledPref.value && autoPref.value
radiogroup.value = "auto"; // 1. Automatically install updates
else // enabledPref.value && !autoPref.value
radiogroup.value = "checkOnly"; // 2. Check, but let me choose
var canCheck = Components.classes["@mozilla.org/updates/update-service;1"].
getService(Components.interfaces.nsIApplicationUpdateService).
canCheckForUpdates;
// canCheck is false if the enabledPref is false and locked,
// or the binary platform or OS version is not known.
// A locked pref is sufficient to disable the radiogroup.
radiogroup.disabled = !canCheck || enabledPref.locked || autoPref.locked;
if (AppConstants.MOZ_MAINTENANCE_SERVICE) {
// Check to see if the maintenance service is installed.
// If it is don't show the preference at all.
var installed;
try {
var wrk = Components.classes["@mozilla.org/windows-registry-key;1"]
.createInstance(Components.interfaces.nsIWindowsRegKey);
wrk.open(wrk.ROOT_KEY_LOCAL_MACHINE,
"SOFTWARE\\Mozilla\\MaintenanceService",
wrk.ACCESS_READ | wrk.WOW64_64);
installed = wrk.readIntValue("Installed");
wrk.close();
} catch (e) {
}
if (installed != 1) {
document.getElementById("useService").hidden = true;
}
}
}
},
/**
* Sets the pref values based on the selected item of the radiogroup.
*/
updateWritePrefs() {
if (AppConstants.MOZ_UPDATER) {
var enabledPref = document.getElementById("app.update.enabled");
var autoPref = document.getElementById("app.update.auto");
var radiogroup = document.getElementById("updateRadioGroup");
switch (radiogroup.value) {
case "auto": // 1. Automatically install updates for Desktop only
enabledPref.value = true;
autoPref.value = true;
break;
case "checkOnly": // 2. Check, but let me choose
enabledPref.value = true;
autoPref.value = false;
break;
case "manual": // 3. Never check for updates.
enabledPref.value = false;
autoPref.value = false;
}
}
},
/**
* Displays the history of installed updates.
*/
showUpdates() {
gSubDialog.open("chrome://mozapps/content/update/history.xul");
},
// ENCRYPTION TAB
/*
* Preferences:
*
* security.default_personal_cert
* - a string:
* "Select Automatically" select a certificate automatically when a site
* requests one
* "Ask Every Time" present a dialog to the user so he can select
* the certificate to use on a site which
* requests one
*/
/**
* Displays the user's certificates and associated options.
*/
showCertificates() {
gSubDialog.open("chrome://pippki/content/certManager.xul");
},
/**
* Displays a dialog from which the user can manage his security devices.
*/
showSecurityDevices() {
gSubDialog.open("chrome://pippki/content/device_manager.xul");
},
observe(aSubject, aTopic, aData) {
if (AppConstants.MOZ_UPDATER) {
switch (aTopic) {
case "nsPref:changed":
this.updateReadPrefs();
break;
case "sitedatamanager:sites-updated":
this.updateTotalSiteDataSize();
break;
}
}
},
};

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

@ -0,0 +1,436 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# 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/.
<!-- Advanced panel -->
<script type="application/javascript"
src="chrome://browser/content/preferences/in-content-old/advanced.js"/>
<preferences id="advancedPreferences" hidden="true" data-category="paneAdvanced">
<preference id="browser.preferences.advanced.selectedTabIndex"
name="browser.preferences.advanced.selectedTabIndex"
type="int"/>
<!-- General tab -->
<preference id="accessibility.browsewithcaret"
name="accessibility.browsewithcaret"
type="bool"/>
<preference id="accessibility.typeaheadfind"
name="accessibility.typeaheadfind"
type="bool"/>
<preference id="accessibility.blockautorefresh"
name="accessibility.blockautorefresh"
type="bool"/>
#ifdef XP_WIN
<preference id="ui.osk.enabled"
name="ui.osk.enabled"
type="bool"/>
#endif
<preference id="general.autoScroll"
name="general.autoScroll"
type="bool"/>
<preference id="general.smoothScroll"
name="general.smoothScroll"
type="bool"/>
<preference id="layers.acceleration.disabled"
name="layers.acceleration.disabled"
type="bool"
inverted="true"/>
#ifdef XP_WIN
<preference id="gfx.direct2d.disabled"
name="gfx.direct2d.disabled"
type="bool"
inverted="true"/>
#endif
<preference id="layout.spellcheckDefault"
name="layout.spellcheckDefault"
type="int"/>
#ifdef MOZ_TELEMETRY_REPORTING
<preference id="toolkit.telemetry.enabled"
name="toolkit.telemetry.enabled"
type="bool"/>
#endif
<!-- Data Choices tab -->
#ifdef MOZ_CRASHREPORTER
<preference id="browser.crashReports.unsubmittedCheck.autoSubmit"
name="browser.crashReports.unsubmittedCheck.autoSubmit"
type="bool"/>
#endif
<!-- Network tab -->
<preference id="browser.cache.disk.capacity"
name="browser.cache.disk.capacity"
type="int"/>
<preference id="browser.offline-apps.notify"
name="browser.offline-apps.notify"
type="bool"/>
<preference id="browser.cache.disk.smart_size.enabled"
name="browser.cache.disk.smart_size.enabled"
inverted="true"
type="bool"/>
<!-- Update tab -->
#ifdef MOZ_UPDATER
<preference id="app.update.enabled"
name="app.update.enabled"
type="bool"/>
<preference id="app.update.auto"
name="app.update.auto"
type="bool"/>
<preference id="app.update.disable_button.showUpdateHistory"
name="app.update.disable_button.showUpdateHistory"
type="bool"/>
#ifdef MOZ_MAINTENANCE_SERVICE
<preference id="app.update.service.enabled"
name="app.update.service.enabled"
type="bool"/>
#endif
#endif
<preference id="browser.search.update"
name="browser.search.update"
type="bool"/>
<!-- Certificates tab -->
<preference id="security.default_personal_cert"
name="security.default_personal_cert"
type="string"/>
<preference id="security.disable_button.openCertManager"
name="security.disable_button.openCertManager"
type="bool"/>
<preference id="security.disable_button.openDeviceManager"
name="security.disable_button.openDeviceManager"
type="bool"/>
<preference id="security.OCSP.enabled"
name="security.OCSP.enabled"
type="int"/>
</preferences>
#ifdef HAVE_SHELL_SERVICE
<stringbundle id="bundleShell" src="chrome://browser/locale/shellservice.properties"/>
<stringbundle id="bundleBrand" src="chrome://branding/locale/brand.properties"/>
#endif
<stringbundle id="bundlePreferences" src="chrome://browser/locale/preferences-old/preferences.properties"/>
<hbox id="header-advanced"
class="header"
hidden="true"
data-category="paneAdvanced">
<label class="header-name" flex="1">&paneAdvanced.title;</label>
<html:a class="help-button" target="_blank" aria-label="&helpButton.label;"></html:a>
</hbox>
<tabbox id="advancedPrefs"
handleCtrlTab="false"
handleCtrlPageUpDown="false"
flex="1"
data-category="paneAdvanced"
hidden="true">
<tabs id="tabsElement">
<tab id="generalTab" label="&generalTab.label;"/>
#ifdef MOZ_DATA_REPORTING
<tab id="dataChoicesTab" label="&dataChoicesTab.label;"/>
#endif
<tab id="networkTab" label="&networkTab.label;"/>
<tab id="updateTab" label="&updateTab.label;"/>
<tab id="encryptionTab" label="&certificateTab.label;"/>
</tabs>
<tabpanels flex="1">
<!-- General -->
<tabpanel id="generalPanel" orient="vertical">
<!-- Accessibility -->
<groupbox id="accessibilityGroup" align="start">
<caption><label>&accessibility.label;</label></caption>
#ifdef XP_WIN
<checkbox id="useOnScreenKeyboard"
hidden="true"
label="&useOnScreenKeyboard.label;"
accesskey="&useOnScreenKeyboard.accesskey;"
preference="ui.osk.enabled"/>
#endif
<checkbox id="useCursorNavigation"
label="&useCursorNavigation.label;"
accesskey="&useCursorNavigation.accesskey;"
preference="accessibility.browsewithcaret"/>
<checkbox id="searchStartTyping"
label="&searchOnStartTyping.label;"
accesskey="&searchOnStartTyping.accesskey;"
preference="accessibility.typeaheadfind"/>
<checkbox id="blockAutoRefresh"
label="&blockAutoReload.label;"
accesskey="&blockAutoReload.accesskey;"
preference="accessibility.blockautorefresh"/>
</groupbox>
<!-- Browsing -->
<groupbox id="browsingGroup" align="start">
<caption><label>&browsing.label;</label></caption>
<checkbox id="useAutoScroll"
label="&useAutoScroll.label;"
accesskey="&useAutoScroll.accesskey;"
preference="general.autoScroll"/>
<checkbox id="useSmoothScrolling"
label="&useSmoothScrolling.label;"
accesskey="&useSmoothScrolling.accesskey;"
preference="general.smoothScroll"/>
<checkbox id="allowHWAccel"
label="&allowHWAccel.label;"
accesskey="&allowHWAccel.accesskey;"
preference="layers.acceleration.disabled"/>
<checkbox id="checkSpelling"
label="&checkUserSpelling.label;"
accesskey="&checkUserSpelling.accesskey;"
onsyncfrompreference="return gAdvancedPane.readCheckSpelling();"
onsynctopreference="return gAdvancedPane.writeCheckSpelling();"
preference="layout.spellcheckDefault"/>
</groupbox>
</tabpanel>
#ifdef MOZ_DATA_REPORTING
<!-- Data Choices -->
<tabpanel id="dataChoicesPanel" orient="vertical">
#ifdef MOZ_TELEMETRY_REPORTING
<groupbox>
<caption>
<checkbox id="submitHealthReportBox" label="&enableHealthReport.label;"
accesskey="&enableHealthReport.accesskey;"/>
</caption>
<vbox>
<hbox class="indent" flex="1">
<label flex="1">&healthReportDesc.label;</label>
<label id="FHRLearnMore" flex="1"
class="learnMore text-link">&healthReportLearnMore.label;</label>
</hbox>
<hbox class="indent">
<groupbox flex="1">
<caption>
<checkbox id="submitTelemetryBox" preference="toolkit.telemetry.enabled"
label="&enableTelemetryData.label;"
accesskey="&enableTelemetryData.accesskey;"/>
</caption>
<hbox class="indent" flex="1">
<label id="telemetryDataDesc" flex="1">&telemetryDesc.label;</label>
<label id="telemetryLearnMore" flex="1"
class="learnMore text-link">&telemetryLearnMore.label;</label>
</hbox>
</groupbox>
</hbox>
</vbox>
</groupbox>
#endif
#ifdef MOZ_CRASHREPORTER
<groupbox>
<caption>
<checkbox id="automaticallySubmitCrashesBox"
preference="browser.crashReports.unsubmittedCheck.autoSubmit"
label="&alwaysSubmitCrashReports.label;"
accesskey="&alwaysSubmitCrashReports.accesskey;"/>
</caption>
<hbox class="indent" flex="1">
<label flex="1">&crashReporterDesc2.label;</label>
<label id="crashReporterLearnMore" flex="1"
class="learnMore text-link">&crashReporterLearnMore.label;</label>
</hbox>
</groupbox>
#endif
</tabpanel>
#endif
<!-- Network -->
<tabpanel id="networkPanel" orient="vertical">
<!-- Connection -->
<groupbox id="connectionGroup">
<caption><label>&connection.label;</label></caption>
<hbox align="center">
<description flex="1" control="connectionSettings">&connectionDesc.label;</description>
<button id="connectionSettings" icon="network" label="&connectionSettings.label;"
accesskey="&connectionSettings.accesskey;"/>
</hbox>
</groupbox>
<!-- Cache -->
<groupbox id="cacheGroup">
<caption><label>&httpCache.label;</label></caption>
<hbox align="center">
<label id="actualDiskCacheSize" flex="1"/>
<button id="clearCacheButton" icon="clear"
label="&clearCacheNow.label;" accesskey="&clearCacheNow.accesskey;"/>
</hbox>
<hbox>
<checkbox preference="browser.cache.disk.smart_size.enabled"
id="allowSmartSize"
onsyncfrompreference="return gAdvancedPane.readSmartSizeEnabled();"
label="&overrideSmartCacheSize.label;"
accesskey="&overrideSmartCacheSize.accesskey;"/>
</hbox>
<hbox align="center" class="indent">
<label id="useCacheBefore" control="cacheSize"
accesskey="&limitCacheSizeBefore.accesskey;">
&limitCacheSizeBefore.label;
</label>
<textbox id="cacheSize" type="number" size="4" max="1024"
aria-labelledby="useCacheBefore cacheSize useCacheAfter"/>
<label id="useCacheAfter" flex="1">&limitCacheSizeAfter.label;</label>
</hbox>
</groupbox>
<!-- Offline apps -->
<groupbox id="offlineGroup">
<caption><label>&offlineStorage2.label;</label></caption>
<hbox align="center">
<label id="actualAppCacheSize" flex="1"/>
<button id="clearOfflineAppCacheButton" icon="clear"
label="&clearOfflineAppCacheNow.label;" accesskey="&clearOfflineAppCacheNow.accesskey;"/>
</hbox>
<hbox align="center">
<checkbox id="offlineNotify"
label="&offlineStorageNotify.label;" accesskey="&offlineStorageNotify.accesskey;"
preference="browser.offline-apps.notify"
onsyncfrompreference="return gAdvancedPane.readOfflineNotify();"/>
<spacer flex="1"/>
<button id="offlineNotifyExceptions"
label="&offlineStorageNotifyExceptions.label;"
accesskey="&offlineStorageNotifyExceptions.accesskey;"/>
</hbox>
<hbox>
<vbox flex="1">
<label id="offlineAppsListLabel">&offlineAppsList2.label;</label>
<listbox id="offlineAppsList"
flex="1"
aria-labelledby="offlineAppsListLabel">
</listbox>
</vbox>
<vbox pack="end">
<button id="offlineAppsListRemove"
disabled="true"
label="&offlineAppsListRemove.label;"
accesskey="&offlineAppsListRemove.accesskey;"/>
</vbox>
</hbox>
</groupbox>
<!-- Site Data -->
<groupbox id="siteDataGroup" hidden="true">
<caption><label>&siteData.label;</label></caption>
<hbox align="baseline">
<label id="totalSiteDataSize"></label>
<label id="siteDataLearnMoreLink" class="learnMore text-link" value="&siteDataLearnMoreLink.label;"></label>
<spacer flex="1" />
<button id="clearSiteDataButton" icon="clear"
label="&clearSiteData.label;" accesskey="&clearSiteData.accesskey;"/>
</hbox>
<vbox align="end">
<button id="siteDataSettings"
label="&siteDataSettings.label;"
accesskey="&siteDataSettings.accesskey;"/>
</vbox>
</groupbox>
</tabpanel>
<!-- Update -->
<tabpanel id="updatePanel" orient="vertical">
#ifdef MOZ_UPDATER
<groupbox id="updateApp" align="start">
<caption><label>&updateApplication.label;</label></caption>
<radiogroup id="updateRadioGroup" align="start">
<radio id="autoDesktop"
value="auto"
label="&updateAuto1.label;"
accesskey="&updateAuto1.accesskey;"/>
<radio value="checkOnly"
label="&updateCheckChoose.label;"
accesskey="&updateCheckChoose.accesskey;"/>
<radio value="manual"
label="&updateManual.label;"
accesskey="&updateManual.accesskey;"/>
</radiogroup>
<separator class="thin"/>
<hbox>
<button id="showUpdateHistory"
label="&updateHistory.label;"
accesskey="&updateHistory.accesskey;"
preference="app.update.disable_button.showUpdateHistory"/>
</hbox>
#ifdef MOZ_MAINTENANCE_SERVICE
<checkbox id="useService"
label="&useService.label;"
accesskey="&useService.accesskey;"
preference="app.update.service.enabled"/>
#endif
</groupbox>
#endif
<groupbox id="updateOthers" align="start">
<caption><label>&autoUpdateOthers.label;</label></caption>
<checkbox id="enableSearchUpdate"
label="&enableSearchUpdate.label;"
accesskey="&enableSearchUpdate.accesskey;"
preference="browser.search.update"/>
</groupbox>
</tabpanel>
<!-- Certificates -->
<tabpanel id="encryptionPanel" orient="vertical">
<groupbox id="certSelection" align="start">
<caption><label>&certPersonal.label;</label></caption>
<description id="CertSelectionDesc" control="certSelection">&certPersonal.description;</description>
<!--
The values on these radio buttons may look like l12y issues, but
they're not - this preference uses *those strings* as its values.
I KID YOU NOT.
-->
<radiogroup id="certSelection"
preftype="string"
preference="security.default_personal_cert"
aria-labelledby="CertSelectionDesc">
<radio label="&selectCerts.auto;"
accesskey="&selectCerts.auto.accesskey;"
value="Select Automatically"/>
<radio label="&selectCerts.ask;"
accesskey="&selectCerts.ask.accesskey;"
value="Ask Every Time"/>
</radiogroup>
</groupbox>
<separator/>
<checkbox id="enableOCSP"
label="&enableOCSP.label;"
accesskey="&enableOCSP.accesskey;"
onsyncfrompreference="return gAdvancedPane.readEnableOCSP();"
onsynctopreference="return gAdvancedPane.writeEnableOCSP();"
preference="security.OCSP.enabled"/>
<separator/>
<hbox>
<button id="viewCertificatesButton"
flex="1"
label="&viewCerts.label;"
accesskey="&viewCerts.accesskey;"
preference="security.disable_button.openCertManager"/>
<button id="viewSecurityDevicesButton"
flex="1"
label="&viewSecurityDevices.label;"
accesskey="&viewSecurityDevices.accesskey;"
preference="security.disable_button.openDeviceManager"/>
<hbox flex="10"/>
</hbox>
</tabpanel>
</tabpanels>
</tabbox>

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

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

@ -0,0 +1,95 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# 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/.
<!-- Applications panel -->
<script type="application/javascript"
src="chrome://browser/content/preferences/in-content-old/applications.js"/>
<preferences id="feedsPreferences" hidden="true" data-category="paneApplications">
<preference id="browser.feeds.handler"
name="browser.feeds.handler"
type="string"/>
<preference id="browser.feeds.handler.default"
name="browser.feeds.handler.default"
type="string"/>
<preference id="browser.feeds.handlers.application"
name="browser.feeds.handlers.application"
type="file"/>
<preference id="browser.feeds.handlers.webservice"
name="browser.feeds.handlers.webservice"
type="string"/>
<preference id="browser.videoFeeds.handler"
name="browser.videoFeeds.handler"
type="string"/>
<preference id="browser.videoFeeds.handler.default"
name="browser.videoFeeds.handler.default"
type="string"/>
<preference id="browser.videoFeeds.handlers.application"
name="browser.videoFeeds.handlers.application"
type="file"/>
<preference id="browser.videoFeeds.handlers.webservice"
name="browser.videoFeeds.handlers.webservice"
type="string"/>
<preference id="browser.audioFeeds.handler"
name="browser.audioFeeds.handler"
type="string"/>
<preference id="browser.audioFeeds.handler.default"
name="browser.audioFeeds.handler.default"
type="string"/>
<preference id="browser.audioFeeds.handlers.application"
name="browser.audioFeeds.handlers.application"
type="file"/>
<preference id="browser.audioFeeds.handlers.webservice"
name="browser.audioFeeds.handlers.webservice"
type="string"/>
<preference id="pref.downloads.disable_button.edit_actions"
name="pref.downloads.disable_button.edit_actions"
type="bool"/>
</preferences>
<keyset data-category="paneApplications">
<!-- Ctrl+f/k focus the search box in the Applications pane.
These <key>s have oncommand attributes because of bug 371900. -->
<key key="&focusSearch1.key;" modifiers="accel" id="focusSearch1" oncommand=";"/>
<key key="&focusSearch2.key;" modifiers="accel" id="focusSearch2" oncommand=";"/>
</keyset>
<hbox id="header-applications"
class="header"
hidden="true"
data-category="paneApplications">
<label class="header-name" flex="1">&paneApplications.title;</label>
<html:a class="help-button" target="_blank" aria-label="&helpButton.label;"></html:a>
</hbox>
<vbox id="applicationsContent"
data-category="paneApplications"
hidden="true"
flex="1">
<hbox>
<textbox id="filter" flex="1"
type="search"
placeholder="&filter.emptytext;"
aria-controls="handlersView"/>
</hbox>
<separator class="thin"/>
<richlistbox id="handlersView" orient="vertical" persist="lastSelectedType"
preference="pref.downloads.disable_button.edit_actions"
flex="1">
<listheader equalsize="always">
<treecol id="typeColumn" label="&typeColumn.label;" value="type"
accesskey="&typeColumn.accesskey;" persist="sortDirection"
flex="1" sortDirection="ascending"/>
<treecol id="actionColumn" label="&actionColumn2.label;" value="action"
accesskey="&actionColumn2.accesskey;" persist="sortDirection"
flex="1"/>
</listheader>
</richlistbox>
</vbox>

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

@ -0,0 +1,99 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
/* import-globals-from preferences.js */
Components.utils.import("resource://gre/modules/AppConstants.jsm");
Components.utils.import("resource://gre/modules/ContextualIdentityService.jsm");
const containersBundle = Services.strings.createBundle("chrome://browser/locale/preferences-old/containers.properties");
const defaultContainerIcon = "fingerprint";
const defaultContainerColor = "blue";
let gContainersPane = {
init() {
this._list = document.getElementById("containersView");
document.getElementById("backContainersLink").addEventListener("click", function() {
gotoPref("privacy");
});
this._rebuildView();
},
_rebuildView() {
const containers = ContextualIdentityService.getPublicIdentities();
while (this._list.firstChild) {
this._list.firstChild.remove();
}
for (let container of containers) {
let item = document.createElement("richlistitem");
item.setAttribute("containerName", ContextualIdentityService.getUserContextLabel(container.userContextId));
item.setAttribute("containerIcon", container.icon);
item.setAttribute("containerColor", container.color);
item.setAttribute("userContextId", container.userContextId);
this._list.appendChild(item);
}
},
onRemoveClick(button) {
let userContextId = parseInt(button.getAttribute("value"), 10);
let count = ContextualIdentityService.countContainerTabs(userContextId);
if (count > 0) {
let bundlePreferences = document.getElementById("bundlePreferences");
let title = bundlePreferences.getString("removeContainerAlertTitle");
let message = PluralForm.get(count, bundlePreferences.getString("removeContainerMsg"))
.replace("#S", count)
let okButton = bundlePreferences.getString("removeContainerOkButton");
let cancelButton = bundlePreferences.getString("removeContainerButton2");
let buttonFlags = (Ci.nsIPrompt.BUTTON_TITLE_IS_STRING * Ci.nsIPrompt.BUTTON_POS_0) +
(Ci.nsIPrompt.BUTTON_TITLE_IS_STRING * Ci.nsIPrompt.BUTTON_POS_1);
let rv = Services.prompt.confirmEx(window, title, message, buttonFlags,
okButton, cancelButton, null, null, {});
if (rv != 0) {
return;
}
ContextualIdentityService.closeContainerTabs(userContextId);
}
ContextualIdentityService.remove(userContextId);
this._rebuildView();
},
onPreferenceClick(button) {
this.openPreferenceDialog(button.getAttribute("value"));
},
onAddButtonClick(button) {
this.openPreferenceDialog(null);
},
openPreferenceDialog(userContextId) {
let identity = {
name: "",
icon: defaultContainerIcon,
color: defaultContainerColor
};
let title;
if (userContextId) {
identity = ContextualIdentityService.getPublicIdentityFromId(userContextId);
// This is required to get the translation string from defaults
identity.name = ContextualIdentityService.getUserContextLabel(identity.userContextId);
title = containersBundle.formatStringFromName("containers.updateContainerTitle", [identity.name], 1);
}
const params = { userContextId, identity, windowTitle: title };
gSubDialog.open("chrome://browser/content/preferences/containers.xul",
null, params);
}
};

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

@ -0,0 +1,54 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# 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/.
<!-- Containers panel -->
<script type="application/javascript"
src="chrome://browser/content/preferences/in-content-old/containers.js"/>
<preferences id="containerPreferences" hidden="true" data-category="paneContainer">
<!-- Containers -->
<preference id="privacy.userContext.enabled"
name="privacy.userContext.enabled"
type="bool"/>
</preferences>
<hbox hidden="true"
class="container-header-links"
data-category="paneContainers">
<label class="text-link" id="backContainersLink" value="&backLink.label;" />
</hbox>
<hbox id="header-containers"
class="header"
hidden="true"
data-category="paneContainers">
<label class="header-name" flex="1">&paneContainers.title;</label>
<button class="help-button"
aria-label="&helpButton.label;"/>
</hbox>
<!-- Containers -->
<groupbox id="browserContainersGroup" data-category="paneContainers" hidden="true">
<vbox id="browserContainersbox">
<richlistbox id="containersView" orient="vertical" persist="lastSelectedType"
flex="1">
<listheader equalsize="always">
<treecol id="typeColumn" value="type"
persist="sortDirection"
flex="1" sortDirection="ascending"/>
<treecol id="actionColumn" value="action"
persist="sortDirection"
flex="1"/>
</listheader>
</richlistbox>
</vbox>
<vbox>
<hbox flex="1">
<button onclick="gContainersPane.onAddButtonClick();" accesskey="&addButton.accesskey;" label="&addButton.label;"/>
</hbox>
</vbox>
</groupbox>

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

@ -0,0 +1,283 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
/* import-globals-from preferences.js */
/* import-globals-from ../../../../toolkit/mozapps/preferences/fontbuilder.js */
XPCOMUtils.defineLazyGetter(this, "AlertsServiceDND", function() {
try {
let alertsService = Cc["@mozilla.org/alerts-service;1"]
.getService(Ci.nsIAlertsService)
.QueryInterface(Ci.nsIAlertsDoNotDisturb);
// This will throw if manualDoNotDisturb isn't implemented.
alertsService.manualDoNotDisturb;
return alertsService;
} catch (ex) {
return undefined;
}
});
var gContentPane = {
init() {
function setEventListener(aId, aEventType, aCallback) {
document.getElementById(aId)
.addEventListener(aEventType, aCallback.bind(gContentPane));
}
// Initializes the fonts dropdowns displayed in this pane.
this._rebuildFonts();
var menulist = document.getElementById("defaultFont");
if (menulist.selectedIndex == -1) {
menulist.value = FontBuilder.readFontSelection(menulist);
}
// Show translation preferences if we may:
const prefName = "browser.translation.ui.show";
if (Services.prefs.getBoolPref(prefName)) {
let row = document.getElementById("translationBox");
row.removeAttribute("hidden");
// Showing attribution only for Bing Translator.
Components.utils.import("resource:///modules/translation/Translation.jsm");
if (Translation.translationEngine == "bing") {
document.getElementById("bingAttribution").removeAttribute("hidden");
}
}
if (AlertsServiceDND) {
let notificationsDoNotDisturbRow =
document.getElementById("notificationsDoNotDisturbRow");
notificationsDoNotDisturbRow.removeAttribute("hidden");
if (AlertsServiceDND.manualDoNotDisturb) {
let notificationsDoNotDisturb =
document.getElementById("notificationsDoNotDisturb");
notificationsDoNotDisturb.setAttribute("checked", true);
}
}
setEventListener("font.language.group", "change",
gContentPane._rebuildFonts);
setEventListener("notificationsPolicyButton", "command",
gContentPane.showNotificationExceptions);
setEventListener("popupPolicyButton", "command",
gContentPane.showPopupExceptions);
setEventListener("advancedFonts", "command",
gContentPane.configureFonts);
setEventListener("colors", "command",
gContentPane.configureColors);
setEventListener("chooseLanguage", "command",
gContentPane.showLanguages);
setEventListener("translationAttributionImage", "click",
gContentPane.openTranslationProviderAttribution);
setEventListener("translateButton", "command",
gContentPane.showTranslationExceptions);
setEventListener("notificationsDoNotDisturb", "command",
gContentPane.toggleDoNotDisturbNotifications);
let notificationInfoURL =
Services.urlFormatter.formatURLPref("app.support.baseURL") + "push";
document.getElementById("notificationsPolicyLearnMore").setAttribute("href",
notificationInfoURL);
let drmInfoURL =
Services.urlFormatter.formatURLPref("app.support.baseURL") + "drm-content";
document.getElementById("playDRMContentLink").setAttribute("href", drmInfoURL);
let emeUIEnabled = Services.prefs.getBoolPref("browser.eme.ui.enabled");
// Force-disable/hide on WinXP:
if (navigator.platform.toLowerCase().startsWith("win")) {
emeUIEnabled = emeUIEnabled && parseFloat(Services.sysinfo.get("version")) >= 6;
}
if (!emeUIEnabled) {
// Don't want to rely on .hidden for the toplevel groupbox because
// of the pane hiding/showing code potentially interfering:
document.getElementById("drmGroup").setAttribute("style", "display: none !important");
}
},
// UTILITY FUNCTIONS
/**
* Utility function to enable/disable the button specified by aButtonID based
* on the value of the Boolean preference specified by aPreferenceID.
*/
updateButtons(aButtonID, aPreferenceID) {
var button = document.getElementById(aButtonID);
var preference = document.getElementById(aPreferenceID);
button.disabled = preference.value != true;
return undefined;
},
// BEGIN UI CODE
/*
* Preferences:
*
* dom.disable_open_during_load
* - true if popups are blocked by default, false otherwise
*/
// NOTIFICATIONS
/**
* Displays the notifications exceptions dialog where specific site notification
* preferences can be set.
*/
showNotificationExceptions() {
let bundlePreferences = document.getElementById("bundlePreferences");
let params = { permissionType: "desktop-notification" };
params.windowTitle = bundlePreferences.getString("notificationspermissionstitle");
params.introText = bundlePreferences.getString("notificationspermissionstext4");
gSubDialog.open("chrome://browser/content/preferences/permissions.xul",
"resizable=yes", params);
try {
Services.telemetry
.getHistogramById("WEB_NOTIFICATION_EXCEPTIONS_OPENED").add();
} catch (e) {}
},
// POP-UPS
/**
* Displays the popup exceptions dialog where specific site popup preferences
* can be set.
*/
showPopupExceptions() {
var bundlePreferences = document.getElementById("bundlePreferences");
var params = { blockVisible: false, sessionVisible: false, allowVisible: true,
prefilledHost: "", permissionType: "popup" }
params.windowTitle = bundlePreferences.getString("popuppermissionstitle");
params.introText = bundlePreferences.getString("popuppermissionstext");
gSubDialog.open("chrome://browser/content/preferences/permissions.xul",
"resizable=yes", params);
},
// FONTS
/**
* Populates the default font list in UI.
*/
_rebuildFonts() {
var preferences = document.getElementById("contentPreferences");
// Ensure preferences are "visible" to ensure bindings work.
preferences.hidden = false;
// Force flush:
preferences.clientHeight;
var langGroupPref = document.getElementById("font.language.group");
this._selectDefaultLanguageGroup(langGroupPref.value,
this._readDefaultFontTypeForLanguage(langGroupPref.value) == "serif");
},
/**
*
*/
_selectDefaultLanguageGroup(aLanguageGroup, aIsSerif) {
const kFontNameFmtSerif = "font.name.serif.%LANG%";
const kFontNameFmtSansSerif = "font.name.sans-serif.%LANG%";
const kFontNameListFmtSerif = "font.name-list.serif.%LANG%";
const kFontNameListFmtSansSerif = "font.name-list.sans-serif.%LANG%";
const kFontSizeFmtVariable = "font.size.variable.%LANG%";
var preferences = document.getElementById("contentPreferences");
var prefs = [{ format: aIsSerif ? kFontNameFmtSerif : kFontNameFmtSansSerif,
type: "fontname",
element: "defaultFont",
fonttype: aIsSerif ? "serif" : "sans-serif" },
{ format: aIsSerif ? kFontNameListFmtSerif : kFontNameListFmtSansSerif,
type: "unichar",
element: null,
fonttype: aIsSerif ? "serif" : "sans-serif" },
{ format: kFontSizeFmtVariable,
type: "int",
element: "defaultFontSize",
fonttype: null }];
for (var i = 0; i < prefs.length; ++i) {
var preference = document.getElementById(prefs[i].format.replace(/%LANG%/, aLanguageGroup));
if (!preference) {
preference = document.createElement("preference");
var name = prefs[i].format.replace(/%LANG%/, aLanguageGroup);
preference.id = name;
preference.setAttribute("name", name);
preference.setAttribute("type", prefs[i].type);
preferences.appendChild(preference);
}
if (!prefs[i].element)
continue;
var element = document.getElementById(prefs[i].element);
if (element) {
element.setAttribute("preference", preference.id);
if (prefs[i].fonttype)
FontBuilder.buildFontList(aLanguageGroup, prefs[i].fonttype, element);
preference.setElementValue(element);
}
}
},
/**
* Returns the type of the current default font for the language denoted by
* aLanguageGroup.
*/
_readDefaultFontTypeForLanguage(aLanguageGroup) {
const kDefaultFontType = "font.default.%LANG%";
var defaultFontTypePref = kDefaultFontType.replace(/%LANG%/, aLanguageGroup);
var preference = document.getElementById(defaultFontTypePref);
if (!preference) {
preference = document.createElement("preference");
preference.id = defaultFontTypePref;
preference.setAttribute("name", defaultFontTypePref);
preference.setAttribute("type", "string");
preference.setAttribute("onchange", "gContentPane._rebuildFonts();");
document.getElementById("contentPreferences").appendChild(preference);
}
return preference.value;
},
/**
* Displays the fonts dialog, where web page font names and sizes can be
* configured.
*/
configureFonts() {
gSubDialog.open("chrome://browser/content/preferences/fonts.xul", "resizable=no");
},
/**
* Displays the colors dialog, where default web page/link/etc. colors can be
* configured.
*/
configureColors() {
gSubDialog.open("chrome://browser/content/preferences/colors.xul", "resizable=no");
},
// LANGUAGES
/**
* Shows a dialog in which the preferred language for web content may be set.
*/
showLanguages() {
gSubDialog.open("chrome://browser/content/preferences/languages.xul");
},
/**
* Displays the translation exceptions dialog where specific site and language
* translation preferences can be set.
*/
showTranslationExceptions() {
gSubDialog.open("chrome://browser/content/preferences/translation.xul");
},
openTranslationProviderAttribution() {
Components.utils.import("resource:///modules/translation/Translation.jsm");
Translation.openProviderAttribution();
},
toggleDoNotDisturbNotifications(event) {
AlertsServiceDND.manualDoNotDisturb = event.target.checked;
},
};

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

@ -0,0 +1,207 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# 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/.
<!-- Content panel -->
<preferences id="contentPreferences" hidden="true" data-category="paneContent">
<!-- DRM content -->
<preference id="media.eme.enabled"
name="media.eme.enabled"
type="bool"/>
<!-- Popups -->
<preference id="dom.disable_open_during_load"
name="dom.disable_open_during_load"
type="bool"/>
<!-- Fonts -->
<preference id="font.language.group"
name="font.language.group"
type="wstring"/>
<!-- Languages -->
<preference id="browser.translation.detectLanguage"
name="browser.translation.detectLanguage"
type="bool"/>
</preferences>
<script type="application/javascript"
src="chrome://mozapps/content/preferences/fontbuilder.js"/>
<script type="application/javascript"
src="chrome://browser/content/preferences/in-content-old/content.js"/>
<hbox id="header-content"
class="header"
hidden="true"
data-category="paneContent">
<label class="header-name" flex="1">&paneContent.title;</label>
<html:a class="help-button" target="_blank" aria-label="&helpButton.label;"></html:a>
</hbox>
<groupbox id="drmGroup" data-category="paneContent" hidden="true">
<caption><label>&drmContent.label;</label></caption>
<grid id="contentGrid2">
<columns>
<column flex="1"/>
<column/>
</columns>
<rows id="contentRows-2">
<row id="playDRMContentRow">
<hbox align="center">
<checkbox id="playDRMContent" preference="media.eme.enabled"
label="&playDRMContent.label;" accesskey="&playDRMContent.accesskey;"/>
<label id="playDRMContentLink" class="learnMore text-link" value="&playDRMContent.learnMore.label;"/>
</hbox>
</row>
</rows>
</grid>
</groupbox>
<groupbox id="notificationsGroup" data-category="paneContent" hidden="true">
<caption><label>&notificationsPolicy.label;</label></caption>
<grid>
<columns>
<column flex="1"/>
<column/>
</columns>
<rows>
<row id="notificationsPolicyRow" align="center">
<hbox align="start">
<label id="notificationsPolicy">&notificationsPolicyDesc3.label;</label>
<label id="notificationsPolicyLearnMore"
class="learnMore text-link"
value="&notificationsPolicyLearnMore.label;"/>
</hbox>
<hbox pack="end">
<button id="notificationsPolicyButton" label="&notificationsPolicyButton.label;"
accesskey="&notificationsPolicyButton.accesskey;"/>
</hbox>
</row>
<row id="notificationsDoNotDisturbRow" hidden="true">
<vbox align="start">
<checkbox id="notificationsDoNotDisturb" label="&notificationsDoNotDisturb.label;"
accesskey="&notificationsDoNotDisturb.accesskey;"/>
<label id="notificationsDoNotDisturbDetails"
class="indent"
value="&notificationsDoNotDisturbDetails.value;"/>
</vbox>
</row>
</rows>
</grid>
</groupbox>
<groupbox id="miscGroup" data-category="paneContent" hidden="true">
<caption><label>&popups.label;</label></caption>
<grid id="contentGrid">
<columns>
<column flex="1"/>
<column/>
</columns>
<rows id="contentRows-1">
<row id="popupPolicyRow">
<vbox align="start">
<checkbox id="popupPolicy" preference="dom.disable_open_during_load"
label="&blockPopups.label;" accesskey="&blockPopups.accesskey;"
onsyncfrompreference="return gContentPane.updateButtons('popupPolicyButton',
'dom.disable_open_during_load');"/>
</vbox>
<hbox pack="end">
<button id="popupPolicyButton" label="&popupExceptions.label;"
accesskey="&popupExceptions.accesskey;"/>
</hbox>
</row>
</rows>
</grid>
</groupbox>
<!-- Fonts and Colors -->
<groupbox id="fontsGroup" data-category="paneContent" hidden="true">
<caption><label>&fontsAndColors.label;</label></caption>
<grid id="fontsGrid">
<columns>
<column flex="1"/>
<column/>
</columns>
<rows id="fontsRows">
<row id="fontRow">
<hbox align="center">
<label control="defaultFont" accesskey="&defaultFont.accesskey;">&defaultFont.label;</label>
<menulist id="defaultFont" delayprefsave="true"/>
<label id="defaultFontSizeLabel" control="defaultFontSize" accesskey="&defaultSize.accesskey;">&defaultSize.label;</label>
<menulist id="defaultFontSize" delayprefsave="true">
<menupopup>
<menuitem value="9" label="9"/>
<menuitem value="10" label="10"/>
<menuitem value="11" label="11"/>
<menuitem value="12" label="12"/>
<menuitem value="13" label="13"/>
<menuitem value="14" label="14"/>
<menuitem value="15" label="15"/>
<menuitem value="16" label="16"/>
<menuitem value="17" label="17"/>
<menuitem value="18" label="18"/>
<menuitem value="20" label="20"/>
<menuitem value="22" label="22"/>
<menuitem value="24" label="24"/>
<menuitem value="26" label="26"/>
<menuitem value="28" label="28"/>
<menuitem value="30" label="30"/>
<menuitem value="32" label="32"/>
<menuitem value="34" label="34"/>
<menuitem value="36" label="36"/>
<menuitem value="40" label="40"/>
<menuitem value="44" label="44"/>
<menuitem value="48" label="48"/>
<menuitem value="56" label="56"/>
<menuitem value="64" label="64"/>
<menuitem value="72" label="72"/>
</menupopup>
</menulist>
</hbox>
<button id="advancedFonts" icon="select-font"
label="&advancedFonts.label;"
accesskey="&advancedFonts.accesskey;"/>
</row>
<row id="colorsRow">
<hbox/>
<button id="colors" icon="select-color"
label="&colors.label;"
accesskey="&colors.accesskey;"/>
</row>
</rows>
</grid>
</groupbox>
<!-- Languages -->
<groupbox id="languagesGroup" data-category="paneContent" hidden="true">
<caption><label>&languages.label;</label></caption>
<hbox id="languagesBox" align="center">
<description flex="1" control="chooseLanguage">&chooseLanguage.label;</description>
<button id="chooseLanguage"
label="&chooseButton.label;"
accesskey="&chooseButton.accesskey;"/>
</hbox>
<hbox id="translationBox" hidden="true">
<hbox align="center" flex="1">
<checkbox id="translate" preference="browser.translation.detectLanguage"
label="&translateWebPages.label;." accesskey="&translateWebPages.accesskey;"
onsyncfrompreference="return gContentPane.updateButtons('translateButton',
'browser.translation.detectLanguage');"/>
<hbox id="bingAttribution" hidden="true">
<label>&translation.options.attribution.beforeLogo;</label>
<separator orient="vertical" class="thin"/>
<image id="translationAttributionImage" aria-label="Microsoft Translator"
src="chrome://browser/content/microsoft-translator-attribution.png"/>
<separator orient="vertical" class="thin"/>
<label>&translation.options.attribution.afterLogo;</label>
</hbox>
</hbox>
<button id="translateButton" label="&translateExceptions.label;"
accesskey="&translateExceptions.accesskey;"/>
</hbox>
</groupbox>

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

@ -0,0 +1,18 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# 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/.
browser.jar:
content/browser/preferences/in-content-old/preferences.js
* content/browser/preferences/in-content-old/preferences.xul
content/browser/preferences/in-content-old/subdialogs.js
content/browser/preferences/in-content-old/main.js
content/browser/preferences/in-content-old/privacy.js
content/browser/preferences/in-content-old/containers.js
content/browser/preferences/in-content-old/advanced.js
content/browser/preferences/in-content-old/applications.js
content/browser/preferences/in-content-old/content.js
content/browser/preferences/in-content-old/sync.js
content/browser/preferences/in-content-old/security.js
content/browser/preferences/in-content-old/search.js

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

@ -0,0 +1,699 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
/* import-globals-from preferences.js */
Components.utils.import("resource://gre/modules/Downloads.jsm");
Components.utils.import("resource://gre/modules/FileUtils.jsm");
Components.utils.import("resource://gre/modules/Task.jsm");
Components.utils.import("resource:///modules/ShellService.jsm");
Components.utils.import("resource:///modules/TransientPrefs.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "OS",
"resource://gre/modules/osfile.jsm");
if (AppConstants.E10S_TESTING_ONLY) {
XPCOMUtils.defineLazyModuleGetter(this, "UpdateUtils",
"resource://gre/modules/UpdateUtils.jsm");
}
var gMainPane = {
/**
* Initialization of this.
*/
init() {
function setEventListener(aId, aEventType, aCallback) {
document.getElementById(aId)
.addEventListener(aEventType, aCallback.bind(gMainPane));
}
if (AppConstants.HAVE_SHELL_SERVICE) {
this.updateSetDefaultBrowser();
if (AppConstants.platform == "win") {
// In Windows 8 we launch the control panel since it's the only
// way to get all file type association prefs. So we don't know
// when the user will select the default. We refresh here periodically
// in case the default changes. On other Windows OS's defaults can also
// be set while the prefs are open.
window.setInterval(this.updateSetDefaultBrowser.bind(this), 1000);
}
}
// set up the "use current page" label-changing listener
this._updateUseCurrentButton();
window.addEventListener("focus", this._updateUseCurrentButton.bind(this));
this.updateBrowserStartupLastSession();
if (AppConstants.platform == "win") {
// Functionality for "Show tabs in taskbar" on Windows 7 and up.
try {
let sysInfo = Cc["@mozilla.org/system-info;1"].
getService(Ci.nsIPropertyBag2);
let ver = parseFloat(sysInfo.getProperty("version"));
let showTabsInTaskbar = document.getElementById("showTabsInTaskbar");
showTabsInTaskbar.hidden = ver < 6.1;
} catch (ex) {}
}
// The "closing multiple tabs" and "opening multiple tabs might slow down
// &brandShortName;" warnings provide options for not showing these
// warnings again. When the user disabled them, we provide checkboxes to
// re-enable the warnings.
if (!TransientPrefs.prefShouldBeVisible("browser.tabs.warnOnClose"))
document.getElementById("warnCloseMultiple").hidden = true;
if (!TransientPrefs.prefShouldBeVisible("browser.tabs.warnOnOpen"))
document.getElementById("warnOpenMany").hidden = true;
setEventListener("browser.privatebrowsing.autostart", "change",
gMainPane.updateBrowserStartupLastSession);
setEventListener("browser.download.dir", "change",
gMainPane.displayDownloadDirPref);
if (AppConstants.HAVE_SHELL_SERVICE) {
setEventListener("setDefaultButton", "command",
gMainPane.setDefaultBrowser);
}
setEventListener("useCurrent", "command",
gMainPane.setHomePageToCurrent);
setEventListener("useBookmark", "command",
gMainPane.setHomePageToBookmark);
setEventListener("restoreDefaultHomePage", "command",
gMainPane.restoreDefaultHomePage);
setEventListener("chooseFolder", "command",
gMainPane.chooseFolder);
if (AppConstants.E10S_TESTING_ONLY) {
setEventListener("e10sAutoStart", "command",
gMainPane.enableE10SChange);
let e10sCheckbox = document.getElementById("e10sAutoStart");
let e10sPref = document.getElementById("browser.tabs.remote.autostart");
let e10sTempPref = document.getElementById("e10sTempPref");
let e10sForceEnable = document.getElementById("e10sForceEnable");
let preffedOn = e10sPref.value || e10sTempPref.value || e10sForceEnable.value;
if (preffedOn) {
// The checkbox is checked if e10s is preffed on and enabled.
e10sCheckbox.checked = Services.appinfo.browserTabsRemoteAutostart;
// but if it's force disabled, then the checkbox is disabled.
e10sCheckbox.disabled = !Services.appinfo.browserTabsRemoteAutostart;
}
}
if (AppConstants.MOZ_DEV_EDITION) {
let uAppData = OS.Constants.Path.userApplicationDataDir;
let ignoreSeparateProfile = OS.Path.join(uAppData, "ignore-dev-edition-profile");
setEventListener("separateProfileMode", "command", gMainPane.separateProfileModeChange);
let separateProfileModeCheckbox = document.getElementById("separateProfileMode");
setEventListener("getStarted", "click", gMainPane.onGetStarted);
OS.File.stat(ignoreSeparateProfile).then(() => separateProfileModeCheckbox.checked = false,
() => separateProfileModeCheckbox.checked = true);
}
// Notify observers that the UI is now ready
Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService)
.notifyObservers(window, "main-pane-loaded", null);
},
enableE10SChange() {
if (AppConstants.E10S_TESTING_ONLY) {
let e10sCheckbox = document.getElementById("e10sAutoStart");
let e10sPref = document.getElementById("browser.tabs.remote.autostart");
let e10sTempPref = document.getElementById("e10sTempPref");
let prefsToChange;
if (e10sCheckbox.checked) {
// Enabling e10s autostart
prefsToChange = [e10sPref];
} else {
// Disabling e10s autostart
prefsToChange = [e10sPref];
if (e10sTempPref.value) {
prefsToChange.push(e10sTempPref);
}
}
let buttonIndex = confirmRestartPrompt(e10sCheckbox.checked, 0,
true, false);
if (buttonIndex == CONFIRM_RESTART_PROMPT_RESTART_NOW) {
for (let prefToChange of prefsToChange) {
prefToChange.value = e10sCheckbox.checked;
}
Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart);
}
// Revert the checkbox in case we didn't quit
e10sCheckbox.checked = e10sPref.value || e10sTempPref.value;
}
},
separateProfileModeChange() {
if (AppConstants.MOZ_DEV_EDITION) {
function quitApp() {
Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestartNotSameProfile);
}
function revertCheckbox(error) {
separateProfileModeCheckbox.checked = !separateProfileModeCheckbox.checked;
if (error) {
Cu.reportError("Failed to toggle separate profile mode: " + error);
}
}
function createOrRemoveSpecialDevEditionFile(onSuccess) {
let uAppData = OS.Constants.Path.userApplicationDataDir;
let ignoreSeparateProfile = OS.Path.join(uAppData, "ignore-dev-edition-profile");
if (separateProfileModeCheckbox.checked) {
OS.File.remove(ignoreSeparateProfile).then(onSuccess, revertCheckbox);
} else {
OS.File.writeAtomic(ignoreSeparateProfile, new Uint8Array()).then(onSuccess, revertCheckbox);
}
}
let separateProfileModeCheckbox = document.getElementById("separateProfileMode");
let button_index = confirmRestartPrompt(separateProfileModeCheckbox.checked,
0, false, true);
switch (button_index) {
case CONFIRM_RESTART_PROMPT_CANCEL:
revertCheckbox();
return;
case CONFIRM_RESTART_PROMPT_RESTART_NOW:
const Cc = Components.classes, Ci = Components.interfaces;
let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"]
.createInstance(Ci.nsISupportsPRBool);
Services.obs.notifyObservers(cancelQuit, "quit-application-requested",
"restart");
if (!cancelQuit.data) {
createOrRemoveSpecialDevEditionFile(quitApp);
return;
}
// Revert the checkbox in case we didn't quit
revertCheckbox();
return;
case CONFIRM_RESTART_PROMPT_RESTART_LATER:
createOrRemoveSpecialDevEditionFile();
}
}
},
onGetStarted(aEvent) {
if (AppConstants.MOZ_DEV_EDITION) {
const Cc = Components.classes, Ci = Components.interfaces;
let wm = Cc["@mozilla.org/appshell/window-mediator;1"]
.getService(Ci.nsIWindowMediator);
let win = wm.getMostRecentWindow("navigator:browser");
if (win) {
let accountsTab = win.gBrowser.addTab("about:accounts?action=signin&entrypoint=dev-edition-setup");
win.gBrowser.selectedTab = accountsTab;
}
}
},
// HOME PAGE
/*
* Preferences:
*
* browser.startup.homepage
* - the user's home page, as a string; if the home page is a set of tabs,
* this will be those URLs separated by the pipe character "|"
* browser.startup.page
* - what page(s) to show when the user starts the application, as an integer:
*
* 0: a blank page
* 1: the home page (as set by the browser.startup.homepage pref)
* 2: the last page the user visited (DEPRECATED)
* 3: windows and tabs from the last session (a.k.a. session restore)
*
* The deprecated option is not exposed in UI; however, if the user has it
* selected and doesn't change the UI for this preference, the deprecated
* option is preserved.
*/
syncFromHomePref() {
let homePref = document.getElementById("browser.startup.homepage");
// If the pref is set to about:home or about:newtab, set the value to ""
// to show the placeholder text (about:home title) rather than
// exposing those URLs to users.
let defaultBranch = Services.prefs.getDefaultBranch("");
let defaultValue = defaultBranch.getComplexValue("browser.startup.homepage",
Ci.nsIPrefLocalizedString).data;
let currentValue = homePref.value.toLowerCase();
if (currentValue == "about:home" ||
(currentValue == defaultValue && currentValue == "about:newtab")) {
return "";
}
// If the pref is actually "", show about:blank. The actual home page
// loading code treats them the same, and we don't want the placeholder text
// to be shown.
if (homePref.value == "")
return "about:blank";
// Otherwise, show the actual pref value.
return undefined;
},
syncToHomePref(value) {
// If the value is "", use about:home.
if (value == "")
return "about:home";
// Otherwise, use the actual textbox value.
return undefined;
},
/**
* Sets the home page to the current displayed page (or frontmost tab, if the
* most recent browser window contains multiple tabs), updating preference
* window UI to reflect this.
*/
setHomePageToCurrent() {
let homePage = document.getElementById("browser.startup.homepage");
let tabs = this._getTabsForHomePage();
function getTabURI(t) {
return t.linkedBrowser.currentURI.spec;
}
// FIXME Bug 244192: using dangerous "|" joiner!
if (tabs.length)
homePage.value = tabs.map(getTabURI).join("|");
},
/**
* Displays a dialog in which the user can select a bookmark to use as home
* page. If the user selects a bookmark, that bookmark's name is displayed in
* UI and the bookmark's address is stored to the home page preference.
*/
setHomePageToBookmark() {
var rv = { urls: null, names: null };
gSubDialog.open("chrome://browser/content/preferences/selectBookmark.xul",
"resizable=yes, modal=yes", rv,
this._setHomePageToBookmarkClosed.bind(this, rv));
},
_setHomePageToBookmarkClosed(rv, aEvent) {
if (aEvent.detail.button != "accept")
return;
if (rv.urls && rv.names) {
var homePage = document.getElementById("browser.startup.homepage");
// XXX still using dangerous "|" joiner!
homePage.value = rv.urls.join("|");
}
},
/**
* Switches the "Use Current Page" button between its singular and plural
* forms.
*/
_updateUseCurrentButton() {
let useCurrent = document.getElementById("useCurrent");
let tabs = this._getTabsForHomePage();
if (tabs.length > 1)
useCurrent.label = useCurrent.getAttribute("label2");
else
useCurrent.label = useCurrent.getAttribute("label1");
// In this case, the button's disabled state is set by preferences.xml.
let prefName = "pref.browser.homepage.disable_button.current_page";
if (document.getElementById(prefName).locked)
return;
useCurrent.disabled = !tabs.length
},
_getTabsForHomePage() {
var win;
var tabs = [];
const Cc = Components.classes, Ci = Components.interfaces;
var wm = Cc["@mozilla.org/appshell/window-mediator;1"]
.getService(Ci.nsIWindowMediator);
win = wm.getMostRecentWindow("navigator:browser");
if (win && win.document.documentElement
.getAttribute("windowtype") == "navigator:browser") {
// We should only include visible & non-pinned tabs
tabs = win.gBrowser.visibleTabs.slice(win.gBrowser._numPinnedTabs);
tabs = tabs.filter(this.isNotAboutPreferences);
}
return tabs;
},
/**
* Check to see if a tab is not about:preferences
*/
isNotAboutPreferences(aElement, aIndex, aArray) {
return !aElement.linkedBrowser.currentURI.spec.startsWith("about:preferences");
},
/**
* Restores the default home page as the user's home page.
*/
restoreDefaultHomePage() {
var homePage = document.getElementById("browser.startup.homepage");
homePage.value = homePage.defaultValue;
},
// DOWNLOADS
/*
* Preferences:
*
* browser.download.useDownloadDir - bool
* True - Save files directly to the folder configured via the
* browser.download.folderList preference.
* False - Always ask the user where to save a file and default to
* browser.download.lastDir when displaying a folder picker dialog.
* browser.download.dir - local file handle
* A local folder the user may have selected for downloaded files to be
* saved. Migration of other browser settings may also set this path.
* This folder is enabled when folderList equals 2.
* browser.download.lastDir - local file handle
* May contain the last folder path accessed when the user browsed
* via the file save-as dialog. (see contentAreaUtils.js)
* browser.download.folderList - int
* Indicates the location users wish to save downloaded files too.
* It is also used to display special file labels when the default
* download location is either the Desktop or the Downloads folder.
* Values:
* 0 - The desktop is the default download location.
* 1 - The system's downloads folder is the default download location.
* 2 - The default download location is elsewhere as specified in
* browser.download.dir.
* browser.download.downloadDir
* deprecated.
* browser.download.defaultFolder
* deprecated.
*/
/**
* Enables/disables the folder field and Browse button based on whether a
* default download directory is being used.
*/
readUseDownloadDir() {
var downloadFolder = document.getElementById("downloadFolder");
var chooseFolder = document.getElementById("chooseFolder");
var preference = document.getElementById("browser.download.useDownloadDir");
downloadFolder.disabled = !preference.value || preference.locked;
chooseFolder.disabled = !preference.value || preference.locked;
// don't override the preference's value in UI
return undefined;
},
/**
* Displays a file picker in which the user can choose the location where
* downloads are automatically saved, updating preferences and UI in
* response to the choice, if one is made.
*/
chooseFolder() {
return this.chooseFolderTask().catch(Components.utils.reportError);
},
chooseFolderTask: Task.async(function* () {
let bundlePreferences = document.getElementById("bundlePreferences");
let title = bundlePreferences.getString("chooseDownloadFolderTitle");
let folderListPref = document.getElementById("browser.download.folderList");
let currentDirPref = yield this._indexToFolder(folderListPref.value);
let defDownloads = yield this._indexToFolder(1);
let fp = Components.classes["@mozilla.org/filepicker;1"].
createInstance(Components.interfaces.nsIFilePicker);
fp.init(window, title, Components.interfaces.nsIFilePicker.modeGetFolder);
fp.appendFilters(Components.interfaces.nsIFilePicker.filterAll);
// First try to open what's currently configured
if (currentDirPref && currentDirPref.exists()) {
fp.displayDirectory = currentDirPref;
} else if (defDownloads && defDownloads.exists()) {
// Try the system's download dir
fp.displayDirectory = defDownloads;
} else {
// Fall back to Desktop
fp.displayDirectory = yield this._indexToFolder(0);
}
let result = yield new Promise(resolve => fp.open(resolve));
if (result != Components.interfaces.nsIFilePicker.returnOK) {
return;
}
let downloadDirPref = document.getElementById("browser.download.dir");
downloadDirPref.value = fp.file;
folderListPref.value = yield this._folderToIndex(fp.file);
// Note, the real prefs will not be updated yet, so dnld manager's
// userDownloadsDirectory may not return the right folder after
// this code executes. displayDownloadDirPref will be called on
// the assignment above to update the UI.
}),
/**
* Initializes the download folder display settings based on the user's
* preferences.
*/
displayDownloadDirPref() {
this.displayDownloadDirPrefTask().catch(Components.utils.reportError);
// don't override the preference's value in UI
return undefined;
},
displayDownloadDirPrefTask: Task.async(function* () {
var folderListPref = document.getElementById("browser.download.folderList");
var bundlePreferences = document.getElementById("bundlePreferences");
var downloadFolder = document.getElementById("downloadFolder");
var currentDirPref = document.getElementById("browser.download.dir");
// Used in defining the correct path to the folder icon.
var ios = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
var fph = ios.getProtocolHandler("file")
.QueryInterface(Components.interfaces.nsIFileProtocolHandler);
var iconUrlSpec;
// Display a 'pretty' label or the path in the UI.
if (folderListPref.value == 2) {
// Custom path selected and is configured
downloadFolder.label = this._getDisplayNameOfFile(currentDirPref.value);
iconUrlSpec = fph.getURLSpecFromFile(currentDirPref.value);
} else if (folderListPref.value == 1) {
// 'Downloads'
// In 1.5, this pointed to a folder we created called 'My Downloads'
// and was available as an option in the 1.5 drop down. On XP this
// was in My Documents, on OSX it was in User Docs. In 2.0, we did
// away with the drop down option, although the special label was
// still supported for the folder if it existed. Because it was
// not exposed it was rarely used.
// With 3.0, a new desktop folder - 'Downloads' was introduced for
// platforms and versions that don't support a default system downloads
// folder. See nsDownloadManager for details.
downloadFolder.label = bundlePreferences.getString("downloadsFolderName");
iconUrlSpec = fph.getURLSpecFromFile(yield this._indexToFolder(1));
} else {
// 'Desktop'
downloadFolder.label = bundlePreferences.getString("desktopFolderName");
iconUrlSpec = fph.getURLSpecFromFile(yield this._getDownloadsFolder("Desktop"));
}
downloadFolder.image = "moz-icon://" + iconUrlSpec + "?size=16";
}),
/**
* Returns the textual path of a folder in readable form.
*/
_getDisplayNameOfFile(aFolder) {
// TODO: would like to add support for 'Downloads on Macintosh HD'
// for OS X users.
return aFolder ? aFolder.path : "";
},
/**
* Returns the Downloads folder. If aFolder is "Desktop", then the Downloads
* folder returned is the desktop folder; otherwise, it is a folder whose name
* indicates that it is a download folder and whose path is as determined by
* the XPCOM directory service via the download manager's attribute
* defaultDownloadsDirectory.
*
* @throws if aFolder is not "Desktop" or "Downloads"
*/
_getDownloadsFolder: Task.async(function* (aFolder) {
switch (aFolder) {
case "Desktop":
var fileLoc = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties);
return fileLoc.get("Desk", Components.interfaces.nsILocalFile);
case "Downloads":
let downloadsDir = yield Downloads.getSystemDownloadsDirectory();
return new FileUtils.File(downloadsDir);
}
throw "ASSERTION FAILED: folder type should be 'Desktop' or 'Downloads'";
}),
/**
* Determines the type of the given folder.
*
* @param aFolder
* the folder whose type is to be determined
* @returns integer
* 0 if aFolder is the Desktop or is unspecified,
* 1 if aFolder is the Downloads folder,
* 2 otherwise
*/
_folderToIndex: Task.async(function* (aFolder) {
if (!aFolder || aFolder.equals(yield this._getDownloadsFolder("Desktop")))
return 0;
else if (aFolder.equals(yield this._getDownloadsFolder("Downloads")))
return 1;
return 2;
}),
/**
* Converts an integer into the corresponding folder.
*
* @param aIndex
* an integer
* @returns the Desktop folder if aIndex == 0,
* the Downloads folder if aIndex == 1,
* the folder stored in browser.download.dir
*/
_indexToFolder: Task.async(function* (aIndex) {
switch (aIndex) {
case 0:
return yield this._getDownloadsFolder("Desktop");
case 1:
return yield this._getDownloadsFolder("Downloads");
}
var currentDirPref = document.getElementById("browser.download.dir");
return currentDirPref.value;
}),
/**
* Hide/show the "Show my windows and tabs from last time" option based
* on the value of the browser.privatebrowsing.autostart pref.
*/
updateBrowserStartupLastSession() {
let pbAutoStartPref = document.getElementById("browser.privatebrowsing.autostart");
let startupPref = document.getElementById("browser.startup.page");
let menu = document.getElementById("browserStartupPage");
let option = document.getElementById("browserStartupLastSession");
if (pbAutoStartPref.value) {
option.setAttribute("disabled", "true");
if (option.selected) {
menu.selectedItem = document.getElementById("browserStartupHomePage");
}
} else {
option.removeAttribute("disabled");
startupPref.updateElements(); // select the correct index in the startup menulist
}
},
// TABS
/*
* Preferences:
*
* browser.link.open_newwindow - int
* Determines where links targeting new windows should open.
* Values:
* 1 - Open in the current window or tab.
* 2 - Open in a new window.
* 3 - Open in a new tab in the most recent window.
* browser.tabs.loadInBackground - bool
* True - Whether browser should switch to a new tab opened from a link.
* browser.tabs.warnOnClose - bool
* True - If when closing a window with multiple tabs the user is warned and
* allowed to cancel the action, false to just close the window.
* browser.tabs.warnOnOpen - bool
* True - Whether the user should be warned when trying to open a lot of
* tabs at once (e.g. a large folder of bookmarks), allowing to
* cancel the action.
* browser.taskbar.previews.enable - bool
* True - Tabs are to be shown in Windows 7 taskbar.
* False - Only the window is to be shown in Windows 7 taskbar.
*/
/**
* Determines where a link which opens a new window will open.
*
* @returns |true| if such links should be opened in new tabs
*/
readLinkTarget() {
var openNewWindow = document.getElementById("browser.link.open_newwindow");
return openNewWindow.value != 2;
},
/**
* Determines where a link which opens a new window will open.
*
* @returns 2 if such links should be opened in new windows,
* 3 if such links should be opened in new tabs
*/
writeLinkTarget() {
var linkTargeting = document.getElementById("linkTargeting");
return linkTargeting.checked ? 3 : 2;
},
/*
* Preferences:
*
* browser.shell.checkDefault
* - true if a default-browser check (and prompt to make it so if necessary)
* occurs at startup, false otherwise
*/
/**
* Show button for setting browser as default browser or information that
* browser is already the default browser.
*/
updateSetDefaultBrowser() {
if (AppConstants.HAVE_SHELL_SERVICE) {
let shellSvc = getShellService();
let defaultBrowserBox = document.getElementById("defaultBrowserBox");
if (!shellSvc) {
defaultBrowserBox.hidden = true;
return;
}
let setDefaultPane = document.getElementById("setDefaultPane");
let isDefault = shellSvc.isDefaultBrowser(false, true);
setDefaultPane.selectedIndex = isDefault ? 1 : 0;
let alwaysCheck = document.getElementById("alwaysCheckDefault");
alwaysCheck.disabled = alwaysCheck.disabled ||
isDefault && alwaysCheck.checked;
}
},
/**
* Set browser as the operating system default browser.
*/
setDefaultBrowser() {
if (AppConstants.HAVE_SHELL_SERVICE) {
let alwaysCheckPref = document.getElementById("browser.shell.checkDefaultBrowser");
alwaysCheckPref.value = true;
let shellSvc = getShellService();
if (!shellSvc)
return;
try {
shellSvc.setDefaultBrowser(true, false);
} catch (ex) {
Cu.reportError(ex);
return;
}
let selectedIndex = shellSvc.isDefaultBrowser(false, true) ? 1 : 0;
document.getElementById("setDefaultPane").selectedIndex = selectedIndex;
}
},
};

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

@ -0,0 +1,301 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# 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/.
<!-- General panel -->
<script type="application/javascript"
src="chrome://browser/content/preferences/in-content-old/main.js"/>
<preferences id="mainPreferences" hidden="true" data-category="paneGeneral">
#ifdef E10S_TESTING_ONLY
<preference id="browser.tabs.remote.autostart"
name="browser.tabs.remote.autostart"
type="bool"/>
<preference id="e10sTempPref"
name="browser.tabs.remote.autostart.2"
type="bool"/>
<preference id="e10sForceEnable"
name="browser.tabs.remote.force-enable"
type="bool"/>
#endif
<!-- Startup -->
<preference id="browser.startup.page"
name="browser.startup.page"
type="int"/>
<preference id="browser.startup.homepage"
name="browser.startup.homepage"
type="wstring"/>
#ifdef HAVE_SHELL_SERVICE
<preference id="browser.shell.checkDefaultBrowser"
name="browser.shell.checkDefaultBrowser"
type="bool"/>
<preference id="pref.general.disable_button.default_browser"
name="pref.general.disable_button.default_browser"
type="bool"/>
#endif
<preference id="pref.browser.homepage.disable_button.current_page"
name="pref.browser.homepage.disable_button.current_page"
type="bool"/>
<preference id="pref.browser.homepage.disable_button.bookmark_page"
name="pref.browser.homepage.disable_button.bookmark_page"
type="bool"/>
<preference id="pref.browser.homepage.disable_button.restore_default"
name="pref.browser.homepage.disable_button.restore_default"
type="bool"/>
<preference id="browser.privatebrowsing.autostart"
name="browser.privatebrowsing.autostart"
type="bool"/>
<!-- Downloads -->
<preference id="browser.download.useDownloadDir"
name="browser.download.useDownloadDir"
type="bool"/>
<preference id="browser.download.folderList"
name="browser.download.folderList"
type="int"/>
<preference id="browser.download.dir"
name="browser.download.dir"
type="file"/>
<!-- Tab preferences
Preferences:
browser.link.open_newwindow
1 opens such links in the most recent window or tab,
2 opens such links in a new window,
3 opens such links in a new tab
browser.tabs.loadInBackground
- true if display should switch to a new tab which has been opened from a
link, false if display shouldn't switch
browser.tabs.warnOnClose
- true if when closing a window with multiple tabs the user is warned and
allowed to cancel the action, false to just close the window
browser.tabs.warnOnOpen
- true if the user should be warned if he attempts to open a lot of tabs at
once (e.g. a large folder of bookmarks), false otherwise
browser.taskbar.previews.enable
- true if tabs are to be shown in the Windows 7 taskbar
-->
<preference id="browser.link.open_newwindow"
name="browser.link.open_newwindow"
type="int"/>
<preference id="browser.tabs.loadInBackground"
name="browser.tabs.loadInBackground"
type="bool"
inverted="true"/>
<preference id="browser.tabs.warnOnClose"
name="browser.tabs.warnOnClose"
type="bool"/>
<preference id="browser.tabs.warnOnOpen"
name="browser.tabs.warnOnOpen"
type="bool"/>
<preference id="browser.sessionstore.restore_on_demand"
name="browser.sessionstore.restore_on_demand"
type="bool"/>
#ifdef XP_WIN
<preference id="browser.taskbar.previews.enable"
name="browser.taskbar.previews.enable"
type="bool"/>
#endif
<preference id="browser.ctrlTab.previews"
name="browser.ctrlTab.previews"
type="bool"/>
</preferences>
<hbox id="header-general"
class="header"
hidden="true"
data-category="paneGeneral">
<label class="header-name" flex="1">&paneGeneral.title;</label>
<html:a class="help-button" target="_blank" aria-label="&helpButton.label;"></html:a>
</hbox>
<!-- Startup -->
<groupbox id="startupGroup"
data-category="paneGeneral"
hidden="true">
<caption><label>&startup.label;</label></caption>
#ifdef MOZ_DEV_EDITION
<vbox id="separateProfileBox">
<checkbox id="separateProfileMode"
label="&separateProfileMode.label;"/>
<hbox align="center" class="indent">
<label id="useFirefoxSync">&useFirefoxSync.label;</label>
<label id="getStarted" class="text-link">&getStarted.label;</label>
</hbox>
</vbox>
#endif
#ifdef E10S_TESTING_ONLY
<checkbox id="e10sAutoStart"
label="&e10sEnabled.label;"/>
#endif
#ifdef HAVE_SHELL_SERVICE
<vbox id="defaultBrowserBox">
<hbox align="center">
<checkbox id="alwaysCheckDefault" preference="browser.shell.checkDefaultBrowser"
label="&alwaysCheckDefault2.label;" accesskey="&alwaysCheckDefault2.accesskey;"/>
</hbox>
<deck id="setDefaultPane">
<hbox align="center" class="indent">
<label id="isNotDefaultLabel" flex="1">&isNotDefault.label;</label>
<button id="setDefaultButton"
label="&setAsMyDefaultBrowser2.label;" accesskey="&setAsMyDefaultBrowser2.accesskey;"
preference="pref.general.disable_button.default_browser"/>
</hbox>
<hbox align="center" class="indent">
<label id="isDefaultLabel" flex="1">&isDefault.label;</label>
</hbox>
</deck>
<separator class="thin"/>
</vbox>
#endif
<html:table id="startupTable">
<html:tr>
<html:td class="label-cell">
<label accesskey="&startupPage.accesskey;"
control="browserStartupPage">&startupPage.label;</label>
</html:td>
<html:td class="content-cell">
<menulist id="browserStartupPage"
class="content-cell-item"
preference="browser.startup.page">
<menupopup>
<menuitem label="&startupUserHomePage.label;"
value="1"
id="browserStartupHomePage"/>
<menuitem label="&startupBlankPage.label;"
value="0"
id="browserStartupBlank"/>
<menuitem label="&startupPrevSession.label;"
value="3"
id="browserStartupLastSession"/>
</menupopup>
</menulist>
</html:td>
</html:tr>
<html:tr>
<html:td class="label-cell">
<label accesskey="&homepage.accesskey;"
control="browserHomePage">&homepage.label;</label>
</html:td>
<html:td class="content-cell">
<textbox id="browserHomePage"
class="padded uri-element content-cell-item"
type="autocomplete"
autocompletesearch="unifiedcomplete"
onsyncfrompreference="return gMainPane.syncFromHomePref();"
onsynctopreference="return gMainPane.syncToHomePref(this.value);"
placeholder="&abouthome.pageTitle;"
preference="browser.startup.homepage"/>
</html:td>
</html:tr>
<html:tr>
<html:td class="label-cell" />
<html:td class="content-cell homepage-buttons">
<button id="useCurrent"
class="content-cell-item"
label=""
accesskey="&useCurrentPage.accesskey;"
label1="&useCurrentPage.label;"
label2="&useMultiple.label;"
preference="pref.browser.homepage.disable_button.current_page"/>
<button id="useBookmark"
class="content-cell-item"
label="&chooseBookmark.label;"
accesskey="&chooseBookmark.accesskey;"
preference="pref.browser.homepage.disable_button.bookmark_page"/>
<button id="restoreDefaultHomePage"
class="content-cell-item"
label="&restoreDefault.label;"
accesskey="&restoreDefault.accesskey;"
preference="pref.browser.homepage.disable_button.restore_default"/>
</html:td>
</html:tr>
</html:table>
</groupbox>
<!-- Downloads -->
<groupbox id="downloadsGroup"
data-category="paneGeneral"
hidden="true">
<caption><label>&downloads.label;</label></caption>
<radiogroup id="saveWhere"
preference="browser.download.useDownloadDir"
onsyncfrompreference="return gMainPane.readUseDownloadDir();">
<hbox id="saveToRow">
<radio id="saveTo"
value="true"
label="&saveTo.label;"
accesskey="&saveTo.accesskey;"
aria-labelledby="saveTo downloadFolder"/>
<filefield id="downloadFolder"
flex="1"
preference="browser.download.folderList"
preference-editable="true"
aria-labelledby="saveTo"
onsyncfrompreference="return gMainPane.displayDownloadDirPref();"/>
<button id="chooseFolder"
#ifdef XP_MACOSX
accesskey="&chooseFolderMac.accesskey;"
label="&chooseFolderMac.label;"
#else
accesskey="&chooseFolderWin.accesskey;"
label="&chooseFolderWin.label;"
#endif
/>
</hbox>
<hbox>
<radio id="alwaysAsk"
value="false"
label="&alwaysAskWhere.label;"
accesskey="&alwaysAskWhere.accesskey;"/>
</hbox>
</radiogroup>
</groupbox>
<!-- Tab preferences -->
<groupbox data-category="paneGeneral"
hidden="true" align="start">
<caption><label>&tabsGroup.label;</label></caption>
<checkbox id="ctrlTabRecentlyUsedOrder" label="&ctrlTabRecentlyUsedOrder.label;"
accesskey="&ctrlTabRecentlyUsedOrder.accesskey;"
preference="browser.ctrlTab.previews"/>
<checkbox id="linkTargeting" label="&newWindowsAsTabs.label;"
accesskey="&newWindowsAsTabs.accesskey;"
preference="browser.link.open_newwindow"
onsyncfrompreference="return gMainPane.readLinkTarget();"
onsynctopreference="return gMainPane.writeLinkTarget();"/>
<checkbox id="warnCloseMultiple" label="&warnOnCloseMultipleTabs.label;"
accesskey="&warnOnCloseMultipleTabs.accesskey;"
preference="browser.tabs.warnOnClose"/>
<checkbox id="warnOpenMany" label="&warnOnOpenManyTabs.label;"
accesskey="&warnOnOpenManyTabs.accesskey;"
preference="browser.tabs.warnOnOpen"/>
<checkbox id="switchToNewTabs" label="&switchLinksToNewTabs.label;"
accesskey="&switchLinksToNewTabs.accesskey;"
preference="browser.tabs.loadInBackground"/>
#ifdef XP_WIN
<checkbox id="showTabsInTaskbar" label="&showTabsInTaskbar.label;"
accesskey="&showTabsInTaskbar.accesskey;"
preference="browser.taskbar.previews.enable"/>
#endif
</groupbox>

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

@ -0,0 +1,13 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# 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/.
for var in ('MOZ_APP_NAME', 'MOZ_MACBUNDLE_NAME'):
DEFINES[var] = CONFIG[var]
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk2', 'gtk3', 'cocoa'):
DEFINES['HAVE_SHELL_SERVICE'] = 1
JAR_MANIFESTS += ['jar.mn']

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

@ -0,0 +1,313 @@
/* - This Source Code Form is subject to the terms of the Mozilla Public
- 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/. */
// Import globals from the files imported by the .xul files.
/* import-globals-from subdialogs.js */
/* import-globals-from advanced.js */
/* import-globals-from main.js */
/* import-globals-from search.js */
/* import-globals-from containers.js */
/* import-globals-from content.js */
/* import-globals-from privacy.js */
/* import-globals-from applications.js */
/* import-globals-from security.js */
/* import-globals-from sync.js */
/* import-globals-from ../../../base/content/utilityOverlay.js */
"use strict";
var Cc = Components.classes;
var Ci = Components.interfaces;
var Cu = Components.utils;
var Cr = Components.results;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/AppConstants.jsm");
var gLastHash = "";
var gCategoryInits = new Map();
function init_category_if_required(category) {
let categoryInfo = gCategoryInits.get(category);
if (!categoryInfo) {
throw "Unknown in-content prefs category! Can't init " + category;
}
if (categoryInfo.inited) {
return;
}
categoryInfo.init();
}
function register_module(categoryName, categoryObject) {
gCategoryInits.set(categoryName, {
inited: false,
init() {
categoryObject.init();
this.inited = true;
}
});
}
document.addEventListener("DOMContentLoaded", init_all, {once: true});
function init_all() {
document.documentElement.instantApply = true;
gSubDialog.init();
register_module("paneGeneral", gMainPane);
register_module("paneSearch", gSearchPane);
register_module("panePrivacy", gPrivacyPane);
register_module("paneContainers", gContainersPane);
register_module("paneAdvanced", gAdvancedPane);
register_module("paneApplications", gApplicationsPane);
register_module("paneContent", gContentPane);
register_module("paneSync", gSyncPane);
register_module("paneSecurity", gSecurityPane);
let categories = document.getElementById("categories");
categories.addEventListener("select", event => gotoPref(event.target.value));
document.documentElement.addEventListener("keydown", function(event) {
if (event.keyCode == KeyEvent.DOM_VK_TAB) {
categories.setAttribute("keyboard-navigation", "true");
}
});
categories.addEventListener("mousedown", function() {
this.removeAttribute("keyboard-navigation");
});
window.addEventListener("hashchange", onHashChange);
gotoPref();
init_dynamic_padding();
var initFinished = new CustomEvent("Initialized", {
"bubbles": true,
"cancelable": true
});
document.dispatchEvent(initFinished);
categories = categories.querySelectorAll("richlistitem.category");
for (let category of categories) {
let name = internalPrefCategoryNameToFriendlyName(category.value);
let helpSelector = `#header-${name} > .help-button`;
let helpButton = document.querySelector(helpSelector);
helpButton.setAttribute("href", getHelpLinkURL(category.getAttribute("helpTopic")));
}
// Wait until initialization of all preferences are complete before
// notifying observers that the UI is now ready.
Services.obs.notifyObservers(window, "advanced-pane-loaded", null);
}
// Make the space above the categories list shrink on low window heights
function init_dynamic_padding() {
let categories = document.getElementById("categories");
let catPadding = Number.parseInt(getComputedStyle(categories)
.getPropertyValue("padding-top"));
let fullHeight = categories.lastElementChild.getBoundingClientRect().bottom;
let mediaRule = `
@media (max-height: ${fullHeight}px) {
#categories {
padding-top: calc(100vh - ${fullHeight - catPadding}px);
}
}
`;
let mediaStyle = document.createElementNS("http://www.w3.org/1999/xhtml", "html:style");
mediaStyle.setAttribute("type", "text/css");
mediaStyle.appendChild(document.createCDATASection(mediaRule));
document.documentElement.appendChild(mediaStyle);
}
function telemetryBucketForCategory(category) {
switch (category) {
case "general":
case "search":
case "content":
case "applications":
case "privacy":
case "security":
case "sync":
return category;
case "advanced":
let advancedPaneTabs = document.getElementById("advancedPrefs");
switch (advancedPaneTabs.selectedTab.id) {
case "generalTab":
return "advancedGeneral";
case "dataChoicesTab":
return "advancedDataChoices";
case "networkTab":
return "advancedNetwork";
case "updateTab":
return "advancedUpdates";
case "encryptionTab":
return "advancedCerts";
}
// fall-through for unknown.
default:
return "unknown";
}
}
function onHashChange() {
gotoPref();
}
function gotoPref(aCategory) {
let categories = document.getElementById("categories");
const kDefaultCategoryInternalName = categories.firstElementChild.value;
let hash = document.location.hash;
let category = aCategory || hash.substr(1) || kDefaultCategoryInternalName;
category = friendlyPrefCategoryNameToInternalName(category);
// Updating the hash (below) or changing the selected category
// will re-enter gotoPref.
if (gLastHash == category)
return;
let item = categories.querySelector(".category[value=" + category + "]");
if (!item) {
category = kDefaultCategoryInternalName;
item = categories.querySelector(".category[value=" + category + "]");
}
try {
init_category_if_required(category);
} catch (ex) {
Cu.reportError("Error initializing preference category " + category + ": " + ex);
throw ex;
}
let friendlyName = internalPrefCategoryNameToFriendlyName(category);
if (gLastHash || category != kDefaultCategoryInternalName) {
document.location.hash = friendlyName;
}
// Need to set the gLastHash before setting categories.selectedItem since
// the categories 'select' event will re-enter the gotoPref codepath.
gLastHash = category;
categories.selectedItem = item;
window.history.replaceState(category, document.title);
search(category, "data-category");
let mainContent = document.querySelector(".main-content");
mainContent.scrollTop = 0;
Services.telemetry
.getHistogramById("FX_PREFERENCES_CATEGORY_OPENED")
.add(telemetryBucketForCategory(friendlyName));
}
function search(aQuery, aAttribute) {
let mainPrefPane = document.getElementById("mainPrefPane");
let elements = mainPrefPane.children;
for (let element of elements) {
let attributeValue = element.getAttribute(aAttribute);
element.hidden = (attributeValue != aQuery);
}
let keysets = mainPrefPane.getElementsByTagName("keyset");
for (let element of keysets) {
let attributeValue = element.getAttribute(aAttribute);
if (attributeValue == aQuery)
element.removeAttribute("disabled");
else
element.setAttribute("disabled", true);
}
}
function helpButtonCommand() {
let pane = history.state;
let categories = document.getElementById("categories");
let helpTopic = categories.querySelector(".category[value=" + pane + "]")
.getAttribute("helpTopic");
openHelpLink(helpTopic);
}
function friendlyPrefCategoryNameToInternalName(aName) {
if (aName.startsWith("pane"))
return aName;
return "pane" + aName.substring(0, 1).toUpperCase() + aName.substr(1);
}
// This function is duplicated inside of utilityOverlay.js's openPreferences.
function internalPrefCategoryNameToFriendlyName(aName) {
return (aName || "").replace(/^pane./, function(toReplace) { return toReplace[4].toLowerCase(); });
}
// Put up a confirm dialog with "ok to restart", "revert without restarting"
// and "restart later" buttons and returns the index of the button chosen.
// We can choose not to display the "restart later", or "revert" buttons,
// altough the later still lets us revert by using the escape key.
//
// The constants are useful to interpret the return value of the function.
const CONFIRM_RESTART_PROMPT_RESTART_NOW = 0;
const CONFIRM_RESTART_PROMPT_CANCEL = 1;
const CONFIRM_RESTART_PROMPT_RESTART_LATER = 2;
function confirmRestartPrompt(aRestartToEnable, aDefaultButtonIndex,
aWantRevertAsCancelButton,
aWantRestartLaterButton) {
let brandName = document.getElementById("bundleBrand").getString("brandShortName");
let bundle = document.getElementById("bundlePreferences");
let msg = bundle.getFormattedString(aRestartToEnable ?
"featureEnableRequiresRestart" :
"featureDisableRequiresRestart",
[brandName]);
let title = bundle.getFormattedString("shouldRestartTitle", [brandName]);
let prompts = Cc["@mozilla.org/embedcomp/prompt-service;1"].getService(Ci.nsIPromptService);
// Set up the first (index 0) button:
let button0Text = bundle.getFormattedString("okToRestartButton", [brandName]);
let buttonFlags = (Services.prompt.BUTTON_POS_0 *
Services.prompt.BUTTON_TITLE_IS_STRING);
// Set up the second (index 1) button:
let button1Text = null;
if (aWantRevertAsCancelButton) {
button1Text = bundle.getString("revertNoRestartButton");
buttonFlags += (Services.prompt.BUTTON_POS_1 *
Services.prompt.BUTTON_TITLE_IS_STRING);
} else {
buttonFlags += (Services.prompt.BUTTON_POS_1 *
Services.prompt.BUTTON_TITLE_CANCEL);
}
// Set up the third (index 2) button:
let button2Text = null;
if (aWantRestartLaterButton) {
button2Text = bundle.getString("restartLater");
buttonFlags += (Services.prompt.BUTTON_POS_2 *
Services.prompt.BUTTON_TITLE_IS_STRING);
}
switch (aDefaultButtonIndex) {
case 0:
buttonFlags += Services.prompt.BUTTON_POS_0_DEFAULT;
break;
case 1:
buttonFlags += Services.prompt.BUTTON_POS_1_DEFAULT;
break;
case 2:
buttonFlags += Services.prompt.BUTTON_POS_2_DEFAULT;
break;
default:
break;
}
let buttonIndex = prompts.confirmEx(window, title, msg, buttonFlags,
button0Text, button1Text, button2Text,
null, {});
// If we have the second confirmation dialog for restart, see if the user
// cancels out at that point.
if (buttonIndex == CONFIRM_RESTART_PROMPT_RESTART_NOW) {
let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"]
.createInstance(Ci.nsISupportsPRBool);
Services.obs.notifyObservers(cancelQuit, "quit-application-requested",
"restart");
if (cancelQuit.data) {
buttonIndex = CONFIRM_RESTART_PROMPT_CANCEL;
}
}
return buttonIndex;
}

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

@ -0,0 +1,224 @@
<?xml version="1.0"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- 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/. -->
<?xml-stylesheet href="chrome://global/skin/global.css"?>
<?xml-stylesheet href="chrome://browser/skin/preferences/preferences.css"?>
<?xml-stylesheet href="chrome://global/skin/in-content/common.css"?>
<?xml-stylesheet
href="chrome://browser/skin/preferences/in-content/preferences.css"?>
<?xml-stylesheet
href="chrome://browser/content/preferences/handlers.css"?>
<?xml-stylesheet href="chrome://browser/skin/preferences/applications.css"?>
<?xml-stylesheet href="chrome://browser/skin/preferences/in-content-old/search.css"?>
<?xml-stylesheet href="chrome://browser/skin/preferences/in-content-old/containers.css"?>
<!DOCTYPE page [
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
<!ENTITY % globalPreferencesDTD SYSTEM "chrome://global/locale/preferences.dtd">
<!ENTITY % preferencesDTD SYSTEM
"chrome://browser/locale/preferences-old/preferences.dtd">
<!ENTITY % privacyDTD SYSTEM "chrome://browser/locale/preferences-old/privacy.dtd">
<!ENTITY % tabsDTD SYSTEM "chrome://browser/locale/preferences-old/tabs.dtd">
<!ENTITY % searchDTD SYSTEM "chrome://browser/locale/preferences-old/search.dtd">
<!ENTITY % syncBrandDTD SYSTEM "chrome://browser/locale/syncBrand.dtd">
<!ENTITY % syncDTD SYSTEM "chrome://browser/locale/preferences-old/sync.dtd">
<!ENTITY % securityDTD SYSTEM
"chrome://browser/locale/preferences-old/security.dtd">
<!ENTITY % containersDTD SYSTEM
"chrome://browser/locale/preferences-old/containers.dtd">
<!ENTITY % sanitizeDTD SYSTEM "chrome://browser/locale/sanitize.dtd">
<!ENTITY % mainDTD SYSTEM "chrome://browser/locale/preferences-old/main.dtd">
<!ENTITY % aboutHomeDTD SYSTEM "chrome://browser/locale/aboutHome.dtd">
<!ENTITY % contentDTD SYSTEM "chrome://browser/locale/preferences-old/content.dtd">
<!ENTITY % applicationsDTD SYSTEM
"chrome://browser/locale/preferences-old/applications.dtd">
<!ENTITY % advancedDTD SYSTEM
"chrome://browser/locale/preferences-old/advanced.dtd">
%brandDTD;
%globalPreferencesDTD;
%preferencesDTD;
%privacyDTD;
%tabsDTD;
%searchDTD;
%syncBrandDTD;
%syncDTD;
%securityDTD;
%containersDTD;
%sanitizeDTD;
%mainDTD;
%aboutHomeDTD;
%contentDTD;
%applicationsDTD;
%advancedDTD;
]>
#ifdef XP_WIN
#define USE_WIN_TITLE_STYLE
#endif
<page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml"
disablefastfind="true"
#ifdef USE_WIN_TITLE_STYLE
title="&prefWindow.titleWin;">
#else
title="&prefWindow.title;">
#endif
<html:link rel="shortcut icon"
href="chrome://browser/skin/preferences/in-content-old/favicon.ico"/>
<script type="application/javascript"
src="chrome://browser/content/utilityOverlay.js"/>
<script type="application/javascript"
src="chrome://browser/content/preferences/in-content-old/preferences.js"/>
<script src="chrome://browser/content/preferences/in-content-old/subdialogs.js"/>
<stringbundle id="bundleBrand"
src="chrome://branding/locale/brand.properties"/>
<stringbundle id="bundlePreferences"
src="chrome://browser/locale/preferences-old/preferences.properties"/>
<stringbundleset id="appManagerBundleset">
<stringbundle id="appManagerBundle"
src="chrome://browser/locale/preferences-old/applicationManager.properties"/>
</stringbundleset>
<stack flex="1">
<hbox flex="1">
<!-- category list -->
<richlistbox id="categories">
<richlistitem id="category-general"
class="category"
value="paneGeneral"
helpTopic="prefs-main"
tooltiptext="&paneGeneral.title;"
align="center">
<image class="category-icon"/>
<label class="category-name" flex="1">&paneGeneral.title;</label>
</richlistitem>
<richlistitem id="category-search"
class="category"
value="paneSearch"
helpTopic="prefs-search"
tooltiptext="&paneSearch.title;"
align="center">
<image class="category-icon"/>
<label class="category-name" flex="1">&paneSearch.title;</label>
</richlistitem>
<richlistitem id="category-content"
class="category"
value="paneContent"
helpTopic="prefs-content"
tooltiptext="&paneContent.title;"
align="center">
<image class="category-icon"/>
<label class="category-name" flex="1">&paneContent.title;</label>
</richlistitem>
<richlistitem id="category-application"
class="category"
value="paneApplications"
helpTopic="prefs-applications"
tooltiptext="&paneApplications.title;"
align="center">
<image class="category-icon"/>
<label class="category-name" flex="1">&paneApplications.title;</label>
</richlistitem>
<richlistitem id="category-privacy"
class="category"
value="panePrivacy"
helpTopic="prefs-privacy"
tooltiptext="&panePrivacy.title;"
align="center">
<image class="category-icon"/>
<label class="category-name" flex="1">&panePrivacy.title;</label>
</richlistitem>
<richlistitem id="category-containers"
class="category"
value="paneContainers"
helpTopic="prefs-containers"
hidden="true"/>
<richlistitem id="category-security"
class="category"
value="paneSecurity"
helpTopic="prefs-security"
tooltiptext="&paneSecurity.title;"
align="center">
<image class="category-icon"/>
<label class="category-name" flex="1">&paneSecurity.title;</label>
</richlistitem>
<richlistitem id="category-sync"
class="category"
value="paneSync"
helpTopic="prefs-weave"
tooltiptext="&paneSync.title;"
align="center">
<image class="category-icon"/>
<label class="category-name" flex="1">&paneSync.title;</label>
</richlistitem>
<richlistitem id="category-advanced"
class="category"
value="paneAdvanced"
helpTopic="prefs-advanced-general"
tooltiptext="&paneAdvanced.title;"
align="center">
<image class="category-icon"/>
<label class="category-name" flex="1">&paneAdvanced.title;</label>
</richlistitem>
</richlistbox>
<keyset>
<!-- Disable the findbar because it doesn't work properly.
Remove this keyset once bug 1094240 ("disablefastfind" attribute
broken in e10s mode) is fixed. -->
<key key="&focusSearch1.key;" modifiers="accel" id="focusSearch1" oncommand=";"/>
</keyset>
<vbox class="main-content" flex="1">
<prefpane id="mainPrefPane">
#include main.xul
#include search.xul
#include privacy.xul
#include containers.xul
#include advanced.xul
#include applications.xul
#include content.xul
#include security.xul
#include sync.xul
</prefpane>
</vbox>
</hbox>
<vbox id="dialogOverlay" align="center" pack="center">
<groupbox id="dialogBox"
orient="vertical"
pack="end"
role="dialog"
aria-labelledby="dialogTitle">
<caption flex="1" align="center">
<label id="dialogTitle" flex="1"></label>
<button id="dialogClose"
class="close-icon"
aria-label="&preferencesCloseButton.label;"/>
</caption>
<browser id="dialogFrame"
name="dialogFrame"
autoscroll="false"
disablehistory="true"/>
</groupbox>
</vbox>
</stack>
</page>

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

@ -0,0 +1,698 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
/* import-globals-from preferences.js */
Components.utils.import("resource://gre/modules/AppConstants.jsm");
Components.utils.import("resource://gre/modules/PluralForm.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ContextualIdentityService",
"resource://gre/modules/ContextualIdentityService.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
"resource://gre/modules/PluralForm.jsm");
var gPrivacyPane = {
/**
* Whether the use has selected the auto-start private browsing mode in the UI.
*/
_autoStartPrivateBrowsing: false,
/**
* Whether the prompt to restart Firefox should appear when changing the autostart pref.
*/
_shouldPromptForRestart: true,
/**
* Show the Tracking Protection UI depending on the
* privacy.trackingprotection.ui.enabled pref, and linkify its Learn More link
*/
_initTrackingProtection() {
if (!Services.prefs.getBoolPref("privacy.trackingprotection.ui.enabled")) {
return;
}
let link = document.getElementById("trackingProtectionLearnMore");
let url = Services.urlFormatter.formatURLPref("app.support.baseURL") + "tracking-protection";
link.setAttribute("href", url);
this.trackingProtectionReadPrefs();
document.getElementById("trackingprotectionbox").hidden = false;
document.getElementById("trackingprotectionpbmbox").hidden = true;
},
/**
* Linkify the Learn More link of the Private Browsing Mode Tracking
* Protection UI.
*/
_initTrackingProtectionPBM() {
let link = document.getElementById("trackingProtectionPBMLearnMore");
let url = Services.urlFormatter.formatURLPref("app.support.baseURL") + "tracking-protection-pbm";
link.setAttribute("href", url);
},
/**
* Initialize autocomplete to ensure prefs are in sync.
*/
_initAutocomplete() {
Components.classes["@mozilla.org/autocomplete/search;1?name=unifiedcomplete"]
.getService(Components.interfaces.mozIPlacesAutoComplete);
},
/**
* Show the Containers UI depending on the privacy.userContext.ui.enabled pref.
*/
_initBrowserContainers() {
if (!Services.prefs.getBoolPref("privacy.userContext.ui.enabled")) {
return;
}
let link = document.getElementById("browserContainersLearnMore");
link.href = Services.urlFormatter.formatURLPref("app.support.baseURL") + "containers";
document.getElementById("browserContainersbox").hidden = false;
document.getElementById("browserContainersCheckbox").checked =
Services.prefs.getBoolPref("privacy.userContext.enabled");
},
_checkBrowserContainers(event) {
let checkbox = document.getElementById("browserContainersCheckbox");
if (checkbox.checked) {
Services.prefs.setBoolPref("privacy.userContext.enabled", true);
return;
}
let count = ContextualIdentityService.countContainerTabs();
if (count == 0) {
Services.prefs.setBoolPref("privacy.userContext.enabled", false);
return;
}
let bundlePreferences = document.getElementById("bundlePreferences");
let title = bundlePreferences.getString("disableContainersAlertTitle");
let message = PluralForm.get(count, bundlePreferences.getString("disableContainersMsg"))
.replace("#S", count)
let okButton = PluralForm.get(count, bundlePreferences.getString("disableContainersOkButton"))
.replace("#S", count)
let cancelButton = bundlePreferences.getString("disableContainersButton2");
let buttonFlags = (Ci.nsIPrompt.BUTTON_TITLE_IS_STRING * Ci.nsIPrompt.BUTTON_POS_0) +
(Ci.nsIPrompt.BUTTON_TITLE_IS_STRING * Ci.nsIPrompt.BUTTON_POS_1);
let rv = Services.prompt.confirmEx(window, title, message, buttonFlags,
okButton, cancelButton, null, null, {});
if (rv == 0) {
ContextualIdentityService.closeContainerTabs();
Services.prefs.setBoolPref("privacy.userContext.enabled", false);
return;
}
checkbox.checked = true;
},
/**
* Sets up the UI for the number of days of history to keep, and updates the
* label of the "Clear Now..." button.
*/
init() {
function setEventListener(aId, aEventType, aCallback) {
document.getElementById(aId)
.addEventListener(aEventType, aCallback.bind(gPrivacyPane));
}
this._updateSanitizeSettingsButton();
this.initializeHistoryMode();
this.updateHistoryModePane();
this.updatePrivacyMicroControls();
this.initAutoStartPrivateBrowsingReverter();
this._initTrackingProtection();
this._initTrackingProtectionPBM();
this._initAutocomplete();
this._initBrowserContainers();
setEventListener("privacy.sanitize.sanitizeOnShutdown", "change",
gPrivacyPane._updateSanitizeSettingsButton);
setEventListener("browser.privatebrowsing.autostart", "change",
gPrivacyPane.updatePrivacyMicroControls);
setEventListener("historyMode", "command", function() {
gPrivacyPane.updateHistoryModePane();
gPrivacyPane.updateHistoryModePrefs();
gPrivacyPane.updatePrivacyMicroControls();
gPrivacyPane.updateAutostart();
});
setEventListener("historyRememberClear", "click", function() {
gPrivacyPane.clearPrivateDataNow(false);
return false;
});
setEventListener("historyRememberCookies", "click", function() {
gPrivacyPane.showCookies();
return false;
});
setEventListener("historyDontRememberClear", "click", function() {
gPrivacyPane.clearPrivateDataNow(true);
return false;
});
setEventListener("doNotTrackSettings", "click", function() {
gPrivacyPane.showDoNotTrackSettings();
return false;
});
setEventListener("privateBrowsingAutoStart", "command",
gPrivacyPane.updateAutostart);
setEventListener("cookieExceptions", "command",
gPrivacyPane.showCookieExceptions);
setEventListener("showCookiesButton", "command",
gPrivacyPane.showCookies);
setEventListener("clearDataSettings", "command",
gPrivacyPane.showClearPrivateDataSettings);
setEventListener("trackingProtectionRadioGroup", "command",
gPrivacyPane.trackingProtectionWritePrefs);
setEventListener("trackingProtectionExceptions", "command",
gPrivacyPane.showTrackingProtectionExceptions);
setEventListener("changeBlockList", "command",
gPrivacyPane.showBlockLists);
setEventListener("changeBlockListPBM", "command",
gPrivacyPane.showBlockLists);
setEventListener("browserContainersCheckbox", "command",
gPrivacyPane._checkBrowserContainers);
setEventListener("browserContainersSettings", "command",
gPrivacyPane.showContainerSettings);
},
// TRACKING PROTECTION MODE
/**
* Selects the right item of the Tracking Protection radiogroup.
*/
trackingProtectionReadPrefs() {
let enabledPref = document.getElementById("privacy.trackingprotection.enabled");
let pbmPref = document.getElementById("privacy.trackingprotection.pbmode.enabled");
let radiogroup = document.getElementById("trackingProtectionRadioGroup");
// Global enable takes precedence over enabled in Private Browsing.
if (enabledPref.value) {
radiogroup.value = "always";
} else if (pbmPref.value) {
radiogroup.value = "private";
} else {
radiogroup.value = "never";
}
},
/**
* Sets the pref values based on the selected item of the radiogroup.
*/
trackingProtectionWritePrefs() {
let enabledPref = document.getElementById("privacy.trackingprotection.enabled");
let pbmPref = document.getElementById("privacy.trackingprotection.pbmode.enabled");
let radiogroup = document.getElementById("trackingProtectionRadioGroup");
switch (radiogroup.value) {
case "always":
enabledPref.value = true;
pbmPref.value = true;
break;
case "private":
enabledPref.value = false;
pbmPref.value = true;
break;
case "never":
enabledPref.value = false;
pbmPref.value = false;
break;
}
},
// HISTORY MODE
/**
* The list of preferences which affect the initial history mode settings.
* If the auto start private browsing mode pref is active, the initial
* history mode would be set to "Don't remember anything".
* If ALL of these preferences are set to the values that correspond
* to keeping some part of history, and the auto-start
* private browsing mode is not active, the initial history mode would be
* set to "Remember everything".
* Otherwise, the initial history mode would be set to "Custom".
*
* Extensions adding their own preferences can set values here if needed.
*/
prefsForKeepingHistory: {
"places.history.enabled": true, // History is enabled
"browser.formfill.enable": true, // Form information is saved
"network.cookie.cookieBehavior": 0, // All cookies are enabled
"network.cookie.lifetimePolicy": 0, // Cookies use supplied lifetime
"privacy.sanitize.sanitizeOnShutdown": false, // Private date is NOT cleared on shutdown
},
/**
* The list of control IDs which are dependent on the auto-start private
* browsing setting, such that in "Custom" mode they would be disabled if
* the auto-start private browsing checkbox is checked, and enabled otherwise.
*
* Extensions adding their own controls can append their IDs to this array if needed.
*/
dependentControls: [
"rememberHistory",
"rememberForms",
"keepUntil",
"keepCookiesUntil",
"alwaysClear",
"clearDataSettings"
],
/**
* Check whether preferences values are set to keep history
*
* @param aPrefs an array of pref names to check for
* @returns boolean true if all of the prefs are set to keep history,
* false otherwise
*/
_checkHistoryValues(aPrefs) {
for (let pref of Object.keys(aPrefs)) {
if (document.getElementById(pref).value != aPrefs[pref])
return false;
}
return true;
},
/**
* Initialize the history mode menulist based on the privacy preferences
*/
initializeHistoryMode() {
let mode;
let getVal = aPref => document.getElementById(aPref).value;
if (getVal("privacy.history.custom"))
mode = "custom";
else if (this._checkHistoryValues(this.prefsForKeepingHistory)) {
if (getVal("browser.privatebrowsing.autostart"))
mode = "dontremember";
else
mode = "remember";
} else
mode = "custom";
document.getElementById("historyMode").value = mode;
},
/**
* Update the selected pane based on the history mode menulist
*/
updateHistoryModePane() {
let selectedIndex = -1;
switch (document.getElementById("historyMode").value) {
case "remember":
selectedIndex = 0;
break;
case "dontremember":
selectedIndex = 1;
break;
case "custom":
selectedIndex = 2;
break;
}
document.getElementById("historyPane").selectedIndex = selectedIndex;
document.getElementById("privacy.history.custom").value = selectedIndex == 2;
},
/**
* Update the private browsing auto-start pref and the history mode
* micro-management prefs based on the history mode menulist
*/
updateHistoryModePrefs() {
let pref = document.getElementById("browser.privatebrowsing.autostart");
switch (document.getElementById("historyMode").value) {
case "remember":
if (pref.value)
pref.value = false;
// select the remember history option if needed
let rememberHistoryCheckbox = document.getElementById("rememberHistory");
if (!rememberHistoryCheckbox.checked)
rememberHistoryCheckbox.checked = true;
// select the remember forms history option
document.getElementById("browser.formfill.enable").value = true;
// select the allow cookies option
document.getElementById("network.cookie.cookieBehavior").value = 0;
// select the cookie lifetime policy option
document.getElementById("network.cookie.lifetimePolicy").value = 0;
// select the clear on close option
document.getElementById("privacy.sanitize.sanitizeOnShutdown").value = false;
break;
case "dontremember":
if (!pref.value)
pref.value = true;
break;
}
},
/**
* Update the privacy micro-management controls based on the
* value of the private browsing auto-start checkbox.
*/
updatePrivacyMicroControls() {
if (document.getElementById("historyMode").value == "custom") {
let disabled = this._autoStartPrivateBrowsing =
document.getElementById("privateBrowsingAutoStart").checked;
this.dependentControls.forEach(function(aElement) {
let control = document.getElementById(aElement);
let preferenceId = control.getAttribute("preference");
if (!preferenceId) {
let dependentControlId = control.getAttribute("control");
if (dependentControlId) {
let dependentControl = document.getElementById(dependentControlId);
preferenceId = dependentControl.getAttribute("preference");
}
}
let preference = preferenceId ? document.getElementById(preferenceId) : {};
control.disabled = disabled || preference.locked;
});
// adjust the cookie controls status
this.readAcceptCookies();
let lifetimePolicy = document.getElementById("network.cookie.lifetimePolicy").value;
if (lifetimePolicy != Ci.nsICookieService.ACCEPT_NORMALLY &&
lifetimePolicy != Ci.nsICookieService.ACCEPT_SESSION &&
lifetimePolicy != Ci.nsICookieService.ACCEPT_FOR_N_DAYS) {
lifetimePolicy = Ci.nsICookieService.ACCEPT_NORMALLY;
}
document.getElementById("keepCookiesUntil").value = disabled ? 2 : lifetimePolicy;
// adjust the checked state of the sanitizeOnShutdown checkbox
document.getElementById("alwaysClear").checked = disabled ? false :
document.getElementById("privacy.sanitize.sanitizeOnShutdown").value;
// adjust the checked state of the remember history checkboxes
document.getElementById("rememberHistory").checked = disabled ? false :
document.getElementById("places.history.enabled").value;
document.getElementById("rememberForms").checked = disabled ? false :
document.getElementById("browser.formfill.enable").value;
if (!disabled) {
// adjust the Settings button for sanitizeOnShutdown
this._updateSanitizeSettingsButton();
}
}
},
// PRIVATE BROWSING
/**
* Initialize the starting state for the auto-start private browsing mode pref reverter.
*/
initAutoStartPrivateBrowsingReverter() {
let mode = document.getElementById("historyMode");
let autoStart = document.getElementById("privateBrowsingAutoStart");
this._lastMode = mode.selectedIndex;
this._lastCheckState = autoStart.hasAttribute("checked");
},
_lastMode: null,
_lastCheckState: null,
updateAutostart() {
let mode = document.getElementById("historyMode");
let autoStart = document.getElementById("privateBrowsingAutoStart");
let pref = document.getElementById("browser.privatebrowsing.autostart");
if ((mode.value == "custom" && this._lastCheckState == autoStart.checked) ||
(mode.value == "remember" && !this._lastCheckState) ||
(mode.value == "dontremember" && this._lastCheckState)) {
// These are all no-op changes, so we don't need to prompt.
this._lastMode = mode.selectedIndex;
this._lastCheckState = autoStart.hasAttribute("checked");
return;
}
if (!this._shouldPromptForRestart) {
// We're performing a revert. Just let it happen.
return;
}
let buttonIndex = confirmRestartPrompt(autoStart.checked, 1,
true, false);
if (buttonIndex == CONFIRM_RESTART_PROMPT_RESTART_NOW) {
pref.value = autoStart.hasAttribute("checked");
let appStartup = Cc["@mozilla.org/toolkit/app-startup;1"]
.getService(Ci.nsIAppStartup);
appStartup.quit(Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart);
return;
}
this._shouldPromptForRestart = false;
if (this._lastCheckState) {
autoStart.checked = "checked";
} else {
autoStart.removeAttribute("checked");
}
pref.value = autoStart.hasAttribute("checked");
mode.selectedIndex = this._lastMode;
mode.doCommand();
this._shouldPromptForRestart = true;
},
/**
* Displays fine-grained, per-site preferences for tracking protection.
*/
showTrackingProtectionExceptions() {
let bundlePreferences = document.getElementById("bundlePreferences");
let params = {
permissionType: "trackingprotection",
hideStatusColumn: true,
windowTitle: bundlePreferences.getString("trackingprotectionpermissionstitle"),
introText: bundlePreferences.getString("trackingprotectionpermissionstext"),
};
gSubDialog.open("chrome://browser/content/preferences/permissions.xul",
null, params);
},
/**
* Displays container panel for customising and adding containers.
*/
showContainerSettings() {
gotoPref("containers");
},
/**
* Displays the available block lists for tracking protection.
*/
showBlockLists() {
var bundlePreferences = document.getElementById("bundlePreferences");
let brandName = document.getElementById("bundleBrand")
.getString("brandShortName");
var params = { brandShortName: brandName,
windowTitle: bundlePreferences.getString("blockliststitle"),
introText: bundlePreferences.getString("blockliststext") };
gSubDialog.open("chrome://browser/content/preferences/blocklists.xul",
null, params);
},
/**
* Displays the Do Not Track settings dialog.
*/
showDoNotTrackSettings() {
gSubDialog.open("chrome://browser/content/preferences/donottrack.xul",
"resizable=no");
},
// HISTORY
/*
* Preferences:
*
* places.history.enabled
* - whether history is enabled or not
* browser.formfill.enable
* - true if entries in forms and the search bar should be saved, false
* otherwise
*/
// COOKIES
/*
* Preferences:
*
* network.cookie.cookieBehavior
* - determines how the browser should handle cookies:
* 0 means enable all cookies
* 1 means reject all third party cookies
* 2 means disable all cookies
* 3 means reject third party cookies unless at least one is already set for the eTLD
* see netwerk/cookie/src/nsCookieService.cpp for details
* network.cookie.lifetimePolicy
* - determines how long cookies are stored:
* 0 means keep cookies until they expire
* 2 means keep cookies until the browser is closed
*/
/**
* Reads the network.cookie.cookieBehavior preference value and
* enables/disables the rest of the cookie UI accordingly, returning true
* if cookies are enabled.
*/
readAcceptCookies() {
var pref = document.getElementById("network.cookie.cookieBehavior");
var acceptThirdPartyLabel = document.getElementById("acceptThirdPartyLabel");
var acceptThirdPartyMenu = document.getElementById("acceptThirdPartyMenu");
var keepUntil = document.getElementById("keepUntil");
var menu = document.getElementById("keepCookiesUntil");
// enable the rest of the UI for anything other than "disable all cookies"
var acceptCookies = (pref.value != 2);
acceptThirdPartyLabel.disabled = acceptThirdPartyMenu.disabled = !acceptCookies;
keepUntil.disabled = menu.disabled = this._autoStartPrivateBrowsing || !acceptCookies;
return acceptCookies;
},
/**
* Enables/disables the "keep until" label and menulist in response to the
* "accept cookies" checkbox being checked or unchecked.
*/
writeAcceptCookies() {
var accept = document.getElementById("acceptCookies");
var acceptThirdPartyMenu = document.getElementById("acceptThirdPartyMenu");
// if we're enabling cookies, automatically select 'accept third party always'
if (accept.checked)
acceptThirdPartyMenu.selectedIndex = 0;
return accept.checked ? 0 : 2;
},
/**
* Converts between network.cookie.cookieBehavior and the third-party cookie UI
*/
readAcceptThirdPartyCookies() {
var pref = document.getElementById("network.cookie.cookieBehavior");
switch (pref.value) {
case 0:
return "always";
case 1:
return "never";
case 2:
return "never";
case 3:
return "visited";
default:
return undefined;
}
},
writeAcceptThirdPartyCookies() {
var accept = document.getElementById("acceptThirdPartyMenu").selectedItem;
switch (accept.value) {
case "always":
return 0;
case "visited":
return 3;
case "never":
return 1;
default:
return undefined;
}
},
/**
* Displays fine-grained, per-site preferences for cookies.
*/
showCookieExceptions() {
var bundlePreferences = document.getElementById("bundlePreferences");
var params = { blockVisible: true,
sessionVisible: true,
allowVisible: true,
prefilledHost: "",
permissionType: "cookie",
windowTitle: bundlePreferences.getString("cookiepermissionstitle"),
introText: bundlePreferences.getString("cookiepermissionstext") };
gSubDialog.open("chrome://browser/content/preferences/permissions.xul",
null, params);
},
/**
* Displays all the user's cookies in a dialog.
*/
showCookies(aCategory) {
gSubDialog.open("chrome://browser/content/preferences/cookies.xul");
},
// CLEAR PRIVATE DATA
/*
* Preferences:
*
* privacy.sanitize.sanitizeOnShutdown
* - true if the user's private data is cleared on startup according to the
* Clear Private Data settings, false otherwise
*/
/**
* Displays the Clear Private Data settings dialog.
*/
showClearPrivateDataSettings() {
gSubDialog.open("chrome://browser/content/preferences/sanitize.xul", "resizable=no");
},
/**
* Displays a dialog from which individual parts of private data may be
* cleared.
*/
clearPrivateDataNow(aClearEverything) {
var ts = document.getElementById("privacy.sanitize.timeSpan");
var timeSpanOrig = ts.value;
if (aClearEverything) {
ts.value = 0;
}
gSubDialog.open("chrome://browser/content/sanitize.xul", "resizable=no", null, () => {
// reset the timeSpan pref
if (aClearEverything) {
ts.value = timeSpanOrig;
}
Services.obs.notifyObservers(null, "clear-private-data", null);
});
},
/**
* Enables or disables the "Settings..." button depending
* on the privacy.sanitize.sanitizeOnShutdown preference value
*/
_updateSanitizeSettingsButton() {
var settingsButton = document.getElementById("clearDataSettings");
var sanitizeOnShutdownPref = document.getElementById("privacy.sanitize.sanitizeOnShutdown");
settingsButton.disabled = !sanitizeOnShutdownPref.value;
},
// CONTAINERS
/*
* preferences:
*
* privacy.userContext.enabled
* - true if containers is enabled
*/
/**
* Enables/disables the Settings button used to configure containers
*/
readBrowserContainersCheckbox() {
var pref = document.getElementById("privacy.userContext.enabled");
var settings = document.getElementById("browserContainersSettings");
settings.disabled = !pref.value;
}
};

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

@ -0,0 +1,311 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# 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/.
<!-- Privacy panel -->
<script type="application/javascript"
src="chrome://browser/content/preferences/in-content-old/privacy.js"/>
<preferences id="privacyPreferences" hidden="true" data-category="panePrivacy">
<!-- Tracking -->
<preference id="privacy.trackingprotection.enabled"
name="privacy.trackingprotection.enabled"
type="bool"/>
<preference id="privacy.trackingprotection.pbmode.enabled"
name="privacy.trackingprotection.pbmode.enabled"
type="bool"/>
<!-- XXX button prefs -->
<preference id="pref.privacy.disable_button.cookie_exceptions"
name="pref.privacy.disable_button.cookie_exceptions"
type="bool"/>
<preference id="pref.privacy.disable_button.view_cookies"
name="pref.privacy.disable_button.view_cookies"
type="bool"/>
<preference id="pref.privacy.disable_button.change_blocklist"
name="pref.privacy.disable_button.change_blocklist"
type="bool"/>
<preference id="pref.privacy.disable_button.tracking_protection_exceptions"
name="pref.privacy.disable_button.tracking_protection_exceptions"
type="bool"/>
<!-- Location Bar -->
<preference id="browser.urlbar.autocomplete.enabled"
name="browser.urlbar.autocomplete.enabled"
type="bool"/>
<preference id="browser.urlbar.suggest.bookmark"
name="browser.urlbar.suggest.bookmark"
type="bool"/>
<preference id="browser.urlbar.suggest.history"
name="browser.urlbar.suggest.history"
type="bool"/>
<preference id="browser.urlbar.suggest.openpage"
name="browser.urlbar.suggest.openpage"
type="bool"/>
<!-- History -->
<preference id="places.history.enabled"
name="places.history.enabled"
type="bool"/>
<preference id="browser.formfill.enable"
name="browser.formfill.enable"
type="bool"/>
<preference id="privacy.history.custom"
name="privacy.history.custom"
type="bool"/>
<!-- Cookies -->
<preference id="network.cookie.cookieBehavior"
name="network.cookie.cookieBehavior"
type="int"/>
<preference id="network.cookie.lifetimePolicy"
name="network.cookie.lifetimePolicy"
type="int"/>
<preference id="network.cookie.blockFutureCookies"
name="network.cookie.blockFutureCookies"
type="bool"/>
<!-- Clear Private Data -->
<preference id="privacy.sanitize.sanitizeOnShutdown"
name="privacy.sanitize.sanitizeOnShutdown"
type="bool"/>
<preference id="privacy.sanitize.timeSpan"
name="privacy.sanitize.timeSpan"
type="int"/>
<!-- Private Browsing -->
<preference id="browser.privatebrowsing.autostart"
name="browser.privatebrowsing.autostart"
type="bool"/>
</preferences>
<hbox id="header-privacy"
class="header"
hidden="true"
data-category="panePrivacy">
<label class="header-name" flex="1">&panePrivacy.title;</label>
<html:a class="help-button" target="_blank" aria-label="&helpButton.label;"></html:a>
</hbox>
<!-- Tracking -->
<groupbox id="trackingGroup" data-category="panePrivacy" hidden="true">
<vbox id="trackingprotectionbox" hidden="true">
<hbox align="start">
<vbox>
<caption><label>&trackingProtectionHeader.label;
<label id="trackingProtectionLearnMore" class="learnMore text-link"
value="&trackingProtectionLearnMore.label;"/>
</label></caption>
<radiogroup id="trackingProtectionRadioGroup">
<radio value="always"
label="&trackingProtectionAlways.label;"
accesskey="&trackingProtectionAlways.accesskey;"/>
<radio value="private"
label="&trackingProtectionPrivate.label;"
accesskey="&trackingProtectionPrivate.accesskey;"/>
<radio value="never"
label="&trackingProtectionNever.label;"
accesskey="&trackingProtectionNever.accesskey;"/>
</radiogroup>
</vbox>
<spacer flex="1" />
<vbox>
<button id="trackingProtectionExceptions"
label="&trackingProtectionExceptions.label;"
accesskey="&trackingProtectionExceptions.accesskey;"
preference="pref.privacy.disable_button.tracking_protection_exceptions"/>
<button id="changeBlockList"
label="&changeBlockList.label;"
accesskey="&changeBlockList.accesskey;"
preference="pref.privacy.disable_button.change_blocklist"/>
</vbox>
</hbox>
</vbox>
<vbox id="trackingprotectionpbmbox">
<caption><label>&tracking.label;</label></caption>
<hbox align="center">
<checkbox id="trackingProtectionPBM"
preference="privacy.trackingprotection.pbmode.enabled"
accesskey="&trackingProtectionPBM5.accesskey;"
label="&trackingProtectionPBM5.label;" />
<label id="trackingProtectionPBMLearnMore"
class="learnMore text-link"
value="&trackingProtectionPBMLearnMore.label;"/>
<spacer flex="1" />
<button id="changeBlockListPBM"
label="&changeBlockList.label;" accesskey="&changeBlockList.accesskey;"
preference="pref.privacy.disable_button.change_blocklist"/>
</hbox>
</vbox>
<vbox>
<description>&doNotTrack.pre.label;<label
class="text-link" id="doNotTrackSettings"
>&doNotTrack.settings.label;</label>&doNotTrack.post.label;</description>
</vbox>
</groupbox>
<!-- History -->
<groupbox id="historyGroup" data-category="panePrivacy" hidden="true">
<caption><label>&history.label;</label></caption>
<hbox align="center">
<label id="historyModeLabel"
control="historyMode"
accesskey="&historyHeader.pre.accesskey;">&historyHeader.pre.label;
</label>
<menulist id="historyMode">
<menupopup>
<menuitem label="&historyHeader.remember.label;" value="remember"/>
<menuitem label="&historyHeader.dontremember.label;" value="dontremember"/>
<menuitem label="&historyHeader.custom.label;" value="custom"/>
</menupopup>
</menulist>
<label>&historyHeader.post.label;</label>
</hbox>
<deck id="historyPane">
<vbox id="historyRememberPane">
<hbox align="center" flex="1">
<vbox flex="1">
<description>&rememberDescription.label;</description>
<separator class="thin"/>
<description>&rememberActions.pre.label;<label
class="text-link" id="historyRememberClear"
>&rememberActions.clearHistory.label;</label>&rememberActions.middle.label;<label
class="text-link" id="historyRememberCookies"
>&rememberActions.removeCookies.label;</label>&rememberActions.post.label;</description>
</vbox>
</hbox>
</vbox>
<vbox id="historyDontRememberPane">
<hbox align="center" flex="1">
<vbox flex="1">
<description>&dontrememberDescription.label;</description>
<separator class="thin"/>
<description>&dontrememberActions.pre.label;<label
class="text-link" id="historyDontRememberClear"
>&dontrememberActions.clearHistory.label;</label>&dontrememberActions.post.label;</description>
</vbox>
</hbox>
</vbox>
<vbox id="historyCustomPane">
<separator class="thin"/>
<vbox>
<vbox align="start">
<checkbox id="privateBrowsingAutoStart"
label="&privateBrowsingPermanent2.label;"
accesskey="&privateBrowsingPermanent2.accesskey;"
preference="browser.privatebrowsing.autostart"/>
</vbox>
<vbox class="indent">
<vbox align="start">
<checkbox id="rememberHistory"
label="&rememberHistory2.label;"
accesskey="&rememberHistory2.accesskey;"
preference="places.history.enabled"/>
<checkbox id="rememberForms"
label="&rememberSearchForm.label;"
accesskey="&rememberSearchForm.accesskey;"
preference="browser.formfill.enable"/>
</vbox>
<hbox id="cookiesBox">
<checkbox id="acceptCookies" label="&acceptCookies.label;"
preference="network.cookie.cookieBehavior"
accesskey="&acceptCookies.accesskey;"
onsyncfrompreference="return gPrivacyPane.readAcceptCookies();"
onsynctopreference="return gPrivacyPane.writeAcceptCookies();"/>
<spacer flex="1" />
<button id="cookieExceptions"
label="&cookieExceptions.label;" accesskey="&cookieExceptions.accesskey;"
preference="pref.privacy.disable_button.cookie_exceptions"/>
</hbox>
<hbox id="acceptThirdPartyRow"
class="indent"
align="center">
<label id="acceptThirdPartyLabel" control="acceptThirdPartyMenu"
accesskey="&acceptThirdParty.pre.accesskey;">&acceptThirdParty.pre.label;</label>
<menulist id="acceptThirdPartyMenu" preference="network.cookie.cookieBehavior"
onsyncfrompreference="return gPrivacyPane.readAcceptThirdPartyCookies();"
onsynctopreference="return gPrivacyPane.writeAcceptThirdPartyCookies();">
<menupopup>
<menuitem label="&acceptThirdParty.always.label;" value="always"/>
<menuitem label="&acceptThirdParty.visited.label;" value="visited"/>
<menuitem label="&acceptThirdParty.never.label;" value="never"/>
</menupopup>
</menulist>
</hbox>
<hbox id="keepRow"
class="indent"
align="center">
<label id="keepUntil"
control="keepCookiesUntil"
accesskey="&keepUntil.accesskey;">&keepUntil.label;</label>
<menulist id="keepCookiesUntil"
preference="network.cookie.lifetimePolicy">
<menupopup>
<menuitem label="&expire.label;" value="0"/>
<menuitem label="&close.label;" value="2"/>
</menupopup>
</menulist>
<spacer flex="1"/>
<button id="showCookiesButton"
label="&showCookies.label;" accesskey="&showCookies.accesskey;"
preference="pref.privacy.disable_button.view_cookies"/>
</hbox>
<hbox id="clearDataBox"
align="center">
<checkbox id="alwaysClear"
preference="privacy.sanitize.sanitizeOnShutdown"
label="&clearOnClose.label;"
accesskey="&clearOnClose.accesskey;"/>
<spacer flex="1"/>
<button id="clearDataSettings" label="&clearOnCloseSettings.label;"
accesskey="&clearOnCloseSettings.accesskey;"/>
</hbox>
</vbox>
</vbox>
</vbox>
</deck>
</groupbox>
<!-- Location Bar -->
<groupbox id="locationBarGroup"
data-category="panePrivacy"
hidden="true">
<caption><label>&locationBar.label;</label></caption>
<label id="locationBarSuggestionLabel">&locbar.suggest.label;</label>
<checkbox id="historySuggestion" label="&locbar.history.label;"
accesskey="&locbar.history.accesskey;"
preference="browser.urlbar.suggest.history"/>
<checkbox id="bookmarkSuggestion" label="&locbar.bookmarks.label;"
accesskey="&locbar.bookmarks.accesskey;"
preference="browser.urlbar.suggest.bookmark"/>
<checkbox id="openpageSuggestion" label="&locbar.openpage.label;"
accesskey="&locbar.openpage.accesskey;"
preference="browser.urlbar.suggest.openpage"/>
<label class="text-link" onclick="gotoPref('search')">
&suggestionSettings.label;
</label>
</groupbox>
<!-- Containers -->
<groupbox id="browserContainersGroup" data-category="panePrivacy" hidden="true">
<vbox id="browserContainersbox" hidden="true">
<caption><label>&browserContainersHeader.label;
<label id="browserContainersLearnMore" class="learnMore text-link"
value="&browserContainersLearnMore.label;"/>
</label></caption>
<hbox align="start">
<vbox>
<checkbox id="browserContainersCheckbox"
label="&browserContainersEnabled.label;"
accesskey="&browserContainersEnabled.accesskey;"
preference="privacy.userContext.enabled"
onsyncfrompreference="return gPrivacyPane.readBrowserContainersCheckbox();"/>
</vbox>
<spacer flex="1"/>
<vbox>
<button id="browserContainersSettings"
label="&browserContainersSettings.label;"
accesskey="&browserContainersSettings.accesskey;"/>
</vbox>
</hbox>
</vbox>
</groupbox>

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

@ -0,0 +1,604 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
/* import-globals-from preferences.js */
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
"resource://gre/modules/PlacesUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Task",
"resource://gre/modules/Task.jsm");
const ENGINE_FLAVOR = "text/x-moz-search-engine";
var gEngineView = null;
var gSearchPane = {
/**
* Initialize autocomplete to ensure prefs are in sync.
*/
_initAutocomplete() {
Components.classes["@mozilla.org/autocomplete/search;1?name=unifiedcomplete"]
.getService(Components.interfaces.mozIPlacesAutoComplete);
},
init() {
gEngineView = new EngineView(new EngineStore());
document.getElementById("engineList").view = gEngineView;
this.buildDefaultEngineDropDown();
let addEnginesLink = document.getElementById("addEngines");
let searchEnginesURL = Services.wm.getMostRecentWindow("navigator:browser")
.BrowserSearch.searchEnginesURL;
addEnginesLink.setAttribute("href", searchEnginesURL);
window.addEventListener("click", this);
window.addEventListener("command", this);
window.addEventListener("dragstart", this);
window.addEventListener("keypress", this);
window.addEventListener("select", this);
window.addEventListener("blur", this, true);
Services.obs.addObserver(this, "browser-search-engine-modified", false);
window.addEventListener("unload", () => {
Services.obs.removeObserver(this, "browser-search-engine-modified");
});
this._initAutocomplete();
let suggestsPref =
document.getElementById("browser.search.suggest.enabled");
suggestsPref.addEventListener("change", () => {
this.updateSuggestsCheckbox();
});
this.updateSuggestsCheckbox();
},
updateSuggestsCheckbox() {
let suggestsPref =
document.getElementById("browser.search.suggest.enabled");
let permanentPB =
Services.prefs.getBoolPref("browser.privatebrowsing.autostart");
let urlbarSuggests = document.getElementById("urlBarSuggestion");
urlbarSuggests.disabled = !suggestsPref.value || permanentPB;
let urlbarSuggestsPref =
document.getElementById("browser.urlbar.suggest.searches");
urlbarSuggests.checked = urlbarSuggestsPref.value;
if (urlbarSuggests.disabled) {
urlbarSuggests.checked = false;
}
let permanentPBLabel =
document.getElementById("urlBarSuggestionPermanentPBLabel");
permanentPBLabel.hidden = urlbarSuggests.hidden || !permanentPB;
},
buildDefaultEngineDropDown() {
// This is called each time something affects the list of engines.
let list = document.getElementById("defaultEngine");
// Set selection to the current default engine.
let currentEngine = Services.search.currentEngine.name;
// If the current engine isn't in the list any more, select the first item.
let engines = gEngineView._engineStore._engines;
if (!engines.some(e => e.name == currentEngine))
currentEngine = engines[0].name;
// Now clean-up and rebuild the list.
list.removeAllItems();
gEngineView._engineStore._engines.forEach(e => {
let item = list.appendItem(e.name);
item.setAttribute("class", "menuitem-iconic searchengine-menuitem menuitem-with-favicon");
if (e.iconURI) {
item.setAttribute("image", e.iconURI.spec);
}
item.engine = e;
if (e.name == currentEngine)
list.selectedItem = item;
});
},
handleEvent(aEvent) {
switch (aEvent.type) {
case "click":
if (aEvent.target.id != "engineChildren" &&
!aEvent.target.classList.contains("searchEngineAction")) {
let engineList = document.getElementById("engineList");
// We don't want to toggle off selection while editing keyword
// so proceed only when the input field is hidden.
// We need to check that engineList.view is defined here
// because the "click" event listener is on <window> and the
// view might have been destroyed if the pane has been navigated
// away from.
if (engineList.inputField.hidden && engineList.view) {
let selection = engineList.view.selection;
if (selection.count > 0) {
selection.toggleSelect(selection.currentIndex);
}
engineList.blur();
}
}
break;
case "command":
switch (aEvent.target.id) {
case "":
if (aEvent.target.parentNode &&
aEvent.target.parentNode.parentNode &&
aEvent.target.parentNode.parentNode.id == "defaultEngine") {
gSearchPane.setDefaultEngine();
}
break;
case "restoreDefaultSearchEngines":
gSearchPane.onRestoreDefaults();
break;
case "removeEngineButton":
Services.search.removeEngine(gEngineView.selectedEngine.originalEngine);
break;
}
break;
case "dragstart":
if (aEvent.target.id == "engineChildren") {
onDragEngineStart(aEvent);
}
break;
case "keypress":
if (aEvent.target.id == "engineList") {
gSearchPane.onTreeKeyPress(aEvent);
}
break;
case "select":
if (aEvent.target.id == "engineList") {
gSearchPane.onTreeSelect();
}
break;
case "blur":
if (aEvent.target.id == "engineList" &&
aEvent.target.inputField == document.getBindingParent(aEvent.originalTarget)) {
gSearchPane.onInputBlur();
}
break;
}
},
observe(aEngine, aTopic, aVerb) {
if (aTopic == "browser-search-engine-modified") {
aEngine.QueryInterface(Components.interfaces.nsISearchEngine);
switch (aVerb) {
case "engine-added":
gEngineView._engineStore.addEngine(aEngine);
gEngineView.rowCountChanged(gEngineView.lastIndex, 1);
gSearchPane.buildDefaultEngineDropDown();
break;
case "engine-changed":
gEngineView._engineStore.reloadIcons();
gEngineView.invalidate();
break;
case "engine-removed":
gSearchPane.remove(aEngine);
break;
case "engine-current":
// If the user is going through the drop down using up/down keys, the
// dropdown may still be open (eg. on Windows) when engine-current is
// fired, so rebuilding the list unconditionally would get in the way.
let selectedEngine =
document.getElementById("defaultEngine").selectedItem.engine;
if (selectedEngine.name != aEngine.name)
gSearchPane.buildDefaultEngineDropDown();
break;
case "engine-default":
// Not relevant
break;
}
}
},
onInputBlur(aEvent) {
let tree = document.getElementById("engineList");
if (!tree.hasAttribute("editing"))
return;
// Accept input unless discarded.
let accept = aEvent.charCode != KeyEvent.DOM_VK_ESCAPE;
tree.stopEditing(accept);
},
onTreeSelect() {
document.getElementById("removeEngineButton").disabled =
!gEngineView.isEngineSelectedAndRemovable();
},
onTreeKeyPress(aEvent) {
let index = gEngineView.selectedIndex;
let tree = document.getElementById("engineList");
if (tree.hasAttribute("editing"))
return;
if (aEvent.charCode == KeyEvent.DOM_VK_SPACE) {
// Space toggles the checkbox.
let newValue = !gEngineView._engineStore.engines[index].shown;
gEngineView.setCellValue(index, tree.columns.getFirstColumn(),
newValue.toString());
// Prevent page from scrolling on the space key.
aEvent.preventDefault();
} else {
let isMac = Services.appinfo.OS == "Darwin";
if ((isMac && aEvent.keyCode == KeyEvent.DOM_VK_RETURN) ||
(!isMac && aEvent.keyCode == KeyEvent.DOM_VK_F2)) {
tree.startEditing(index, tree.columns.getLastColumn());
} else if (aEvent.keyCode == KeyEvent.DOM_VK_DELETE ||
(isMac && aEvent.shiftKey &&
aEvent.keyCode == KeyEvent.DOM_VK_BACK_SPACE &&
gEngineView.isEngineSelectedAndRemovable())) {
// Delete and Shift+Backspace (Mac) removes selected engine.
Services.search.removeEngine(gEngineView.selectedEngine.originalEngine);
}
}
},
onRestoreDefaults() {
let num = gEngineView._engineStore.restoreDefaultEngines();
gEngineView.rowCountChanged(0, num);
gEngineView.invalidate();
},
showRestoreDefaults(aEnable) {
document.getElementById("restoreDefaultSearchEngines").disabled = !aEnable;
},
remove(aEngine) {
let index = gEngineView._engineStore.removeEngine(aEngine);
gEngineView.rowCountChanged(index, -1);
gEngineView.invalidate();
gEngineView.selection.select(Math.min(index, gEngineView.lastIndex));
gEngineView.ensureRowIsVisible(gEngineView.currentIndex);
document.getElementById("engineList").focus();
},
editKeyword: Task.async(function* (aEngine, aNewKeyword) {
let keyword = aNewKeyword.trim();
if (keyword) {
let eduplicate = false;
let dupName = "";
// Check for duplicates in Places keywords.
let bduplicate = !!(yield PlacesUtils.keywords.fetch(keyword));
// Check for duplicates in changes we haven't committed yet
let engines = gEngineView._engineStore.engines;
for (let engine of engines) {
if (engine.alias == keyword &&
engine.name != aEngine.name) {
eduplicate = true;
dupName = engine.name;
break;
}
}
// Notify the user if they have chosen an existing engine/bookmark keyword
if (eduplicate || bduplicate) {
let strings = document.getElementById("engineManagerBundle");
let dtitle = strings.getString("duplicateTitle");
let bmsg = strings.getString("duplicateBookmarkMsg");
let emsg = strings.getFormattedString("duplicateEngineMsg", [dupName]);
Services.prompt.alert(window, dtitle, eduplicate ? emsg : bmsg);
return false;
}
}
gEngineView._engineStore.changeEngine(aEngine, "alias", keyword);
gEngineView.invalidate();
return true;
}),
saveOneClickEnginesList() {
let hiddenList = [];
for (let engine of gEngineView._engineStore.engines) {
if (!engine.shown)
hiddenList.push(engine.name);
}
document.getElementById("browser.search.hiddenOneOffs").value =
hiddenList.join(",");
},
setDefaultEngine() {
Services.search.currentEngine =
document.getElementById("defaultEngine").selectedItem.engine;
}
};
function onDragEngineStart(event) {
var selectedIndex = gEngineView.selectedIndex;
var tree = document.getElementById("engineList");
var row = { }, col = { }, child = { };
tree.treeBoxObject.getCellAt(event.clientX, event.clientY, row, col, child);
if (selectedIndex >= 0 && !gEngineView.isCheckBox(row.value, col.value)) {
event.dataTransfer.setData(ENGINE_FLAVOR, selectedIndex.toString());
event.dataTransfer.effectAllowed = "move";
}
}
function EngineStore() {
let pref = document.getElementById("browser.search.hiddenOneOffs").value;
this.hiddenList = pref ? pref.split(",") : [];
this._engines = Services.search.getVisibleEngines().map(this._cloneEngine, this);
this._defaultEngines = Services.search.getDefaultEngines().map(this._cloneEngine, this);
// check if we need to disable the restore defaults button
var someHidden = this._defaultEngines.some(e => e.hidden);
gSearchPane.showRestoreDefaults(someHidden);
}
EngineStore.prototype = {
_engines: null,
_defaultEngines: null,
get engines() {
return this._engines;
},
set engines(val) {
this._engines = val;
return val;
},
_getIndexForEngine(aEngine) {
return this._engines.indexOf(aEngine);
},
_getEngineByName(aName) {
return this._engines.find(engine => engine.name == aName);
},
_cloneEngine(aEngine) {
var clonedObj = {};
for (var i in aEngine)
clonedObj[i] = aEngine[i];
clonedObj.originalEngine = aEngine;
clonedObj.shown = this.hiddenList.indexOf(clonedObj.name) == -1;
return clonedObj;
},
// Callback for Array's some(). A thisObj must be passed to some()
_isSameEngine(aEngineClone) {
return aEngineClone.originalEngine == this.originalEngine;
},
addEngine(aEngine) {
this._engines.push(this._cloneEngine(aEngine));
},
moveEngine(aEngine, aNewIndex) {
if (aNewIndex < 0 || aNewIndex > this._engines.length - 1)
throw new Error("ES_moveEngine: invalid aNewIndex!");
var index = this._getIndexForEngine(aEngine);
if (index == -1)
throw new Error("ES_moveEngine: invalid engine?");
if (index == aNewIndex)
return; // nothing to do
// Move the engine in our internal store
var removedEngine = this._engines.splice(index, 1)[0];
this._engines.splice(aNewIndex, 0, removedEngine);
Services.search.moveEngine(aEngine.originalEngine, aNewIndex);
},
removeEngine(aEngine) {
if (this._engines.length == 1) {
throw new Error("Cannot remove last engine!");
}
let engineName = aEngine.name;
let index = this._engines.findIndex(element => element.name == engineName);
if (index == -1)
throw new Error("invalid engine?");
let removedEngine = this._engines.splice(index, 1)[0];
if (this._defaultEngines.some(this._isSameEngine, removedEngine))
gSearchPane.showRestoreDefaults(true);
gSearchPane.buildDefaultEngineDropDown();
return index;
},
restoreDefaultEngines() {
var added = 0;
for (var i = 0; i < this._defaultEngines.length; ++i) {
var e = this._defaultEngines[i];
// If the engine is already in the list, just move it.
if (this._engines.some(this._isSameEngine, e)) {
this.moveEngine(this._getEngineByName(e.name), i);
} else {
// Otherwise, add it back to our internal store
// The search service removes the alias when an engine is hidden,
// so clear any alias we may have cached before unhiding the engine.
e.alias = "";
this._engines.splice(i, 0, e);
let engine = e.originalEngine;
engine.hidden = false;
Services.search.moveEngine(engine, i);
added++;
}
}
Services.search.resetToOriginalDefaultEngine();
gSearchPane.showRestoreDefaults(false);
gSearchPane.buildDefaultEngineDropDown();
return added;
},
changeEngine(aEngine, aProp, aNewValue) {
var index = this._getIndexForEngine(aEngine);
if (index == -1)
throw new Error("invalid engine?");
this._engines[index][aProp] = aNewValue;
aEngine.originalEngine[aProp] = aNewValue;
},
reloadIcons() {
this._engines.forEach(function(e) {
e.uri = e.originalEngine.uri;
});
}
};
function EngineView(aEngineStore) {
this._engineStore = aEngineStore;
}
EngineView.prototype = {
_engineStore: null,
tree: null,
get lastIndex() {
return this.rowCount - 1;
},
get selectedIndex() {
var seln = this.selection;
if (seln.getRangeCount() > 0) {
var min = {};
seln.getRangeAt(0, min, {});
return min.value;
}
return -1;
},
get selectedEngine() {
return this._engineStore.engines[this.selectedIndex];
},
// Helpers
rowCountChanged(index, count) {
this.tree.rowCountChanged(index, count);
},
invalidate() {
this.tree.invalidate();
},
ensureRowIsVisible(index) {
this.tree.ensureRowIsVisible(index);
},
getSourceIndexFromDrag(dataTransfer) {
return parseInt(dataTransfer.getData(ENGINE_FLAVOR));
},
isCheckBox(index, column) {
return column.id == "engineShown";
},
isEngineSelectedAndRemovable() {
return this.selectedIndex != -1 && this.lastIndex != 0;
},
// nsITreeView
get rowCount() {
return this._engineStore.engines.length;
},
getImageSrc(index, column) {
if (column.id == "engineName") {
if (this._engineStore.engines[index].iconURI)
return this._engineStore.engines[index].iconURI.spec;
if (window.devicePixelRatio > 1)
return "chrome://browser/skin/search-engine-placeholder@2x.png";
return "chrome://browser/skin/search-engine-placeholder.png";
}
return "";
},
getCellText(index, column) {
if (column.id == "engineName")
return this._engineStore.engines[index].name;
else if (column.id == "engineKeyword")
return this._engineStore.engines[index].alias;
return "";
},
setTree(tree) {
this.tree = tree;
},
canDrop(targetIndex, orientation, dataTransfer) {
var sourceIndex = this.getSourceIndexFromDrag(dataTransfer);
return (sourceIndex != -1 &&
sourceIndex != targetIndex &&
sourceIndex != targetIndex + orientation);
},
drop(dropIndex, orientation, dataTransfer) {
var sourceIndex = this.getSourceIndexFromDrag(dataTransfer);
var sourceEngine = this._engineStore.engines[sourceIndex];
const nsITreeView = Components.interfaces.nsITreeView;
if (dropIndex > sourceIndex) {
if (orientation == nsITreeView.DROP_BEFORE)
dropIndex--;
} else if (orientation == nsITreeView.DROP_AFTER) {
dropIndex++;
}
this._engineStore.moveEngine(sourceEngine, dropIndex);
gSearchPane.showRestoreDefaults(true);
gSearchPane.buildDefaultEngineDropDown();
// Redraw, and adjust selection
this.invalidate();
this.selection.select(dropIndex);
},
selection: null,
getRowProperties(index) { return ""; },
getCellProperties(index, column) { return ""; },
getColumnProperties(column) { return ""; },
isContainer(index) { return false; },
isContainerOpen(index) { return false; },
isContainerEmpty(index) { return false; },
isSeparator(index) { return false; },
isSorted(index) { return false; },
getParentIndex(index) { return -1; },
hasNextSibling(parentIndex, index) { return false; },
getLevel(index) { return 0; },
getProgressMode(index, column) { },
getCellValue(index, column) {
if (column.id == "engineShown")
return this._engineStore.engines[index].shown;
return undefined;
},
toggleOpenState(index) { },
cycleHeader(column) { },
selectionChanged() { },
cycleCell(row, column) { },
isEditable(index, column) { return column.id != "engineName"; },
isSelectable(index, column) { return false; },
setCellValue(index, column, value) {
if (column.id == "engineShown") {
this._engineStore.engines[index].shown = value == "true";
gEngineView.invalidate();
gSearchPane.saveOneClickEnginesList();
}
},
setCellText(index, column, value) {
if (column.id == "engineKeyword") {
gSearchPane.editKeyword(this._engineStore.engines[index], value)
.then(valid => {
if (!valid)
document.getElementById("engineList").startEditing(index, column);
});
}
},
performAction(action) { },
performActionOnRow(action, index) { },
performActionOnCell(action, index, column) { }
};

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

@ -0,0 +1,86 @@
<preferences id="searchPreferences" hidden="true" data-category="paneSearch">
<preference id="browser.search.suggest.enabled"
name="browser.search.suggest.enabled"
type="bool"/>
<preference id="browser.urlbar.suggest.searches"
name="browser.urlbar.suggest.searches"
type="bool"/>
<preference id="browser.search.hiddenOneOffs"
name="browser.search.hiddenOneOffs"
type="unichar"/>
</preferences>
<script type="application/javascript"
src="chrome://browser/content/preferences/in-content-old/search.js"/>
<stringbundle id="engineManagerBundle" src="chrome://browser/locale/engineManager.properties"/>
<hbox id="header-search"
class="header"
hidden="true"
data-category="paneSearch">
<label class="header-name" flex="1">&paneSearch.title;</label>
<html:a class="help-button" target="_blank" aria-label="&helpButton.label;"></html:a>
</hbox>
<!-- Default Search Engine -->
<groupbox id="defaultEngineGroup" align="start" data-category="paneSearch">
<caption label="&defaultSearchEngine.label;"/>
<label>&chooseYourDefaultSearchEngine.label;</label>
<menulist id="defaultEngine">
<menupopup/>
</menulist>
<checkbox id="suggestionsInSearchFieldsCheckbox"
label="&provideSearchSuggestions.label;"
accesskey="&provideSearchSuggestions.accesskey;"
preference="browser.search.suggest.enabled"/>
<vbox class="indent">
<checkbox id="urlBarSuggestion" label="&showURLBarSuggestions.label;"
accesskey="&showURLBarSuggestions.accesskey;"
preference="browser.urlbar.suggest.searches"/>
<hbox id="urlBarSuggestionPermanentPBLabel"
align="center" class="indent">
<label flex="1">&urlBarSuggestionsPermanentPB.label;</label>
</hbox>
</vbox>
</groupbox>
<groupbox id="oneClickSearchProvidersGroup" data-category="paneSearch">
<caption label="&oneClickSearchEngines.label;"/>
<label>&chooseWhichOneToDisplay.label;</label>
<tree id="engineList" flex="1" rows="8" hidecolumnpicker="true" editable="true"
seltype="single">
<treechildren id="engineChildren" flex="1"/>
<treecols>
<treecol id="engineShown" type="checkbox" editable="true" sortable="false"/>
<treecol id="engineName" flex="4" label="&engineNameColumn.label;" sortable="false"/>
<treecol id="engineKeyword" flex="1" label="&engineKeywordColumn.label;" editable="true"
sortable="false"/>
</treecols>
</tree>
<hbox>
<button id="restoreDefaultSearchEngines"
label="&restoreDefaultSearchEngines.label;"
accesskey="&restoreDefaultSearchEngines.accesskey;"
/>
<spacer flex="1"/>
<button id="removeEngineButton"
class="searchEngineAction"
label="&removeEngine.label;"
accesskey="&removeEngine.accesskey;"
disabled="true"
/>
</hbox>
<separator class="thin"/>
<hbox id="addEnginesBox" pack="start">
<label id="addEngines" class="text-link" value="&addMoreSearchEngines.label;"/>
</hbox>
</groupbox>

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

@ -0,0 +1,292 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
/* import-globals-from preferences.js */
XPCOMUtils.defineLazyModuleGetter(this, "LoginHelper",
"resource://gre/modules/LoginHelper.jsm");
Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
var gSecurityPane = {
_pane: null,
/**
* Initializes master password UI.
*/
init() {
function setEventListener(aId, aEventType, aCallback) {
document.getElementById(aId)
.addEventListener(aEventType, aCallback.bind(gSecurityPane));
}
this._pane = document.getElementById("paneSecurity");
this._initMasterPasswordUI();
this._initSafeBrowsing();
setEventListener("addonExceptions", "command",
gSecurityPane.showAddonExceptions);
setEventListener("passwordExceptions", "command",
gSecurityPane.showPasswordExceptions);
setEventListener("useMasterPassword", "command",
gSecurityPane.updateMasterPasswordButton);
setEventListener("changeMasterPassword", "command",
gSecurityPane.changeMasterPassword);
setEventListener("showPasswords", "command",
gSecurityPane.showPasswords);
},
// ADD-ONS
/*
* Preferences:
*
* xpinstall.whitelist.required
* - true if a site must be added to a site whitelist before extensions
* provided by the site may be installed from it, false if the extension
* may be directly installed after a confirmation dialog
*/
/**
* Enables/disables the add-ons Exceptions button depending on whether
* or not add-on installation warnings are displayed.
*/
readWarnAddonInstall() {
var warn = document.getElementById("xpinstall.whitelist.required");
var exceptions = document.getElementById("addonExceptions");
exceptions.disabled = !warn.value;
// don't override the preference value
return undefined;
},
/**
* Displays the exceptions lists for add-on installation warnings.
*/
showAddonExceptions() {
var bundlePrefs = document.getElementById("bundlePreferences");
var params = this._addonParams;
if (!params.windowTitle || !params.introText) {
params.windowTitle = bundlePrefs.getString("addons_permissions_title");
params.introText = bundlePrefs.getString("addonspermissionstext");
}
gSubDialog.open("chrome://browser/content/preferences/permissions.xul",
null, params);
},
/**
* Parameters for the add-on install permissions dialog.
*/
_addonParams:
{
blockVisible: false,
sessionVisible: false,
allowVisible: true,
prefilledHost: "",
permissionType: "install"
},
// PASSWORDS
/*
* Preferences:
*
* signon.rememberSignons
* - true if passwords are remembered, false otherwise
*/
/**
* Enables/disables the Exceptions button used to configure sites where
* passwords are never saved. When browser is set to start in Private
* Browsing mode, the "Remember passwords" UI is useless, so we disable it.
*/
readSavePasswords() {
var pref = document.getElementById("signon.rememberSignons");
var excepts = document.getElementById("passwordExceptions");
if (PrivateBrowsingUtils.permanentPrivateBrowsing) {
document.getElementById("savePasswords").disabled = true;
excepts.disabled = true;
return false;
}
excepts.disabled = !pref.value;
// don't override pref value in UI
return undefined;
},
/**
* Displays a dialog in which the user can view and modify the list of sites
* where passwords are never saved.
*/
showPasswordExceptions() {
var bundlePrefs = document.getElementById("bundlePreferences");
var params = {
blockVisible: true,
sessionVisible: false,
allowVisible: false,
hideStatusColumn: true,
prefilledHost: "",
permissionType: "login-saving",
windowTitle: bundlePrefs.getString("savedLoginsExceptions_title"),
introText: bundlePrefs.getString("savedLoginsExceptions_desc")
};
gSubDialog.open("chrome://browser/content/preferences/permissions.xul",
null, params);
},
/**
* Initializes master password UI: the "use master password" checkbox, selects
* the master password button to show, and enables/disables it as necessary.
* The master password is controlled by various bits of NSS functionality, so
* the UI for it can't be controlled by the normal preference bindings.
*/
_initMasterPasswordUI() {
var noMP = !LoginHelper.isMasterPasswordSet();
var button = document.getElementById("changeMasterPassword");
button.disabled = noMP;
var checkbox = document.getElementById("useMasterPassword");
checkbox.checked = !noMP;
},
_initSafeBrowsing() {
let enableSafeBrowsing = document.getElementById("enableSafeBrowsing");
let blockDownloads = document.getElementById("blockDownloads");
let blockUncommonUnwanted = document.getElementById("blockUncommonUnwanted");
let safeBrowsingPhishingPref = document.getElementById("browser.safebrowsing.phishing.enabled");
let safeBrowsingMalwarePref = document.getElementById("browser.safebrowsing.malware.enabled");
let blockDownloadsPref = document.getElementById("browser.safebrowsing.downloads.enabled");
let malwareTable = document.getElementById("urlclassifier.malwareTable");
let blockUnwantedPref = document.getElementById("browser.safebrowsing.downloads.remote.block_potentially_unwanted");
let blockUncommonPref = document.getElementById("browser.safebrowsing.downloads.remote.block_uncommon");
enableSafeBrowsing.addEventListener("command", function() {
safeBrowsingPhishingPref.value = enableSafeBrowsing.checked;
safeBrowsingMalwarePref.value = enableSafeBrowsing.checked;
if (enableSafeBrowsing.checked) {
blockDownloads.removeAttribute("disabled");
if (blockDownloads.checked) {
blockUncommonUnwanted.removeAttribute("disabled");
}
} else {
blockDownloads.setAttribute("disabled", "true");
blockUncommonUnwanted.setAttribute("disabled", "true");
}
});
blockDownloads.addEventListener("command", function() {
blockDownloadsPref.value = blockDownloads.checked;
if (blockDownloads.checked) {
blockUncommonUnwanted.removeAttribute("disabled");
} else {
blockUncommonUnwanted.setAttribute("disabled", "true");
}
});
blockUncommonUnwanted.addEventListener("command", function() {
blockUnwantedPref.value = blockUncommonUnwanted.checked;
blockUncommonPref.value = blockUncommonUnwanted.checked;
let malware = malwareTable.value
.split(",")
.filter(x => x !== "goog-unwanted-shavar" && x !== "test-unwanted-simple");
if (blockUncommonUnwanted.checked) {
malware.push("goog-unwanted-shavar");
malware.push("test-unwanted-simple");
}
// sort alphabetically to keep the pref consistent
malware.sort();
malwareTable.value = malware.join(",");
});
// set initial values
enableSafeBrowsing.checked = safeBrowsingPhishingPref.value && safeBrowsingMalwarePref.value;
if (!enableSafeBrowsing.checked) {
blockDownloads.setAttribute("disabled", "true");
blockUncommonUnwanted.setAttribute("disabled", "true");
}
blockDownloads.checked = blockDownloadsPref.value;
if (!blockDownloadsPref.value) {
blockUncommonUnwanted.setAttribute("disabled", "true");
}
blockUncommonUnwanted.checked = blockUnwantedPref.value && blockUncommonPref.value;
},
/**
* Enables/disables the master password button depending on the state of the
* "use master password" checkbox, and prompts for master password removal if
* one is set.
*/
updateMasterPasswordButton() {
var checkbox = document.getElementById("useMasterPassword");
var button = document.getElementById("changeMasterPassword");
button.disabled = !checkbox.checked;
// unchecking the checkbox should try to immediately remove the master
// password, because it's impossible to non-destructively remove the master
// password used to encrypt all the passwords without providing it (by
// design), and it would be extremely odd to pop up that dialog when the
// user closes the prefwindow and saves his settings
if (!checkbox.checked)
this._removeMasterPassword();
else
this.changeMasterPassword();
this._initMasterPasswordUI();
},
/**
* Displays the "remove master password" dialog to allow the user to remove
* the current master password. When the dialog is dismissed, master password
* UI is automatically updated.
*/
_removeMasterPassword() {
var secmodDB = Cc["@mozilla.org/security/pkcs11moduledb;1"].
getService(Ci.nsIPKCS11ModuleDB);
if (secmodDB.isFIPSEnabled) {
var promptService = Cc["@mozilla.org/embedcomp/prompt-service;1"].
getService(Ci.nsIPromptService);
var bundle = document.getElementById("bundlePreferences");
promptService.alert(window,
bundle.getString("pw_change_failed_title"),
bundle.getString("pw_change2empty_in_fips_mode"));
this._initMasterPasswordUI();
} else {
gSubDialog.open("chrome://mozapps/content/preferences/removemp.xul",
null, null, this._initMasterPasswordUI.bind(this));
}
},
/**
* Displays a dialog in which the master password may be changed.
*/
changeMasterPassword() {
gSubDialog.open("chrome://mozapps/content/preferences/changemp.xul",
"resizable=no", null, this._initMasterPasswordUI.bind(this));
},
/**
* Shows the sites where the user has saved passwords and the associated login
* information.
*/
showPasswords() {
gSubDialog.open("chrome://passwordmgr/content/passwordManager.xul");
}
};

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

@ -0,0 +1,131 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# 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/.
<!-- Security panel -->
<script type="application/javascript"
src="chrome://browser/content/preferences/in-content-old/security.js"/>
<preferences id="securityPreferences" hidden="true" data-category="paneSecurity">
<!-- XXX buttons -->
<preference id="pref.privacy.disable_button.view_passwords"
name="pref.privacy.disable_button.view_passwords"
type="bool"/>
<preference id="pref.privacy.disable_button.view_passwords_exceptions"
name="pref.privacy.disable_button.view_passwords_exceptions"
type="bool"/>
<!-- Add-ons, malware, phishing -->
<preference id="xpinstall.whitelist.required"
name="xpinstall.whitelist.required"
type="bool"/>
<preference id="browser.safebrowsing.malware.enabled"
name="browser.safebrowsing.malware.enabled"
type="bool"/>
<preference id="browser.safebrowsing.phishing.enabled"
name="browser.safebrowsing.phishing.enabled"
type="bool"/>
<preference id="browser.safebrowsing.downloads.enabled"
name="browser.safebrowsing.downloads.enabled"
type="bool"/>
<preference id="urlclassifier.malwareTable"
name="urlclassifier.malwareTable"
type="string"/>
<preference id="browser.safebrowsing.downloads.remote.block_potentially_unwanted"
name="browser.safebrowsing.downloads.remote.block_potentially_unwanted"
type="bool"/>
<preference id="browser.safebrowsing.downloads.remote.block_uncommon"
name="browser.safebrowsing.downloads.remote.block_uncommon"
type="bool"/>
<!-- Passwords -->
<preference id="signon.rememberSignons" name="signon.rememberSignons" type="bool"/>
</preferences>
<hbox id="header-security"
class="header"
hidden="true"
data-category="paneSecurity">
<label class="header-name" flex="1">&paneSecurity.title;</label>
<html:a class="help-button" target="_blank" aria-label="&helpButton.label;"></html:a>
</hbox>
<!-- addons, forgery (phishing) UI -->
<groupbox id="addonsPhishingGroup" data-category="paneSecurity" hidden="true">
<caption><label>&general.label;</label></caption>
<hbox id="addonInstallBox">
<checkbox id="warnAddonInstall"
label="&warnOnAddonInstall.label;"
accesskey="&warnOnAddonInstall.accesskey;"
preference="xpinstall.whitelist.required"
onsyncfrompreference="return gSecurityPane.readWarnAddonInstall();"/>
<spacer flex="1"/>
<button id="addonExceptions"
label="&addonExceptions.label;"
accesskey="&addonExceptions.accesskey;"/>
</hbox>
<separator class="thin"/>
<vbox align="start">
<checkbox id="enableSafeBrowsing"
label="&enableSafeBrowsing.label;"
accesskey="&enableSafeBrowsing.accesskey;" />
<vbox class="indent">
<checkbox id="blockDownloads"
label="&blockDownloads.label;"
accesskey="&blockDownloads.accesskey;" />
<checkbox id="blockUncommonUnwanted"
label="&blockUncommonAndUnwanted.label;"
accesskey="&blockUncommonAndUnwanted.accesskey;" />
</vbox>
</vbox>
</groupbox>
<!-- Passwords -->
<groupbox id="passwordsGroup" orient="vertical" data-category="paneSecurity" hidden="true">
<caption><label>&logins.label;</label></caption>
<hbox id="savePasswordsBox">
<checkbox id="savePasswords"
label="&rememberLogins.label;" accesskey="&rememberLogins.accesskey;"
preference="signon.rememberSignons"
onsyncfrompreference="return gSecurityPane.readSavePasswords();"/>
<spacer flex="1"/>
<button id="passwordExceptions"
label="&passwordExceptions.label;"
accesskey="&passwordExceptions.accesskey;"
preference="pref.privacy.disable_button.view_passwords_exceptions"/>
</hbox>
<grid id="passwordGrid">
<columns>
<column flex="1"/>
<column/>
</columns>
<rows id="passwordRows">
<row id="masterPasswordRow">
<hbox id="masterPasswordBox">
<checkbox id="useMasterPassword"
label="&useMasterPassword.label;"
accesskey="&useMasterPassword.accesskey;"/>
<spacer flex="1"/>
</hbox>
<button id="changeMasterPassword"
label="&changeMasterPassword.label;"
accesskey="&changeMasterPassword.accesskey;"/>
</row>
<row id="showPasswordRow">
<hbox id="showPasswordsBox"/>
<button id="showPasswords"
label="&savedLogins.label;" accesskey="&savedLogins.accesskey;"
preference="pref.privacy.disable_button.view_passwords"/>
</row>
</rows>
</grid>
</groupbox>

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

@ -0,0 +1,438 @@
/* - This Source Code Form is subject to the terms of the Mozilla Public
- 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/. */
/* import-globals-from ../../../base/content/utilityOverlay.js */
/* import-globals-from preferences.js */
"use strict";
var gSubDialog = {
_closingCallback: null,
_closingEvent: null,
_isClosing: false,
_frame: null,
_overlay: null,
_box: null,
_openedURL: null,
_injectedStyleSheets: [
"chrome://browser/skin/preferences/preferences.css",
"chrome://global/skin/in-content-old/common.css",
"chrome://browser/skin/preferences/in-content-old/preferences.css",
"chrome://browser/skin/preferences/in-content-old/dialog.css",
],
_resizeObserver: null,
init() {
this._frame = document.getElementById("dialogFrame");
this._overlay = document.getElementById("dialogOverlay");
this._box = document.getElementById("dialogBox");
this._closeButton = document.getElementById("dialogClose");
},
updateTitle(aEvent) {
if (aEvent.target != gSubDialog._frame.contentDocument)
return;
document.getElementById("dialogTitle").textContent = gSubDialog._frame.contentDocument.title;
},
injectXMLStylesheet(aStylesheetURL) {
let contentStylesheet = this._frame.contentDocument.createProcessingInstruction(
"xml-stylesheet",
'href="' + aStylesheetURL + '" type="text/css"'
);
this._frame.contentDocument.insertBefore(contentStylesheet,
this._frame.contentDocument.documentElement);
},
open(aURL, aFeatures = null, aParams = null, aClosingCallback = null) {
// If we're already open/opening on this URL, do nothing.
if (this._openedURL == aURL && !this._isClosing) {
return;
}
// If we're open on some (other) URL or we're closing, open when closing has finished.
if (this._openedURL || this._isClosing) {
if (!this._isClosing) {
this.close();
}
let args = Array.from(arguments);
this._closingPromise.then(() => {
this.open.apply(this, args);
});
return;
}
this._addDialogEventListeners();
let features = (aFeatures ? aFeatures + "," : "") + "resizable,dialog=no,centerscreen";
let dialog = window.openDialog(aURL, "dialogFrame", features, aParams);
if (aClosingCallback) {
this._closingCallback = aClosingCallback.bind(dialog);
}
this._closingEvent = null;
this._isClosing = false;
this._openedURL = aURL;
features = features.replace(/,/g, "&");
let featureParams = new URLSearchParams(features.toLowerCase());
this._box.setAttribute("resizable", featureParams.has("resizable") &&
featureParams.get("resizable") != "no" &&
featureParams.get("resizable") != "0");
},
close(aEvent = null) {
if (this._isClosing) {
return;
}
this._isClosing = true;
this._closingPromise = new Promise(resolve => {
this._resolveClosePromise = resolve;
});
if (this._closingCallback) {
try {
this._closingCallback.call(null, aEvent);
} catch (ex) {
Cu.reportError(ex);
}
this._closingCallback = null;
}
this._removeDialogEventListeners();
this._overlay.style.visibility = "";
// Clear the sizing inline styles.
this._frame.removeAttribute("style");
// Clear the sizing attributes
this._box.removeAttribute("width");
this._box.removeAttribute("height");
this._box.style.removeProperty("min-height");
this._box.style.removeProperty("min-width");
setTimeout(() => {
// Unload the dialog after the event listeners run so that the load of about:blank isn't
// cancelled by the ESC <key>.
let onBlankLoad = e => {
if (this._frame.contentWindow.location.href == "about:blank") {
this._frame.removeEventListener("load", onBlankLoad);
// We're now officially done closing, so update the state to reflect that.
this._openedURL = null;
this._isClosing = false;
this._resolveClosePromise();
}
};
this._frame.addEventListener("load", onBlankLoad);
this._frame.loadURI("about:blank");
}, 0);
},
handleEvent(aEvent) {
switch (aEvent.type) {
case "command":
this._frame.contentWindow.close();
break;
case "dialogclosing":
this._onDialogClosing(aEvent);
break;
case "DOMTitleChanged":
this.updateTitle(aEvent);
break;
case "DOMFrameContentLoaded":
this._onContentLoaded(aEvent);
break;
case "load":
this._onLoad(aEvent);
break;
case "unload":
this._onUnload(aEvent);
break;
case "keydown":
this._onKeyDown(aEvent);
break;
case "focus":
this._onParentWinFocus(aEvent);
break;
}
},
/* Private methods */
_onUnload(aEvent) {
if (aEvent.target.location.href == this._openedURL) {
this._frame.contentWindow.close();
}
},
_onContentLoaded(aEvent) {
if (aEvent.target != this._frame || aEvent.target.contentWindow.location == "about:blank") {
return;
}
for (let styleSheetURL of this._injectedStyleSheets) {
this.injectXMLStylesheet(styleSheetURL);
}
// Provide the ability for the dialog to know that it is being loaded "in-content".
this._frame.contentDocument.documentElement.setAttribute("subdialog", "true");
this._frame.contentWindow.addEventListener("dialogclosing", this);
let oldResizeBy = this._frame.contentWindow.resizeBy;
this._frame.contentWindow.resizeBy = function(resizeByWidth, resizeByHeight) {
// Only handle resizeByHeight currently.
let frameHeight = gSubDialog._frame.clientHeight;
let boxMinHeight = parseFloat(getComputedStyle(gSubDialog._box).minHeight, 10);
gSubDialog._frame.style.height = (frameHeight + resizeByHeight) + "px";
gSubDialog._box.style.minHeight = (boxMinHeight + resizeByHeight) + "px";
oldResizeBy.call(gSubDialog._frame.contentWindow, resizeByWidth, resizeByHeight);
};
// Make window.close calls work like dialog closing.
let oldClose = this._frame.contentWindow.close;
this._frame.contentWindow.close = function() {
var closingEvent = gSubDialog._closingEvent;
if (!closingEvent) {
closingEvent = new CustomEvent("dialogclosing", {
bubbles: true,
detail: { button: null },
});
gSubDialog._frame.contentWindow.dispatchEvent(closingEvent);
}
gSubDialog.close(closingEvent);
oldClose.call(gSubDialog._frame.contentWindow);
};
// XXX: Hack to make focus during the dialog's load functions work. Make the element visible
// sooner in DOMContentLoaded but mostly invisible instead of changing visibility just before
// the dialog's load event.
this._overlay.style.visibility = "visible";
this._overlay.style.opacity = "0.01";
},
_onLoad(aEvent) {
if (aEvent.target.contentWindow.location == "about:blank") {
return;
}
// Do this on load to wait for the CSS to load and apply before calculating the size.
let docEl = this._frame.contentDocument.documentElement;
let groupBoxTitle = document.getAnonymousElementByAttribute(this._box, "class", "groupbox-title");
let groupBoxTitleHeight = groupBoxTitle.clientHeight +
parseFloat(getComputedStyle(groupBoxTitle).borderBottomWidth);
let groupBoxBody = document.getAnonymousElementByAttribute(this._box, "class", "groupbox-body");
// These are deduced from styles which we don't change, so it's safe to get them now:
let boxVerticalPadding = 2 * parseFloat(getComputedStyle(groupBoxBody).paddingTop);
let boxHorizontalPadding = 2 * parseFloat(getComputedStyle(groupBoxBody).paddingLeft);
let boxHorizontalBorder = 2 * parseFloat(getComputedStyle(this._box).borderLeftWidth);
let boxVerticalBorder = 2 * parseFloat(getComputedStyle(this._box).borderTopWidth);
// The difference between the frame and box shouldn't change, either:
let boxRect = this._box.getBoundingClientRect();
let frameRect = this._frame.getBoundingClientRect();
let frameSizeDifference = (frameRect.top - boxRect.top) + (boxRect.bottom - frameRect.bottom);
// Then determine and set a bunch of width stuff:
let frameMinWidth = docEl.style.width || docEl.scrollWidth + "px";
let frameWidth = docEl.getAttribute("width") ? docEl.getAttribute("width") + "px" :
frameMinWidth;
this._frame.style.width = frameWidth;
this._box.style.minWidth = "calc(" +
(boxHorizontalBorder + boxHorizontalPadding) +
"px + " + frameMinWidth + ")";
// Now do the same but for the height. We need to do this afterwards because otherwise
// XUL assumes we'll optimize for height and gives us "wrong" values which then are no
// longer correct after we set the width:
let frameMinHeight = docEl.style.height || docEl.scrollHeight + "px";
let frameHeight = docEl.getAttribute("height") ? docEl.getAttribute("height") + "px" :
frameMinHeight;
// Now check if the frame height we calculated is possible at this window size,
// accounting for titlebar, padding/border and some spacing.
let maxHeight = window.innerHeight - frameSizeDifference - 30;
// Do this with a frame height in pixels...
let comparisonFrameHeight;
if (frameHeight.endsWith("em")) {
let fontSize = parseFloat(getComputedStyle(this._frame).fontSize);
comparisonFrameHeight = parseFloat(frameHeight, 10) * fontSize;
} else if (frameHeight.endsWith("px")) {
comparisonFrameHeight = parseFloat(frameHeight, 10);
} else {
Cu.reportError("This dialog (" + this._frame.contentWindow.location.href + ") " +
"set a height in non-px-non-em units ('" + frameHeight + "'), " +
"which is likely to lead to bad sizing in in-content preferences. " +
"Please consider changing this.");
comparisonFrameHeight = parseFloat(frameHeight);
}
if (comparisonFrameHeight > maxHeight) {
// If the height is bigger than that of the window, we should let the contents scroll:
frameHeight = maxHeight + "px";
frameMinHeight = maxHeight + "px";
let containers = this._frame.contentDocument.querySelectorAll(".largeDialogContainer");
for (let container of containers) {
container.classList.add("doScroll");
}
}
this._frame.style.height = frameHeight;
this._box.style.minHeight = "calc(" +
(boxVerticalBorder + groupBoxTitleHeight + boxVerticalPadding) +
"px + " + frameMinHeight + ")";
this._overlay.style.visibility = "visible";
this._overlay.style.opacity = ""; // XXX: focus hack continued from _onContentLoaded
if (this._box.getAttribute("resizable") == "true") {
this._resizeObserver = new MutationObserver(this._onResize);
this._resizeObserver.observe(this._box, {attributes: true});
}
this._trapFocus();
},
_onResize(mutations) {
let frame = gSubDialog._frame;
// The width and height styles are needed for the initial
// layout of the frame, but afterward they need to be removed
// or their presence will restrict the contents of the <browser>
// from resizing to a smaller size.
frame.style.removeProperty("width");
frame.style.removeProperty("height");
let docEl = frame.contentDocument.documentElement;
let persistedAttributes = docEl.getAttribute("persist");
if (!persistedAttributes ||
(!persistedAttributes.includes("width") &&
!persistedAttributes.includes("height"))) {
return;
}
for (let mutation of mutations) {
if (mutation.attributeName == "width") {
docEl.setAttribute("width", docEl.scrollWidth);
} else if (mutation.attributeName == "height") {
docEl.setAttribute("height", docEl.scrollHeight);
}
}
},
_onDialogClosing(aEvent) {
this._frame.contentWindow.removeEventListener("dialogclosing", this);
this._closingEvent = aEvent;
},
_onKeyDown(aEvent) {
if (aEvent.currentTarget == window && aEvent.keyCode == aEvent.DOM_VK_ESCAPE &&
!aEvent.defaultPrevented) {
this.close(aEvent);
return;
}
if (aEvent.keyCode != aEvent.DOM_VK_TAB ||
aEvent.ctrlKey || aEvent.altKey || aEvent.metaKey) {
return;
}
let fm = Services.focus;
function isLastFocusableElement(el) {
// XXXgijs unfortunately there is no way to get the last focusable element without asking
// the focus manager to move focus to it.
let rv = el == fm.moveFocus(gSubDialog._frame.contentWindow, null, fm.MOVEFOCUS_LAST, 0);
fm.setFocus(el, 0);
return rv;
}
let forward = !aEvent.shiftKey;
// check if focus is leaving the frame (incl. the close button):
if ((aEvent.target == this._closeButton && !forward) ||
(isLastFocusableElement(aEvent.originalTarget) && forward)) {
aEvent.preventDefault();
aEvent.stopImmediatePropagation();
let parentWin = this._getBrowser().ownerGlobal;
if (forward) {
fm.moveFocus(parentWin, null, fm.MOVEFOCUS_FIRST, fm.FLAG_BYKEY);
} else {
// Somehow, moving back 'past' the opening doc is not trivial. Cheat by doing it in 2 steps:
fm.moveFocus(window, null, fm.MOVEFOCUS_ROOT, fm.FLAG_BYKEY);
fm.moveFocus(parentWin, null, fm.MOVEFOCUS_BACKWARD, fm.FLAG_BYKEY);
}
}
},
_onParentWinFocus(aEvent) {
// Explicitly check for the focus target of |window| to avoid triggering this when the window
// is refocused
if (aEvent.target != this._closeButton && aEvent.target != window) {
this._closeButton.focus();
}
},
_addDialogEventListeners() {
// Make the close button work.
this._closeButton.addEventListener("command", this);
// DOMTitleChanged isn't fired on the frame, only on the chromeEventHandler
let chromeBrowser = this._getBrowser();
chromeBrowser.addEventListener("DOMTitleChanged", this, true);
// Similarly DOMFrameContentLoaded only fires on the top window
window.addEventListener("DOMFrameContentLoaded", this, true);
// Wait for the stylesheets injected during DOMContentLoaded to load before showing the dialog
// otherwise there is a flicker of the stylesheet applying.
this._frame.addEventListener("load", this);
chromeBrowser.addEventListener("unload", this, true);
// Ensure we get <esc> keypresses even if nothing in the subdialog is focusable
// (happens on OS X when only text inputs and lists are focusable, and
// the subdialog only has checkboxes/radiobuttons/buttons)
window.addEventListener("keydown", this, true);
},
_removeDialogEventListeners() {
let chromeBrowser = this._getBrowser();
chromeBrowser.removeEventListener("DOMTitleChanged", this, true);
chromeBrowser.removeEventListener("unload", this, true);
this._closeButton.removeEventListener("command", this);
window.removeEventListener("DOMFrameContentLoaded", this, true);
this._frame.removeEventListener("load", this);
this._frame.contentWindow.removeEventListener("dialogclosing", this);
window.removeEventListener("keydown", this, true);
if (this._resizeObserver) {
this._resizeObserver.disconnect();
this._resizeObserver = null;
}
this._untrapFocus();
},
_trapFocus() {
let fm = Services.focus;
fm.moveFocus(this._frame.contentWindow, null, fm.MOVEFOCUS_FIRST, 0);
this._frame.contentDocument.addEventListener("keydown", this, true);
this._closeButton.addEventListener("keydown", this);
window.addEventListener("focus", this, true);
},
_untrapFocus() {
this._frame.contentDocument.removeEventListener("keydown", this, true);
this._closeButton.removeEventListener("keydown", this);
window.removeEventListener("focus", this);
},
_getBrowser() {
return window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell)
.chromeEventHandler;
},
};

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

@ -0,0 +1,492 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
/* import-globals-from preferences.js */
Components.utils.import("resource://services-sync/main.js");
Components.utils.import("resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyGetter(this, "FxAccountsCommon", function() {
return Components.utils.import("resource://gre/modules/FxAccountsCommon.js", {});
});
XPCOMUtils.defineLazyModuleGetter(this, "fxAccounts",
"resource://gre/modules/FxAccounts.jsm");
const FXA_PAGE_LOGGED_OUT = 0;
const FXA_PAGE_LOGGED_IN = 1;
// Indexes into the "login status" deck.
// We are in a successful verified state - everything should work!
const FXA_LOGIN_VERIFIED = 0;
// We have logged in to an unverified account.
const FXA_LOGIN_UNVERIFIED = 1;
// We are logged in locally, but the server rejected our credentials.
const FXA_LOGIN_FAILED = 2;
var gSyncPane = {
prefArray: ["engine.bookmarks", "engine.passwords", "engine.prefs",
"engine.tabs", "engine.history"],
get page() {
return document.getElementById("weavePrefsDeck").selectedIndex;
},
set page(val) {
document.getElementById("weavePrefsDeck").selectedIndex = val;
},
init() {
this._setupEventListeners();
// If the Service hasn't finished initializing, wait for it.
let xps = Components.classes["@mozilla.org/weave/service;1"]
.getService(Components.interfaces.nsISupports)
.wrappedJSObject;
if (xps.ready) {
this._init();
return;
}
// it may take some time before we can determine what provider to use
// and the state of that provider, so show the "please wait" page.
this._showLoadPage(xps);
let onUnload = function() {
window.removeEventListener("unload", onUnload);
try {
Services.obs.removeObserver(onReady, "weave:service:ready");
} catch (e) {}
};
let onReady = function() {
Services.obs.removeObserver(onReady, "weave:service:ready");
window.removeEventListener("unload", onUnload);
this._init();
}.bind(this);
Services.obs.addObserver(onReady, "weave:service:ready", false);
window.addEventListener("unload", onUnload);
xps.ensureLoaded();
},
_showLoadPage(xps) {
let username = Services.prefs.getCharPref("services.sync.username", "");
if (!username) {
this.page = FXA_PAGE_LOGGED_OUT;
return;
}
// Use cached values while we wait for the up-to-date values
let cachedComputerName = Services.prefs.getCharPref("services.sync.client.name", "");
document.getElementById("fxaEmailAddress1").textContent = username;
this._populateComputerName(cachedComputerName);
this.page = FXA_PAGE_LOGGED_IN;
},
_init() {
let topics = ["weave:service:login:error",
"weave:service:login:finish",
"weave:service:start-over:finish",
"weave:service:setup-complete",
"weave:service:logout:finish",
FxAccountsCommon.ONVERIFIED_NOTIFICATION,
FxAccountsCommon.ONLOGIN_NOTIFICATION,
FxAccountsCommon.ON_PROFILE_CHANGE_NOTIFICATION,
];
// Add the observers now and remove them on unload
// XXXzpao This should use Services.obs.* but Weave's Obs does nice handling
// of `this`. Fix in a followup. (bug 583347)
topics.forEach(function(topic) {
Weave.Svc.Obs.add(topic, this.updateWeavePrefs, this);
}, this);
window.addEventListener("unload", function() {
topics.forEach(function(topic) {
Weave.Svc.Obs.remove(topic, this.updateWeavePrefs, this);
}, gSyncPane);
});
XPCOMUtils.defineLazyGetter(this, "_accountsStringBundle", () => {
return Services.strings.createBundle("chrome://browser/locale/accounts.properties");
});
let url = Services.prefs.getCharPref("identity.mobilepromo.android") + "sync-preferences";
document.getElementById("fxaMobilePromo-android").setAttribute("href", url);
document.getElementById("fxaMobilePromo-android-hasFxaAccount").setAttribute("href", url);
url = Services.prefs.getCharPref("identity.mobilepromo.ios") + "sync-preferences";
document.getElementById("fxaMobilePromo-ios").setAttribute("href", url);
document.getElementById("fxaMobilePromo-ios-hasFxaAccount").setAttribute("href", url);
document.getElementById("tosPP-small-ToS").setAttribute("href", Weave.Svc.Prefs.get("fxa.termsURL"));
document.getElementById("tosPP-small-PP").setAttribute("href", Weave.Svc.Prefs.get("fxa.privacyURL"));
fxAccounts.promiseAccountsManageURI(this._getEntryPoint()).then(accountsManageURI => {
document.getElementById("verifiedManage").setAttribute("href", accountsManageURI);
});
this.updateWeavePrefs();
this._initProfileImageUI();
},
_toggleComputerNameControls(editMode) {
let textbox = document.getElementById("fxaSyncComputerName");
textbox.disabled = !editMode;
document.getElementById("fxaChangeDeviceName").hidden = editMode;
document.getElementById("fxaCancelChangeDeviceName").hidden = !editMode;
document.getElementById("fxaSaveChangeDeviceName").hidden = !editMode;
},
_focusComputerNameTextbox() {
let textbox = document.getElementById("fxaSyncComputerName");
let valLength = textbox.value.length;
textbox.focus();
textbox.setSelectionRange(valLength, valLength);
},
_blurComputerNameTextbox() {
document.getElementById("fxaSyncComputerName").blur();
},
_focusAfterComputerNameTextbox() {
// Focus the most appropriate element that's *not* the "computer name" box.
Services.focus.moveFocus(window,
document.getElementById("fxaSyncComputerName"),
Services.focus.MOVEFOCUS_FORWARD, 0);
},
_updateComputerNameValue(save) {
if (save) {
let textbox = document.getElementById("fxaSyncComputerName");
Weave.Service.clientsEngine.localName = textbox.value;
}
this._populateComputerName(Weave.Service.clientsEngine.localName);
},
_setupEventListeners() {
function setEventListener(aId, aEventType, aCallback) {
document.getElementById(aId)
.addEventListener(aEventType, aCallback.bind(gSyncPane));
}
setEventListener("fxaChangeDeviceName", "command", function() {
this._toggleComputerNameControls(true);
this._focusComputerNameTextbox();
});
setEventListener("fxaCancelChangeDeviceName", "command", function() {
// We explicitly blur the textbox because of bug 75324, then after
// changing the state of the buttons, force focus to whatever the focus
// manager thinks should be next (which on the mac, depends on an OSX
// keyboard access preference)
this._blurComputerNameTextbox();
this._toggleComputerNameControls(false);
this._updateComputerNameValue(false);
this._focusAfterComputerNameTextbox();
});
setEventListener("fxaSaveChangeDeviceName", "command", function() {
// Work around bug 75324 - see above.
this._blurComputerNameTextbox();
this._toggleComputerNameControls(false);
this._updateComputerNameValue(true);
this._focusAfterComputerNameTextbox();
});
setEventListener("noFxaSignUp", "command", function() {
gSyncPane.signUp();
return false;
});
setEventListener("noFxaSignIn", "command", function() {
gSyncPane.signIn();
return false;
});
setEventListener("fxaUnlinkButton", "command", function() {
gSyncPane.unlinkFirefoxAccount(true);
});
setEventListener("verifyFxaAccount", "command",
gSyncPane.verifyFirefoxAccount);
setEventListener("unverifiedUnlinkFxaAccount", "command", function() {
/* no warning as account can't have previously synced */
gSyncPane.unlinkFirefoxAccount(false);
});
setEventListener("rejectReSignIn", "command",
gSyncPane.reSignIn);
setEventListener("rejectUnlinkFxaAccount", "command", function() {
gSyncPane.unlinkFirefoxAccount(true);
});
setEventListener("fxaSyncComputerName", "keypress", function(e) {
if (e.keyCode == KeyEvent.DOM_VK_RETURN) {
document.getElementById("fxaSaveChangeDeviceName").click();
} else if (e.keyCode == KeyEvent.DOM_VK_ESCAPE) {
document.getElementById("fxaCancelChangeDeviceName").click();
}
});
},
_initProfileImageUI() {
try {
if (Services.prefs.getBoolPref("identity.fxaccounts.profile_image.enabled")) {
document.getElementById("fxaProfileImage").hidden = false;
}
} catch (e) { }
},
updateWeavePrefs() {
let service = Components.classes["@mozilla.org/weave/service;1"]
.getService(Components.interfaces.nsISupports)
.wrappedJSObject;
let displayNameLabel = document.getElementById("fxaDisplayName");
let fxaEmailAddress1Label = document.getElementById("fxaEmailAddress1");
fxaEmailAddress1Label.hidden = false;
displayNameLabel.hidden = true;
let profileInfoEnabled = Services.prefs.getBoolPref("identity.fxaccounts.profile_image.enabled", false);
// determine the fxa status...
this._showLoadPage(service);
fxAccounts.getSignedInUser().then(data => {
if (!data) {
this.page = FXA_PAGE_LOGGED_OUT;
return false;
}
this.page = FXA_PAGE_LOGGED_IN;
// We are logged in locally, but maybe we are in a state where the
// server rejected our credentials (eg, password changed on the server)
let fxaLoginStatus = document.getElementById("fxaLoginStatus");
let syncReady;
// Not Verfied implies login error state, so check that first.
if (!data.verified) {
fxaLoginStatus.selectedIndex = FXA_LOGIN_UNVERIFIED;
syncReady = false;
// So we think we are logged in, so login problems are next.
// (Although if the Sync identity manager is still initializing, we
// ignore login errors and assume all will eventually be good.)
// LOGIN_FAILED_LOGIN_REJECTED explicitly means "you must log back in".
// All other login failures are assumed to be transient and should go
// away by themselves, so aren't reflected here.
} else if (Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED) {
fxaLoginStatus.selectedIndex = FXA_LOGIN_FAILED;
syncReady = false;
// Else we must be golden (or in an error state we expect to magically
// resolve itself)
} else {
fxaLoginStatus.selectedIndex = FXA_LOGIN_VERIFIED;
syncReady = true;
}
fxaEmailAddress1Label.textContent = data.email;
document.getElementById("fxaEmailAddress2").textContent = data.email;
document.getElementById("fxaEmailAddress3").textContent = data.email;
this._populateComputerName(Weave.Service.clientsEngine.localName);
let engines = document.getElementById("fxaSyncEngines")
for (let checkbox of engines.querySelectorAll("checkbox")) {
checkbox.disabled = !syncReady;
}
document.getElementById("fxaChangeDeviceName").disabled = !syncReady;
// Clear the profile image (if any) of the previously logged in account.
document.getElementById("fxaProfileImage").style.removeProperty("list-style-image");
// If the account is verified the next promise in the chain will
// fetch profile data.
return data.verified;
}).then(isVerified => {
if (isVerified) {
return fxAccounts.getSignedInUserProfile();
}
return null;
}).then(data => {
let fxaLoginStatus = document.getElementById("fxaLoginStatus");
if (data && profileInfoEnabled) {
if (data.displayName) {
fxaLoginStatus.setAttribute("hasName", true);
displayNameLabel.hidden = false;
displayNameLabel.textContent = data.displayName;
} else {
fxaLoginStatus.removeAttribute("hasName");
}
if (data.avatar) {
let bgImage = "url(\"" + data.avatar + "\")";
let profileImageElement = document.getElementById("fxaProfileImage");
profileImageElement.style.listStyleImage = bgImage;
let img = new Image();
img.onerror = () => {
// Clear the image if it has trouble loading. Since this callback is asynchronous
// we check to make sure the image is still the same before we clear it.
if (profileImageElement.style.listStyleImage === bgImage) {
profileImageElement.style.removeProperty("list-style-image");
}
};
img.src = data.avatar;
}
} else {
fxaLoginStatus.removeAttribute("hasName");
}
}, err => {
FxAccountsCommon.log.error(err);
}).catch(err => {
// If we get here something's really busted
Cu.reportError(String(err));
});
},
_getEntryPoint() {
let params = new URLSearchParams(document.URL.split("#")[0].split("?")[1] || "");
return params.get("entrypoint") || "preferences";
},
_openAboutAccounts(action) {
let entryPoint = this._getEntryPoint();
let params = new URLSearchParams();
if (action) {
params.set("action", action);
}
params.set("entrypoint", entryPoint);
this.replaceTabWithUrl("about:accounts?" + params);
},
openContentInBrowser(url, options) {
let win = Services.wm.getMostRecentWindow("navigator:browser");
if (!win) {
openUILinkIn(url, "tab");
return;
}
win.switchToTabHavingURI(url, true, options);
},
// Replace the current tab with the specified URL.
replaceTabWithUrl(url) {
// Get the <browser> element hosting us.
let browser = window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell)
.chromeEventHandler;
// And tell it to load our URL.
browser.loadURI(url);
},
signUp() {
this._openAboutAccounts("signup");
},
signIn() {
this._openAboutAccounts("signin");
},
reSignIn() {
this._openAboutAccounts("reauth");
},
clickOrSpaceOrEnterPressed(event) {
// Note: charCode is deprecated, but 'char' not yet implemented.
// Replace charCode with char when implemented, see Bug 680830
return ((event.type == "click" && event.button == 0) ||
(event.type == "keypress" &&
(event.charCode == KeyEvent.DOM_VK_SPACE || event.keyCode == KeyEvent.DOM_VK_RETURN)));
},
openChangeProfileImage(event) {
if (this.clickOrSpaceOrEnterPressed(event)) {
fxAccounts.promiseAccountsChangeProfileURI(this._getEntryPoint(), "avatar")
.then(url => {
this.openContentInBrowser(url, {
replaceQueryString: true
});
});
// Prevent page from scrolling on the space key.
event.preventDefault();
}
},
openManageFirefoxAccount(event) {
if (this.clickOrSpaceOrEnterPressed(event)) {
this.manageFirefoxAccount();
// Prevent page from scrolling on the space key.
event.preventDefault();
}
},
manageFirefoxAccount() {
fxAccounts.promiseAccountsManageURI(this._getEntryPoint())
.then(url => {
this.openContentInBrowser(url, {
replaceQueryString: true
});
});
},
verifyFirefoxAccount() {
let showVerifyNotification = (data) => {
let isError = !data;
let maybeNot = isError ? "Not" : "";
let sb = this._accountsStringBundle;
let title = sb.GetStringFromName("verification" + maybeNot + "SentTitle");
let email = !isError && data ? data.email : "";
let body = sb.formatStringFromName("verification" + maybeNot + "SentBody", [email], 1);
new Notification(title, { body })
}
let onError = () => {
showVerifyNotification();
};
let onSuccess = data => {
if (data) {
showVerifyNotification(data);
} else {
onError();
}
};
fxAccounts.resendVerificationEmail()
.then(fxAccounts.getSignedInUser, onError)
.then(onSuccess, onError);
},
unlinkFirefoxAccount(confirm) {
if (confirm) {
// We use a string bundle shared with aboutAccounts.
let sb = Services.strings.createBundle("chrome://browser/locale/syncSetup.properties");
let disconnectLabel = sb.GetStringFromName("disconnect.label");
let title = sb.GetStringFromName("disconnect.verify.title");
let body = sb.GetStringFromName("disconnect.verify.bodyHeading") +
"\n\n" +
sb.GetStringFromName("disconnect.verify.bodyText");
let ps = Services.prompt;
let buttonFlags = (ps.BUTTON_POS_0 * ps.BUTTON_TITLE_IS_STRING) +
(ps.BUTTON_POS_1 * ps.BUTTON_TITLE_CANCEL) +
ps.BUTTON_POS_1_DEFAULT;
let factory = Cc["@mozilla.org/prompter;1"]
.getService(Ci.nsIPromptFactory);
let prompt = factory.getPrompt(window, Ci.nsIPrompt);
let bag = prompt.QueryInterface(Ci.nsIWritablePropertyBag2);
bag.setPropertyAsBool("allowTabModal", true);
let pressed = prompt.confirmEx(title, body, buttonFlags,
disconnectLabel, null, null, null, {});
if (pressed != 0) { // 0 is the "continue" button
return;
}
}
fxAccounts.signOut().then(() => {
this.updateWeavePrefs();
});
},
_populateComputerName(value) {
let textbox = document.getElementById("fxaSyncComputerName");
if (!textbox.hasAttribute("placeholder")) {
textbox.setAttribute("placeholder",
Weave.Utils.getDefaultDeviceName());
}
textbox.value = value;
},
};

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

@ -0,0 +1,225 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# 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/.
<!-- Sync panel -->
<preferences id="syncEnginePrefs" hidden="true" data-category="paneSync">
<preference id="engine.addons"
name="services.sync.engine.addons"
type="bool"/>
<preference id="engine.bookmarks"
name="services.sync.engine.bookmarks"
type="bool"/>
<preference id="engine.history"
name="services.sync.engine.history"
type="bool"/>
<preference id="engine.tabs"
name="services.sync.engine.tabs"
type="bool"/>
<preference id="engine.prefs"
name="services.sync.engine.prefs"
type="bool"/>
<preference id="engine.passwords"
name="services.sync.engine.passwords"
type="bool"/>
</preferences>
<script type="application/javascript"
src="chrome://browser/content/preferences/in-content-old/sync.js"/>
<hbox id="header-sync"
class="header"
hidden="true"
data-category="paneSync">
<label class="header-name" flex="1">&paneSync.title;</label>
<html:a class="help-button text-link" target="_blank" aria-label="&helpButton.label;"></html:a>
</hbox>
<deck id="weavePrefsDeck" data-category="paneSync" hidden="true">
<vbox id="noFxaAccount">
<hbox>
<vbox id="fxaContentWrapper">
<groupbox id="noFxaGroup">
<vbox>
<label id="noFxaCaption">&signedOut.caption;</label>
<description id="noFxaDescription" flex="1">&signedOut.description;</description>
<hbox class="fxaAccountBox">
<vbox>
<image class="fxaFirefoxLogo"/>
</vbox>
<vbox flex="1">
<label id="signedOutAccountBoxTitle">&signedOut.accountBox.title;</label>
<hbox class="fxaAccountBoxButtons">
<button id="noFxaSignUp" label="&signedOut.accountBox.create;" accesskey="&signedOut.accountBox.create.accesskey;"></button>
<button id="noFxaSignIn" label="&signedOut.accountBox.signin;" accesskey="&signedOut.accountBox.signin.accesskey;"></button>
</hbox>
</vbox>
</hbox>
</vbox>
</groupbox>
</vbox>
<vbox>
<html:img class="fxaSyncIllustration" src="chrome://browser/skin/fxa/sync-illustration.svg#blueFill"/>
</vbox>
</hbox>
<label class="fxaMobilePromo">
&mobilePromo3.start;<!-- We put these comments to avoid inserting white spaces
--><label id="fxaMobilePromo-android"
class="androidLink text-link"><!--
-->&mobilePromo3.androidLink;</label><!--
-->&mobilePromo3.iOSBefore;<!--
--><label id="fxaMobilePromo-ios"
class="iOSLink text-link"><!--
-->&mobilePromo3.iOSLink;</label><!--
-->&mobilePromo3.end;
</label>
</vbox>
<vbox id="hasFxaAccount">
<hbox>
<vbox id="fxaContentWrapper">
<groupbox id="fxaGroup">
<caption><label>&syncBrand.fxAccount.label;</label></caption>
<deck id="fxaLoginStatus">
<!-- logged in and verified and all is good -->
<hbox id="fxaLoginVerified" class="fxaAccountBox">
<vbox align="center" pack="center">
<image id="fxaProfileImage" class="actionable"
role="button"
onclick="gSyncPane.openChangeProfileImage(event);" hidden="true"
onkeypress="gSyncPane.openChangeProfileImage(event);"
tooltiptext="&profilePicture.tooltip;"/>
</vbox>
<vbox flex="1" pack="center">
<label id="fxaDisplayName" hidden="true"/>
<label id="fxaEmailAddress1"/>
<hbox class="fxaAccountBoxButtons">
<button id="fxaUnlinkButton" label="&disconnect.label;" accesskey="&disconnect.accesskey;"/>
<html:a id="verifiedManage" target="_blank"
accesskey="&verifiedManage.accesskey;"
onkeypress="gSyncPane.openManageFirefoxAccount(event);"><!--
-->&verifiedManage.label;</html:a>
</hbox>
</vbox>
</hbox>
<!-- logged in to an unverified account -->
<hbox id="fxaLoginUnverified" class="fxaAccountBox">
<vbox>
<image id="fxaProfileImage"/>
</vbox>
<vbox flex="1">
<hbox>
<vbox><image id="fxaLoginRejectedWarning"/></vbox>
<description flex="1">
&signedInUnverified.beforename.label;
<label id="fxaEmailAddress2"/>
&signedInUnverified.aftername.label;
</description>
</hbox>
<hbox class="fxaAccountBoxButtons">
<button id="verifyFxaAccount" label="&verify.label;" accesskey="&verify.accesskey;"></button>
<button id="unverifiedUnlinkFxaAccount" label="&forget.label;" accesskey="&forget.accesskey;"></button>
</hbox>
</vbox>
</hbox>
<!-- logged in locally but server rejected credentials -->
<hbox id="fxaLoginRejected" class="fxaAccountBox">
<vbox>
<image id="fxaProfileImage"/>
</vbox>
<vbox flex="1">
<hbox>
<vbox><image id="fxaLoginRejectedWarning"/></vbox>
<description flex="1">
&signedInLoginFailure.beforename.label;
<label id="fxaEmailAddress3"/>
&signedInLoginFailure.aftername.label;
</description>
</hbox>
<hbox class="fxaAccountBoxButtons">
<button id="rejectReSignIn" label="&signIn.label;" accesskey="&signIn.accesskey;"></button>
<button id="rejectUnlinkFxaAccount" label="&forget.label;" accesskey="&forget.accesskey;"></button>
</hbox>
</vbox>
</hbox>
</deck>
</groupbox>
<groupbox id="syncOptions">
<caption><label>&signedIn.engines.label;</label></caption>
<hbox id="fxaSyncEngines">
<vbox align="start" flex="1">
<checkbox label="&engine.tabs.label2;"
accesskey="&engine.tabs.accesskey;"
preference="engine.tabs"/>
<checkbox label="&engine.bookmarks.label;"
accesskey="&engine.bookmarks.accesskey;"
preference="engine.bookmarks"/>
<checkbox label="&engine.passwords.label;"
accesskey="&engine.passwords.accesskey;"
preference="engine.passwords"/>
</vbox>
<vbox align="start" flex="1">
<checkbox label="&engine.history.label;"
accesskey="&engine.history.accesskey;"
preference="engine.history"/>
<checkbox label="&engine.addons.label;"
accesskey="&engine.addons.accesskey;"
preference="engine.addons"/>
<checkbox label="&engine.prefs.label;"
accesskey="&engine.prefs.accesskey;"
preference="engine.prefs"/>
</vbox>
<spacer/>
</hbox>
</groupbox>
</vbox>
<vbox>
<html:img class="fxaSyncIllustration" src="chrome://browser/skin/fxa/sync-illustration.svg#blueFill"/>
</vbox>
</hbox>
<groupbox>
<caption>
<label control="fxaSyncComputerName">
&fxaSyncDeviceName.label;
</label>
</caption>
<hbox id="fxaDeviceName">
<textbox id="fxaSyncComputerName" disabled="true"/>
<hbox>
<button id="fxaChangeDeviceName"
label="&changeSyncDeviceName.label;"
accesskey="&changeSyncDeviceName.accesskey;"/>
<button id="fxaCancelChangeDeviceName"
label="&cancelChangeSyncDeviceName.label;"
accesskey="&cancelChangeSyncDeviceName.accesskey;"
hidden="true"/>
<button id="fxaSaveChangeDeviceName"
label="&saveChangeSyncDeviceName.label;"
accesskey="&saveChangeSyncDeviceName.accesskey;"
hidden="true"/>
</hbox>
</hbox>
</groupbox>
<label class="fxaMobilePromo">
&mobilePromo3.start;<!-- We put these comments to avoid inserting white spaces
--><label class="androidLink text-link" id="fxaMobilePromo-android-hasFxaAccount"><!--
-->&mobilePromo3.androidLink;</label><!--
-->&mobilePromo3.iOSBefore;<!--
--><label class="iOSLink text-link" id="fxaMobilePromo-ios-hasFxaAccount"><!--
-->&mobilePromo3.iOSLink;</label><!--
-->&mobilePromo3.end;
</label>
<vbox id="tosPP-small" align="start">
<label id="tosPP-small-ToS" class="text-link">
&prefs.tosLink.label;
</label>
<label id="tosPP-small-PP" class="text-link">
&fxaPrivacyNotice.link.label;
</label>
</vbox>
</vbox>
</deck>

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

@ -0,0 +1,7 @@
"use strict";
module.exports = {
"extends": [
"plugin:mozilla/browser-test"
]
};

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

@ -0,0 +1,47 @@
[DEFAULT]
support-files =
head.js
privacypane_tests_perwindow.js
site_data_test.html
[browser_applications_selection.js]
[browser_advanced_siteData.js]
[browser_advanced_update.js]
skip-if = !updater
[browser_basic_rebuild_fonts_test.js]
[browser_bug410900.js]
[browser_bug705422.js]
[browser_bug731866.js]
[browser_bug795764_cachedisabled.js]
[browser_bug1018066_resetScrollPosition.js]
[browser_bug1020245_openPreferences_to_paneContent.js]
[browser_bug1184989_prevent_scrolling_when_preferences_flipped.js]
support-files =
browser_bug1184989_prevent_scrolling_when_preferences_flipped.xul
[browser_change_app_handler.js]
skip-if = os != "win" # This test tests the windows-specific app selection dialog, so can't run on non-Windows
[browser_connection.js]
[browser_connection_bug388287.js]
[browser_cookies_exceptions.js]
[browser_defaultbrowser_alwayscheck.js]
[browser_healthreport.js]
skip-if = true || !healthreport # Bug 1185403 for the "true"
[browser_homepages_filter_aboutpreferences.js]
[browser_notifications_do_not_disturb.js]
[browser_permissions_urlFieldHidden.js]
[browser_proxy_backup.js]
[browser_privacypane_1.js]
[browser_privacypane_3.js]
[browser_privacypane_4.js]
[browser_privacypane_5.js]
[browser_privacypane_8.js]
[browser_sanitizeOnShutdown_prefLocked.js]
[browser_searchsuggestions.js]
[browser_security.js]
[browser_subdialogs.js]
support-files =
subdialog.xul
subdialog2.xul
[browser_telemetry.js]
# Skip this test on Android as FHR and Telemetry are separate systems there.
skip-if = !healthreport || !telemetry || (os == 'linux' && debug) || (os == 'android')

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

@ -0,0 +1,649 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
/* import-globals-from ../../../../../testing/modules/sinon-1.16.1.js */
Services.scriptloader.loadSubScript("resource://testing-common/sinon-1.16.1.js");
const TEST_HOST = "example.com";
const TEST_ORIGIN = "http://" + TEST_HOST;
const TEST_BASE_URL = TEST_ORIGIN + "/browser/browser/components/preferences/in-content-old/tests/";
const REMOVE_DIALOG_URL = "chrome://browser/content/preferences/siteDataRemoveSelected.xul";
const { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm", {});
const { SiteDataManager } = Cu.import("resource:///modules/SiteDataManager.jsm", {});
const { OfflineAppCacheHelper } = Cu.import("resource:///modules/offlineAppCache.jsm", {});
const mockOfflineAppCacheHelper = {
clear: null,
originalClear: null,
register() {
this.originalClear = OfflineAppCacheHelper.clear;
this.clear = sinon.spy();
OfflineAppCacheHelper.clear = this.clear;
},
unregister() {
OfflineAppCacheHelper.clear = this.originalClear;
}
};
const mockSiteDataManager = {
sites: new Map([
[
"https://account.xyz.com/",
{
usage: 1024 * 200,
host: "account.xyz.com",
status: Ci.nsIPermissionManager.ALLOW_ACTION
}
],
[
"https://shopping.xyz.com/",
{
usage: 1024 * 100,
host: "shopping.xyz.com",
status: Ci.nsIPermissionManager.DENY_ACTION
}
],
[
"https://video.bar.com/",
{
usage: 1024 * 20,
host: "video.bar.com",
status: Ci.nsIPermissionManager.ALLOW_ACTION
}
],
[
"https://music.bar.com/",
{
usage: 1024 * 10,
host: "music.bar.com",
status: Ci.nsIPermissionManager.DENY_ACTION
}
],
[
"https://books.foo.com/",
{
usage: 1024 * 2,
host: "books.foo.com",
status: Ci.nsIPermissionManager.ALLOW_ACTION
}
],
[
"https://news.foo.com/",
{
usage: 1024,
host: "news.foo.com",
status: Ci.nsIPermissionManager.DENY_ACTION
}
]
]),
_originalGetSites: null,
getSites() {
let list = [];
this.sites.forEach((data, origin) => {
list.push({
usage: data.usage,
status: data.status,
uri: NetUtil.newURI(origin)
});
});
return Promise.resolve(list);
},
register() {
this._originalGetSites = SiteDataManager.getSites;
SiteDataManager.getSites = this.getSites.bind(this);
},
unregister() {
SiteDataManager.getSites = this._originalGetSites;
}
};
function addPersistentStoragePerm(origin) {
let uri = NetUtil.newURI(origin);
let principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {});
Services.perms.addFromPrincipal(principal, "persistent-storage", Ci.nsIPermissionManager.ALLOW_ACTION);
}
function removePersistentStoragePerm(origin) {
let uri = NetUtil.newURI(origin);
let principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {});
Services.perms.removeFromPrincipal(principal, "persistent-storage");
}
function getPersistentStoragePermStatus(origin) {
let uri = NetUtil.newURI(origin);
let principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {});
return Services.perms.testExactPermissionFromPrincipal(principal, "persistent-storage");
}
function getQuotaUsage(origin) {
return new Promise(resolve => {
let uri = NetUtil.newURI(origin);
let principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {});
Services.qms.getUsageForPrincipal(principal, request => resolve(request.result.usage));
});
}
// XXX: The intermittent bug 1331851
// The implementation of nsICacheStorageConsumptionObserver must be passed as weak referenced,
// so we must hold this observer here well. If we didn't, there would be a chance that
// in Linux debug test run the observer was released before the operation at gecko was completed
// (may be because of a relatively quicker GC cycle or a relatively slower operation).
// As a result of that, we would never get the cache usage we want so the test would fail from timeout.
const cacheUsageGetter = {
_promise: null,
_resolve: null,
get() {
if (!this._promise) {
this._promise = new Promise(resolve => {
this._resolve = resolve;
Services.cache2.asyncGetDiskConsumption(this);
});
}
return this._promise;
},
// nsICacheStorageConsumptionObserver implementations
onNetworkCacheDiskConsumption(usage) {
cacheUsageGetter._promise = null;
cacheUsageGetter._resolve(usage);
},
QueryInterface: XPCOMUtils.generateQI([
Components.interfaces.nsICacheStorageConsumptionObserver,
Components.interfaces.nsISupportsWeakReference
]),
};
function openSettingsDialog() {
let doc = gBrowser.selectedBrowser.contentDocument;
let settingsBtn = doc.getElementById("siteDataSettings");
let dialogOverlay = doc.getElementById("dialogOverlay");
let dialogLoadPromise = promiseLoadSubDialog("chrome://browser/content/preferences/siteDataSettings.xul");
let dialogInitPromise = TestUtils.topicObserved("sitedata-settings-init", () => true);
let fullyLoadPromise = Promise.all([ dialogLoadPromise, dialogInitPromise ]).then(() => {
is(dialogOverlay.style.visibility, "visible", "The Settings dialog should be visible");
});
settingsBtn.doCommand();
return fullyLoadPromise;
}
function promiseSettingsDialogClose() {
return new Promise(resolve => {
let doc = gBrowser.selectedBrowser.contentDocument;
let dialogOverlay = doc.getElementById("dialogOverlay");
let win = content.gSubDialog._frame.contentWindow;
win.addEventListener("unload", function unload() {
if (win.document.documentURI === "chrome://browser/content/preferences/siteDataSettings.xul") {
isnot(dialogOverlay.style.visibility, "visible", "The Settings dialog should be hidden");
resolve();
}
}, { once: true });
});
}
function promiseSitesUpdated() {
return TestUtils.topicObserved("sitedatamanager:sites-updated", () => true);
}
function promiseCookiesCleared() {
return TestUtils.topicObserved("cookie-changed", (subj, data) => {
return data === "cleared";
});
}
function assertSitesListed(doc, origins) {
let frameDoc = doc.getElementById("dialogFrame").contentDocument;
let removeBtn = frameDoc.getElementById("removeSelected");
let removeAllBtn = frameDoc.getElementById("removeAll");
let sitesList = frameDoc.getElementById("sitesList");
let totalSitesNumber = sitesList.getElementsByTagName("richlistitem").length;
is(totalSitesNumber, origins.length, "Should list the right sites number");
origins.forEach(origin => {
let site = sitesList.querySelector(`richlistitem[data-origin="${origin}"]`);
let host = site.getAttribute("host");
ok(origin.includes(host), `Should list the site of ${origin}`);
});
is(removeBtn.disabled, false, "Should enable the removeSelected button");
is(removeAllBtn.disabled, false, "Should enable the removeAllBtn button");
}
registerCleanupFunction(function() {
delete window.sinon;
delete window.setImmediate;
delete window.clearImmediate;
mockOfflineAppCacheHelper.unregister();
});
add_task(function* () {
yield SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]});
addPersistentStoragePerm(TEST_ORIGIN);
yield BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_BASE_URL + "site_data_test.html");
yield waitForEvent(gBrowser.selectedBrowser.contentWindow, "test-indexedDB-done");
yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
yield openPreferencesViaOpenPreferencesAPI("advanced", "networkTab", { leaveOpen: true });
// Test the initial states
let cacheUsage = yield cacheUsageGetter.get();
let quotaUsage = yield getQuotaUsage(TEST_ORIGIN);
let totalUsage = yield SiteDataManager.getTotalUsage();
Assert.greater(cacheUsage, 0, "The cache usage should not be 0");
Assert.greater(quotaUsage, 0, "The quota usage should not be 0");
Assert.greater(totalUsage, 0, "The total usage should not be 0");
// Test cancelling "Clear All Data"
// Click "Clear All Data" button and then cancel
let doc = gBrowser.selectedBrowser.contentDocument;
let cancelPromise = promiseAlertDialogOpen("cancel");
let clearBtn = doc.getElementById("clearSiteDataButton");
clearBtn.doCommand();
yield cancelPromise;
// Test the items are not removed
let status = getPersistentStoragePermStatus(TEST_ORIGIN);
is(status, Ci.nsIPermissionManager.ALLOW_ACTION, "Should not remove permission");
cacheUsage = yield cacheUsageGetter.get();
quotaUsage = yield getQuotaUsage(TEST_ORIGIN);
totalUsage = yield SiteDataManager.getTotalUsage();
Assert.greater(cacheUsage, 0, "The cache usage should not be 0");
Assert.greater(quotaUsage, 0, "The quota usage should not be 0");
Assert.greater(totalUsage, 0, "The total usage should not be 0");
// Test cancelling "Clear All Data" ends
// Test accepting "Clear All Data"
// Click "Clear All Data" button and then accept
let acceptPromise = promiseAlertDialogOpen("accept");
let updatePromise = promiseSitesUpdated();
let cookiesClearedPromise = promiseCookiesCleared();
mockOfflineAppCacheHelper.register();
clearBtn.doCommand();
yield acceptPromise;
yield updatePromise;
mockOfflineAppCacheHelper.unregister();
// Test all the items are removed
yield cookiesClearedPromise;
ok(mockOfflineAppCacheHelper.clear.calledOnce, "Should clear app cache");
status = getPersistentStoragePermStatus(TEST_ORIGIN);
is(status, Ci.nsIPermissionManager.UNKNOWN_ACTION, "Should remove permission");
cacheUsage = yield cacheUsageGetter.get();
quotaUsage = yield getQuotaUsage(TEST_ORIGIN);
totalUsage = yield SiteDataManager.getTotalUsage();
is(cacheUsage, 0, "The cahce usage should be removed");
is(quotaUsage, 0, "The quota usage should be removed");
is(totalUsage, 0, "The total usage should be removed");
// Test accepting "Clear All Data" ends
yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
});
add_task(function* () {
yield SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]});
mockSiteDataManager.register();
let updatePromise = promiseSitesUpdated();
yield openPreferencesViaOpenPreferencesAPI("advanced", "networkTab", { leaveOpen: true });
yield updatePromise;
yield openSettingsDialog();
let doc = gBrowser.selectedBrowser.contentDocument;
let dialogFrame = doc.getElementById("dialogFrame");
let frameDoc = dialogFrame.contentDocument;
let hostCol = frameDoc.getElementById("hostCol");
let usageCol = frameDoc.getElementById("usageCol");
let statusCol = frameDoc.getElementById("statusCol");
let sitesList = frameDoc.getElementById("sitesList");
let mockSites = mockSiteDataManager.sites;
// Test default sorting
assertSortByHost("ascending");
// Test sorting on the host column
hostCol.click();
assertSortByHost("descending");
hostCol.click();
assertSortByHost("ascending");
// Test sorting on the permission status column
statusCol.click();
assertSortByStatus("ascending");
statusCol.click();
assertSortByStatus("descending");
// Test sorting on the usage column
usageCol.click();
assertSortByUsage("ascending");
usageCol.click();
assertSortByUsage("descending");
mockSiteDataManager.unregister();
yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
function assertSortByHost(order) {
let siteItems = sitesList.getElementsByTagName("richlistitem");
for (let i = 0; i < siteItems.length - 1; ++i) {
let aOrigin = siteItems[i].getAttribute("data-origin");
let bOrigin = siteItems[i + 1].getAttribute("data-origin");
let a = mockSites.get(aOrigin);
let b = mockSites.get(bOrigin);
let result = a.host.localeCompare(b.host);
if (order == "ascending") {
Assert.lessOrEqual(result, 0, "Should sort sites in the ascending order by host");
} else {
Assert.greaterOrEqual(result, 0, "Should sort sites in the descending order by host");
}
}
}
function assertSortByStatus(order) {
let siteItems = sitesList.getElementsByTagName("richlistitem");
for (let i = 0; i < siteItems.length - 1; ++i) {
let aOrigin = siteItems[i].getAttribute("data-origin");
let bOrigin = siteItems[i + 1].getAttribute("data-origin");
let a = mockSites.get(aOrigin);
let b = mockSites.get(bOrigin);
let result = a.status - b.status;
if (order == "ascending") {
Assert.lessOrEqual(result, 0, "Should sort sites in the ascending order by permission status");
} else {
Assert.greaterOrEqual(result, 0, "Should sort sites in the descending order by permission status");
}
}
}
function assertSortByUsage(order) {
let siteItems = sitesList.getElementsByTagName("richlistitem");
for (let i = 0; i < siteItems.length - 1; ++i) {
let aOrigin = siteItems[i].getAttribute("data-origin");
let bOrigin = siteItems[i + 1].getAttribute("data-origin");
let a = mockSites.get(aOrigin);
let b = mockSites.get(bOrigin);
let result = a.usage - b.usage;
if (order == "ascending") {
Assert.lessOrEqual(result, 0, "Should sort sites in the ascending order by usage");
} else {
Assert.greaterOrEqual(result, 0, "Should sort sites in the descending order by usage");
}
}
}
});
add_task(function* () {
yield SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]});
mockSiteDataManager.register();
let updatePromise = promiseSitesUpdated();
yield openPreferencesViaOpenPreferencesAPI("advanced", "networkTab", { leaveOpen: true });
yield updatePromise;
yield openSettingsDialog();
let doc = gBrowser.selectedBrowser.contentDocument;
let frameDoc = doc.getElementById("dialogFrame").contentDocument;
let searchBox = frameDoc.getElementById("searchBox");
let mockOrigins = Array.from(mockSiteDataManager.sites.keys());
searchBox.value = "xyz";
searchBox.doCommand();
assertSitesListed(doc, mockOrigins.filter(o => o.includes("xyz")));
searchBox.value = "bar";
searchBox.doCommand();
assertSitesListed(doc, mockOrigins.filter(o => o.includes("bar")));
searchBox.value = "";
searchBox.doCommand();
assertSitesListed(doc, mockOrigins);
mockSiteDataManager.unregister();
yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
});
// Test selecting and removing all sites one by one
add_task(function* () {
yield SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]});
let fakeOrigins = [
"https://news.foo.com/",
"https://mails.bar.com/",
"https://videos.xyz.com/",
"https://books.foo.com/",
"https://account.bar.com/",
"https://shopping.xyz.com/"
];
fakeOrigins.forEach(origin => addPersistentStoragePerm(origin));
let updatePromise = promiseSitesUpdated();
yield openPreferencesViaOpenPreferencesAPI("advanced", "networkTab", { leaveOpen: true });
yield updatePromise;
yield openSettingsDialog();
let doc = gBrowser.selectedBrowser.contentDocument;
let frameDoc = null;
let saveBtn = null;
let cancelBtn = null;
let settingsDialogClosePromise = null;
// Test the initial state
assertAllSitesListed();
// Test the "Cancel" button
settingsDialogClosePromise = promiseSettingsDialogClose();
frameDoc = doc.getElementById("dialogFrame").contentDocument;
cancelBtn = frameDoc.getElementById("cancel");
removeAllSitesOneByOne();
assertAllSitesNotListed();
cancelBtn.doCommand();
yield settingsDialogClosePromise;
yield openSettingsDialog();
assertAllSitesListed();
// Test the "Save Changes" button but cancelling save
let cancelPromise = promiseAlertDialogOpen("cancel");
settingsDialogClosePromise = promiseSettingsDialogClose();
frameDoc = doc.getElementById("dialogFrame").contentDocument;
saveBtn = frameDoc.getElementById("save");
removeAllSitesOneByOne();
assertAllSitesNotListed();
saveBtn.doCommand();
yield cancelPromise;
yield settingsDialogClosePromise;
yield openSettingsDialog();
assertAllSitesListed();
// Test the "Save Changes" button and accepting save
let acceptPromise = promiseAlertDialogOpen("accept");
settingsDialogClosePromise = promiseSettingsDialogClose();
updatePromise = promiseSitesUpdated();
frameDoc = doc.getElementById("dialogFrame").contentDocument;
saveBtn = frameDoc.getElementById("save");
removeAllSitesOneByOne();
assertAllSitesNotListed();
saveBtn.doCommand();
yield acceptPromise;
yield settingsDialogClosePromise;
yield updatePromise;
yield openSettingsDialog();
assertAllSitesNotListed();
// Always clean up the fake origins
fakeOrigins.forEach(origin => removePersistentStoragePerm(origin));
yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
function removeAllSitesOneByOne() {
frameDoc = doc.getElementById("dialogFrame").contentDocument;
let removeBtn = frameDoc.getElementById("removeSelected");
let sitesList = frameDoc.getElementById("sitesList");
let sites = sitesList.getElementsByTagName("richlistitem");
for (let i = sites.length - 1; i >= 0; --i) {
sites[i].click();
removeBtn.doCommand();
}
}
function assertAllSitesListed() {
frameDoc = doc.getElementById("dialogFrame").contentDocument;
let removeBtn = frameDoc.getElementById("removeSelected");
let removeAllBtn = frameDoc.getElementById("removeAll");
let sitesList = frameDoc.getElementById("sitesList");
let sites = sitesList.getElementsByTagName("richlistitem");
is(sites.length, fakeOrigins.length, "Should list all sites");
is(removeBtn.disabled, false, "Should enable the removeSelected button");
is(removeAllBtn.disabled, false, "Should enable the removeAllBtn button");
}
function assertAllSitesNotListed() {
frameDoc = doc.getElementById("dialogFrame").contentDocument;
let removeBtn = frameDoc.getElementById("removeSelected");
let removeAllBtn = frameDoc.getElementById("removeAll");
let sitesList = frameDoc.getElementById("sitesList");
let sites = sitesList.getElementsByTagName("richlistitem");
is(sites.length, 0, "Should not list all sites");
is(removeBtn.disabled, true, "Should disable the removeSelected button");
is(removeAllBtn.disabled, true, "Should disable the removeAllBtn button");
}
});
// Test selecting and removing partial sites
add_task(function* () {
yield SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]});
let fakeOrigins = [
"https://news.foo.com/",
"https://mails.bar.com/",
"https://videos.xyz.com/",
"https://books.foo.com/",
"https://account.bar.com/",
"https://shopping.xyz.com/"
];
fakeOrigins.forEach(origin => addPersistentStoragePerm(origin));
let updatePromise = promiseSitesUpdated();
yield openPreferencesViaOpenPreferencesAPI("advanced", "networkTab", { leaveOpen: true });
yield updatePromise;
yield openSettingsDialog();
let doc = gBrowser.selectedBrowser.contentDocument;
let frameDoc = null;
let saveBtn = null;
let cancelBtn = null;
let removeDialogOpenPromise = null;
let settingsDialogClosePromise = null;
// Test the initial state
assertSitesListed(doc, fakeOrigins);
// Test the "Cancel" button
settingsDialogClosePromise = promiseSettingsDialogClose();
frameDoc = doc.getElementById("dialogFrame").contentDocument;
cancelBtn = frameDoc.getElementById("cancel");
removeSelectedSite(fakeOrigins.slice(0, 4));
assertSitesListed(doc, fakeOrigins.slice(4));
cancelBtn.doCommand();
yield settingsDialogClosePromise;
yield openSettingsDialog();
assertSitesListed(doc, fakeOrigins);
// Test the "Save Changes" button but canceling save
removeDialogOpenPromise = promiseWindowDialogOpen("cancel", REMOVE_DIALOG_URL);
settingsDialogClosePromise = promiseSettingsDialogClose();
frameDoc = doc.getElementById("dialogFrame").contentDocument;
saveBtn = frameDoc.getElementById("save");
removeSelectedSite(fakeOrigins.slice(0, 4));
assertSitesListed(doc, fakeOrigins.slice(4));
saveBtn.doCommand();
yield removeDialogOpenPromise;
yield settingsDialogClosePromise;
yield openSettingsDialog();
assertSitesListed(doc, fakeOrigins);
// Test the "Save Changes" button and accepting save
removeDialogOpenPromise = promiseWindowDialogOpen("accept", REMOVE_DIALOG_URL);
settingsDialogClosePromise = promiseSettingsDialogClose();
frameDoc = doc.getElementById("dialogFrame").contentDocument;
saveBtn = frameDoc.getElementById("save");
removeSelectedSite(fakeOrigins.slice(0, 4));
assertSitesListed(doc, fakeOrigins.slice(4));
saveBtn.doCommand();
yield removeDialogOpenPromise;
yield settingsDialogClosePromise;
yield openSettingsDialog();
assertSitesListed(doc, fakeOrigins.slice(4));
// Always clean up the fake origins
fakeOrigins.forEach(origin => removePersistentStoragePerm(origin));
yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
function removeSelectedSite(origins) {
frameDoc = doc.getElementById("dialogFrame").contentDocument;
let removeBtn = frameDoc.getElementById("removeSelected");
let sitesList = frameDoc.getElementById("sitesList");
origins.forEach(origin => {
let site = sitesList.querySelector(`richlistitem[data-origin="${origin}"]`);
if (site) {
site.click();
removeBtn.doCommand();
} else {
ok(false, `Should not select and remove inexisted site of ${origin}`);
}
});
}
});
add_task(function* () {
yield SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]});
let fakeOrigins = [
"https://news.foo.com/",
"https://books.foo.com/",
"https://mails.bar.com/",
"https://account.bar.com/",
"https://videos.xyz.com/",
"https://shopping.xyz.com/"
];
fakeOrigins.forEach(origin => addPersistentStoragePerm(origin));
let updatePromise = promiseSitesUpdated();
yield openPreferencesViaOpenPreferencesAPI("advanced", "networkTab", { leaveOpen: true });
yield updatePromise;
yield openSettingsDialog();
// Search "foo" to only list foo.com sites
let doc = gBrowser.selectedBrowser.contentDocument;
let frameDoc = doc.getElementById("dialogFrame").contentDocument;
let searchBox = frameDoc.getElementById("searchBox");
searchBox.value = "foo";
searchBox.doCommand();
assertSitesListed(doc, fakeOrigins.slice(0, 2));
// Test only removing all visible sites listed
updatePromise = promiseSitesUpdated();
let acceptRemovePromise = promiseWindowDialogOpen("accept", REMOVE_DIALOG_URL);
let settingsDialogClosePromise = promiseSettingsDialogClose();
let removeAllBtn = frameDoc.getElementById("removeAll");
let saveBtn = frameDoc.getElementById("save");
removeAllBtn.doCommand();
saveBtn.doCommand();
yield acceptRemovePromise;
yield settingsDialogClosePromise;
yield updatePromise;
yield openSettingsDialog();
assertSitesListed(doc, fakeOrigins.slice(2));
// Always clean up the fake origins
fakeOrigins.forEach(origin => removePersistentStoragePerm(origin));
yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
});

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

@ -0,0 +1,155 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const { classes: Cc, interfaces: Ci, manager: Cm, utils: Cu, results: Cr } = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
const uuidGenerator = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator);
const mockUpdateManager = {
contractId: "@mozilla.org/updates/update-manager;1",
_mockClassId: uuidGenerator.generateUUID(),
_originalClassId: "",
_originalFactory: null,
QueryInterface: XPCOMUtils.generateQI([Ci.nsIUpdateManager]),
createInstance(outer, iiD) {
if (outer) {
throw Cr.NS_ERROR_NO_AGGREGATION;
}
return this.QueryInterface(iiD);
},
register() {
let registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
if (!registrar.isCIDRegistered(this._mockClassId)) {
this._originalClassId = registrar.contractIDToCID(this.contractId);
this._originalFactory = Cm.getClassObject(Cc[this.contractId], Ci.nsIFactory);
registrar.unregisterFactory(this._originalClassId, this._originalFactory);
registrar.registerFactory(this._mockClassId, "Unregister after testing", this.contractId, this);
}
},
unregister() {
let registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
registrar.unregisterFactory(this._mockClassId, this);
registrar.registerFactory(this._originalClassId, "", this.contractId, this._originalFactory);
},
get updateCount() {
return this._updates.length;
},
getUpdateAt(index) {
return this._updates[index];
},
_updates: [
{
name: "Firefox Developer Edition 49.0a2",
statusText: "The Update was successfully installed",
buildID: "20160728004010",
type: "minor",
installDate: 1469763105156,
detailsURL: "https://www.mozilla.org/firefox/aurora/"
},
{
name: "Firefox Developer Edition 43.0a2",
statusText: "The Update was successfully installed",
buildID: "20150929004011",
type: "minor",
installDate: 1443585886224,
detailsURL: "https://www.mozilla.org/firefox/aurora/"
},
{
name: "Firefox Developer Edition 42.0a2",
statusText: "The Update was successfully installed",
buildID: "20150920004018",
type: "major",
installDate: 1442818147544,
detailsURL: "https://www.mozilla.org/firefox/aurora/"
}
]
};
function resetPreferences() {
Services.prefs.clearUserPref("browser.search.update");
}
function formatInstallDate(sec) {
var date = new Date(sec);
const dtOptions = { year: "numeric", month: "long", day: "numeric",
hour: "numeric", minute: "numeric", second: "numeric" };
return date.toLocaleString(undefined, dtOptions);
}
registerCleanupFunction(resetPreferences);
add_task(function*() {
yield openPreferencesViaOpenPreferencesAPI("advanced", "updateTab", { leaveOpen: true });
resetPreferences();
Services.prefs.setBoolPref("browser.search.update", false);
let doc = gBrowser.selectedBrowser.contentDocument;
let enableSearchUpdate = doc.getElementById("enableSearchUpdate");
is_element_visible(enableSearchUpdate, "Check search update preference is visible");
// Ensure that the update pref dialog reflects the actual pref value.
ok(!enableSearchUpdate.checked, "Ensure search updates are disabled");
Services.prefs.setBoolPref("browser.search.update", true);
ok(enableSearchUpdate.checked, "Ensure search updates are enabled");
gBrowser.removeCurrentTab();
});
add_task(function*() {
mockUpdateManager.register();
yield openPreferencesViaOpenPreferencesAPI("advanced", "updateTab", { leaveOpen: true });
let doc = gBrowser.selectedBrowser.contentDocument;
let showBtn = doc.getElementById("showUpdateHistory");
let dialogOverlay = doc.getElementById("dialogOverlay");
// Test the dialog window opens
is(dialogOverlay.style.visibility, "", "The dialog should be invisible");
showBtn.doCommand();
yield promiseLoadSubDialog("chrome://mozapps/content/update/history.xul");
is(dialogOverlay.style.visibility, "visible", "The dialog should be visible");
let dialogFrame = doc.getElementById("dialogFrame");
let frameDoc = dialogFrame.contentDocument;
let updates = frameDoc.querySelectorAll("update");
// Test the update history numbers are correct
is(updates.length, mockUpdateManager.updateCount, "The update count is incorrect.");
// Test the updates are displayed correctly
let update = null;
let updateData = null;
for (let i = 0; i < updates.length; ++i) {
update = updates[i];
updateData = mockUpdateManager.getUpdateAt(i);
is(update.name, updateData.name + " (" + updateData.buildID + ")", "Wrong update name");
is(update.type, updateData.type == "major" ? "New Version" : "Security Update", "Wrong update type");
is(update.installDate, formatInstallDate(updateData.installDate), "Wrong update installDate");
is(update.detailsURL, updateData.detailsURL, "Wrong update detailsURL");
is(update.status, updateData.statusText, "Wrong update status");
}
// Test the dialog window closes
let closeBtn = doc.getElementById("dialogClose");
closeBtn.doCommand();
is(dialogOverlay.style.visibility, "", "The dialog should be invisible");
mockUpdateManager.unregister();
gBrowser.removeCurrentTab();
});

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

@ -0,0 +1,79 @@
var win;
var feedItem;
var container;
SimpleTest.requestCompleteLog();
add_task(function* setup() {
yield openPreferencesViaOpenPreferencesAPI("applications", null, {leaveOpen: true});
info("Preferences page opened on the applications pane.");
registerCleanupFunction(() => {
gBrowser.removeCurrentTab();
});
});
add_task(function* getFeedItem() {
win = gBrowser.selectedBrowser.contentWindow;
container = win.document.getElementById("handlersView");
feedItem = container.querySelector("richlistitem[type='application/vnd.mozilla.maybe.feed']");
Assert.ok(feedItem, "feedItem is present in handlersView.");
})
add_task(function* selectInternalOptionForFeed() {
// Select the item.
feedItem.scrollIntoView();
container.selectItem(feedItem);
Assert.ok(feedItem.selected, "Should be able to select our item.");
// Wait for the menu.
let list = yield waitForCondition(() =>
win.document.getAnonymousElementByAttribute(feedItem, "class", "actionsMenu"));
info("Got list after item was selected");
// Find the "Add Live bookmarks option".
let chooseItems = list.getElementsByAttribute("action", Ci.nsIHandlerInfo.handleInternally);
Assert.equal(chooseItems.length, 1, "Should only be one action to handle internally");
// Select the option.
let cmdEvent = win.document.createEvent("xulcommandevent");
cmdEvent.initCommandEvent("command", true, true, win, 0, false, false, false, false, null);
chooseItems[0].dispatchEvent(cmdEvent);
// Check that we display the correct result.
list = yield waitForCondition(() =>
win.document.getAnonymousElementByAttribute(feedItem, "class", "actionsMenu"));
info("Got list after item was selected");
Assert.ok(list.selectedItem, "Should have a selected item.");
Assert.equal(list.selectedItem.getAttribute("action"),
Ci.nsIHandlerInfo.handleInternally,
"Newly selected item should be the expected one.");
});
// This builds on the previous selectInternalOptionForFeed task.
add_task(function* reselectInternalOptionForFeed() {
// Now select a different option in the list - use the pdf item as that doesn't
// need to load any favicons.
let anotherItem = container.querySelector("richlistitem[type='application/pdf']");
container.selectItem(anotherItem);
// Wait for the menu so that we don't hit race conditions.
yield waitForCondition(() =>
win.document.getAnonymousElementByAttribute(anotherItem, "class", "actionsMenu"));
info("Got list after item was selected");
// Now select the feed item again, and check what it is displaying.
container.selectItem(feedItem);
let list = yield waitForCondition(() =>
win.document.getAnonymousElementByAttribute(feedItem, "class", "actionsMenu"));
info("Got list after item was selected");
Assert.ok(list.selectedItem,
"Should have a selected item");
Assert.equal(list.selectedItem.getAttribute("action"),
Ci.nsIHandlerInfo.handleInternally,
"Selected item should still be the same as the previously selected item.");
});

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

@ -0,0 +1,76 @@
Services.prefs.setBoolPref("browser.preferences.instantApply", true);
registerCleanupFunction(function() {
Services.prefs.clearUserPref("browser.preferences.instantApply");
});
add_task(function*() {
yield openPreferencesViaOpenPreferencesAPI("paneContent", null, {leaveOpen: true});
let doc = gBrowser.contentDocument;
var langGroup = Services.prefs.getComplexValue("font.language.group", Ci.nsIPrefLocalizedString).data
is(doc.getElementById("font.language.group").value, langGroup,
"Language group should be set correctly.");
let defaultFontType = Services.prefs.getCharPref("font.default." + langGroup);
let fontFamily = Services.prefs.getCharPref("font.name." + defaultFontType + "." + langGroup);
let fontFamilyField = doc.getElementById("defaultFont");
is(fontFamilyField.value, fontFamily, "Font family should be set correctly.");
let defaultFontSize = Services.prefs.getIntPref("font.size.variable." + langGroup);
let fontSizeField = doc.getElementById("defaultFontSize");
is(fontSizeField.value, defaultFontSize, "Font size should be set correctly.");
doc.getElementById("advancedFonts").click();
let win = yield promiseLoadSubDialog("chrome://browser/content/preferences/fonts.xul");
doc = win.document;
// Simulate a dumb font backend.
win.FontBuilder._enumerator = {
_list: ["MockedFont1", "MockedFont2", "MockedFont3"],
EnumerateFonts(lang, type, list) {
return this._list;
},
EnumerateAllFonts() {
return this._list;
},
getDefaultFont() { return null; },
getStandardFamilyName(name) { return name; },
};
win.FontBuilder._allFonts = null;
win.FontBuilder._langGroupSupported = false;
let langGroupElement = doc.getElementById("font.language.group");
let selectLangsField = doc.getElementById("selectLangs");
let serifField = doc.getElementById("serif");
let armenian = "x-armn";
let western = "x-western";
langGroupElement.value = armenian;
selectLangsField.value = armenian;
is(serifField.value, "", "Font family should not be set.");
langGroupElement.value = western;
selectLangsField.value = western;
// Simulate a font backend supporting language-specific enumeration.
// NB: FontBuilder has cached the return value from EnumerateAllFonts(),
// so _allFonts will always have 3 elements regardless of subsequent
// _list changes.
win.FontBuilder._enumerator._list = ["MockedFont2"];
langGroupElement.value = armenian;
selectLangsField.value = armenian;
is(serifField.value, "MockedFont2", "Font family should be set.");
langGroupElement.value = western;
selectLangsField.value = western;
// Simulate a system that has no fonts for the specified language.
win.FontBuilder._enumerator._list = [];
langGroupElement.value = armenian;
selectLangsField.value = armenian;
is(serifField.value, "", "Font family should not be set.");
gBrowser.removeCurrentTab();
});

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

@ -0,0 +1,24 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
var originalWindowHeight;
registerCleanupFunction(function() {
window.resizeTo(window.outerWidth, originalWindowHeight);
while (gBrowser.tabs[1])
gBrowser.removeTab(gBrowser.tabs[1]);
});
add_task(function*() {
originalWindowHeight = window.outerHeight;
window.resizeTo(window.outerWidth, 300);
let prefs = yield openPreferencesViaOpenPreferencesAPI("paneApplications", undefined, {leaveOpen: true});
is(prefs.selectedPane, "paneApplications", "Applications pane was selected");
let mainContent = gBrowser.contentDocument.querySelector(".main-content");
mainContent.scrollTop = 50;
is(mainContent.scrollTop, 50, "main-content should be scrolled 50 pixels");
gBrowser.contentWindow.gotoPref("paneGeneral");
is(mainContent.scrollTop, 0,
"Switching to a different category should reset the scroll position");
});

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

@ -0,0 +1,41 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
Services.prefs.setBoolPref("browser.preferences.instantApply", true);
registerCleanupFunction(function() {
Services.prefs.clearUserPref("browser.preferences.instantApply");
});
add_task(function*() {
let prefs = yield openPreferencesViaOpenPreferencesAPI("paneContent");
is(prefs.selectedPane, "paneContent", "Content pane was selected");
prefs = yield openPreferencesViaOpenPreferencesAPI("advanced", "updateTab");
is(prefs.selectedPane, "paneAdvanced", "Advanced pane was selected");
is(prefs.selectedAdvancedTab, "updateTab", "The update tab within the advanced prefs should be selected");
prefs = yield openPreferencesViaHash("privacy");
is(prefs.selectedPane, "panePrivacy", "Privacy pane is selected when hash is 'privacy'");
prefs = yield openPreferencesViaOpenPreferencesAPI("nonexistant-category");
is(prefs.selectedPane, "paneGeneral", "General pane is selected by default when a nonexistant-category is requested");
prefs = yield openPreferencesViaHash("nonexistant-category");
is(prefs.selectedPane, "paneGeneral", "General pane is selected when hash is a nonexistant-category");
prefs = yield openPreferencesViaHash();
is(prefs.selectedPane, "paneGeneral", "General pane is selected by default");
});
function openPreferencesViaHash(aPane) {
let deferred = Promise.defer();
gBrowser.selectedTab = gBrowser.addTab("about:preferences" + (aPane ? "#" + aPane : ""));
let newTabBrowser = gBrowser.selectedBrowser;
newTabBrowser.addEventListener("Initialized", function() {
newTabBrowser.contentWindow.addEventListener("load", function() {
let win = gBrowser.contentWindow;
let selectedPane = win.history.state;
gBrowser.removeCurrentTab();
deferred.resolve({selectedPane});
}, {once: true});
}, {capture: true, once: true});
return deferred.promise;
}

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

@ -0,0 +1,95 @@
const ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
const {Utils} = Cu.import("resource://gre/modules/sessionstore/Utils.jsm", {});
const triggeringPrincipal_base64 = Utils.SERIALIZED_SYSTEMPRINCIPAL;
add_task(function* () {
waitForExplicitFinish();
const tabURL = getRootDirectory(gTestPath) + "browser_bug1184989_prevent_scrolling_when_preferences_flipped.xul";
yield BrowserTestUtils.withNewTab({ gBrowser, url: tabURL }, function* (browser) {
let doc = browser.contentDocument;
let container = doc.getElementById("container");
// Test button
let button = doc.getElementById("button");
button.focus();
EventUtils.synthesizeKey(" ", {});
yield checkPageScrolling(container, "button");
// Test checkbox
let checkbox = doc.getElementById("checkbox");
checkbox.focus();
EventUtils.synthesizeKey(" ", {});
ok(checkbox.checked, "Checkbox is checked");
yield checkPageScrolling(container, "checkbox");
// Test listbox
let listbox = doc.getElementById("listbox");
let listitem = doc.getElementById("listitem");
listbox.focus();
EventUtils.synthesizeKey(" ", {});
ok(listitem.selected, "Listitem is selected");
yield checkPageScrolling(container, "listbox");
// Test radio
let radiogroup = doc.getElementById("radiogroup");
radiogroup.focus();
EventUtils.synthesizeKey(" ", {});
yield checkPageScrolling(container, "radio");
});
yield BrowserTestUtils.withNewTab({ gBrowser, url: "about:preferences#search" }, function* (browser) {
let doc = browser.contentDocument;
let container = doc.getElementsByClassName("main-content")[0];
// Test search
let engineList = doc.getElementById("engineList");
engineList.focus();
EventUtils.synthesizeKey(" ", {});
is(engineList.view.selection.currentIndex, 0, "Search engineList is selected");
EventUtils.synthesizeKey(" ", {});
yield checkPageScrolling(container, "search engineList");
});
// Test session restore
const CRASH_URL = "about:mozilla";
const CRASH_FAVICON = "chrome://branding/content/icon32.png";
const CRASH_SHENTRY = {url: CRASH_URL};
const CRASH_TAB = {entries: [CRASH_SHENTRY], image: CRASH_FAVICON};
const CRASH_STATE = {windows: [{tabs: [CRASH_TAB]}]};
const TAB_URL = "about:sessionrestore";
const TAB_FORMDATA = {url: TAB_URL, id: {sessionData: CRASH_STATE}};
const TAB_SHENTRY = {url: TAB_URL, triggeringPrincipal_base64};
const TAB_STATE = {entries: [TAB_SHENTRY], formdata: TAB_FORMDATA};
let tab = gBrowser.selectedTab = gBrowser.addTab("about:blank");
// Fake a post-crash tab
ss.setTabState(tab, JSON.stringify(TAB_STATE));
yield BrowserTestUtils.browserLoaded(tab.linkedBrowser);
let doc = tab.linkedBrowser.contentDocument;
// Make body scrollable
doc.body.style.height = (doc.body.clientHeight + 100) + "px";
let tabList = doc.getElementById("tabList");
tabList.focus();
EventUtils.synthesizeKey(" ", {});
yield checkPageScrolling(doc.documentElement, "session restore");
gBrowser.removeCurrentTab();
finish();
});
function checkPageScrolling(container, type) {
return new Promise(resolve => {
setTimeout(() => {
is(container.scrollTop, 0, "Page should not scroll when " + type + " flipped");
resolve();
}, 0);
});
}

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

@ -0,0 +1,33 @@
<?xml version="1.0"?>
<!--
XUL Widget Test for Bug 1184989
-->
<page title="Bug 1184989 Test"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<vbox id="container" style="height: 200px; overflow: auto;">
<vbox style="height: 500px;">
<hbox>
<button id="button" label="button" />
</hbox>
<hbox>
<checkbox id="checkbox" label="checkbox" />
</hbox>
<hbox style="height: 50px;">
<listbox id="listbox">
<listitem id="listitem" label="listitem" />
<listitem label="listitem" />
</listbox>
</hbox>
<hbox>
<radiogroup id="radiogroup">
<radio id="radio" label="radio" />
</radiogroup>
</hbox>
</vbox>
</vbox>
</page>

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

@ -0,0 +1,46 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
Components.utils.import("resource://gre/modules/PlacesUtils.jsm");
Components.utils.import("resource://gre/modules/NetUtil.jsm");
function test() {
waitForExplicitFinish();
// Setup a phony handler to ensure the app pane will be populated.
var handler = Cc["@mozilla.org/uriloader/web-handler-app;1"].
createInstance(Ci.nsIWebHandlerApp);
handler.name = "App pane alive test";
handler.uriTemplate = "http://test.mozilla.org/%s";
var extps = Cc["@mozilla.org/uriloader/external-protocol-service;1"].
getService(Ci.nsIExternalProtocolService);
var info = extps.getProtocolHandlerInfo("apppanetest");
info.possibleApplicationHandlers.appendElement(handler, false);
var hserv = Cc["@mozilla.org/uriloader/handler-service;1"].
getService(Ci.nsIHandlerService);
hserv.store(info);
openPreferencesViaOpenPreferencesAPI("applications", null, {leaveOpen: true}).then(
() => runTest(gBrowser.selectedBrowser.contentWindow)
);
}
function runTest(win) {
var rbox = win.document.getElementById("handlersView");
ok(rbox, "handlersView is present");
var items = rbox && rbox.getElementsByTagName("richlistitem");
ok(items && items.length > 0, "App handler list populated");
var handlerAdded = false;
for (let i = 0; i < items.length; i++) {
if (items[i].getAttribute("type") == "apppanetest")
handlerAdded = true;
}
ok(handlerAdded, "apppanetest protocol handler was successfully added");
gBrowser.removeCurrentTab();
finish();
}

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

@ -0,0 +1,144 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
function test() {
waitForExplicitFinish();
// Allow all cookies, then actually set up the test
SpecialPowers.pushPrefEnv({"set": [["network.cookie.cookieBehavior", 0]]}, initTest);
}
function initTest() {
const searchTerm = "example";
const dummyTerm = "elpmaxe";
var cm = Components.classes["@mozilla.org/cookiemanager;1"]
.getService(Components.interfaces.nsICookieManager);
// delete all cookies (might be left over from other tests)
cm.removeAll();
// data for cookies
var vals = [[searchTerm + ".com", dummyTerm, dummyTerm], // match
[searchTerm + ".org", dummyTerm, dummyTerm], // match
[dummyTerm + ".com", searchTerm, dummyTerm], // match
[dummyTerm + ".edu", searchTerm + dummyTerm, dummyTerm], // match
[dummyTerm + ".net", dummyTerm, searchTerm], // match
[dummyTerm + ".org", dummyTerm, searchTerm + dummyTerm], // match
[dummyTerm + ".int", dummyTerm, dummyTerm]]; // no match
// matches must correspond to above data
const matches = 6;
var ios = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
var cookieSvc = Components.classes["@mozilla.org/cookieService;1"]
.getService(Components.interfaces.nsICookieService);
var v;
// inject cookies
for (v in vals) {
let [host, name, value] = vals[v];
var cookieUri = ios.newURI("http://" + host);
cookieSvc.setCookieString(cookieUri, null, name + "=" + value + ";", null);
}
// open cookie manager
var cmd = window.openDialog("chrome://browser/content/preferences/cookies.xul",
"Browser:Cookies", "", {});
// when it has loaded, run actual tests
cmd.addEventListener("load", function() { executeSoon(function() { runTest(cmd, searchTerm, vals.length, matches); }); });
}
function isDisabled(win, expectation) {
var disabled = win.document.getElementById("removeAllCookies").disabled;
is(disabled, expectation, "Remove all cookies button has correct state: " + (expectation ? "disabled" : "enabled"));
}
function runTest(win, searchTerm, cookies, matches) {
var cm = Components.classes["@mozilla.org/cookiemanager;1"]
.getService(Components.interfaces.nsICookieManager);
// number of cookies should match injected cookies
var injectedCookies = 0,
injectedEnumerator = cm.enumerator;
while (injectedEnumerator.hasMoreElements()) {
injectedCookies++;
injectedEnumerator.getNext();
}
is(injectedCookies, cookies, "Number of cookies match injected cookies");
// "delete all cookies" should be enabled
isDisabled(win, false);
// filter cookies and count matches
win.gCookiesWindow.setFilter(searchTerm);
is(win.gCookiesWindow._view.rowCount, matches, "Correct number of cookies shown after filter is applied");
// "delete all cookies" should be enabled
isDisabled(win, false);
// select first cookie and delete
var tree = win.document.getElementById("cookiesList");
var deleteButton = win.document.getElementById("removeSelectedCookies");
var rect = tree.treeBoxObject.getCoordsForCellItem(0, tree.columns[0], "cell");
EventUtils.synthesizeMouse(tree.body, rect.x + rect.width / 2, rect.y + rect.height / 2, {}, win);
EventUtils.synthesizeMouseAtCenter(deleteButton, {}, win);
// count cookies should be matches-1
is(win.gCookiesWindow._view.rowCount, matches - 1, "Deleted selected cookie");
// select two adjacent cells and delete
EventUtils.synthesizeMouse(tree.body, rect.x + rect.width / 2, rect.y + rect.height / 2, {}, win);
var eventObj = {};
if (navigator.platform.indexOf("Mac") >= 0)
eventObj.metaKey = true;
else
eventObj.ctrlKey = true;
rect = tree.treeBoxObject.getCoordsForCellItem(1, tree.columns[0], "cell");
EventUtils.synthesizeMouse(tree.body, rect.x + rect.width / 2, rect.y + rect.height / 2, eventObj, win);
EventUtils.synthesizeMouseAtCenter(deleteButton, {}, win);
// count cookies should be matches-3
is(win.gCookiesWindow._view.rowCount, matches - 3, "Deleted selected two adjacent cookies");
// "delete all cookies" should be enabled
isDisabled(win, false);
// delete all cookies and count
var deleteAllButton = win.document.getElementById("removeAllCookies");
EventUtils.synthesizeMouseAtCenter(deleteAllButton, {}, win);
is(win.gCookiesWindow._view.rowCount, 0, "Deleted all matching cookies");
// "delete all cookies" should be disabled
isDisabled(win, true);
// clear filter and count should be cookies-matches
win.gCookiesWindow.setFilter("");
is(win.gCookiesWindow._view.rowCount, cookies - matches, "Unmatched cookies remain");
// "delete all cookies" should be enabled
isDisabled(win, false);
// delete all cookies and count should be 0
EventUtils.synthesizeMouseAtCenter(deleteAllButton, {}, win);
is(win.gCookiesWindow._view.rowCount, 0, "Deleted all cookies");
// check that datastore is also at 0
var remainingCookies = 0,
remainingEnumerator = cm.enumerator;
while (remainingEnumerator.hasMoreElements()) {
remainingCookies++;
remainingEnumerator.getNext();
}
is(remainingCookies, 0, "Zero cookies remain");
// "delete all cookies" should be disabled
isDisabled(win, true);
// clean up
win.close();
finish();
}

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

@ -0,0 +1,52 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
Components.utils.import("resource://gre/modules/PlacesUtils.jsm");
Components.utils.import("resource://gre/modules/NetUtil.jsm");
function test() {
waitForExplicitFinish();
open_preferences(runTest);
}
var gElements;
function checkElements(expectedPane) {
for (let element of gElements) {
// keyset and preferences elements fail is_element_visible checks because they are never visible.
// special-case the drmGroup item because its visibility depends on pref + OS version
if (element.nodeName == "keyset" ||
element.nodeName == "preferences" ||
element.id === "drmGroup") {
continue;
}
let attributeValue = element.getAttribute("data-category");
let suffix = " (id=" + element.id + ")";
if (attributeValue == "pane" + expectedPane) {
is_element_visible(element, expectedPane + " elements should be visible" + suffix);
} else {
is_element_hidden(element, "Elements not in " + expectedPane + " should be hidden" + suffix);
}
}
}
function runTest(win) {
is(gBrowser.currentURI.spec, "about:preferences", "about:preferences loaded");
let tab = win.document;
gElements = tab.getElementById("mainPrefPane").children;
let panes = [
"General", "Search", "Content", "Applications",
"Privacy", "Security", "Sync", "Advanced",
];
for (let pane of panes) {
win.gotoPref("pane" + pane);
checkElements(pane);
}
gBrowser.removeCurrentTab();
win.close();
finish();
}

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

@ -0,0 +1,52 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
Components.utils.import("resource://gre/modules/PlacesUtils.jsm");
Components.utils.import("resource://gre/modules/NetUtil.jsm");
function test() {
waitForExplicitFinish();
let prefs = [
"browser.cache.offline.enable",
"browser.cache.disk.enable",
"browser.cache.memory.enable",
];
registerCleanupFunction(function() {
for (let pref of prefs) {
Services.prefs.clearUserPref(pref);
}
});
for (let pref of prefs) {
Services.prefs.setBoolPref(pref, false);
}
open_preferences(runTest);
}
function runTest(win) {
is(gBrowser.currentURI.spec, "about:preferences", "about:preferences loaded");
let tab = win.document;
let elements = tab.getElementById("mainPrefPane").children;
// Test if advanced pane is opened correctly
win.gotoPref("paneAdvanced");
for (let element of elements) {
if (element.nodeName == "preferences") {
continue;
}
let attributeValue = element.getAttribute("data-category");
if (attributeValue == "paneAdvanced") {
is_element_visible(element, "Advanced elements should be visible");
} else {
is_element_hidden(element, "Non-Advanced elements should be hidden");
}
}
gBrowser.removeCurrentTab();
win.close();
finish();
}

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

@ -0,0 +1,98 @@
var gMimeSvc = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
var gHandlerSvc = Cc["@mozilla.org/uriloader/handler-service;1"].getService(Ci.nsIHandlerService);
SimpleTest.requestCompleteLog();
function setupFakeHandler() {
let info = gMimeSvc.getFromTypeAndExtension("text/plain", "foo.txt");
ok(info.possibleLocalHandlers.length, "Should have at least one known handler");
let handler = info.possibleLocalHandlers.queryElementAt(0, Ci.nsILocalHandlerApp);
let infoToModify = gMimeSvc.getFromTypeAndExtension("text/x-test-handler", null);
infoToModify.possibleApplicationHandlers.appendElement(handler, false);
gHandlerSvc.store(infoToModify);
}
add_task(function*() {
setupFakeHandler();
yield openPreferencesViaOpenPreferencesAPI("applications", null, {leaveOpen: true});
info("Preferences page opened on the applications pane.");
let win = gBrowser.selectedBrowser.contentWindow;
let container = win.document.getElementById("handlersView");
let ourItem = container.querySelector("richlistitem[type='text/x-test-handler']");
ok(ourItem, "handlersView is present");
ourItem.scrollIntoView();
container.selectItem(ourItem);
ok(ourItem.selected, "Should be able to select our item.");
let list = yield waitForCondition(() => win.document.getAnonymousElementByAttribute(ourItem, "class", "actionsMenu"));
info("Got list after item was selected");
let chooseItem = list.firstChild.querySelector(".choose-app-item");
let dialogLoadedPromise = promiseLoadSubDialog("chrome://global/content/appPicker.xul");
let cmdEvent = win.document.createEvent("xulcommandevent");
cmdEvent.initCommandEvent("command", true, true, win, 0, false, false, false, false, null);
chooseItem.dispatchEvent(cmdEvent);
let dialog = yield dialogLoadedPromise;
info("Dialog loaded");
let dialogDoc = dialog.document;
let dialogList = dialogDoc.getElementById("app-picker-listbox");
dialogList.selectItem(dialogList.firstChild);
let selectedApp = dialogList.firstChild.handlerApp;
dialogDoc.documentElement.acceptDialog();
// Verify results are correct in mime service:
let mimeInfo = gMimeSvc.getFromTypeAndExtension("text/x-test-handler", null);
ok(mimeInfo.preferredApplicationHandler.equals(selectedApp), "App should be set as preferred.");
// Check that we display this result:
list = yield waitForCondition(() => win.document.getAnonymousElementByAttribute(ourItem, "class", "actionsMenu"));
info("Got list after item was selected");
ok(list.selectedItem, "Should have a selected item");
ok(mimeInfo.preferredApplicationHandler.equals(list.selectedItem.handlerApp),
"App should be visible as preferred item.");
// Now try to 'manage' this list:
dialogLoadedPromise = promiseLoadSubDialog("chrome://browser/content/preferences/applicationManager.xul");
let manageItem = list.firstChild.querySelector(".manage-app-item");
cmdEvent = win.document.createEvent("xulcommandevent");
cmdEvent.initCommandEvent("command", true, true, win, 0, false, false, false, false, null);
manageItem.dispatchEvent(cmdEvent);
dialog = yield dialogLoadedPromise;
info("Dialog loaded the second time");
dialogDoc = dialog.document;
dialogList = dialogDoc.getElementById("appList");
let itemToRemove = dialogList.querySelector('listitem[label="' + selectedApp.name + '"]');
dialogList.selectItem(itemToRemove);
let itemsBefore = dialogList.children.length;
dialogDoc.getElementById("remove").click();
ok(!itemToRemove.parentNode, "Item got removed from DOM");
is(dialogList.children.length, itemsBefore - 1, "Item got removed");
dialogDoc.documentElement.acceptDialog();
// Verify results are correct in mime service:
mimeInfo = gMimeSvc.getFromTypeAndExtension("text/x-test-handler", null);
ok(!mimeInfo.preferredApplicationHandler, "App should no longer be set as preferred.");
// Check that we display this result:
list = yield waitForCondition(() => win.document.getAnonymousElementByAttribute(ourItem, "class", "actionsMenu"));
ok(list.selectedItem, "Should have a selected item");
ok(!list.selectedItem.handlerApp,
"No app should be visible as preferred item.");
gBrowser.removeCurrentTab();
});
registerCleanupFunction(function() {
let infoToModify = gMimeSvc.getFromTypeAndExtension("text/x-test-handler", null);
gHandlerSvc.remove(infoToModify);
});

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

@ -0,0 +1,99 @@
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import("resource://gre/modules/Task.jsm");
function test() {
waitForExplicitFinish();
// network.proxy.type needs to be backed up and restored because mochitest
// changes this setting from the default
let oldNetworkProxyType = Services.prefs.getIntPref("network.proxy.type");
registerCleanupFunction(function() {
Services.prefs.setIntPref("network.proxy.type", oldNetworkProxyType);
Services.prefs.clearUserPref("network.proxy.no_proxies_on");
Services.prefs.clearUserPref("browser.preferences.instantApply");
});
let connectionURL = "chrome://browser/content/preferences/connection.xul";
/*
The connection dialog alone won't save onaccept since it uses type="child",
so it has to be opened as a sub dialog of the main pref tab.
Open the main tab here.
*/
open_preferences(Task.async(function* tabOpened(aContentWindow) {
is(gBrowser.currentURI.spec, "about:preferences", "about:preferences loaded");
let dialog = yield openAndLoadSubDialog(connectionURL);
let dialogClosingPromise = waitForEvent(dialog.document.documentElement, "dialogclosing");
ok(dialog, "connection window opened");
runConnectionTests(dialog);
dialog.document.documentElement.acceptDialog();
let dialogClosingEvent = yield dialogClosingPromise;
ok(dialogClosingEvent, "connection window closed");
// runConnectionTests will have changed this pref - make sure it was
// sanitized correctly when the dialog was accepted
is(Services.prefs.getCharPref("network.proxy.no_proxies_on"),
".a.com,.b.com,.c.com", "no_proxies_on pref has correct value");
gBrowser.removeCurrentTab();
finish();
}));
}
// run a bunch of tests on the window containing connection.xul
function runConnectionTests(win) {
let doc = win.document;
let networkProxyNone = doc.getElementById("networkProxyNone");
let networkProxyNonePref = doc.getElementById("network.proxy.no_proxies_on");
let networkProxyTypePref = doc.getElementById("network.proxy.type");
// make sure the networkProxyNone textbox is formatted properly
is(networkProxyNone.getAttribute("multiline"), "true",
"networkProxyNone textbox is multiline");
is(networkProxyNone.getAttribute("rows"), "2",
"networkProxyNone textbox has two rows");
// check if sanitizing the given input for the no_proxies_on pref results in
// expected string
function testSanitize(input, expected, errorMessage) {
networkProxyNonePref.value = input;
win.gConnectionsDialog.sanitizeNoProxiesPref();
is(networkProxyNonePref.value, expected, errorMessage);
}
// change this pref so proxy exceptions are actually configurable
networkProxyTypePref.value = 1;
is(networkProxyNone.disabled, false, "networkProxyNone textbox is enabled");
testSanitize(".a.com", ".a.com",
"sanitize doesn't mess up single filter");
testSanitize(".a.com, .b.com, .c.com", ".a.com, .b.com, .c.com",
"sanitize doesn't mess up multiple comma/space sep filters");
testSanitize(".a.com\n.b.com", ".a.com,.b.com",
"sanitize turns line break into comma");
testSanitize(".a.com,\n.b.com", ".a.com,.b.com",
"sanitize doesn't add duplicate comma after comma");
testSanitize(".a.com\n,.b.com", ".a.com,.b.com",
"sanitize doesn't add duplicate comma before comma");
testSanitize(".a.com,\n,.b.com", ".a.com,,.b.com",
"sanitize doesn't add duplicate comma surrounded by commas");
testSanitize(".a.com, \n.b.com", ".a.com, .b.com",
"sanitize doesn't add comma after comma/space");
testSanitize(".a.com\n .b.com", ".a.com, .b.com",
"sanitize adds comma before space");
testSanitize(".a.com\n\n\n;;\n;\n.b.com", ".a.com,.b.com",
"sanitize only adds one comma per substring of bad chars");
testSanitize(".a.com,,.b.com", ".a.com,,.b.com",
"duplicate commas from user are untouched");
testSanitize(".a.com\n.b.com\n.c.com,\n.d.com,\n.e.com",
".a.com,.b.com,.c.com,.d.com,.e.com",
"sanitize replaces things globally");
// will check that this was sanitized properly after window closes
networkProxyNonePref.value = ".a.com;.b.com\n.c.com";
}

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

@ -0,0 +1,125 @@
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import("resource://gre/modules/Task.jsm");
function test() {
waitForExplicitFinish();
const connectionURL = "chrome://browser/content/preferences/connection.xul";
let closeable = false;
let finalTest = false;
// The changed preferences need to be backed up and restored because this mochitest
// changes them setting from the default
let oldNetworkProxyType = Services.prefs.getIntPref("network.proxy.type");
registerCleanupFunction(function() {
Services.prefs.setIntPref("network.proxy.type", oldNetworkProxyType);
Services.prefs.clearUserPref("network.proxy.share_proxy_settings");
for (let proxyType of ["http", "ssl", "ftp", "socks"]) {
Services.prefs.clearUserPref("network.proxy." + proxyType);
Services.prefs.clearUserPref("network.proxy." + proxyType + "_port");
if (proxyType == "http") {
continue;
}
Services.prefs.clearUserPref("network.proxy.backup." + proxyType);
Services.prefs.clearUserPref("network.proxy.backup." + proxyType + "_port");
}
});
/*
The connection dialog alone won't save onaccept since it uses type="child",
so it has to be opened as a sub dialog of the main pref tab.
Open the main tab here.
*/
open_preferences(Task.async(function* tabOpened(aContentWindow) {
let dialog, dialogClosingPromise;
let doc, proxyTypePref, sharePref, httpPref, httpPortPref, ftpPref, ftpPortPref;
// Convenient function to reset the variables for the new window
function* setDoc() {
if (closeable) {
let dialogClosingEvent = yield dialogClosingPromise;
ok(dialogClosingEvent, "Connection dialog closed");
}
if (finalTest) {
gBrowser.removeCurrentTab();
finish();
return;
}
dialog = yield openAndLoadSubDialog(connectionURL);
dialogClosingPromise = waitForEvent(dialog.document.documentElement, "dialogclosing");
doc = dialog.document;
proxyTypePref = doc.getElementById("network.proxy.type");
sharePref = doc.getElementById("network.proxy.share_proxy_settings");
httpPref = doc.getElementById("network.proxy.http");
httpPortPref = doc.getElementById("network.proxy.http_port");
ftpPref = doc.getElementById("network.proxy.ftp");
ftpPortPref = doc.getElementById("network.proxy.ftp_port");
}
// This batch of tests should not close the dialog
yield setDoc();
// Testing HTTP port 0 with share on
proxyTypePref.value = 1;
sharePref.value = true;
httpPref.value = "localhost";
httpPortPref.value = 0;
doc.documentElement.acceptDialog();
// Testing HTTP port 0 + FTP port 80 with share off
sharePref.value = false;
ftpPref.value = "localhost";
ftpPortPref.value = 80;
doc.documentElement.acceptDialog();
// Testing HTTP port 80 + FTP port 0 with share off
httpPortPref.value = 80;
ftpPortPref.value = 0;
doc.documentElement.acceptDialog();
// From now on, the dialog should close since we are giving it legitimate inputs.
// The test will timeout if the onbeforeaccept kicks in erroneously.
closeable = true;
// Both ports 80, share on
httpPortPref.value = 80;
ftpPortPref.value = 80;
doc.documentElement.acceptDialog();
// HTTP 80, FTP 0, with share on
yield setDoc();
proxyTypePref.value = 1;
sharePref.value = true;
ftpPref.value = "localhost";
httpPref.value = "localhost";
httpPortPref.value = 80;
ftpPortPref.value = 0;
doc.documentElement.acceptDialog();
// HTTP host empty, port 0 with share on
yield setDoc();
proxyTypePref.value = 1;
sharePref.value = true;
httpPref.value = "";
httpPortPref.value = 0;
doc.documentElement.acceptDialog();
// HTTP 0, but in no proxy mode
yield setDoc();
proxyTypePref.value = 0;
sharePref.value = true;
httpPref.value = "localhost";
httpPortPref.value = 0;
// This is the final test, don't spawn another connection window
finalTest = true;
doc.documentElement.acceptDialog();
yield setDoc();
}));
}

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