mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-11 20:35:50 +00:00
Merge autoland to m-c. a=merge
This commit is contained in:
commit
ee0df52b99
@ -5,6 +5,8 @@
|
||||
const LOGGER_NAME = "Toolkit.Telemetry";
|
||||
const LOGGER_PREFIX = "DataNotificationInfoBar::";
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Preferences",
|
||||
"resource://gre/modules/Preferences.jsm");
|
||||
/**
|
||||
* Represents an info bar that shows a data submission notification.
|
||||
*/
|
||||
@ -64,7 +66,13 @@ var gDataNotificationInfoBar = {
|
||||
popup: null,
|
||||
callback: () => {
|
||||
this._actionTaken = true;
|
||||
window.openAdvancedPreferences("dataChoicesTab");
|
||||
// The advanced subpanes are only supported in the old organization, which will
|
||||
// be removed by bug 1349689.
|
||||
if (Preferences.get("browser.preferences.useOldOrganization", false)) {
|
||||
window.openAdvancedPreferences("dataChoicesTab");
|
||||
} else {
|
||||
window.openPreferences("paneAdvanced");
|
||||
}
|
||||
},
|
||||
}];
|
||||
|
||||
|
@ -167,7 +167,7 @@ var gEMEHandler = {
|
||||
let mainAction = {
|
||||
label: gNavigatorBundle.getString(btnLabelId),
|
||||
accessKey: gNavigatorBundle.getString(btnAccessKeyId),
|
||||
callback() { openPreferences("paneContent"); },
|
||||
callback() { openPreferences("panePrivacy"); },
|
||||
dismiss: true
|
||||
};
|
||||
let options = {
|
||||
|
@ -13,6 +13,9 @@ Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/ContextualIdentityService.jsm");
|
||||
Cu.import("resource://gre/modules/NotificationDB.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Preferences",
|
||||
"resource://gre/modules/Preferences.jsm");
|
||||
|
||||
// lazy module getters
|
||||
|
||||
/* global AboutHome:false, AddonWatcher:false,
|
||||
@ -502,7 +505,14 @@ const gStoragePressureObserver = {
|
||||
label: prefStrBundle.getString(prefButtonLabelStringID),
|
||||
accessKey: prefStrBundle.getString(prefButtonAccesskeyStringID),
|
||||
callback(notificationBar, button) {
|
||||
gBrowser.ownerGlobal.openPreferences("advanced", { advancedTab: "networkTab" });
|
||||
// The advanced subpanes are only supported in the old organization, which will
|
||||
// be removed by bug 1349689.
|
||||
let win = gBrowser.ownerGlobal;
|
||||
if (Preferences.get("browser.preferences.useOldOrganization", false)) {
|
||||
win.openAdvancedPreferences("networkTab");
|
||||
} else {
|
||||
win.openPreferences("panePrivacy");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -6275,7 +6285,13 @@ var OfflineApps = {
|
||||
},
|
||||
|
||||
manage() {
|
||||
openAdvancedPreferences("networkTab");
|
||||
// The advanced subpanes are only supported in the old organization, which will
|
||||
// be removed by bug 1349689.
|
||||
if (Preferences.get("browser.preferences.useOldOrganization", false)) {
|
||||
openAdvancedPreferences("networkTab");
|
||||
} else {
|
||||
openPreferences("panePrivacy");
|
||||
}
|
||||
},
|
||||
|
||||
receiveMessage(msg) {
|
||||
|
@ -8,7 +8,7 @@ add_task(function* test_settingsOpen_observer() {
|
||||
gBrowser,
|
||||
url: "about:robots"
|
||||
}, function* dummyTabTask(aBrowser) {
|
||||
let tabPromise = BrowserTestUtils.waitForNewTab(gBrowser, "about:preferences#content");
|
||||
let tabPromise = BrowserTestUtils.waitForNewTab(gBrowser, "about:preferences#privacy");
|
||||
info("simulate a notifications-open-settings notification");
|
||||
let uri = NetUtil.newURI("https://example.com");
|
||||
let principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {});
|
||||
@ -40,7 +40,7 @@ add_task(function* test_settingsOpen_button() {
|
||||
}
|
||||
|
||||
let closePromise = promiseWindowClosed(alertWindow);
|
||||
let tabPromise = BrowserTestUtils.waitForNewTab(gBrowser, "about:preferences#content");
|
||||
let tabPromise = BrowserTestUtils.waitForNewTab(gBrowser, "about:preferences#privacy");
|
||||
let openSettingsMenuItem = alertWindow.document.getElementById("openSettingsMenuItem");
|
||||
openSettingsMenuItem.click();
|
||||
|
||||
|
@ -120,6 +120,16 @@ const SELECT_STYLE_OF_OPTION_IS_BASED_ON_FOCUS_OF_SELECT =
|
||||
' <option selected="true">{"end": "true"}</option>' +
|
||||
"</select></body></html>";
|
||||
|
||||
const SELECT_STYLE_OF_OPTION_CHANGES_AFTER_FOCUS_EVENT =
|
||||
"<html><body><select id='one'>" +
|
||||
' <option>{"color": "rgb(255, 0, 0)", "backgroundColor": "rgba(0, 0, 0, 0)"}</option>' +
|
||||
' <option selected="true">{"end": "true"}</option>' +
|
||||
"</select></body><scr" +
|
||||
"ipt>" +
|
||||
" var select = document.getElementById('one');" +
|
||||
" select.addEventListener('focus', () => select.style.color = 'red');" +
|
||||
"</script></html>";
|
||||
|
||||
function getSystemColor(color) {
|
||||
// Need to convert system color to RGB color.
|
||||
let textarea = document.createElementNS("http://www.w3.org/1999/xhtml", "textarea");
|
||||
@ -169,6 +179,15 @@ function* testSelectColors(select, itemCount, options) {
|
||||
yield BrowserTestUtils.synthesizeMouseAtCenter("#one", { type: "mousedown" }, gBrowser.selectedBrowser);
|
||||
yield popupShownPromise;
|
||||
|
||||
if (options.waitForComputedStyle) {
|
||||
let property = options.waitForComputedStyle.property;
|
||||
let value = options.waitForComputedStyle.value;
|
||||
yield BrowserTestUtils.waitForCondition(() => {
|
||||
info(`<select> has ${property}: ${getComputedStyle(selectPopup)[property]}`);
|
||||
return getComputedStyle(selectPopup)[property] == value;
|
||||
}, `Waiting for <select> to have ${property}: ${value}`);
|
||||
}
|
||||
|
||||
is(selectPopup.parentNode.itemCount, itemCount, "Correct number of items");
|
||||
let child = selectPopup.firstChild;
|
||||
let idx = 1;
|
||||
@ -335,3 +354,14 @@ add_task(function* test_style_of_options_is_dependent_on_focus_of_select() {
|
||||
|
||||
yield testSelectColors(SELECT_STYLE_OF_OPTION_IS_BASED_ON_FOCUS_OF_SELECT, 2, options);
|
||||
});
|
||||
|
||||
add_task(function* test_style_of_options_is_dependent_on_focus_of_select() {
|
||||
let options = {
|
||||
skipSelectColorTest: true,
|
||||
waitForComputedStyle: {
|
||||
property: "color",
|
||||
value: "rgb(255, 0, 0)"
|
||||
}
|
||||
};
|
||||
yield testSelectColors(SELECT_STYLE_OF_OPTION_CHANGES_AFTER_FOCUS_EVENT, 2, options);
|
||||
});
|
||||
|
@ -25,10 +25,8 @@ registerCleanupFunction(function() {
|
||||
function checkInContentPreferences(win) {
|
||||
let doc = win.document;
|
||||
let sel = doc.getElementById("categories").selectedItems[0].id;
|
||||
let tab = doc.getElementById("advancedPrefs").selectedTab.id;
|
||||
is(gBrowser.currentURI.spec, "about:preferences#advanced", "about:preferences loaded");
|
||||
is(sel, "category-advanced", "Advanced pane was selected");
|
||||
is(tab, "networkTab", "Network tab is selected");
|
||||
is(gBrowser.currentURI.spec, "about:preferences#privacy", "about:preferences loaded");
|
||||
is(sel, "category-privacy", "Privacy pane was selected");
|
||||
// all good, we are done.
|
||||
win.close();
|
||||
finish();
|
||||
|
@ -8,9 +8,9 @@ function notifyStoragePressure(usage = 100) {
|
||||
return notifyPromise;
|
||||
}
|
||||
|
||||
function advancedAboutPrefPromise() {
|
||||
function privacyAboutPrefPromise() {
|
||||
let promises = [
|
||||
BrowserTestUtils.waitForLocationChange(gBrowser, "about:preferences#advanced"),
|
||||
BrowserTestUtils.waitForLocationChange(gBrowser, "about:preferences#privacy"),
|
||||
TestUtils.topicObserved("advanced-pane-loaded", () => true)
|
||||
];
|
||||
return Promise.all(promises);
|
||||
@ -53,10 +53,10 @@ add_task(function* () {
|
||||
ok(notification instanceof XULElement, "Should display storage pressure notification");
|
||||
|
||||
let prefBtn = notification.getElementsByTagName("button")[1];
|
||||
let aboutPrefPromise = advancedAboutPrefPromise();
|
||||
let aboutPrefPromise = privacyAboutPrefPromise();
|
||||
prefBtn.doCommand();
|
||||
yield aboutPrefPromise;
|
||||
let prefDoc = gBrowser.selectedBrowser.contentDocument;
|
||||
let advancedPrefs = prefDoc.getElementById("advancedPrefs");
|
||||
is(advancedPrefs.selectedIndex, 2, "Should open the Network tab in about:preferences#advanced");
|
||||
let offlineGroup = prefDoc.getElementById("offlineGroup");
|
||||
is_element_visible(offlineGroup, "Should open the Network tab in about:preferences#privacy");
|
||||
});
|
||||
|
@ -24,7 +24,7 @@ add_task(function*() {
|
||||
yield loaded;
|
||||
yield popupclosed;
|
||||
|
||||
is(gBrowser.selectedBrowser.currentURI.spec, "about:preferences#search",
|
||||
is(gBrowser.selectedBrowser.currentURI.spec, "about:preferences#general",
|
||||
"Should have loaded the right page");
|
||||
});
|
||||
});
|
||||
|
@ -151,7 +151,7 @@ function* backgroundUpdateTest(url, id, checkIconFn) {
|
||||
is(win.gViewController.currentViewId, VIEW, "about:addons is at extensions list");
|
||||
|
||||
// Wait for the permission prompt and accept it this time
|
||||
updatePromise = promiseInstallEvent(addon, "onInstallEnded");
|
||||
updatePromise = waitForUpdate(addon);
|
||||
panel = yield popupPromise;
|
||||
panel.button.click();
|
||||
|
||||
@ -176,7 +176,6 @@ function checkDefaultIcon(icon) {
|
||||
|
||||
add_task(() => backgroundUpdateTest(`${BASE}/browser_webext_update1.xpi`,
|
||||
ID, checkDefaultIcon));
|
||||
|
||||
function checkNonDefaultIcon(icon) {
|
||||
// The icon should come from the extension, don't bother with the precise
|
||||
// path, just make sure we've got a jar url pointing to the right path
|
||||
@ -209,7 +208,7 @@ async function testNoPrompt(origUrl, id) {
|
||||
{once: true});
|
||||
|
||||
// Trigger an update check and wait for the update to be applied.
|
||||
let updatePromise = promiseInstallEvent(addon, "onInstallEnded");
|
||||
let updatePromise = waitForUpdate(addon);
|
||||
AddonManagerPrivate.backgroundUpdateCheck();
|
||||
await updatePromise;
|
||||
|
||||
@ -239,4 +238,3 @@ add_task(() => testNoPrompt(`${BASE}/browser_webext_update_perms1.xpi`,
|
||||
// doesn't show a prompt even when the webextension uses
|
||||
// promptable required permissions.
|
||||
add_task(() => testNoPrompt(`${BASE}/browser_legacy.xpi`, ID_LEGACY));
|
||||
|
||||
|
@ -34,7 +34,7 @@ async function testUpdateNoPrompt(filename, id,
|
||||
PopupNotifications.panel.addEventListener("popupshown", popupListener);
|
||||
|
||||
// Trigger an update check, we should see the update get applied
|
||||
let updatePromise = promiseInstallEvent(addon, "onInstallEnded");
|
||||
let updatePromise = waitForUpdate(addon);
|
||||
win.gViewController.doCommand("cmd_findAllUpdates");
|
||||
await updatePromise;
|
||||
|
||||
|
@ -7,8 +7,7 @@
|
||||
"update_link": "https://example.com/browser/browser/base/content/test/webextensions/browser_webext_update2.xpi",
|
||||
"applications": {
|
||||
"gecko": {
|
||||
"strict_min_version": "1",
|
||||
"advisory_max_version": "55.0"
|
||||
"strict_min_version": "1"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -21,8 +20,7 @@
|
||||
"update_link": "https://example.com/browser/browser/base/content/test/webextensions/browser_webext_update_icon2.xpi",
|
||||
"applications": {
|
||||
"gecko": {
|
||||
"strict_min_version": "1",
|
||||
"advisory_max_version": "55.0"
|
||||
"strict_min_version": "1"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -35,8 +33,7 @@
|
||||
"update_link": "https://example.com/browser/browser/base/content/test/webextensions/browser_webext_update_perms2.xpi",
|
||||
"applications": {
|
||||
"gecko": {
|
||||
"strict_min_version": "1",
|
||||
"advisory_max_version": "55.0"
|
||||
"strict_min_version": "1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,11 @@ const BASE = getRootDirectory(gTestPath)
|
||||
.replace("chrome://mochitests/content/", "https://example.com/");
|
||||
|
||||
Cu.import("resource:///modules/ExtensionsUI.jsm");
|
||||
XPCOMUtils.defineLazyGetter(this, "Management", () => {
|
||||
const {Management} = Components.utils.import("resource://gre/modules/Extension.jsm", {});
|
||||
return Management;
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Wait for the given PopupNotification to display
|
||||
@ -65,19 +70,58 @@ function promiseInstallEvent(addon, event) {
|
||||
* Resolves when the extension has been installed with the Addon
|
||||
* object as the resolution value.
|
||||
*/
|
||||
function promiseInstallAddon(url) {
|
||||
return AddonManager.getInstallForURL(url, null, "application/x-xpinstall")
|
||||
.then(install => {
|
||||
ok(install, "Created install");
|
||||
return new Promise(resolve => {
|
||||
install.addListener({
|
||||
onInstallEnded(_install, addon) {
|
||||
resolve(addon);
|
||||
},
|
||||
});
|
||||
install.install();
|
||||
});
|
||||
});
|
||||
async function promiseInstallAddon(url) {
|
||||
let install = await AddonManager.getInstallForURL(url, null, "application/x-xpinstall");
|
||||
install.install();
|
||||
|
||||
let addon = await new Promise(resolve => {
|
||||
install.addListener({
|
||||
onInstallEnded(_install, _addon) {
|
||||
resolve(_addon);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
if (addon.isWebExtension) {
|
||||
await new Promise(resolve => {
|
||||
function listener(event, extension) {
|
||||
if (extension.id == addon.id) {
|
||||
Management.off("ready", listener);
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
Management.on("ready", listener);
|
||||
});
|
||||
}
|
||||
|
||||
return addon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for an update to the given webextension to complete.
|
||||
* (This does not actually perform an update, it just watches for
|
||||
* the events that occur as a result of an update.)
|
||||
*
|
||||
* @param {AddonWrapper} addon
|
||||
* The addon to be updated.
|
||||
*
|
||||
* @returns {Promise}
|
||||
* Resolves when the extension has ben updated.
|
||||
*/
|
||||
async function waitForUpdate(addon) {
|
||||
let installPromise = promiseInstallEvent(addon, "onInstallEnded");
|
||||
let readyPromise = new Promise(resolve => {
|
||||
function listener(event, extension) {
|
||||
if (extension.id == addon.id) {
|
||||
Management.off("ready", listener);
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
Management.on("ready", listener);
|
||||
});
|
||||
|
||||
let [newAddon, ] = await Promise.all([installPromise, readyPromise]);
|
||||
return newAddon;
|
||||
}
|
||||
|
||||
function isDefaultIcon(icon) {
|
||||
|
@ -113,7 +113,9 @@ function getObserver() {
|
||||
},
|
||||
onBeginUpdateBatch: function() {},
|
||||
onEndUpdateBatch: function() {},
|
||||
onTitleChanged: function() {},
|
||||
onTitleChanged: function(uri, title) {
|
||||
this.emit("titleChanged", {url: uri.spec, title: title});
|
||||
},
|
||||
onClearHistory: function() {
|
||||
this.emit("visitRemoved", {allHistory: true, urls: []});
|
||||
},
|
||||
@ -241,6 +243,17 @@ extensions.registerSchemaAPI("history", "addon_parent", context => {
|
||||
getObserver().off("visitRemoved", listener);
|
||||
};
|
||||
}).api(),
|
||||
|
||||
onTitleChanged: new SingletonEventManager(context, "history.onTitleChanged", fire => {
|
||||
let listener = (event, data) => {
|
||||
fire.sync(data);
|
||||
};
|
||||
|
||||
getObserver().on("titleChanged", listener);
|
||||
return () => {
|
||||
getObserver().off("titleChanged", listener);
|
||||
};
|
||||
}).api(),
|
||||
},
|
||||
};
|
||||
});
|
||||
|
@ -310,6 +310,27 @@
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "onTitleChanged",
|
||||
"type": "function",
|
||||
"description": "Fired when the title of a URL is changed in the browser history.",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "changed",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "The URL for which the title has changed"
|
||||
},
|
||||
"title": {
|
||||
"type": "string",
|
||||
"description": "The new title for the URL."
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -422,6 +422,13 @@ add_task(function* test_on_visited() {
|
||||
{date: new Date(visitDate += 1000)},
|
||||
],
|
||||
},
|
||||
{
|
||||
url: SINGLE_VISIT_URL,
|
||||
title: "Title Changed",
|
||||
visits: [
|
||||
{date: new Date(visitDate)},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
function background() {
|
||||
@ -432,11 +439,16 @@ add_task(function* test_on_visited() {
|
||||
return;
|
||||
}
|
||||
onVisitedData.push(data);
|
||||
if (onVisitedData.length == 3) {
|
||||
if (onVisitedData.length == 4) {
|
||||
browser.test.sendMessage("on-visited-data", onVisitedData);
|
||||
}
|
||||
});
|
||||
|
||||
// Verifying onTitleChange Event along with onVisited event
|
||||
browser.history.onTitleChanged.addListener(data => {
|
||||
browser.test.sendMessage("on-title-changed-data", data);
|
||||
});
|
||||
|
||||
browser.test.sendMessage("ready");
|
||||
}
|
||||
|
||||
@ -483,5 +495,14 @@ add_task(function* test_on_visited() {
|
||||
expected.visitCount = 2;
|
||||
checkOnVisitedData(2, expected);
|
||||
|
||||
expected.url = PAGE_INFOS[2].url;
|
||||
expected.title = PAGE_INFOS[2].title;
|
||||
expected.time = PAGE_INFOS[2].visits[0].date.getTime();
|
||||
expected.visitCount = 2;
|
||||
checkOnVisitedData(3, expected);
|
||||
|
||||
let onTitleChangedData = yield extension.awaitMessage("on-title-changed-data");
|
||||
equal(onTitleChangedData.title, "Title Changed", "ontitleChanged received the expected title.");
|
||||
|
||||
yield extension.unload();
|
||||
});
|
||||
|
@ -72,7 +72,7 @@ SearchProvider.prototype = {
|
||||
|
||||
manageEngines(browser) {
|
||||
const browserWin = browser.ownerGlobal;
|
||||
browserWin.openPreferences("paneSearch");
|
||||
browserWin.openPreferences("paneGeneral");
|
||||
},
|
||||
|
||||
asyncGetState: Task.async(function*() {
|
||||
|
@ -205,7 +205,7 @@ BrowserGlue.prototype = {
|
||||
observe: function BG_observe(subject, topic, data) {
|
||||
switch (topic) {
|
||||
case "notifications-open-settings":
|
||||
this._openPreferences("content");
|
||||
this._openPreferences("privacy");
|
||||
break;
|
||||
case "prefservice:after-app-defaults":
|
||||
this._onAppDefaults();
|
||||
|
@ -9,9 +9,6 @@ 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 = {
|
||||
@ -27,11 +24,6 @@ var 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() {
|
||||
@ -50,101 +42,22 @@ var gAdvancedPane = {
|
||||
this.initSubmitHealthReport();
|
||||
}
|
||||
this.updateOnScreenKeyboardVisibility();
|
||||
this.updateCacheSizeInputField();
|
||||
this.updateActualCacheSize();
|
||||
|
||||
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);
|
||||
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 (Services.prefs.getBoolPref("browser.preferences.offlineGroup.enabled")) {
|
||||
this.updateOfflineApps();
|
||||
this.updateActualAppCacheSize();
|
||||
setEventListener("offlineNotifyExceptions", "command",
|
||||
gAdvancedPane.showOfflineExceptions);
|
||||
setEventListener("offlineAppsList", "select",
|
||||
gAdvancedPane.offlineAppSelected);
|
||||
setEventListener("offlineAppsListRemove", "command",
|
||||
gAdvancedPane.removeOfflineApp);
|
||||
setEventListener("clearOfflineAppCacheButton", "command",
|
||||
gAdvancedPane.clearOfflineAppCache);
|
||||
let bundlePrefs = document.getElementById("bundlePreferences");
|
||||
document.getElementById("offlineAppsList")
|
||||
.style.height = bundlePrefs.getString("offlineAppsList.height");
|
||||
let offlineGroup = document.getElementById("offlineGroup");
|
||||
offlineGroup.hidden = false;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
@ -212,26 +125,6 @@ var gAdvancedPane = {
|
||||
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,
|
||||
@ -337,326 +230,6 @@ var gAdvancedPane = {
|
||||
}
|
||||
},
|
||||
|
||||
// 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) {}
|
||||
},
|
||||
|
||||
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();
|
||||
},
|
||||
|
||||
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();
|
||||
}
|
||||
},
|
||||
|
||||
// Methods for Offline Apps(Appcache)
|
||||
|
||||
/**
|
||||
* Clears the application cache.
|
||||
*/
|
||||
clearOfflineAppCache() {
|
||||
Components.utils.import("resource:///modules/offlineAppCache.jsm");
|
||||
OfflineAppCacheHelper.clear();
|
||||
|
||||
this.updateActualAppCacheSize();
|
||||
this.updateOfflineApps();
|
||||
},
|
||||
|
||||
// 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) {}
|
||||
},
|
||||
|
||||
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();
|
||||
},
|
||||
// Methods for Offline Apps(Appcache) end
|
||||
|
||||
// UPDATE TAB
|
||||
|
||||
/*
|
||||
* Preferences:
|
||||
*
|
||||
@ -776,19 +349,6 @@ var gAdvancedPane = {
|
||||
* 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) {
|
||||
|
@ -12,69 +12,14 @@
|
||||
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 -->
|
||||
<!-- 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 -->
|
||||
<!-- Update tab -->
|
||||
#ifdef MOZ_UPDATER
|
||||
<preference id="app.update.enabled"
|
||||
name="app.update.enabled"
|
||||
@ -97,340 +42,108 @@
|
||||
<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/preferences.properties"/>
|
||||
|
||||
<hbox id="header-advanced"
|
||||
class="header"
|
||||
hidden="true"
|
||||
data-category="paneAdvanced">
|
||||
<label class="header-name" flex="1">&paneAdvanced.title;</label>
|
||||
<label class="header-name" flex="1">&paneUpdates.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" hidden="true">
|
||||
<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">
|
||||
<!-- Update -->
|
||||
#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>
|
||||
<groupbox id="updateApp" align="start" data-category="paneAdvanced" hidden="true">
|
||||
<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"/>
|
||||
<checkbox id="useService"
|
||||
label="&useService.label;"
|
||||
accesskey="&useService.accesskey;"
|
||||
preference="app.update.service.enabled"/>
|
||||
#endif
|
||||
</groupbox>
|
||||
</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>
|
||||
<groupbox id="updateOthers" align="start" data-category="paneAdvanced" hidden="true">
|
||||
<caption><label>&autoUpdateOthers.label;</label></caption>
|
||||
<checkbox id="enableSearchUpdate"
|
||||
label="&enableSearchUpdate.label;"
|
||||
accesskey="&enableSearchUpdate.accesskey;"
|
||||
preference="browser.search.update"/>
|
||||
</groupbox>
|
||||
|
||||
<!-- 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>
|
||||
<!-- Data Choices -->
|
||||
#ifdef MOZ_TELEMETRY_REPORTING
|
||||
<groupbox id="historyGroup" data-category="paneAdvanced" hidden="true">
|
||||
<caption><label>&reports.label;</label></caption>
|
||||
<vbox>
|
||||
<caption>
|
||||
<checkbox id="submitHealthReportBox" label="&enableHealthReport.label;"
|
||||
accesskey="&enableHealthReport.accesskey;"/>
|
||||
</caption>
|
||||
<hbox class="indent">
|
||||
<label>&healthReportDesc.label;</label>
|
||||
<label id="FHRLearnMore"
|
||||
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">
|
||||
<label id="telemetryDataDesc">&telemetryDesc.label;</label>
|
||||
<label id="telemetryLearnMore"
|
||||
class="learnMore text-link">&telemetryLearnMore.label;</label>
|
||||
</hbox>
|
||||
</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>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</groupbox>
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_DATA_REPORTING
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
<groupbox data-category="paneAdvanced" hidden="true">
|
||||
<caption>
|
||||
<checkbox id="automaticallySubmitCrashesBox"
|
||||
preference="browser.crashReports.unsubmittedCheck.autoSubmit"
|
||||
label="&alwaysSubmitCrashReports.label;"
|
||||
accesskey="&alwaysSubmitCrashReports.accesskey;"/>
|
||||
</caption>
|
||||
<hbox class="indent">
|
||||
<label>&crashReporterDesc2.label;</label>
|
||||
<label id="crashReporterLearnMore"
|
||||
class="learnMore text-link">&crashReporterLearnMore.label;</label>
|
||||
</hbox>
|
||||
</groupbox>
|
||||
|
||||
#endif
|
||||
#endif
|
@ -10,6 +10,8 @@
|
||||
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Components.utils.import("resource://gre/modules/AppConstants.jsm");
|
||||
Components.utils.import("resource://gre/modules/Task.jsm");
|
||||
|
||||
const TYPE_MAYBE_FEED = "application/vnd.mozilla.maybe.feed";
|
||||
const TYPE_MAYBE_VIDEO_FEED = "application/vnd.mozilla.maybe.video.feed";
|
||||
const TYPE_MAYBE_AUDIO_FEED = "application/vnd.mozilla.maybe.audio.feed";
|
||||
@ -910,6 +912,8 @@ var gApplicationsPane = {
|
||||
gApplicationsPane.onSelectionChanged);
|
||||
setEventListener("typeColumn", "click", gApplicationsPane.sort);
|
||||
setEventListener("actionColumn", "click", gApplicationsPane.sort);
|
||||
setEventListener("chooseFolder", "command", gApplicationsPane.chooseFolder);
|
||||
setEventListener("browser.download.dir", "change", gApplicationsPane.displayDownloadDirPref);
|
||||
|
||||
// Listen for window unload so we can remove our preference observers.
|
||||
window.addEventListener("unload", this);
|
||||
@ -1892,6 +1896,216 @@ var gApplicationsPane = {
|
||||
// the icon, or if we couldn't retrieve the icon for some other reason,
|
||||
// then use a generic icon.
|
||||
return ICON_URL_APP;
|
||||
}
|
||||
},
|
||||
|
||||
// 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;
|
||||
})
|
||||
|
||||
};
|
||||
|
@ -63,7 +63,7 @@
|
||||
class="header"
|
||||
hidden="true"
|
||||
data-category="paneApplications">
|
||||
<label class="header-name" flex="1">&paneApplications.title;</label>
|
||||
<label class="header-name" flex="1">&paneDownloadLinks.title;</label>
|
||||
<html:a class="help-button" target="_blank" aria-label="&helpButton.label;"></html:a>
|
||||
</hbox>
|
||||
|
||||
@ -71,6 +71,46 @@
|
||||
data-category="paneApplications"
|
||||
hidden="true"
|
||||
flex="1">
|
||||
|
||||
<!--Downloads-->
|
||||
<groupbox id="downloadsGroup"
|
||||
data-category="paneApplications"
|
||||
hidden="false">
|
||||
<caption><label>&downloads.label;</label></caption>
|
||||
|
||||
<radiogroup id="saveWhere"
|
||||
preference="browser.download.useDownloadDir"
|
||||
onsyncfrompreference="return gApplicationsPane.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 gApplicationsPane.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>
|
||||
<hbox>
|
||||
<textbox id="filter" flex="1"
|
||||
type="search"
|
||||
|
@ -1,283 +0,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/. */
|
||||
|
||||
/* 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;
|
||||
},
|
||||
};
|
@ -1,207 +0,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/.
|
||||
|
||||
<!-- 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/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>¬ificationsPolicy.label;</label></caption>
|
||||
<grid>
|
||||
<columns>
|
||||
<column flex="1"/>
|
||||
<column/>
|
||||
</columns>
|
||||
<rows>
|
||||
<row id="notificationsPolicyRow" align="center">
|
||||
<hbox align="start">
|
||||
<label id="notificationsPolicy">¬ificationsPolicyDesc3.label;</label>
|
||||
<label id="notificationsPolicyLearnMore"
|
||||
class="learnMore text-link"
|
||||
value="¬ificationsPolicyLearnMore.label;"/>
|
||||
</hbox>
|
||||
<hbox pack="end">
|
||||
<button id="notificationsPolicyButton" label="¬ificationsPolicyButton.label;"
|
||||
accesskey="¬ificationsPolicyButton.accesskey;"/>
|
||||
</hbox>
|
||||
</row>
|
||||
<row id="notificationsDoNotDisturbRow" hidden="true">
|
||||
<vbox align="start">
|
||||
<checkbox id="notificationsDoNotDisturb" label="¬ificationsDoNotDisturb.label;"
|
||||
accesskey="¬ificationsDoNotDisturb.accesskey;"/>
|
||||
<label id="notificationsDoNotDisturbDetails"
|
||||
class="indent"
|
||||
value="¬ificationsDoNotDisturbDetails.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>
|
@ -12,7 +12,4 @@ browser.jar:
|
||||
content/browser/preferences/in-content/containers.js
|
||||
content/browser/preferences/in-content/advanced.js
|
||||
content/browser/preferences/in-content/applications.js
|
||||
content/browser/preferences/in-content/content.js
|
||||
content/browser/preferences/in-content/sync.js
|
||||
content/browser/preferences/in-content/security.js
|
||||
content/browser/preferences/in-content/search.js
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -7,6 +7,11 @@
|
||||
<script type="application/javascript"
|
||||
src="chrome://browser/content/preferences/in-content/main.js"/>
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mozapps/content/preferences/fontbuilder.js"/>
|
||||
|
||||
<stringbundle id="engineManagerBundle" src="chrome://browser/locale/engineManager.properties"/>
|
||||
|
||||
<preferences id="mainPreferences" hidden="true" data-category="paneGeneral">
|
||||
|
||||
#ifdef E10S_TESTING_ONLY
|
||||
@ -53,6 +58,19 @@
|
||||
name="browser.privatebrowsing.autostart"
|
||||
type="bool"/>
|
||||
|
||||
<!-- Search Engine -->
|
||||
<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"/>
|
||||
|
||||
<!-- Downloads -->
|
||||
<preference id="browser.download.useDownloadDir"
|
||||
name="browser.download.useDownloadDir"
|
||||
@ -108,6 +126,60 @@
|
||||
<preference id="browser.ctrlTab.previews"
|
||||
name="browser.ctrlTab.previews"
|
||||
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"/>
|
||||
|
||||
<!-- General tab -->
|
||||
|
||||
<!-- Accessibility -->
|
||||
<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
|
||||
<!-- Browsing -->
|
||||
<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
|
||||
</preferences>
|
||||
|
||||
<hbox id="header-general"
|
||||
@ -226,44 +298,62 @@
|
||||
</html:table>
|
||||
</groupbox>
|
||||
|
||||
<!-- Downloads -->
|
||||
<groupbox id="downloadsGroup"
|
||||
data-category="paneGeneral"
|
||||
hidden="true">
|
||||
<caption><label>&downloads.label;</label></caption>
|
||||
<!-- Default Search Engine -->
|
||||
<groupbox id="defaultEngineGroup" align="start" data-category="paneGeneral">
|
||||
<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>
|
||||
|
||||
<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 id="oneClickSearchProvidersGroup" data-category="paneGeneral">
|
||||
<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>
|
||||
|
||||
<!-- Tab preferences -->
|
||||
@ -299,3 +389,145 @@
|
||||
preference="browser.taskbar.previews.enable"/>
|
||||
#endif
|
||||
</groupbox>
|
||||
|
||||
<!-- Accessibility -->
|
||||
<groupbox data-category="paneGeneral" 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>
|
||||
|
||||
<!-- Languages -->
|
||||
<groupbox id="languagesGroup" data-category="paneGeneral" 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 gMainPane.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>
|
||||
<hbox>
|
||||
<checkbox id="checkSpelling"
|
||||
label="&checkUserSpelling.label;"
|
||||
accesskey="&checkUserSpelling.accesskey;"
|
||||
onsyncfrompreference="return gMainPane.readCheckSpelling();"
|
||||
onsynctopreference="return gMainPane.writeCheckSpelling();"
|
||||
preference="layout.spellcheckDefault"/>
|
||||
</hbox>
|
||||
</groupbox>
|
||||
|
||||
|
||||
<!-- Fonts and Colors -->
|
||||
<groupbox id="fontsGroup" data-category="paneGeneral" 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>
|
||||
|
||||
<!-- Browsing -->
|
||||
<groupbox id="browsingGroup" align="start" data-category="paneGeneral">
|
||||
<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"/>
|
||||
</groupbox>
|
||||
|
@ -6,12 +6,9 @@
|
||||
/* 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 */
|
||||
|
||||
@ -57,14 +54,11 @@ function init_all() {
|
||||
|
||||
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));
|
||||
@ -123,29 +117,13 @@ function init_dynamic_padding() {
|
||||
|
||||
function telemetryBucketForCategory(category) {
|
||||
switch (category) {
|
||||
case "general":
|
||||
case "search":
|
||||
case "content":
|
||||
case "applications":
|
||||
case "advanced":
|
||||
case "containers":
|
||||
case "general":
|
||||
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";
|
||||
}
|
||||
@ -193,7 +171,7 @@ function gotoPref(aCategory) {
|
||||
mainContent.scrollTop = 0;
|
||||
|
||||
Services.telemetry
|
||||
.getHistogramById("FX_PREFERENCES_CATEGORY_OPENED")
|
||||
.getHistogramById("FX_PREFERENCES_CATEGORY_OPENED_V2")
|
||||
.add(telemetryBucketForCategory(friendlyName));
|
||||
}
|
||||
|
||||
|
@ -102,44 +102,14 @@
|
||||
<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;"
|
||||
tooltiptext="&paneDownloadLinks.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>
|
||||
<label class="category-name" flex="1">&paneDownloadLinks.title;</label>
|
||||
</richlistitem>
|
||||
|
||||
<richlistitem id="category-containers"
|
||||
@ -148,34 +118,34 @@
|
||||
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;"
|
||||
tooltiptext="&paneSync1.title;"
|
||||
align="center">
|
||||
<image class="category-icon"/>
|
||||
<label class="category-name" flex="1">&paneSync.title;</label>
|
||||
<label class="category-name" flex="1">&paneSync1.title;</label>
|
||||
</richlistitem>
|
||||
|
||||
<richlistitem id="category-privacy"
|
||||
class="category"
|
||||
value="panePrivacy"
|
||||
helpTopic="prefs-privacy"
|
||||
tooltiptext="&panePrivacySecurity.title;"
|
||||
align="center">
|
||||
<image class="category-icon"/>
|
||||
<label class="category-name" flex="1">&panePrivacySecurity.title;</label>
|
||||
</richlistitem>
|
||||
|
||||
<richlistitem id="category-advanced"
|
||||
class="category"
|
||||
value="paneAdvanced"
|
||||
helpTopic="prefs-advanced-general"
|
||||
tooltiptext="&paneAdvanced.title;"
|
||||
tooltiptext="&paneUpdates.title;"
|
||||
align="center">
|
||||
<image class="category-icon"/>
|
||||
<label class="category-name" flex="1">&paneAdvanced.title;</label>
|
||||
<label class="category-name" flex="1">&paneUpdates.title;</label>
|
||||
</richlistitem>
|
||||
</richlistbox>
|
||||
|
||||
@ -189,13 +159,10 @@
|
||||
<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>
|
||||
|
@ -11,8 +11,28 @@ XPCOMUtils.defineLazyModuleGetter(this, "ContextualIdentityService",
|
||||
"resource://gre/modules/ContextualIdentityService.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
|
||||
"resource://gre/modules/PluralForm.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "LoginHelper",
|
||||
"resource://gre/modules/LoginHelper.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "SiteDataManager",
|
||||
"resource:///modules/SiteDataManager.jsm");
|
||||
|
||||
Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||
|
||||
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 gPrivacyPane = {
|
||||
_pane: null,
|
||||
|
||||
/**
|
||||
* Whether the use has selected the auto-start private browsing mode in the UI.
|
||||
@ -180,6 +200,104 @@ var gPrivacyPane = {
|
||||
gPrivacyPane._checkBrowserContainers);
|
||||
setEventListener("browserContainersSettings", "command",
|
||||
gPrivacyPane.showContainerSettings);
|
||||
setEventListener("passwordExceptions", "command",
|
||||
gPrivacyPane.showPasswordExceptions);
|
||||
setEventListener("useMasterPassword", "command",
|
||||
gPrivacyPane.updateMasterPasswordButton);
|
||||
setEventListener("changeMasterPassword", "command",
|
||||
gPrivacyPane.changeMasterPassword);
|
||||
setEventListener("showPasswords", "command",
|
||||
gPrivacyPane.showPasswords);
|
||||
setEventListener("addonExceptions", "command",
|
||||
gPrivacyPane.showAddonExceptions);
|
||||
setEventListener("viewCertificatesButton", "command",
|
||||
gPrivacyPane.showCertificates);
|
||||
setEventListener("viewSecurityDevicesButton", "command",
|
||||
gPrivacyPane.showSecurityDevices);
|
||||
setEventListener("connectionSettings", "command",
|
||||
gPrivacyPane.showConnections);
|
||||
setEventListener("clearCacheButton", "command",
|
||||
gPrivacyPane.clearCache);
|
||||
|
||||
this._pane = document.getElementById("panePrivacy");
|
||||
this._initMasterPasswordUI();
|
||||
this._initSafeBrowsing();
|
||||
this.updateCacheSizeInputField();
|
||||
this.updateActualCacheSize();
|
||||
|
||||
setEventListener("notificationsPolicyButton", "command",
|
||||
gPrivacyPane.showNotificationExceptions);
|
||||
setEventListener("popupPolicyButton", "command",
|
||||
gPrivacyPane.showPopupExceptions);
|
||||
setEventListener("notificationsDoNotDisturb", "command",
|
||||
gPrivacyPane.toggleDoNotDisturbNotifications);
|
||||
|
||||
if (AlertsServiceDND) {
|
||||
let notificationsDoNotDisturbRow =
|
||||
document.getElementById("notificationsDoNotDisturbRow");
|
||||
notificationsDoNotDisturbRow.removeAttribute("hidden");
|
||||
if (AlertsServiceDND.manualDoNotDisturb) {
|
||||
let notificationsDoNotDisturb =
|
||||
document.getElementById("notificationsDoNotDisturb");
|
||||
notificationsDoNotDisturb.setAttribute("checked", true);
|
||||
}
|
||||
}
|
||||
|
||||
setEventListener("cacheSize", "change",
|
||||
gPrivacyPane.updateCacheSizePref);
|
||||
|
||||
if (Services.prefs.getBoolPref("browser.preferences.offlineGroup.enabled")) {
|
||||
this.updateOfflineApps();
|
||||
this.updateActualAppCacheSize();
|
||||
setEventListener("offlineNotifyExceptions", "command",
|
||||
gPrivacyPane.showOfflineExceptions);
|
||||
setEventListener("offlineAppsList", "select",
|
||||
gPrivacyPane.offlineAppSelected);
|
||||
setEventListener("offlineAppsListRemove", "command",
|
||||
gPrivacyPane.removeOfflineApp);
|
||||
setEventListener("clearOfflineAppCacheButton", "command",
|
||||
gPrivacyPane.clearOfflineAppCache);
|
||||
let bundlePrefs = document.getElementById("bundlePreferences");
|
||||
document.getElementById("offlineAppsList")
|
||||
.style.height = bundlePrefs.getString("offlineAppsList.height");
|
||||
let offlineGroup = document.getElementById("offlineGroup");
|
||||
offlineGroup.hidden = false;
|
||||
}
|
||||
|
||||
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",
|
||||
gPrivacyPane.clearSiteData);
|
||||
setEventListener("siteDataSettings", "command",
|
||||
gPrivacyPane.showSiteDataSettings);
|
||||
}
|
||||
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
// TRACKING PROTECTION MODE
|
||||
@ -691,6 +809,635 @@ var gPrivacyPane = {
|
||||
var settings = document.getElementById("browserContainersSettings");
|
||||
|
||||
settings.disabled = !pref.value;
|
||||
}
|
||||
},
|
||||
|
||||
toggleDoNotDisturbNotifications(event) {
|
||||
AlertsServiceDND.manualDoNotDisturb = event.target.checked;
|
||||
},
|
||||
|
||||
// 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);
|
||||
},
|
||||
|
||||
// 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
|
||||
*/
|
||||
|
||||
// POP-UPS
|
||||
|
||||
/**
|
||||
* 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;
|
||||
},
|
||||
|
||||
/**
|
||||
* 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 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");
|
||||
},
|
||||
|
||||
/**
|
||||
* 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;
|
||||
},
|
||||
|
||||
/**
|
||||
* 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;
|
||||
},
|
||||
|
||||
_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;
|
||||
},
|
||||
|
||||
/**
|
||||
* 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"
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* 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;
|
||||
},
|
||||
|
||||
/**
|
||||
* 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");
|
||||
},
|
||||
|
||||
// NETWORK
|
||||
/**
|
||||
* Displays a dialog in which proxy settings may be changed.
|
||||
*/
|
||||
showConnections() {
|
||||
gSubDialog.open("chrome://browser/content/preferences/connection.xul");
|
||||
},
|
||||
|
||||
/**
|
||||
* 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();
|
||||
},
|
||||
|
||||
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);
|
||||
},
|
||||
|
||||
|
||||
offlineAppSelected() {
|
||||
var removeButton = document.getElementById("offlineAppsListRemove");
|
||||
var list = document.getElementById("offlineAppsList");
|
||||
if (list.selectedItem) {
|
||||
removeButton.setAttribute("disabled", "false");
|
||||
} else {
|
||||
removeButton.setAttribute("disabled", "true");
|
||||
}
|
||||
},
|
||||
|
||||
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) {}
|
||||
},
|
||||
|
||||
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.
|
||||
*
|
||||
* Preferences:
|
||||
*
|
||||
* browser.cache.disk.capacity
|
||||
* - the size of the browser cache in KB
|
||||
* - Only used if browser.cache.disk.smart_size.enabled is disabled
|
||||
*/
|
||||
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;
|
||||
},
|
||||
|
||||
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();
|
||||
}
|
||||
},
|
||||
|
||||
// Methods for Offline Apps (AppCache)
|
||||
|
||||
/**
|
||||
* Clears the application cache.
|
||||
*/
|
||||
clearOfflineAppCache() {
|
||||
Components.utils.import("resource:///modules/offlineAppCache.jsm");
|
||||
OfflineAppCacheHelper.clear();
|
||||
|
||||
this.updateActualAppCacheSize();
|
||||
this.updateOfflineApps();
|
||||
},
|
||||
|
||||
// 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) {}
|
||||
},
|
||||
|
||||
readOfflineNotify() {
|
||||
var pref = document.getElementById("browser.offline-apps.notify");
|
||||
var button = document.getElementById("offlineNotifyExceptions");
|
||||
button.disabled = !pref.value;
|
||||
return pref.value;
|
||||
},
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
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);
|
||||
gPrivacyPane.offlineAppSelected();
|
||||
this.updateActualAppCacheSize();
|
||||
},
|
||||
// Methods for Offline Apps (AppCache) end
|
||||
};
|
||||
|
@ -76,72 +76,96 @@
|
||||
<preference id="browser.privatebrowsing.autostart"
|
||||
name="browser.privatebrowsing.autostart"
|
||||
type="bool"/>
|
||||
|
||||
<!-- 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"/>
|
||||
<!-- Passwords -->
|
||||
<preference id="signon.rememberSignons" name="signon.rememberSignons" type="bool"/>
|
||||
|
||||
<!-- 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"/>
|
||||
|
||||
<!-- 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"/>
|
||||
|
||||
<!-- 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"/>
|
||||
|
||||
<!-- 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"/>
|
||||
|
||||
</preferences>
|
||||
|
||||
<stringbundle id="bundlePreferences" src="chrome://browser/locale/preferences/preferences.properties"/>
|
||||
|
||||
<hbox id="header-privacy"
|
||||
class="header"
|
||||
hidden="true"
|
||||
data-category="panePrivacy">
|
||||
<label class="header-name" flex="1">&panePrivacy.title;</label>
|
||||
<label class="header-name" flex="1">&panePrivacySecurity.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">
|
||||
@ -265,6 +289,164 @@
|
||||
</deck>
|
||||
</groupbox>
|
||||
|
||||
<!-- Passwords -->
|
||||
<groupbox id="passwordsGroup" orient="vertical" data-category="panePrivacy" hidden="true">
|
||||
<caption><label>&formsAndPasswords.label;</label></caption>
|
||||
|
||||
<hbox id="savePasswordsBox">
|
||||
<checkbox id="savePasswords"
|
||||
label="&rememberLogins1.label;" accesskey="&rememberLogins1.accesskey;"
|
||||
preference="signon.rememberSignons"
|
||||
onsyncfrompreference="return gPrivacyPane.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>
|
||||
|
||||
<!-- Tracking -->
|
||||
<groupbox id="trackingGroup" data-category="panePrivacy" hidden="true">
|
||||
<vbox id="trackingprotectionbox" hidden="true">
|
||||
<hbox align="start">
|
||||
<vbox hidden="false">
|
||||
<caption><label>&trackingProtectionHeader2.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 hidden="true">
|
||||
<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 hidden="false">
|
||||
<description>&doNotTrack.pre.label;<label
|
||||
class="text-link" id="doNotTrackSettings"
|
||||
>&doNotTrack.settings.label;</label>&doNotTrack.post.label;</description>
|
||||
</vbox>
|
||||
</groupbox>
|
||||
|
||||
<!-- Pop-ups -->
|
||||
<groupbox id="miscGroup" data-category="panePrivacy" 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 gPrivacyPane.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>
|
||||
|
||||
<!-- Notifications -->
|
||||
<groupbox id="notificationsGroup" data-category="panePrivacy" hidden="true">
|
||||
<caption><label>¬ificationsPolicy.label;</label></caption>
|
||||
<grid>
|
||||
<columns>
|
||||
<column flex="1"/>
|
||||
<column/>
|
||||
</columns>
|
||||
<rows>
|
||||
<row id="notificationsPolicyRow" align="center">
|
||||
<hbox align="start">
|
||||
<label id="notificationsPolicy">¬ificationsPolicyDesc3.label;</label>
|
||||
<label id="notificationsPolicyLearnMore"
|
||||
class="learnMore text-link"
|
||||
value="¬ificationsPolicyLearnMore.label;"/>
|
||||
</hbox>
|
||||
<hbox pack="end">
|
||||
<button id="notificationsPolicyButton" label="¬ificationsPolicyButton.label;"
|
||||
accesskey="¬ificationsPolicyButton.accesskey;"/>
|
||||
</hbox>
|
||||
</row>
|
||||
<row id="notificationsDoNotDisturbRow" hidden="true">
|
||||
<vbox align="start">
|
||||
<checkbox id="notificationsDoNotDisturb" label="¬ificationsDoNotDisturb.label;"
|
||||
accesskey="¬ificationsDoNotDisturb.accesskey;"/>
|
||||
<label id="notificationsDoNotDisturbDetails"
|
||||
class="indent"
|
||||
value="¬ificationsDoNotDisturbDetails.value;"/>
|
||||
</vbox>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
</groupbox>
|
||||
|
||||
<!-- Location Bar -->
|
||||
<groupbox id="locationBarGroup"
|
||||
data-category="panePrivacy"
|
||||
@ -280,11 +462,106 @@
|
||||
<checkbox id="openpageSuggestion" label="&locbar.openpage.label;"
|
||||
accesskey="&locbar.openpage.accesskey;"
|
||||
preference="browser.urlbar.suggest.openpage"/>
|
||||
<label class="text-link" onclick="gotoPref('search')">
|
||||
<label class="text-link" onclick="gotoPref('general')">
|
||||
&suggestionSettings.label;
|
||||
</label>
|
||||
</groupbox>
|
||||
|
||||
<!-- addons, forgery (phishing) UI Security -->
|
||||
<groupbox id="addonsPhishingGroup" data-category="panePrivacy" hidden="true">
|
||||
<caption><label>&security.label;</label></caption>
|
||||
|
||||
<hbox id="addonInstallBox">
|
||||
<checkbox id="warnAddonInstall"
|
||||
label="&warnOnAddonInstall.label;"
|
||||
accesskey="&warnOnAddonInstall.accesskey;"
|
||||
preference="xpinstall.whitelist.required"
|
||||
onsyncfrompreference="return gPrivacyPane.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>
|
||||
|
||||
<!-- Certificates -->
|
||||
<groupbox id="certSelection" align="start" data-category="panePrivacy" hidden="true">
|
||||
<caption><label>&certificateTab.label;</label></caption>
|
||||
<description id="CertSelectionDesc" control="certSelection">&certPersonal.description;</description>
|
||||
|
||||
<!--
|
||||
The values on these radio buttons may look like l10n 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>
|
||||
<checkbox id="enableOCSP"
|
||||
label="&enableOCSP.label;"
|
||||
accesskey="&enableOCSP.accesskey;"
|
||||
onsyncfrompreference="return gPrivacyPane.readEnableOCSP();"
|
||||
onsynctopreference="return gPrivacyPane.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>
|
||||
</groupbox>
|
||||
|
||||
<!-- DRM Content -->
|
||||
<groupbox id="drmGroup" data-category="panePrivacy" 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>
|
||||
|
||||
<!-- Containers -->
|
||||
<groupbox id="browserContainersGroup" data-category="panePrivacy" hidden="true">
|
||||
<vbox id="browserContainersbox" hidden="true">
|
||||
@ -309,3 +586,94 @@
|
||||
</hbox>
|
||||
</vbox>
|
||||
</groupbox>
|
||||
|
||||
<!-- Network -->
|
||||
<!-- Connection -->
|
||||
<groupbox id="connectionGroup" data-category="panePrivacy" hidden="true">
|
||||
<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" data-category="panePrivacy" hidden="true">
|
||||
<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 gPrivacyPane.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" data-category="panePrivacy" hidden="true">
|
||||
<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 gPrivacyPane.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" data-category="panePrivacy">
|
||||
<caption><label>&siteData.label;</label></caption>
|
||||
|
||||
<hbox align="center">
|
||||
<label id="totalSiteDataSize" flex="1"></label>
|
||||
<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>
|
||||
|
@ -1,604 +0,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/. */
|
||||
|
||||
/* 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) { }
|
||||
};
|
@ -1,86 +0,0 @@
|
||||
<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/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>
|
@ -1,292 +0,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/. */
|
||||
|
||||
/* 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");
|
||||
}
|
||||
|
||||
};
|
@ -1,131 +0,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/.
|
||||
|
||||
<!-- Security panel -->
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://browser/content/preferences/in-content/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>
|
@ -32,7 +32,7 @@
|
||||
class="header"
|
||||
hidden="true"
|
||||
data-category="paneSync">
|
||||
<label class="header-name" flex="1">&paneSync.title;</label>
|
||||
<label class="header-name" flex="1">&paneSync1.title;</label>
|
||||
<html:a class="help-button text-link" target="_blank" aria-label="&helpButton.label;"></html:a>
|
||||
</hbox>
|
||||
|
||||
@ -191,8 +191,8 @@
|
||||
<textbox id="fxaSyncComputerName" disabled="true"/>
|
||||
<hbox>
|
||||
<button id="fxaChangeDeviceName"
|
||||
label="&changeSyncDeviceName.label;"
|
||||
accesskey="&changeSyncDeviceName.accesskey;"/>
|
||||
label="&changeSyncDeviceName1.label;"
|
||||
accesskey="&changeSyncDeviceName1.accesskey;"/>
|
||||
<button id="fxaCancelChangeDeviceName"
|
||||
label="&cancelChangeSyncDeviceName.label;"
|
||||
accesskey="&cancelChangeSyncDeviceName.accesskey;"
|
||||
|
@ -233,7 +233,7 @@ add_task(function* () {
|
||||
yield waitForEvent(gBrowser.selectedBrowser.contentWindow, "test-indexedDB-done");
|
||||
yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||
|
||||
yield openPreferencesViaOpenPreferencesAPI("advanced", "networkTab", { leaveOpen: true });
|
||||
yield openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
|
||||
|
||||
// Test the initial states
|
||||
let cacheUsage = yield cacheUsageGetter.get();
|
||||
@ -299,7 +299,7 @@ add_task(function* () {
|
||||
|
||||
mockSiteDataManager.register();
|
||||
let updatePromise = promiseSitesUpdated();
|
||||
yield openPreferencesViaOpenPreferencesAPI("advanced", "networkTab", { leaveOpen: true });
|
||||
yield openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
|
||||
yield updatePromise;
|
||||
yield openSettingsDialog();
|
||||
|
||||
@ -390,7 +390,7 @@ add_task(function* () {
|
||||
|
||||
mockSiteDataManager.register();
|
||||
let updatePromise = promiseSitesUpdated();
|
||||
yield openPreferencesViaOpenPreferencesAPI("advanced", "networkTab", { leaveOpen: true });
|
||||
yield openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
|
||||
yield updatePromise;
|
||||
yield openSettingsDialog();
|
||||
|
||||
@ -429,7 +429,7 @@ add_task(function* () {
|
||||
fakeOrigins.forEach(origin => addPersistentStoragePerm(origin));
|
||||
|
||||
let updatePromise = promiseSitesUpdated();
|
||||
yield openPreferencesViaOpenPreferencesAPI("advanced", "networkTab", { leaveOpen: true });
|
||||
yield openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
|
||||
yield updatePromise;
|
||||
yield openSettingsDialog();
|
||||
|
||||
@ -533,7 +533,7 @@ add_task(function* () {
|
||||
fakeOrigins.forEach(origin => addPersistentStoragePerm(origin));
|
||||
|
||||
let updatePromise = promiseSitesUpdated();
|
||||
yield openPreferencesViaOpenPreferencesAPI("advanced", "networkTab", { leaveOpen: true });
|
||||
yield openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
|
||||
yield updatePromise;
|
||||
yield openSettingsDialog();
|
||||
|
||||
@ -617,7 +617,7 @@ add_task(function* () {
|
||||
fakeOrigins.forEach(origin => addPersistentStoragePerm(origin));
|
||||
|
||||
let updatePromise = promiseSitesUpdated();
|
||||
yield openPreferencesViaOpenPreferencesAPI("advanced", "networkTab", { leaveOpen: true });
|
||||
yield openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
|
||||
yield updatePromise;
|
||||
yield openSettingsDialog();
|
||||
|
||||
|
@ -93,7 +93,7 @@ function formatInstallDate(sec) {
|
||||
registerCleanupFunction(resetPreferences);
|
||||
|
||||
add_task(function*() {
|
||||
yield openPreferencesViaOpenPreferencesAPI("advanced", "updateTab", { leaveOpen: true });
|
||||
yield openPreferencesViaOpenPreferencesAPI("advanced", { leaveOpen: true });
|
||||
resetPreferences();
|
||||
Services.prefs.setBoolPref("browser.search.update", false);
|
||||
|
||||
@ -112,7 +112,7 @@ add_task(function*() {
|
||||
add_task(function*() {
|
||||
mockUpdateManager.register();
|
||||
|
||||
yield openPreferencesViaOpenPreferencesAPI("advanced", "updateTab", { leaveOpen: true });
|
||||
yield openPreferencesViaOpenPreferencesAPI("advanced", { leaveOpen: true });
|
||||
let doc = gBrowser.selectedBrowser.contentDocument;
|
||||
|
||||
let showBtn = doc.getElementById("showUpdateHistory");
|
||||
|
@ -5,7 +5,7 @@ var container;
|
||||
SimpleTest.requestCompleteLog();
|
||||
|
||||
add_task(function* setup() {
|
||||
yield openPreferencesViaOpenPreferencesAPI("applications", null, {leaveOpen: true});
|
||||
yield openPreferencesViaOpenPreferencesAPI("applications", {leaveOpen: true});
|
||||
info("Preferences page opened on the applications pane.");
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
|
@ -5,7 +5,7 @@ registerCleanupFunction(function() {
|
||||
});
|
||||
|
||||
add_task(function*() {
|
||||
yield openPreferencesViaOpenPreferencesAPI("paneContent", null, {leaveOpen: true});
|
||||
yield openPreferencesViaOpenPreferencesAPI("paneGeneral", {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,
|
||||
|
@ -11,7 +11,7 @@ registerCleanupFunction(function() {
|
||||
add_task(function*() {
|
||||
originalWindowHeight = window.outerHeight;
|
||||
window.resizeTo(window.outerWidth, 300);
|
||||
let prefs = yield openPreferencesViaOpenPreferencesAPI("paneApplications", undefined, {leaveOpen: true});
|
||||
let prefs = yield openPreferencesViaOpenPreferencesAPI("paneApplications", {leaveOpen: true});
|
||||
is(prefs.selectedPane, "paneApplications", "Applications pane was selected");
|
||||
let mainContent = gBrowser.contentDocument.querySelector(".main-content");
|
||||
mainContent.scrollTop = 50;
|
||||
|
@ -8,11 +8,10 @@ registerCleanupFunction(function() {
|
||||
});
|
||||
|
||||
add_task(function*() {
|
||||
let prefs = yield openPreferencesViaOpenPreferencesAPI("paneContent");
|
||||
is(prefs.selectedPane, "paneContent", "Content pane was selected");
|
||||
prefs = yield openPreferencesViaOpenPreferencesAPI("advanced", "updateTab");
|
||||
let prefs = yield openPreferencesViaOpenPreferencesAPI("panePrivacy");
|
||||
is(prefs.selectedPane, "panePrivacy", "Privacy pane was selected");
|
||||
prefs = yield openPreferencesViaOpenPreferencesAPI("advanced");
|
||||
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");
|
||||
|
@ -40,7 +40,7 @@ add_task(function* () {
|
||||
yield checkPageScrolling(container, "radio");
|
||||
});
|
||||
|
||||
yield BrowserTestUtils.withNewTab({ gBrowser, url: "about:preferences#search" }, function* (browser) {
|
||||
yield BrowserTestUtils.withNewTab({ gBrowser, url: "about:preferences" }, function* (browser) {
|
||||
let doc = browser.contentDocument;
|
||||
let container = doc.getElementsByClassName("main-content")[0];
|
||||
|
||||
|
@ -22,7 +22,7 @@ function test() {
|
||||
getService(Ci.nsIHandlerService);
|
||||
hserv.store(info);
|
||||
|
||||
openPreferencesViaOpenPreferencesAPI("applications", null, {leaveOpen: true}).then(
|
||||
openPreferencesViaOpenPreferencesAPI("applications", {leaveOpen: true}).then(
|
||||
() => runTest(gBrowser.selectedBrowser.contentWindow)
|
||||
);
|
||||
}
|
||||
|
@ -37,8 +37,8 @@ function runTest(win) {
|
||||
gElements = tab.getElementById("mainPrefPane").children;
|
||||
|
||||
let panes = [
|
||||
"General", "Search", "Content", "Applications",
|
||||
"Privacy", "Security", "Sync", "Advanced",
|
||||
"General", "Applications",
|
||||
"Privacy", "Sync", "Advanced",
|
||||
];
|
||||
|
||||
for (let pane of panes) {
|
||||
|
@ -16,7 +16,7 @@ function setupFakeHandler() {
|
||||
|
||||
add_task(function*() {
|
||||
setupFakeHandler();
|
||||
yield openPreferencesViaOpenPreferencesAPI("applications", null, {leaveOpen: true});
|
||||
yield openPreferencesViaOpenPreferencesAPI("applications", {leaveOpen: true});
|
||||
info("Preferences page opened on the applications pane.");
|
||||
let win = gBrowser.selectedBrowser.contentWindow;
|
||||
|
||||
|
@ -334,7 +334,7 @@ var testRunner = {
|
||||
Services.prefs.clearUserPref("privacy.history.custom");
|
||||
});
|
||||
|
||||
openPreferencesViaOpenPreferencesAPI("panePrivacy", null, {leaveOpen: true}).then(function() {
|
||||
openPreferencesViaOpenPreferencesAPI("panePrivacy", {leaveOpen: true}).then(function() {
|
||||
let doc = gBrowser.contentDocument;
|
||||
let historyMode = doc.getElementById("historyMode");
|
||||
historyMode.value = "custom";
|
||||
|
@ -1,7 +1,7 @@
|
||||
add_task(function*() {
|
||||
is(gBrowser.currentURI.spec, "about:blank", "Test starts with about:blank open");
|
||||
yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:home");
|
||||
yield openPreferencesViaOpenPreferencesAPI("paneGeneral", null, {leaveOpen: true});
|
||||
yield openPreferencesViaOpenPreferencesAPI("paneGeneral", {leaveOpen: true});
|
||||
let doc = gBrowser.contentDocument;
|
||||
is(gBrowser.currentURI.spec, "about:preferences#general",
|
||||
"#general should be in the URI for about:preferences");
|
||||
|
@ -8,8 +8,8 @@ registerCleanupFunction(function() {
|
||||
});
|
||||
|
||||
add_task(function*() {
|
||||
let prefs = yield openPreferencesViaOpenPreferencesAPI("paneContent", undefined, {leaveOpen: true});
|
||||
is(prefs.selectedPane, "paneContent", "Content pane was selected");
|
||||
let prefs = yield openPreferencesViaOpenPreferencesAPI("panePrivacy", {leaveOpen: true});
|
||||
is(prefs.selectedPane, "panePrivacy", "Privacy pane was selected");
|
||||
|
||||
let doc = gBrowser.contentDocument;
|
||||
let notificationsDoNotDisturbRow = doc.getElementById("notificationsDoNotDisturbRow");
|
||||
|
@ -3,7 +3,7 @@
|
||||
const PERMISSIONS_URL = "chrome://browser/content/preferences/permissions.xul";
|
||||
|
||||
add_task(function* urlFieldVisibleForPopupPermissions(finish) {
|
||||
yield openPreferencesViaOpenPreferencesAPI("paneContent", null, {leaveOpen: true});
|
||||
yield openPreferencesViaOpenPreferencesAPI("panePrivacy", {leaveOpen: true});
|
||||
let win = gBrowser.selectedBrowser.contentWindow;
|
||||
let doc = win.document;
|
||||
let popupPolicyCheckbox = doc.getElementById("popupPolicy");
|
||||
@ -26,7 +26,7 @@ add_task(function* urlFieldVisibleForPopupPermissions(finish) {
|
||||
});
|
||||
|
||||
add_task(function* urlFieldHiddenForNotificationPermissions() {
|
||||
yield openPreferencesViaOpenPreferencesAPI("paneContent", null, {leaveOpen: true});
|
||||
yield openPreferencesViaOpenPreferencesAPI("panePrivacy", {leaveOpen: true});
|
||||
let win = gBrowser.selectedBrowser.contentWindow;
|
||||
let doc = win.document;
|
||||
let notificationsPolicyButton = doc.getElementById("notificationsPolicyButton");
|
||||
|
@ -28,12 +28,12 @@ add_task(function setup() {
|
||||
});
|
||||
|
||||
add_task(function* test_preference_enabled_when_unlocked() {
|
||||
yield openPreferencesViaOpenPreferencesAPI("panePrivacy", undefined, {leaveOpen: true});
|
||||
yield openPreferencesViaOpenPreferencesAPI("panePrivacy", {leaveOpen: true});
|
||||
testPrefStateMatchesLockedState();
|
||||
});
|
||||
|
||||
add_task(function* test_preference_disabled_when_locked() {
|
||||
Services.prefs.lockPref("privacy.sanitize.sanitizeOnShutdown");
|
||||
yield openPreferencesViaOpenPreferencesAPI("panePrivacy", undefined, {leaveOpen: true});
|
||||
yield openPreferencesViaOpenPreferencesAPI("panePrivacy", {leaveOpen: true});
|
||||
testPrefStateMatchesLockedState();
|
||||
});
|
||||
|
@ -8,7 +8,7 @@ registerCleanupFunction(() => {
|
||||
add_task(function*() {
|
||||
Services.prefs.setBoolPref("browser.search.suggest.enabled", true);
|
||||
|
||||
yield openPreferencesViaOpenPreferencesAPI("search", undefined, { leaveOpen: true });
|
||||
yield openPreferencesViaOpenPreferencesAPI("general", { leaveOpen: true });
|
||||
|
||||
let doc = gBrowser.selectedBrowser.contentDocument;
|
||||
let urlbarBox = doc.getElementById("urlBarSuggestion");
|
||||
@ -25,7 +25,7 @@ add_task(function*() {
|
||||
add_task(function*() {
|
||||
Services.prefs.setBoolPref("browser.search.suggest.enabled", false);
|
||||
|
||||
yield openPreferencesViaOpenPreferencesAPI("search", undefined, { leaveOpen: true });
|
||||
yield openPreferencesViaOpenPreferencesAPI("general", { leaveOpen: true });
|
||||
|
||||
let doc = gBrowser.selectedBrowser.contentDocument;
|
||||
let urlbarBox = doc.getElementById("urlBarSuggestion");
|
||||
|
@ -21,7 +21,7 @@ add_task(function*() {
|
||||
Services.prefs.setBoolPref("browser.safebrowsing.phishing.enabled", val1);
|
||||
Services.prefs.setBoolPref("browser.safebrowsing.malware.enabled", val2);
|
||||
|
||||
yield openPreferencesViaOpenPreferencesAPI("security", undefined, { leaveOpen: true });
|
||||
yield openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
|
||||
|
||||
let doc = gBrowser.selectedBrowser.contentDocument;
|
||||
let checkbox = doc.getElementById("enableSafeBrowsing");
|
||||
@ -33,7 +33,8 @@ add_task(function*() {
|
||||
is(blockDownloads.hasAttribute("disabled"), !checked, "block downloads checkbox is set correctly");
|
||||
is(blockUncommon.hasAttribute("disabled"), !checked, "block uncommon checkbox is set correctly");
|
||||
|
||||
// click the checkbox
|
||||
// scroll the checkbox into the viewport and click checkbox
|
||||
checkbox.scrollIntoView();
|
||||
EventUtils.synthesizeMouseAtCenter(checkbox, {}, gBrowser.selectedBrowser.contentWindow);
|
||||
|
||||
// check that both settings are now turned on or off
|
||||
@ -61,7 +62,7 @@ add_task(function*() {
|
||||
function* checkPrefSwitch(val) {
|
||||
Services.prefs.setBoolPref("browser.safebrowsing.downloads.enabled", val);
|
||||
|
||||
yield openPreferencesViaOpenPreferencesAPI("security", undefined, { leaveOpen: true });
|
||||
yield openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
|
||||
|
||||
let doc = gBrowser.selectedBrowser.contentDocument;
|
||||
let checkbox = doc.getElementById("blockDownloads");
|
||||
@ -71,7 +72,8 @@ add_task(function*() {
|
||||
// should be disabled when val is false (= pref is turned off)
|
||||
is(blockUncommon.hasAttribute("disabled"), !val, "block uncommon checkbox is set correctly");
|
||||
|
||||
// click the checkbox
|
||||
// scroll the checkbox into view, otherwise the synthesizeMouseAtCenter will be ignored, and click it
|
||||
checkbox.scrollIntoView();
|
||||
EventUtils.synthesizeMouseAtCenter(checkbox, {}, gBrowser.selectedBrowser.contentWindow);
|
||||
|
||||
// check that setting is now turned on or off
|
||||
@ -94,14 +96,15 @@ add_task(function*() {
|
||||
Services.prefs.setBoolPref("browser.safebrowsing.downloads.remote.block_potentially_unwanted", val1);
|
||||
Services.prefs.setBoolPref("browser.safebrowsing.downloads.remote.block_uncommon", val2);
|
||||
|
||||
yield openPreferencesViaOpenPreferencesAPI("security", undefined, { leaveOpen: true });
|
||||
yield openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
|
||||
|
||||
let doc = gBrowser.selectedBrowser.contentDocument;
|
||||
let checkbox = doc.getElementById("blockUncommonUnwanted");
|
||||
let checked = checkbox.checked;
|
||||
is(checked, val1 && val2, "unwanted/uncommon preference is initialized correctly");
|
||||
|
||||
// click the checkbox
|
||||
// scroll the checkbox into view, otherwise the synthesizeMouseAtCenter will be ignored, and click it
|
||||
checkbox.scrollIntoView();
|
||||
EventUtils.synthesizeMouseAtCenter(checkbox, {}, gBrowser.selectedBrowser.contentWindow);
|
||||
|
||||
// check that both settings are now turned on or off
|
||||
|
@ -119,21 +119,19 @@ function waitForEvent(aSubject, aEventName, aTimeoutMs, aTarget) {
|
||||
return eventDeferred.promise.then(cleanup, cleanup);
|
||||
}
|
||||
|
||||
function openPreferencesViaOpenPreferencesAPI(aPane, aAdvancedTab, aOptions) {
|
||||
function openPreferencesViaOpenPreferencesAPI(aPane, aOptions) {
|
||||
let deferred = Promise.defer();
|
||||
gBrowser.selectedTab = gBrowser.addTab("about:blank");
|
||||
openPreferences(aPane, aAdvancedTab ? {advancedTab: aAdvancedTab} : undefined);
|
||||
openPreferences(aPane);
|
||||
let newTabBrowser = gBrowser.selectedBrowser;
|
||||
|
||||
newTabBrowser.addEventListener("Initialized", function() {
|
||||
newTabBrowser.contentWindow.addEventListener("load", function() {
|
||||
let win = gBrowser.contentWindow;
|
||||
let selectedPane = win.history.state;
|
||||
let doc = win.document;
|
||||
let selectedAdvancedTab = aAdvancedTab && doc.getElementById("advancedPrefs").selectedTab.id;
|
||||
if (!aOptions || !aOptions.leaveOpen)
|
||||
gBrowser.removeCurrentTab();
|
||||
deferred.resolve({selectedPane, selectedAdvancedTab});
|
||||
deferred.resolve({selectedPane});
|
||||
}, {once: true});
|
||||
}, {capture: true, once: true});
|
||||
|
||||
|
@ -1420,7 +1420,7 @@
|
||||
<method name="showSettings">
|
||||
<body><![CDATA[
|
||||
BrowserUITelemetry.countSearchSettingsEvent(this.telemetryOrigin);
|
||||
openPreferences("paneSearch");
|
||||
openPreferences("paneGeneral");
|
||||
// If the preference tab was already selected, the panel doesn't
|
||||
// close itself automatically.
|
||||
this.popup.hidePopup();
|
||||
|
@ -41,7 +41,7 @@
|
||||
<p>&searchreset.pageInfo1;</p>
|
||||
<p>&searchreset.selector.label;<span id="defaultEngine"/></p>
|
||||
|
||||
<p>&searchreset.beforelink.pageInfo2;<a id="linkSettingsPage" href="about:preferences#search">&searchreset.link.pageInfo2;</a>&searchreset.afterlink.pageInfo2;</p>
|
||||
<p>&searchreset.beforelink.pageInfo2;<a id="linkSettingsPage" href="about:preferences">&searchreset.link.pageInfo2;</a>&searchreset.afterlink.pageInfo2;</p>
|
||||
</div>
|
||||
|
||||
<div class="button-container">
|
||||
|
@ -106,7 +106,7 @@ var gTests = [
|
||||
*run() {
|
||||
let loadPromise = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser,
|
||||
false,
|
||||
"about:preferences#search")
|
||||
"about:preferences")
|
||||
gBrowser.contentDocument.getElementById("linkSettingsPage").click();
|
||||
yield loadPromise;
|
||||
|
||||
|
@ -72,7 +72,7 @@ add_task(function* test_yandex_attribution() {
|
||||
|
||||
add_task(function* test_preference_attribution() {
|
||||
|
||||
let prefUrl = "about:preferences#content";
|
||||
let prefUrl = "about:preferences#general";
|
||||
let tab = yield promiseTestPageLoad(prefUrl);
|
||||
|
||||
let browser = gBrowser.getBrowserForTab(tab);
|
||||
|
@ -126,7 +126,7 @@
|
||||
label="&translation.options.neverForSite.label;"
|
||||
accesskey="&translation.options.neverForSite.accesskey;"/>
|
||||
<xul:menuseparator/>
|
||||
<xul:menuitem oncommand="openPreferences('paneContent');"
|
||||
<xul:menuitem oncommand="openPreferences('paneGeneral');"
|
||||
label="&translation.options.preferences.label;"
|
||||
accesskey="&translation.options.preferences.accesskey;"/>
|
||||
<xul:menuitem class="subviewbutton panel-subview-footer"
|
||||
|
19
browser/extensions/e10srollout/bootstrap.js
vendored
19
browser/extensions/e10srollout/bootstrap.js
vendored
@ -9,6 +9,7 @@ const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
Cu.import("resource://gre/modules/Preferences.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/UpdateUtils.jsm");
|
||||
Cu.import("resource://gre/modules/AppConstants.jsm");
|
||||
|
||||
// The amount of people to be part of e10s
|
||||
const TEST_THRESHOLD = {
|
||||
@ -23,6 +24,24 @@ const ADDON_ROLLOUT_POLICY = {
|
||||
"esr": "esrA", // WebExtensions and Addons with mpc=true
|
||||
};
|
||||
|
||||
if (AppConstants.RELEASE_OR_BETA) {
|
||||
// Bug 1348576 - e10s is never enabled for non-official release builds
|
||||
// This is hacky, but the problem it solves is the following:
|
||||
// the e10s rollout is controlled by the channel name, which
|
||||
// is the only way to distinguish between Beta and Release.
|
||||
// However, non-official release builds (like the ones done by distros
|
||||
// to ship Firefox on their package managers) do not set a value
|
||||
// for the release channel, which gets them to the default value
|
||||
// of.. (drumroll) "default".
|
||||
// But we can't just always configure the same settings for the
|
||||
// "default" channel because that's also the name that a locally
|
||||
// built Firefox gets, and e10s is managed in a different way
|
||||
// there (directly by prefs, on Nightly and Aurora).
|
||||
TEST_THRESHOLD.default = TEST_THRESHOLD.release;
|
||||
ADDON_ROLLOUT_POLICY.default = ADDON_ROLLOUT_POLICY.release;
|
||||
}
|
||||
|
||||
|
||||
const PREF_COHORT_SAMPLE = "e10s.rollout.cohortSample";
|
||||
const PREF_COHORT_NAME = "e10s.rollout.cohort";
|
||||
const PREF_E10S_OPTED_IN = "browser.tabs.remote.autostart";
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
<Description about="urn:mozilla:install-manifest">
|
||||
<em:id>e10srollout@mozilla.org</em:id>
|
||||
<em:version>1.14</em:version>
|
||||
<em:version>1.15</em:version>
|
||||
<em:type>2</em:type>
|
||||
<em:bootstrap>true</em:bootstrap>
|
||||
<em:multiprocessCompatible>true</em:multiprocessCompatible>
|
||||
|
@ -163,6 +163,7 @@ let ProfileAutocomplete = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
|
||||
|
||||
_lastAutoCompleteResult: null,
|
||||
_lastAutoCompleteFocusedInput: null,
|
||||
_registered: false,
|
||||
_factory: null,
|
||||
|
||||
@ -196,6 +197,7 @@ let ProfileAutocomplete = {
|
||||
|
||||
setProfileAutoCompleteResult(result) {
|
||||
this._lastAutoCompleteResult = result;
|
||||
this._lastAutoCompleteFocusedInput = formFillController.focusedInput;
|
||||
},
|
||||
|
||||
observe(subject, topic, data) {
|
||||
@ -218,6 +220,16 @@ let ProfileAutocomplete = {
|
||||
.getInterface(Ci.nsIContentFrameMessageManager);
|
||||
},
|
||||
|
||||
_getSelectedIndex(contentWindow) {
|
||||
let mm = this._frameMMFromWindow(contentWindow);
|
||||
let selectedIndexResult = mm.sendSyncMessage("FormAutoComplete:GetSelectedIndex", {});
|
||||
if (selectedIndexResult.length != 1 || !Number.isInteger(selectedIndexResult[0])) {
|
||||
throw new Error("Invalid autocomplete selectedIndex");
|
||||
}
|
||||
|
||||
return selectedIndexResult[0];
|
||||
},
|
||||
|
||||
_fillFromAutocompleteRow(focusedInput) {
|
||||
this.log.debug("_fillFromAutocompleteRow:", focusedInput);
|
||||
let formDetails = FormAutofillContent.getFormDetails(focusedInput);
|
||||
@ -226,13 +238,7 @@ let ProfileAutocomplete = {
|
||||
return;
|
||||
}
|
||||
|
||||
let mm = this._frameMMFromWindow(focusedInput.ownerGlobal);
|
||||
let selectedIndexResult = mm.sendSyncMessage("FormAutoComplete:GetSelectedIndex", {});
|
||||
if (selectedIndexResult.length != 1 || !Number.isInteger(selectedIndexResult[0])) {
|
||||
throw new Error("Invalid autocomplete selectedIndex");
|
||||
}
|
||||
let selectedIndex = selectedIndexResult[0];
|
||||
|
||||
let selectedIndex = this._getSelectedIndex(focusedInput.ownerGlobal);
|
||||
if (selectedIndex == -1 ||
|
||||
!this._lastAutoCompleteResult ||
|
||||
this._lastAutoCompleteResult.getStyleAt(selectedIndex) != "autofill-profile") {
|
||||
@ -244,6 +250,35 @@ let ProfileAutocomplete = {
|
||||
|
||||
formHandler.autofillFormFields(profile, focusedInput);
|
||||
},
|
||||
|
||||
_clearProfilePreview() {
|
||||
let focusedInput = formFillController.focusedInput || this._lastAutoCompleteFocusedInput;
|
||||
if (!focusedInput || !FormAutofillContent.getFormDetails(focusedInput)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let formHandler = FormAutofillContent.getFormHandler(focusedInput);
|
||||
|
||||
formHandler.clearPreviewedFormFields();
|
||||
},
|
||||
|
||||
_previewSelectedProfile(selectedIndex) {
|
||||
let focusedInput = formFillController.focusedInput;
|
||||
if (!focusedInput || !FormAutofillContent.getFormDetails(focusedInput)) {
|
||||
// The observer notification is for a different process/frame.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this._lastAutoCompleteResult ||
|
||||
this._lastAutoCompleteResult.getStyleAt(selectedIndex) != "autofill-profile") {
|
||||
return;
|
||||
}
|
||||
|
||||
let profile = JSON.parse(this._lastAutoCompleteResult.getCommentAt(selectedIndex));
|
||||
let formHandler = FormAutofillContent.getFormHandler(focusedInput);
|
||||
|
||||
formHandler.previewFormFields(profile);
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
@ -303,7 +338,8 @@ var FormAutofillContent = {
|
||||
getInputDetails(element) {
|
||||
let formDetails = this.getFormDetails(element);
|
||||
for (let detail of formDetails) {
|
||||
if (element == detail.element) {
|
||||
let detailElement = detail.elementWeakRef.get();
|
||||
if (detailElement && element == detailElement) {
|
||||
return detail;
|
||||
}
|
||||
}
|
||||
@ -376,13 +412,29 @@ var FormAutofillContent = {
|
||||
|
||||
this._formsDetails.set(form.rootElement, formHandler);
|
||||
this.log.debug("Adding form handler to _formsDetails:", formHandler);
|
||||
formHandler.fieldDetails.forEach(detail => this._markAsAutofillField(detail.element));
|
||||
formHandler.fieldDetails.forEach(detail =>
|
||||
this._markAsAutofillField(detail.elementWeakRef.get())
|
||||
);
|
||||
});
|
||||
},
|
||||
|
||||
_markAsAutofillField(field) {
|
||||
if (!field) {
|
||||
return;
|
||||
}
|
||||
|
||||
formFillController.markAsAutofillField(field);
|
||||
},
|
||||
|
||||
_previewProfile(doc) {
|
||||
let selectedIndex = ProfileAutocomplete._getSelectedIndex(doc.ownerGlobal);
|
||||
|
||||
if (selectedIndex === -1) {
|
||||
ProfileAutocomplete._clearProfilePreview();
|
||||
} else {
|
||||
ProfileAutocomplete._previewSelectedProfile(selectedIndex);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
@ -85,7 +85,7 @@ FormAutofillHandler.prototype = {
|
||||
addressType: info.addressType,
|
||||
contactType: info.contactType,
|
||||
fieldName: info.fieldName,
|
||||
element, // TODO: Apply Cu.getWeakReference and use get API for strong ref.
|
||||
elementWeakRef: Cu.getWeakReference(element),
|
||||
};
|
||||
|
||||
this.fieldDetails.push(formatWithElement);
|
||||
@ -113,15 +113,52 @@ FormAutofillHandler.prototype = {
|
||||
// 2. a non-empty input field
|
||||
// 3. the invalid value set
|
||||
|
||||
if (fieldDetail.element === focusedInput ||
|
||||
fieldDetail.element.value) {
|
||||
let element = fieldDetail.elementWeakRef.get();
|
||||
if (!element || element === focusedInput || element.value) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let value = profile[fieldDetail.fieldName];
|
||||
if (value) {
|
||||
fieldDetail.element.setUserInput(value);
|
||||
element.setUserInput(value);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Populates result to the preview layers with given profile.
|
||||
*
|
||||
* @param {Object} profile
|
||||
* A profile to be previewed with
|
||||
*/
|
||||
previewFormFields(profile) {
|
||||
log.debug("preview profile in autofillFormFields:", profile);
|
||||
/*
|
||||
for (let fieldDetail of this.fieldDetails) {
|
||||
let value = profile[fieldDetail.fieldName] || "";
|
||||
|
||||
// Skip the fields that already has text entered
|
||||
if (fieldDetail.element.value) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: Set highlight style and preview text.
|
||||
}
|
||||
*/
|
||||
},
|
||||
|
||||
clearPreviewedFormFields() {
|
||||
log.debug("clear previewed fields in:", this.form);
|
||||
/*
|
||||
for (let fieldDetail of this.fieldDetails) {
|
||||
// TODO: Clear preview text
|
||||
|
||||
// We keep the highlight of all fields if this form has
|
||||
// already been auto-filled with a profile.
|
||||
if (this.filledProfileGUID == null) {
|
||||
// TODO: Remove highlight style
|
||||
}
|
||||
}
|
||||
*/
|
||||
},
|
||||
};
|
||||
|
@ -8,6 +8,8 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
/* global content */
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
@ -22,6 +24,8 @@ Cu.import("resource://formautofill/FormAutofillContent.jsm");
|
||||
var FormAutofillFrameScript = {
|
||||
init() {
|
||||
addEventListener("DOMContentLoaded", this);
|
||||
addMessageListener("FormAutofill:PreviewProfile", this);
|
||||
addMessageListener("FormAutoComplete:PopupClosed", this);
|
||||
},
|
||||
|
||||
handleEvent(evt) {
|
||||
@ -44,6 +48,19 @@ var FormAutofillFrameScript = {
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
receiveMessage(aMessage) {
|
||||
if (!Services.prefs.getBoolPref("browser.formautofill.enabled")) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (aMessage.name) {
|
||||
case "FormAutofill:PreviewProfile":
|
||||
case "FormAutoComplete:PopupClosed":
|
||||
FormAutofillContent._previewProfile(content.document);
|
||||
break;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
FormAutofillFrameScript.init();
|
||||
|
@ -43,6 +43,23 @@
|
||||
]]>
|
||||
</constructor>
|
||||
|
||||
<property name="selected" onget="return this.getAttribute('selected') == 'true';">
|
||||
<setter><![CDATA[
|
||||
/* global Cu */
|
||||
if (val) {
|
||||
this.setAttribute("selected", "true");
|
||||
} else {
|
||||
this.removeAttribute("selected");
|
||||
}
|
||||
|
||||
let {AutoCompletePopup} = Cu.import("resource://gre/modules/AutoCompletePopup.jsm", {});
|
||||
|
||||
AutoCompletePopup.sendMessageToBrowser("FormAutofill:PreviewProfile");
|
||||
|
||||
return val;
|
||||
]]></setter>
|
||||
</property>
|
||||
|
||||
<method name="_cleanup">
|
||||
<body>
|
||||
<![CDATA[
|
||||
@ -51,6 +68,10 @@
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="_onChanged">
|
||||
<body></body>
|
||||
</method>
|
||||
|
||||
<method name="_onOverflow">
|
||||
<body></body>
|
||||
</method>
|
||||
|
@ -141,6 +141,7 @@ const TESTCASES = [
|
||||
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "country", "element": {}},
|
||||
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "email", "element": {}},
|
||||
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "tel", "element": {}},
|
||||
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "organization", "element": null},
|
||||
],
|
||||
profileData: {
|
||||
"guid": "123",
|
||||
@ -175,7 +176,7 @@ for (let tc of TESTCASES) {
|
||||
handler.fieldDetails = testcase.fieldDetails;
|
||||
handler.fieldDetails.forEach((field, index) => {
|
||||
let element = doc.querySelectorAll("input")[index];
|
||||
field.element = element;
|
||||
field.elementWeakRef = Cu.getWeakReference(element);
|
||||
if (!testcase.profileData[field.fieldName]) {
|
||||
// Avoid waiting for `change` event of a input with a blank value to
|
||||
// be filled.
|
||||
|
@ -25,11 +25,11 @@ const TESTCASES = [
|
||||
<input id="email" autocomplete="email">
|
||||
<input id="tel" autocomplete="tel"></form>`,
|
||||
fieldDetails: [
|
||||
{"section": "", "addressType": "", "contactType": "", "fieldName": "street-address", "element": {}},
|
||||
{"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2", "element": {}},
|
||||
{"section": "", "addressType": "", "contactType": "", "fieldName": "country", "element": {}},
|
||||
{"section": "", "addressType": "", "contactType": "", "fieldName": "email", "element": {}},
|
||||
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel", "element": {}},
|
||||
{"section": "", "addressType": "", "contactType": "", "fieldName": "street-address"},
|
||||
{"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2"},
|
||||
{"section": "", "addressType": "", "contactType": "", "fieldName": "country"},
|
||||
{"section": "", "addressType": "", "contactType": "", "fieldName": "email"},
|
||||
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel"},
|
||||
],
|
||||
},
|
||||
{
|
||||
@ -42,11 +42,11 @@ const TESTCASES = [
|
||||
<input id='email' autocomplete="shipping email">
|
||||
<input id="tel" autocomplete="shipping tel"></form>`,
|
||||
fieldDetails: [
|
||||
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "street-address", "element": {}},
|
||||
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "address-level2", "element": {}},
|
||||
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "country", "element": {}},
|
||||
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "email", "element": {}},
|
||||
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "tel", "element": {}},
|
||||
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "street-address"},
|
||||
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "address-level2"},
|
||||
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "country"},
|
||||
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "email"},
|
||||
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "tel"},
|
||||
],
|
||||
},
|
||||
{
|
||||
@ -59,11 +59,11 @@ const TESTCASES = [
|
||||
<input id='email' autocomplete="shipping email">
|
||||
<input id="tel" autocomplete="shipping tel"></form>`,
|
||||
fieldDetails: [
|
||||
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "street-address", "element": {}},
|
||||
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "address-level2", "element": {}},
|
||||
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "country", "element": {}},
|
||||
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "email", "element": {}},
|
||||
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "tel", "element": {}},
|
||||
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "street-address"},
|
||||
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "address-level2"},
|
||||
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "country"},
|
||||
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "email"},
|
||||
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "tel"},
|
||||
],
|
||||
},
|
||||
];
|
||||
@ -77,12 +77,22 @@ for (let tc of TESTCASES) {
|
||||
let doc = MockDocument.createTestDocument("http://localhost:8080/test/",
|
||||
testcase.document);
|
||||
let form = doc.querySelector("form");
|
||||
|
||||
testcase.fieldDetails.forEach((detail) => {
|
||||
detail.elementWeakRef = Cu.getWeakReference(doc.querySelector(
|
||||
"input[autocomplete*='" + detail.fieldName + "']"));
|
||||
});
|
||||
let handler = new FormAutofillHandler(form);
|
||||
|
||||
handler.collectFormFields();
|
||||
|
||||
Assert.deepEqual(handler.fieldDetails, testcase.fieldDetails,
|
||||
"Check the fieldDetails were set correctly");
|
||||
handler.fieldDetails.forEach((detail, index) => {
|
||||
Assert.equal(detail.section, testcase.fieldDetails[index].section);
|
||||
Assert.equal(detail.addressType, testcase.fieldDetails[index].addressType);
|
||||
Assert.equal(detail.contactType, testcase.fieldDetails[index].contactType);
|
||||
Assert.equal(detail.fieldName, testcase.fieldDetails[index].fieldName);
|
||||
Assert.equal(detail.elementWeakRef.get(), testcase.fieldDetails[index].elementWeakRef.get());
|
||||
});
|
||||
});
|
||||
})();
|
||||
}
|
||||
|
@ -70,6 +70,13 @@ const TESTCASES = [
|
||||
},
|
||||
];
|
||||
|
||||
function inputDetailAssertion(detail, expected) {
|
||||
Assert.equal(detail.section, expected.section);
|
||||
Assert.equal(detail.addressType, expected.addressType);
|
||||
Assert.equal(detail.contactType, expected.contactType);
|
||||
Assert.equal(detail.fieldName, expected.fieldName);
|
||||
Assert.equal(detail.elementWeakRef.get(), expected.elementWeakRef.get());
|
||||
}
|
||||
|
||||
TESTCASES.forEach(testcase => {
|
||||
add_task(function* () {
|
||||
@ -84,21 +91,22 @@ TESTCASES.forEach(testcase => {
|
||||
|
||||
// Put the input element reference to `element` to make sure the result of
|
||||
// `getInputDetails` contains the same input element.
|
||||
testcase.expectedResult[i].input.element = input;
|
||||
Assert.deepEqual(FormAutofillContent.getInputDetails(input),
|
||||
testcase.expectedResult[i].input,
|
||||
"Check if returned input information is correct.");
|
||||
testcase.expectedResult[i].input.elementWeakRef = Cu.getWeakReference(input);
|
||||
|
||||
inputDetailAssertion(FormAutofillContent.getInputDetails(input),
|
||||
testcase.expectedResult[i].input);
|
||||
|
||||
let formDetails = testcase.expectedResult[i].form;
|
||||
for (let formDetail of formDetails) {
|
||||
// Compose a query string to get the exact reference of the input
|
||||
// element, e.g. #form1 > input[autocomplete="street-address"]
|
||||
let queryString = "#" + testcase.expectedResult[i].formId + " > input[autocomplete=" + formDetail.fieldName + "]";
|
||||
formDetail.element = doc.querySelector(queryString);
|
||||
formDetail.elementWeakRef = Cu.getWeakReference(doc.querySelector(queryString));
|
||||
}
|
||||
Assert.deepEqual(FormAutofillContent.getFormDetails(input),
|
||||
formDetails,
|
||||
"Check if returned form information is correct.");
|
||||
|
||||
FormAutofillContent.getFormDetails(input).forEach((detail, index) => {
|
||||
inputDetailAssertion(detail, formDetails[index]);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -101,6 +101,8 @@
|
||||
<!ENTITY enableSearchUpdate.label "Search Engines">
|
||||
<!ENTITY enableSearchUpdate.accesskey "E">
|
||||
|
||||
<!ENTITY reports.label "Reports">
|
||||
|
||||
<!ENTITY offlineStorageNotify.label "Tell you when a website asks to store data for offline use">
|
||||
<!ENTITY offlineStorageNotify.accesskey "T">
|
||||
<!ENTITY offlineStorageNotifyExceptions.label "Exceptions…">
|
||||
@ -113,7 +115,6 @@
|
||||
<!ENTITY offlineAppRemove.confirm "Remove offline data">
|
||||
|
||||
<!ENTITY certificateTab.label "Certificates">
|
||||
<!ENTITY certPersonal.label "Requests">
|
||||
<!ENTITY certPersonal.description "When a server requests your personal certificate:">
|
||||
<!ENTITY selectCerts.auto "Select one automatically">
|
||||
<!ENTITY selectCerts.auto.accesskey "S">
|
||||
|
@ -13,17 +13,13 @@
|
||||
<!ENTITY prefWinMinSize.styleMac "width: 47em; min-height: 40em;">
|
||||
<!ENTITY prefWinMinSize.styleGNOME "width: 45.5em; min-height: 40.5em;">
|
||||
|
||||
<!ENTITY paneGeneral.title "General">
|
||||
<!ENTITY paneTabs.title "Tabs">
|
||||
<!ENTITY paneSearch.title "Search">
|
||||
<!ENTITY paneContent.title "Content">
|
||||
<!ENTITY paneApplications.title "Applications">
|
||||
<!ENTITY panePrivacy.title "Privacy">
|
||||
<!ENTITY paneContainers.title "Container Tabs">
|
||||
<!ENTITY paneSecurity.title "Security">
|
||||
<!ENTITY paneAdvanced.title "Advanced">
|
||||
<!ENTITY paneGeneral.title "General">
|
||||
<!ENTITY paneDownloadLinks.title "Downloads & Links">
|
||||
<!ENTITY panePrivacySecurity.title "Privacy & Security">
|
||||
<!ENTITY paneContainers.title "Container Tabs">
|
||||
<!ENTITY paneUpdates.title "Updates">
|
||||
|
||||
<!-- LOCALIZATION NOTE (paneSync.title): This should match syncBrand.shortName.label in ../syncBrand.dtd -->
|
||||
<!ENTITY paneSync.title "Sync">
|
||||
<!-- LOCALIZATION NOTE (paneSync1.title): This should match syncBrand.fxAccount.label in ../syncBrand.dtd -->
|
||||
<!ENTITY paneSync1.title "Firefox Account">
|
||||
|
||||
<!ENTITY helpButton.label "Help">
|
||||
|
@ -2,7 +2,7 @@
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<!ENTITY trackingProtectionHeader.label "Use Tracking Protection">
|
||||
<!ENTITY trackingProtectionHeader2.label "Tracking Protection">
|
||||
<!ENTITY trackingProtectionAlways.label "Always">
|
||||
<!ENTITY trackingProtectionAlways.accesskey "y">
|
||||
<!ENTITY trackingProtectionPrivate.label "Only in private windows">
|
||||
|
@ -2,7 +2,7 @@
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<!ENTITY general.label "General">
|
||||
<!ENTITY security.label "Security">
|
||||
|
||||
<!ENTITY warnOnAddonInstall.label "Warn you when sites try to install add-ons">
|
||||
<!ENTITY warnOnAddonInstall.accesskey "W">
|
||||
@ -24,10 +24,10 @@
|
||||
<!ENTITY addonExceptions.accesskey "E">
|
||||
|
||||
|
||||
<!ENTITY logins.label "Logins">
|
||||
<!ENTITY formsAndPasswords.label "Forms & Passwords">
|
||||
|
||||
<!ENTITY rememberLogins.label "Remember logins for sites">
|
||||
<!ENTITY rememberLogins.accesskey "R">
|
||||
<!ENTITY rememberLogins1.label "Remember logins and passwords for sites">
|
||||
<!ENTITY rememberLogins1.accesskey "R">
|
||||
<!ENTITY passwordExceptions.label "Exceptions…">
|
||||
<!ENTITY passwordExceptions.accesskey "x">
|
||||
|
||||
|
@ -19,8 +19,8 @@
|
||||
|
||||
<!-- Device Settings -->
|
||||
<!ENTITY fxaSyncDeviceName.label "Device Name">
|
||||
<!ENTITY changeSyncDeviceName.label "Change Device Name…">
|
||||
<!ENTITY changeSyncDeviceName.accesskey "h">
|
||||
<!ENTITY changeSyncDeviceName1.label "Change Device Name">
|
||||
<!ENTITY changeSyncDeviceName1.accesskey "h">
|
||||
<!ENTITY cancelChangeSyncDeviceName.label "Cancel">
|
||||
<!ENTITY cancelChangeSyncDeviceName.accesskey "n">
|
||||
<!ENTITY saveChangeSyncDeviceName.label "Save">
|
||||
|
@ -420,7 +420,7 @@ this.ContentSearch = {
|
||||
|
||||
_onMessageManageEngines(msg, data) {
|
||||
let browserWin = msg.target.ownerGlobal;
|
||||
browserWin.openPreferences("paneSearch");
|
||||
browserWin.openPreferences("paneGeneral");
|
||||
},
|
||||
|
||||
_onMessageGetSuggestions: Task.async(function* (msg, data) {
|
||||
|
@ -10,29 +10,22 @@ const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/PromiseUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Timer.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
const HTML_NS = "http://www.w3.org/1999/xhtml";
|
||||
const XUL_PAGE = "data:application/vnd.mozilla.xul+xml;charset=utf-8,<window%20id='win'/>";
|
||||
|
||||
/**
|
||||
* An hidden frame object. It takes care of creating an IFRAME and attaching it the
|
||||
* |hiddenDOMWindow|.
|
||||
* An hidden frame object. It takes care of creating a windowless browser and
|
||||
* passing the window containing a blank XUL <window> back.
|
||||
*/
|
||||
function HiddenFrame() {}
|
||||
|
||||
HiddenFrame.prototype = {
|
||||
_frame: null,
|
||||
_browser: null,
|
||||
_listener: null,
|
||||
_webProgress: null,
|
||||
_deferred: null,
|
||||
_retryTimerId: null,
|
||||
|
||||
get hiddenDOMDocument() {
|
||||
return Services.appShell.hiddenDOMWindow.document;
|
||||
},
|
||||
|
||||
get isReady() {
|
||||
return this.hiddenDOMDocument.readyState === "complete";
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the |contentWindow| of the hidden frame. Creates the frame if needed.
|
||||
@ -49,38 +42,43 @@ HiddenFrame.prototype = {
|
||||
},
|
||||
|
||||
destroy() {
|
||||
clearTimeout(this._retryTimerId);
|
||||
|
||||
if (this._frame) {
|
||||
if (!Cu.isDeadWrapper(this._frame)) {
|
||||
this._frame.removeEventListener("load", this, true);
|
||||
this._frame.remove();
|
||||
if (this._browser) {
|
||||
if (this._listener) {
|
||||
this._webProgress.removeProgressListener(this._listener);
|
||||
this._listener = null;
|
||||
this._webProgress = null;
|
||||
}
|
||||
|
||||
this._frame = null;
|
||||
this._deferred = null;
|
||||
}
|
||||
},
|
||||
|
||||
handleEvent() {
|
||||
let contentWindow = this._frame.contentWindow;
|
||||
if (contentWindow.location.href === XUL_PAGE) {
|
||||
this._frame.removeEventListener("load", this, true);
|
||||
this._deferred.resolve(contentWindow);
|
||||
} else {
|
||||
contentWindow.location = XUL_PAGE;
|
||||
this._browser.close();
|
||||
this._browser = null;
|
||||
}
|
||||
},
|
||||
|
||||
_create() {
|
||||
if (this.isReady) {
|
||||
let doc = this.hiddenDOMDocument;
|
||||
this._frame = doc.createElementNS(HTML_NS, "iframe");
|
||||
this._frame.addEventListener("load", this, true);
|
||||
doc.documentElement.appendChild(this._frame);
|
||||
} else {
|
||||
// Check again if |hiddenDOMDocument| is ready as soon as possible.
|
||||
this._retryTimerId = setTimeout(this._create.bind(this), 0);
|
||||
}
|
||||
this._browser = Services.appShell.createWindowlessBrowser(true);
|
||||
this._browser.QueryInterface(Ci.nsIInterfaceRequestor);
|
||||
this._webProgress = this._browser.getInterface(Ci.nsIWebProgress);
|
||||
this._listener = {
|
||||
QueryInterface: XPCOMUtils.generateQI([
|
||||
Ci.nsIWebProgressListener, Ci.nsIWebProgressListener2,
|
||||
Ci.nsISupportsWeakReference]),
|
||||
};
|
||||
this._listener.onStateChange = (wbp, request, stateFlags, status) => {
|
||||
if (!request) {
|
||||
return;
|
||||
}
|
||||
if (stateFlags & Ci.nsIWebProgressListener.STATE_STOP) {
|
||||
this._webProgress.removeProgressListener(this._listener);
|
||||
this._listener = null;
|
||||
this._webProgress = null;
|
||||
// Get the window reference via the document.
|
||||
this._frame = this._browser.document.ownerGlobal;
|
||||
this._deferred.resolve(this._frame);
|
||||
}
|
||||
};
|
||||
this._webProgress.addProgressListener(this._listener, Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
|
||||
this._browser.document.location = XUL_PAGE;
|
||||
}
|
||||
};
|
||||
|
@ -72,6 +72,9 @@ var SelfSupportBackendInternal = {
|
||||
_log: null,
|
||||
_progressListener: null,
|
||||
|
||||
// Whether we're invited to let test code talk to our frame.
|
||||
_testing: false,
|
||||
|
||||
/**
|
||||
* Initializes the self support backend.
|
||||
*/
|
||||
@ -136,6 +139,9 @@ var SelfSupportBackendInternal = {
|
||||
this._frame.destroy();
|
||||
this._frame = null;
|
||||
}
|
||||
if (this._testing) {
|
||||
Services.obs.notifyObservers(this._browser, "self-support-browser-destroyed", "");
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@ -195,6 +201,9 @@ var SelfSupportBackendInternal = {
|
||||
this._browser.setAttribute("disableglobalhistory", "true");
|
||||
this._browser.setAttribute("src", aURL);
|
||||
|
||||
if (this._testing) {
|
||||
Services.obs.notifyObservers(this._browser, "self-support-browser-created", "");
|
||||
}
|
||||
doc.documentElement.appendChild(this._browser);
|
||||
});
|
||||
},
|
||||
|
@ -26,29 +26,13 @@ function sendSessionRestoredNotification() {
|
||||
selfSupportBackendImpl.observe(null, "sessionstore-windows-restored", null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a browser, with an IFRAME as parent, who has aURL as the source attribute.
|
||||
*
|
||||
* @param aURL The URL to look for to identify the browser.
|
||||
*
|
||||
* @returns {Object} The browser element or null on failure.
|
||||
*/
|
||||
function findSelfSupportBrowser(aURL) {
|
||||
let frames = Services.appShell.hiddenDOMWindow.document.querySelectorAll("iframe");
|
||||
for (let frame of frames) {
|
||||
try {
|
||||
let browser = frame.contentDocument.getElementById("win").querySelectorAll("browser")[0];
|
||||
let url = browser.getAttribute("src");
|
||||
if (url == aURL) {
|
||||
return browser;
|
||||
}
|
||||
} catch (e) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
function toggleSelfSupportTestMode(testing) {
|
||||
let selfSupportBackendImpl =
|
||||
Cu.import("resource:///modules/SelfSupportBackend.jsm", {}).SelfSupportBackendInternal;
|
||||
selfSupportBackendImpl._testing = testing;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Wait for self support page to load.
|
||||
*
|
||||
@ -60,13 +44,19 @@ function findSelfSupportBrowser(aURL) {
|
||||
function promiseSelfSupportLoad(aURL) {
|
||||
return new Promise((resolve, reject) => {
|
||||
// Find the SelfSupport browser.
|
||||
let browserPromise = waitForConditionPromise(() => !!findSelfSupportBrowser(aURL),
|
||||
"SelfSupport browser not found.",
|
||||
TEST_WAIT_RETRIES);
|
||||
let browser = null;
|
||||
let browserPromise = TestUtils.topicObserved("self-support-browser-created",
|
||||
(subject, topic) => {
|
||||
let url = subject.getAttribute("src");
|
||||
Cu.reportError("Got browser with src: " + url);
|
||||
if (url == aURL) {
|
||||
browser = subject;
|
||||
}
|
||||
return url == aURL;
|
||||
});
|
||||
|
||||
// Once found, append a "load" listener to catch page loads.
|
||||
browserPromise.then(() => {
|
||||
let browser = findSelfSupportBrowser(aURL);
|
||||
if (browser.contentDocument.readyState === "complete") {
|
||||
resolve(browser);
|
||||
} else {
|
||||
@ -80,19 +70,6 @@ function promiseSelfSupportLoad(aURL) {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for self support to close.
|
||||
*
|
||||
* @param aURL The URL to look for to identify the browser.
|
||||
*
|
||||
* @returns {Promise} Return a promise which is resolved when SelfSupport browser cannot
|
||||
* be found anymore.
|
||||
*/
|
||||
function promiseSelfSupportClose(aURL) {
|
||||
return waitForConditionPromise(() => !findSelfSupportBrowser(aURL),
|
||||
"SelfSupport browser is still open.", TEST_WAIT_RETRIES);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the test environment.
|
||||
*/
|
||||
@ -129,16 +106,21 @@ add_task(function* setupEnvironment() {
|
||||
* Test that the self support page can use the UITour API and close itself.
|
||||
*/
|
||||
add_task(function* test_selfSupport() {
|
||||
toggleSelfSupportTestMode(true);
|
||||
registerCleanupFunction(toggleSelfSupportTestMode.bind(null, false));
|
||||
// Initialise the SelfSupport backend and trigger the load.
|
||||
SelfSupportBackend.init();
|
||||
|
||||
// Wait for the SelfSupport page to load.
|
||||
let selfSupportBrowserPromise = promiseSelfSupportLoad(TEST_PAGE_URL_HTTPS);
|
||||
|
||||
// SelfSupportBackend waits for "sessionstore-windows-restored" to start loading. Send it.
|
||||
info("Sending sessionstore-windows-restored");
|
||||
sendSessionRestoredNotification();
|
||||
|
||||
// Wait for the SelfSupport page to load.
|
||||
info("Waiting for the SelfSupport local page to load.");
|
||||
let selfSupportBrowser = yield promiseSelfSupportLoad(TEST_PAGE_URL_HTTPS);
|
||||
let selfSupportBrowser = yield selfSupportBrowserPromise;
|
||||
Assert.ok(!!selfSupportBrowser, "SelfSupport browser must exist.");
|
||||
|
||||
// Get a reference to the UITour API.
|
||||
@ -176,39 +158,15 @@ add_task(function* test_selfSupport() {
|
||||
yield observePromise;
|
||||
info("Observed in the hidden frame");
|
||||
|
||||
let selfSupportClosed = TestUtils.topicObserved("self-support-browser-destroyed");
|
||||
// Close SelfSupport from content.
|
||||
contentWindow.close();
|
||||
|
||||
// Wait until SelfSupport closes.
|
||||
info("Waiting for the SelfSupport to close.");
|
||||
yield promiseSelfSupportClose(TEST_PAGE_URL_HTTPS);
|
||||
|
||||
// Find the SelfSupport browser, again. We don't expect to find it.
|
||||
selfSupportBrowser = findSelfSupportBrowser(TEST_PAGE_URL_HTTPS);
|
||||
Assert.ok(!selfSupportBrowser, "SelfSupport browser must not exist.");
|
||||
yield selfSupportClosed;
|
||||
Assert.ok(!selfSupportBrowser.parentNode, "SelfSupport browser must have been removed.");
|
||||
|
||||
// We shouldn't need this, but let's keep it to make sure closing SelfSupport twice
|
||||
// doesn't create any problem.
|
||||
SelfSupportBackend.uninit();
|
||||
});
|
||||
|
||||
/**
|
||||
* Test that SelfSupportBackend only allows HTTPS.
|
||||
*/
|
||||
add_task(function* test_selfSupport_noHTTPS() {
|
||||
Preferences.set(PREF_SELFSUPPORT_URL, TEST_PAGE_URL);
|
||||
|
||||
SelfSupportBackend.init();
|
||||
|
||||
// SelfSupportBackend waits for "sessionstore-windows-restored" to start loading. Send it.
|
||||
info("Sending sessionstore-windows-restored");
|
||||
sendSessionRestoredNotification();
|
||||
|
||||
// Find the SelfSupport browser. We don't expect to find it since we are not using https.
|
||||
let selfSupportBrowser = findSelfSupportBrowser(TEST_PAGE_URL);
|
||||
Assert.ok(!selfSupportBrowser, "SelfSupport browser must not exist.");
|
||||
|
||||
// We shouldn't need this, but let's keep it to make sure closing SelfSupport twice
|
||||
// doesn't create any problem.
|
||||
SelfSupportBackend.uninit();
|
||||
})
|
||||
|
@ -37,11 +37,36 @@
|
||||
<path d="M18.909,9.783h-0.863V8.086C18.046,4.725,15.339,2,12,2 C8.661,2,5.954,4.725,5.954,8.086v1.697H5.091c-0.955,0-1.728,0.779-1.728,1.739v8.738c0,0.961,0.773,1.74,1.728,1.74h13.818 c0.954,0,1.728-0.779,1.728-1.74v-8.738C20.637,10.562,19.863,9.783,18.909,9.783z M8.545,8.086c0-1.92,1.547-3.478,3.455-3.478 c1.908,0,3.455,1.557,3.455,3.478v1.697h-6.91V8.086z M5.181,16.092l-0.909-1.2v-2.284l2.728,3.483H5.181z M8.818,16.092 l-2.773-3.657h1.727l2.864,3.657H8.818z M12,16.092l-2.773-3.657h1.727l2.864,3.657H12z M15.637,16.092l-2.773-3.657h1.727 l2.864,3.657H15.637z M19.728,16.092h-0.455l-2.773-3.657h1.727l1.501,1.916V16.092z"/>
|
||||
</g>
|
||||
<g id="sync-shape">
|
||||
<path d="M17.024,3.351 c-0.562,0.331 -1.311,0.879 -1.821,1.698 -0.367,0.592 -0.752,1.288 -1.08,1.914 0.987,0.413 1.862,1.095 2.476,2.029 0.614,0.957 0.929,2.122 0.83,3.351 -0.201,1.787 -1.359,3.433 -3.046,4.36 -0.696,-0.774 -1.951,-2.945 -1.951,-2.945 -0.007,0.007 -0.004,2.556 -0.871,4.334 -0.573,1.184 -1.24,2.202 -2.305,2.995 1.431,0.51 2.915,0.886 4.282,0.909 l 0.162,0.002 c 2.99,0.021 5.844,-0.48 5.844,-0.48 0,0 -1.236,-0.802 -1.808,-1.346 1.86,-1.072 3.111,-2.791 3.634,-4.708 0.283,-0.759 0.478,-1.566 0.57,-2.409 C 22.383,9.011 20.33,5.278 17.024,3.351 Z M 6.569,12.302 C 6.526,10.271 7.755,8.327 9.644,7.29 c 0.696,0.774 2.32,2.899 2.32,2.899 0,0 -0.064,-5.157 1.657,-7.973 -6.097,-0.668 -9.69,0.443 -9.69,0.443 0,0 1.763,0.607 2.333,1.136 C 6.122,3.891 5.984,3.992 5.85,4.096 4.4,5.064 3.368,6.449 2.825,7.994 2.436,8.892 2.171,9.863 2.06,10.887 1.622,14.886 3.629,18.572 6.871,20.515 7.39,20.124 7.975,19.631 8.61,18.983 9.189,18.389 9.647,17.682 10.021,16.967 8.082,16.208 6.714,14.404 6.569,12.302 Z"/>
|
||||
<path style="fill:#F1F1F1;" d="M0.9,19.9h3.3H15h3.3c0.5,0,0.9-0.4,0.9-0.9v-1.1c0-1-0.5-1.9-1.2-2.5c-2.3-1.8-4.6-2.9-5.1-3.1
|
||||
c-0.1,0-0.1-0.1-0.1-0.2v-1.6c0.3-0.5,0.4-1,0.5-1.5c0.2,0.1,0.6,0.1,1-1.3c0.3-1.1,0.1-1.5-0.2-1.6C15,1.7,13,1.6,13,1.6
|
||||
S12.7,1,11.8,0.5C11.3,0.2,10.5-0.1,9.5,0C9.1,0,8.8,0.1,8.5,0.2c-0.4,0.1-0.7,0.3-1,0.5C7.1,1,6.8,1.2,6.4,1.6
|
||||
c-0.5,0.5-1,1.2-1.1,2C5.1,4.3,5.1,5,5.4,5.8C5,5.7,4.6,5.9,5,7.4c0.3,1.1,0.6,1.4,0.8,1.4c0.1,0.6,0.3,1.3,0.7,1.9v1.4
|
||||
c0,0.1,0,0.1-0.1,0.2c-0.5,0.2-2.8,1.4-5.1,3.1C0.5,16,0,16.9,0,17.9V19C0,19.5,0.4,19.9,0.9,19.9"/>
|
||||
</g>
|
||||
<g id="advanced-shape">
|
||||
<path d="M19.173,16.163c0.004,0.04,0.007,0.08,0.007,0.121c0,1.748-3.197,3.165-7.14,3.165 c-3.943,0-7.14-1.417-7.14-3.165c0 -0.037,0.003-0.073,0.006-0.109C3.11,16.572,2,17.243,2,18.341C2,20.362,6.477,22,12,22 c5.523,0,10-1.638,10-3.659 C22,17.22,20.922,16.553,19.173,16.163z"/>
|
||||
<path d="M18.224,15.979c0.006-0.11-0.018-0.285-0.054-0.39c0,0-0.762-2.205-1.176-3.403 c-0.624-1.807-2.112-6.139-2.112-6.139c-0.036-0.104-0.031-0.273,0.01-0.376l0.497-1.234c0.041-0.102,0.116-0.266,0.166-0.364 l0.986-1.942c0.05-0.098,0.013-0.133-0.081-0.077L9.965,5.871c-0.095,0.056-0.203,0.186-0.24,0.29c0,0-0.252,0.7-0.412,1.144 C8.64,9.173,7.968,11.04,7.296,12.908c-0.26,0.723-0.52,1.446-0.78,2.168c-0.056,0.156-0.112,0.311-0.168,0.466 c-0.093,0.26-0.049,0.617,0.032,0.881c0.237,0.763,1.001,1.189,1.708,1.435c0.611,0.213,1.254,0.328,1.895,0.403 c0.895,0.105,1.805,0.14,2.706,0.112c1.356-0.041,2.767-0.261,4.004-0.846c0.429-0.203,0.854-0.459,1.174-0.816 c0.121-0.135,0.226-0.287,0.297-0.455C18.215,16.134,18.224,15.979,18.224,15.979z M14.063,16.131 c0.019,0.108-0.046,0.156-0.143,0.104l-1.466-0.772c-0.097-0.052-0.257-0.052-0.354,0l-1.466,0.773 c-0.097,0.052-0.162,0.004-0.143-0.104l0.28-1.636c0.019-0.109-0.031-0.261-0.109-0.338l-1.186-1.158 c-0.079-0.077-0.054-0.153,0.055-0.169l1.638-0.239c0.109-0.016,0.238-0.11,0.286-0.209l0.733-1.488 c0.049-0.099,0.128-0.099,0.177,0l0.733,1.488c0.049,0.099,0.178,0.193,0.286,0.209l1.639,0.239 c0.109,0.016,0.134,0.092,0.055,0.169l-1.186,1.158c-0.079,0.077-0.128,0.229-0.109,0.338L14.063,16.131z"/>
|
||||
<path style="fill:#F1F1F1;" d="M19.3,13.4C19.3,13.4,19.3,13.4,19.3,13.4L19.3,13.4C19.3,13.4,19.3,13.4,19.3,13.4L19.3,13.4z
|
||||
M19.3,13.4c-0.1,1-0.5,1.8-1.2,2.4c-0.5,0.5-1.1,0.9-1.7,1.2c-0.2,0.4-0.4,0.7-0.8,1c-0.5,0.4-1.3,0.8-2.1,1
|
||||
c-0.9,0.2-1.6,0.3-2.3,0.3h-0.9c0.1,0.2,0.2,0.2,0.4,0.2c-1.1-0.1-2.1-0.3-2.9-0.5c0.2,0.2,0.5,0.4,0.8,0.4c-1.5-0.3-2.9-1-4.1-1.9
|
||||
c-0.3-0.2-0.4-0.3-0.5-0.4c-1-0.8-1.7-1.6-2.3-2.6c-0.7-1.1-1.1-2.5-1.3-4.1c-0.1,0.5-0.1,0.9-0.1,1.1C0.1,10.2,0.1,9,0.4,7.9
|
||||
C0.3,8.2,0.1,8.6,0,9c0.1-0.8,0.4-1.8,0.9-2.8C1,5.8,1.2,5.5,1.3,5.4V4.3c0-0.1,0-0.3,0.1-0.6c0-0.2,0.1-0.4,0.2-0.6v0.1
|
||||
c0,0,0-0.1,0-0.1c0-0.1,0-0.1,0-0.1c0-0.1,0-0.2,0.1-0.2v0.1c0,0,0-0.1,0-0.1c0,0,0-0.1,0-0.1s0-0.1,0-0.2C2,2.2,2,2.1,2,2.1
|
||||
C2.2,2,2.2,1.9,2.3,1.9V2c0,0.2,0.1,0.5,0.3,1l0-0.1C2.8,3.1,3,3.4,3.4,3.7c0.8-0.2,1.5-0.3,2.4-0.1C5.9,3.5,5.9,3.4,6,3.3v0.1
|
||||
C6.1,3.2,6.3,3.1,6.6,3v0c0.2-0.1,0.5-0.3,1-0.4L7.5,2.6c0.1-0.1,0.2-0.1,0.3-0.1c0.1,0,0.2,0,0.3,0c0.1,0,0.3,0,0.4,0
|
||||
c-0.1,0-0.1,0.1-0.1,0.1c0,0-0.1,0.1-0.1,0.1s-0.1,0-0.1,0h0.1C7.8,3.2,7.4,3.7,7.2,4.4c-0.1,0-0.1,0.1-0.1,0.2l0.1,0.1
|
||||
c0.2,0.3,0.5,0.5,0.9,0.5h1.4c0.2,0.1,0.3,0.2,0.3,0.2c0,0.2-0.1,0.4-0.3,0.6c0,0.1-0.1,0.2-0.3,0.4C8.5,7,8,7.3,7.7,7.6v0.1
|
||||
c0,0,0,0,0,0.1c0,0,0,0,0,0.1c-0.1,0-0.1,0-0.1,0.1C7.7,7.9,7.8,8,7.8,8.2c0,0.2,0,0.4-0.1,0.6c0,0-0.1-0.1-0.1-0.1
|
||||
c-0.1,0-0.1,0-0.1,0c0.1,0.1,0.2,0.1,0.2,0.2V9c0,0-0.1,0-0.1,0c0,0-0.1-0.1-0.1-0.1l-0.1,0c-0.1,0-0.1,0-0.2-0.1
|
||||
c-0.1,0-0.1,0-0.1,0L7,8.7c-0.1,0-0.1,0-0.1,0L7,8.7c-0.1,0-0.1,0-0.2,0l-0.1,0C6.5,8.8,6.4,9,6.4,9.3c0,0.6,0.4,1.1,1.1,1.5
|
||||
C7.7,11,8,11.1,8.3,11.2c0.3,0,0.5,0,0.7,0c0.2-0.1,0.4-0.1,0.6-0.2s0.4-0.2,0.5-0.2c0.7-0.2,1.4,0,1.9,0.5c0.2,0.1,0.2,0.2,0.1,0.4
|
||||
c-0.1,0.2-0.2,0.3-0.4,0.2c-0.1,0-0.2,0-0.2,0c-0.1,0-0.1,0-0.3,0.1S11.1,12,11,12s-0.2,0.1-0.3,0.2c-0.1,0.1-0.3,0.2-0.4,0.3
|
||||
c-0.9,0.5-1.9,0.6-3,0.4c0.4,0.4,0.7,0.7,1.1,0.9c0.1,0,0.2,0.1,0.6,0.1c0.3,0,0.5,0.1,0.6,0.2C9.4,14,9.1,14,8.9,14.1
|
||||
c0.8,0.5,1.7,0.7,2.8,0.5c0.4-0.1,0.7-0.2,1-0.4c-0.1,0.1-0.1,0.3-0.2,0.4c0.1,0.1,0.4-0.1,0.6-0.5c0.1-0.1,0.3-0.3,0.6-0.4
|
||||
c0,0,0,0.1,0,0.2c0,0.1,0,0.1,0,0.2s0,0.1,0.1,0.1c0.4,0,0.7-0.4,1.1-1.3c0.3-0.6,0.5-1.3,0.6-2.2c0.1,0.2,0.2,0.5,0.2,0.8
|
||||
c0.2-0.5,0.3-1,0.3-1.3c0-0.3,0-1.3-0.1-2.9c0.3,0.4,0.5,0.7,0.7,1.1c0.1-1.2-0.1-2.2-0.5-3.1c-0.4-0.8-0.9-1.5-1.4-1.9
|
||||
c0.5,0.1,1,0.3,1.4,0.6l-0.3-0.2c-1.4-1.4-3.1-2.2-5.1-2.4c-2-0.2-3.8,0.3-5.4,1.4c-0.6,0-1.1,0-1.5,0.1C3.6,2.7,3.5,2.6,3.5,2.5
|
||||
C5.3,0.8,7.4,0,9.9,0s4.6,0.8,6.5,2.4L16.2,2c0.6,0.3,1,0.7,1.4,1.2l-0.1-0.3l0,0.1l0-0.1c0.9,0.7,1.4,1.6,1.7,2.7
|
||||
c0.2,0.9,0.2,1.6,0.1,2.3c0.1,0.1,0.1,0.1,0.1,0.3l0.3-1.1c0.1,0.3,0.2,0.7,0.2,1C20,8.5,20,8.9,20,9.2c0,0.4-0.1,0.7-0.1,1
|
||||
c-0.1,0.3-0.1,0.7-0.2,1s-0.2,0.6-0.3,0.8c-0.1,0.2-0.2,0.5-0.3,0.7C19.1,12.8,19.2,13,19.3,13.4L19.3,13.4z"/>
|
||||
</g>
|
||||
</defs>
|
||||
<use id="general" xlink:href="#general-shape"/>
|
||||
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 9.5 KiB |
@ -82,11 +82,11 @@ treecol {
|
||||
}
|
||||
|
||||
#category-application > .category-icon {
|
||||
list-style-image: url("chrome://browser/skin/preferences/in-content/icons.svg#applications");
|
||||
list-style-image: url("chrome://browser/skin/preferences/in-content/icons.svg#content");
|
||||
}
|
||||
|
||||
#category-privacy > .category-icon {
|
||||
list-style-image: url("chrome://browser/skin/preferences/in-content/icons.svg#privacy");
|
||||
list-style-image: url("chrome://browser/skin/preferences/in-content/icons.svg#security");
|
||||
}
|
||||
|
||||
#category-security > .category-icon {
|
||||
|
@ -19,13 +19,13 @@
|
||||
# program.
|
||||
@template
|
||||
def try_compile(includes=None, body='', language='C++', flags=None, check_msg=None,
|
||||
when=None):
|
||||
when=None, onerror=lambda: None):
|
||||
compiler = {
|
||||
'C': c_compiler,
|
||||
'C++': cxx_compiler,
|
||||
}[language]
|
||||
|
||||
return compiler.try_compile(includes, body, flags, check_msg, when=when)
|
||||
return compiler.try_compile(includes, body, flags, check_msg, when=when, onerror=onerror)
|
||||
|
||||
|
||||
# Checks for the presence of the given header on the target system by compiling
|
||||
|
@ -34,6 +34,14 @@
|
||||
fun:_ZN13CrashReporter14SetupExtraDataEP7nsIFileRK10nsACString
|
||||
...
|
||||
}
|
||||
{
|
||||
PR_SetEnv requires its argument to be leaked, but does not appear on stacks. (See bug 1345153.)
|
||||
Memcheck:Leak
|
||||
fun:malloc
|
||||
...
|
||||
fun:_ZN13CrashReporterL27SetupCrashReporterDirectoryEP7nsIFilePKcS3_PS1_
|
||||
...
|
||||
}
|
||||
{
|
||||
We purposely leak the StatisticsReporter object
|
||||
Memcheck:Leak
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "nsIScriptError.h"
|
||||
#include "nsIWindowMediator.h"
|
||||
#include "nsIPrefService.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Printf.h"
|
||||
#include "mozilla/StyleSheet.h"
|
||||
#include "mozilla/StyleSheetInlines.h"
|
||||
|
26
devtools/client/netmonitor/README.md
Normal file
26
devtools/client/netmonitor/README.md
Normal file
@ -0,0 +1,26 @@
|
||||
# netmonitor
|
||||
|
||||
The Network Monitor shows you all the network requests Firefox makes (for example, when it loads a page, or due to XMLHttpRequests), how long each request takes, and details of each request.
|
||||
|
||||
## Prerequisite
|
||||
|
||||
* [node](https://nodejs.org/) >= 6.9.x
|
||||
* [npm](https://docs.npmjs.com/getting-started/installing-node) >= 3.x
|
||||
* [yarn](https://yarnpkg.com/docs/install) >= 0.21.x
|
||||
|
||||
## Quick Setup
|
||||
|
||||
Assume you are in netmonitor folder
|
||||
|
||||
```bash
|
||||
# Install packages
|
||||
yarn install
|
||||
|
||||
# Create a dev server instance for hosting netmonitor on browser
|
||||
yarn start
|
||||
|
||||
# Run firefox
|
||||
firefox http://localhost:8000 --start-debugger-server 6080
|
||||
```
|
||||
|
||||
Then open localhost:8000 in any browser to see all tabs in Firefox.
|
29
devtools/client/netmonitor/bin/configure.js
Normal file
29
devtools/client/netmonitor/bin/configure.js
Normal file
@ -0,0 +1,29 @@
|
||||
/* 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/. */
|
||||
|
||||
/* eslint-env node */
|
||||
|
||||
"use strict";
|
||||
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
function getConfig() {
|
||||
if (process.env.TARGET === "firefox-panel") {
|
||||
return require("../configs/firefox-panel.json");
|
||||
}
|
||||
|
||||
const developmentConfig = require("../configs/development.json");
|
||||
|
||||
let localConfig = {};
|
||||
if (fs.existsSync(path.resolve(__dirname, "../configs/local.json"))) {
|
||||
localConfig = require("../configs/local.json");
|
||||
}
|
||||
|
||||
return Object.assign({}, developmentConfig, localConfig);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getConfig,
|
||||
};
|
31
devtools/client/netmonitor/bin/dev-server.js
Normal file
31
devtools/client/netmonitor/bin/dev-server.js
Normal file
@ -0,0 +1,31 @@
|
||||
/* 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/. */
|
||||
|
||||
/* eslint-env node */
|
||||
|
||||
"use strict";
|
||||
|
||||
const path = require("path");
|
||||
|
||||
const toolbox = require("devtools-launchpad/index");
|
||||
const feature = require("devtools-config");
|
||||
const express = require("express");
|
||||
const { getConfig } = require("./configure");
|
||||
|
||||
const envConfig = getConfig();
|
||||
|
||||
feature.setConfig(envConfig);
|
||||
|
||||
let webpackConfig = require("../webpack.config");
|
||||
|
||||
let { app } = toolbox.startDevServer(envConfig, webpackConfig, __dirname);
|
||||
|
||||
app.use(
|
||||
"/integration/examples",
|
||||
express.static("src/test/mochitest/examples")
|
||||
);
|
||||
|
||||
app.get("/integration", function (req, res) {
|
||||
res.sendFile(path.join(__dirname, "../src/test/integration/index.html"));
|
||||
});
|
35
devtools/client/netmonitor/configs/development.json
Normal file
35
devtools/client/netmonitor/configs/development.json
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
"title": "Netmonitor",
|
||||
"environment": "development",
|
||||
"baseWorkerURL": "http://localhost:8000/public/build/",
|
||||
"host": "",
|
||||
"theme": "light",
|
||||
"dir": "ltr",
|
||||
"logging": {
|
||||
"client": false,
|
||||
"firefoxProxy": false,
|
||||
"actions": false
|
||||
},
|
||||
"features": {
|
||||
},
|
||||
"chrome": {
|
||||
"debug": true,
|
||||
"host": "localhost",
|
||||
"port": 9222
|
||||
},
|
||||
"node": {
|
||||
"debug": true,
|
||||
"host": "localhost",
|
||||
"port": 9229
|
||||
},
|
||||
"firefox": {
|
||||
"webSocketConnection": false,
|
||||
"proxyHost": "localhost:9000",
|
||||
"webSocketHost": "localhost:6080",
|
||||
"mcPath": "./firefox"
|
||||
},
|
||||
"development": {
|
||||
"serverPort": 8000,
|
||||
"examplesPort": 7999
|
||||
}
|
||||
}
|
11
devtools/client/netmonitor/configs/firefox-panel.json
Normal file
11
devtools/client/netmonitor/configs/firefox-panel.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"environment": "firefox-panel",
|
||||
"baseWorkerURL": "resource://devtools/client/netmonitor/",
|
||||
"logging": false,
|
||||
"clientLogging": false,
|
||||
"firefox": {
|
||||
"mcPath": "./firefox"
|
||||
},
|
||||
"features": {
|
||||
}
|
||||
}
|
31
devtools/client/netmonitor/index.js
Normal file
31
devtools/client/netmonitor/index.js
Normal file
@ -0,0 +1,31 @@
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* This script is the entry point of devtools-launchpad. Make netmonitor possible
|
||||
* to run on standalone browser tab without chrome privilege.
|
||||
* See README.md for more information.
|
||||
*/
|
||||
const React = require("react");
|
||||
const ReactDOM = require("react-dom");
|
||||
const { bootstrap } = require("devtools-launchpad");
|
||||
const { EventEmitter } = require("devtools-sham-modules");
|
||||
const { configureStore } = require("./src/utils/create-store");
|
||||
|
||||
// require("./src/assets/styles/netmonitor.css");
|
||||
|
||||
EventEmitter.decorate(window);
|
||||
|
||||
const App = require("./src/components/app");
|
||||
const store = window.gStore = configureStore();
|
||||
const { NetMonitorController } = require("./src/netmonitor-controller");
|
||||
|
||||
bootstrap(React, ReactDOM, App, null, store).then(connection => {
|
||||
if (!connection || !connection.tab) {
|
||||
return;
|
||||
}
|
||||
NetMonitorController.startupNetMonitor(connection);
|
||||
});
|
@ -1,20 +1,32 @@
|
||||
{
|
||||
"name": "netmonitor",
|
||||
"version": "0.0.1",
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
},
|
||||
"description": "Network monitor in developer tools",
|
||||
"dependencies": {
|
||||
"codemirror": "^5.24.2",
|
||||
"devtools-launchpad": "^0.0.59",
|
||||
"devtools-modules": "^0.0.18",
|
||||
"devtools-reps": "^0.4.0",
|
||||
"devtools-sham-modules": "^0.0.17",
|
||||
"express": "^4.15.2",
|
||||
"immutable": "^3.8.1",
|
||||
"jszip": "^3.1.3",
|
||||
"react": "=15.3.2",
|
||||
"react-dom": "=15.3.2",
|
||||
"react-redux": "=5.0.3",
|
||||
"redux": "^3.6.0",
|
||||
"redux-thunk": "^2.2.0",
|
||||
"reselect": "^2.5.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"amd-loader": "0.0.5",
|
||||
"babel-preset-es2015": "^6.6.0",
|
||||
"babel-register": "^6.7.2",
|
||||
"cross-env": "^3.1.3",
|
||||
"enzyme": "^2.4.1",
|
||||
"expect": "^1.16.0",
|
||||
"jsdom": "^9.4.1",
|
||||
"jsdom-global": "^2.0.0",
|
||||
"mocha": "^2.5.3",
|
||||
"require-hacker": "^2.1.4"
|
||||
"babel-register": "^6.24.0",
|
||||
"file-loader": "^0.10.1"
|
||||
},
|
||||
"scripts": {
|
||||
"postinstall": "cd ../ && npm install && cd netmonitor",
|
||||
"test": "cross-env NODE_PATH=../../../ mocha test/**/*.test.js --compilers js:babel-register -r jsdom-global/register -r ./test/require-helper.js"
|
||||
"start": "node bin/dev-server"
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
const { KeyCodes } = require("devtools/client/shared/keycodes");
|
||||
const {
|
||||
createClass,
|
||||
createFactory,
|
||||
@ -176,36 +175,36 @@ const RequestListContent = createClass({
|
||||
* Handler for keyboard events. For arrow up/down, page up/down, home/end,
|
||||
* move the selection up or down.
|
||||
*/
|
||||
onKeyDown(e) {
|
||||
onKeyDown(evt) {
|
||||
let delta;
|
||||
|
||||
switch (e.keyCode) {
|
||||
case KeyCodes.DOM_VK_UP:
|
||||
case KeyCodes.DOM_VK_LEFT:
|
||||
switch (evt.key) {
|
||||
case "ArrowUp":
|
||||
case "ArrowLeft":
|
||||
delta = -1;
|
||||
break;
|
||||
case KeyCodes.DOM_VK_DOWN:
|
||||
case KeyCodes.DOM_VK_RIGHT:
|
||||
case "ArrowDown":
|
||||
case "ArrowRight":
|
||||
delta = +1;
|
||||
break;
|
||||
case KeyCodes.DOM_VK_PAGE_UP:
|
||||
case "PageUp":
|
||||
delta = "PAGE_UP";
|
||||
break;
|
||||
case KeyCodes.DOM_VK_PAGE_DOWN:
|
||||
case "PageDown":
|
||||
delta = "PAGE_DOWN";
|
||||
break;
|
||||
case KeyCodes.DOM_VK_HOME:
|
||||
case "Home":
|
||||
delta = -Infinity;
|
||||
break;
|
||||
case KeyCodes.DOM_VK_END:
|
||||
case "End":
|
||||
delta = +Infinity;
|
||||
break;
|
||||
}
|
||||
|
||||
if (delta) {
|
||||
// Prevent scrolling when pressing navigation keys.
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
this.props.onSelectDelta(delta);
|
||||
}
|
||||
},
|
||||
|
@ -10,7 +10,6 @@ const {
|
||||
DOM,
|
||||
} = require("devtools/client/shared/vendor/react");
|
||||
const { connect } = require("devtools/client/shared/vendor/react-redux");
|
||||
const { setNamedTimeout } = require("devtools/client/shared/widgets/view-helpers");
|
||||
const Actions = require("../actions/index");
|
||||
const { getWaterfallScale } = require("../selectors/index");
|
||||
const { getFormattedTime } = require("../utils/format-utils");
|
||||
@ -71,10 +70,10 @@ const RequestListHeader = createClass({
|
||||
resizeWaterfall() {
|
||||
// Measure its width and update the 'waterfallWidth' property in the store.
|
||||
// The 'waterfallWidth' will be further updated on every window resize.
|
||||
setNamedTimeout("resize-events", 50, () => {
|
||||
const { width } = this.refs.header.getBoundingClientRect();
|
||||
setTimeout(() => {
|
||||
let { width } = this.refs.header.getBoundingClientRect();
|
||||
this.props.resizeWaterfall(width);
|
||||
});
|
||||
}, 50);
|
||||
},
|
||||
|
||||
render() {
|
||||
|
@ -68,7 +68,7 @@ add_task(function* () {
|
||||
yield testWindow();
|
||||
|
||||
info("Moving toolbox back to the bottom...");
|
||||
yield monitor.toolbox.switchHost(Toolbox.HostType.BOTTOM);
|
||||
yield monitor.toolbox.switchHost("bottom");
|
||||
return teardown(monitor);
|
||||
|
||||
function storeFirstPrefValues() {
|
||||
@ -218,7 +218,7 @@ add_task(function* () {
|
||||
|
||||
info("Moving toolbox to the side...");
|
||||
|
||||
yield monitor.toolbox.switchHost(Toolbox.HostType.SIDE);
|
||||
yield monitor.toolbox.switchHost("side");
|
||||
info("Testing prefs reload for a side host.");
|
||||
storeFirstPrefValues();
|
||||
|
||||
@ -243,7 +243,7 @@ add_task(function* () {
|
||||
|
||||
info("Moving toolbox into a window...");
|
||||
|
||||
yield monitor.toolbox.switchHost(Toolbox.HostType.WINDOW);
|
||||
yield monitor.toolbox.switchHost("window");
|
||||
info("Testing prefs reload for a window host.");
|
||||
storeFirstPrefValues();
|
||||
|
||||
|
@ -14,7 +14,6 @@ Services.scriptloader.loadSubScript(
|
||||
this);
|
||||
|
||||
const { EVENTS } = require("devtools/client/netmonitor/src/constants");
|
||||
let { Toolbox } = require("devtools/client/framework/toolbox");
|
||||
const {
|
||||
decodeUnicodeUrl,
|
||||
getUrlBaseName,
|
||||
|
99
devtools/client/netmonitor/webpack.config.js
Normal file
99
devtools/client/netmonitor/webpack.config.js
Normal file
@ -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/. */
|
||||
|
||||
/* eslint-env node */
|
||||
/* eslint max-len: [0] */
|
||||
|
||||
"use strict";
|
||||
|
||||
const path = require("path");
|
||||
const { isDevelopment } = require("devtools-config");
|
||||
const { NormalModuleReplacementPlugin } = require("webpack");
|
||||
const { toolboxConfig } = require("./node_modules/devtools-launchpad/index");
|
||||
const { getConfig } = require("./bin/configure");
|
||||
|
||||
let webpackConfig = {
|
||||
entry: {
|
||||
netmonitor: [path.join(__dirname, "index.js")]
|
||||
},
|
||||
|
||||
module: {
|
||||
loaders: [
|
||||
{
|
||||
test: /\.(png|svg)$/,
|
||||
loader: "file-loader?name=[name].[ext]",
|
||||
},
|
||||
]
|
||||
},
|
||||
|
||||
output: {
|
||||
path: path.join(__dirname, "assets/build"),
|
||||
filename: "[name].js",
|
||||
publicPath: "/assets/build",
|
||||
libraryTarget: "umd",
|
||||
},
|
||||
|
||||
// Fallback compatibility for npm link
|
||||
resolve: {
|
||||
fallback: path.join(__dirname, "node_modules"),
|
||||
alias: {
|
||||
"react": path.join(__dirname, "node_modules/react"),
|
||||
"devtools/client/framework/devtools": "devtools-sham-modules",
|
||||
"devtools/client/framework/menu": "devtools-sham-modules",
|
||||
"devtools/client/framework/menu-item": "devtools-sham-modules",
|
||||
"devtools/client/locales": path.join(__dirname, "../locales/en-US"),
|
||||
"devtools/client/shared/components/reps/reps": "devtools-reps",
|
||||
"devtools/client/shared/components/search-box": "devtools-sham-modules",
|
||||
"devtools/client/shared/components/splitter/split-box": "devtools-modules",
|
||||
"devtools/client/shared/components/tabs/tabbar": "devtools-sham-modules",
|
||||
"devtools/client/shared/components/tabs/tabs": "devtools-sham-modules",
|
||||
"devtools/client/shared/components/tree/tree-view": "devtools-modules",
|
||||
"devtools/client/shared/components/tree/tree-row": "devtools-modules",
|
||||
"devtools/client/shared/curl": "devtools-modules",
|
||||
"devtools/client/shared/file-saver": "devtools-modules",
|
||||
"devtools/client/shared/prefs": "devtools-sham-modules",
|
||||
"devtools/client/shared/redux/middleware/thunk": "redux-thunk",
|
||||
"devtools/client/shared/vendor/immutable": "immutable",
|
||||
"devtools/client/shared/vendor/react": "react",
|
||||
"devtools/client/shared/vendor/react-dom": "react-dom",
|
||||
"devtools/client/shared/vendor/react-redux": "react-redux",
|
||||
"devtools/client/shared/vendor/redux": "redux",
|
||||
"devtools/client/shared/vendor/reselect": "reselect",
|
||||
"devtools/client/shared/vendor/jszip": "jszip",
|
||||
"devtools/client/shared/widgets/view-helpers": "devtools-sham-modules",
|
||||
"devtools/client/shared/widgets/tooltip/HTMLTooltip": "devtools-sham-modules",
|
||||
"devtools/client/shared/widgets/tooltip/ImageTooltipHelper": "devtools-sham-modules",
|
||||
"devtools/client/shared/widgets/Chart": "devtools-sham-modules",
|
||||
"devtools/client/sourceeditor/editor": "devtools-modules",
|
||||
"devtools/shared/fronts/timeline": "devtools-sham-modules",
|
||||
"devtools/shared/l10n": "devtools-modules",
|
||||
"devtools/shared/platform/clipboard": "devtools-modules",
|
||||
"devtools/shared/plural-form": "devtools-modules",
|
||||
"Services": "devtools-modules",
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
if (!isDevelopment()) {
|
||||
webpackConfig.output.libraryTarget = "umd";
|
||||
webpackConfig.plugins = [];
|
||||
|
||||
const mappings = [
|
||||
[/\.\/mocha/, "./mochitest"],
|
||||
[/\.\.\/utils\/mocha/, "../utils/mochitest"],
|
||||
[/\.\/utils\/mocha/, "./utils/mochitest"],
|
||||
];
|
||||
|
||||
mappings.forEach(([regex, res]) => {
|
||||
webpackConfig.plugins.push(new NormalModuleReplacementPlugin(regex, res));
|
||||
});
|
||||
}
|
||||
|
||||
let config = toolboxConfig(webpackConfig, getConfig());
|
||||
|
||||
// Remove loaders from devtools-launchpad webpack config
|
||||
config.module.loaders = config.module.loaders
|
||||
.filter((loader) => !["svg-inline"].includes(loader.loader));
|
||||
|
||||
module.exports = config;
|
4378
devtools/client/netmonitor/yarn.lock
Normal file
4378
devtools/client/netmonitor/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
@ -51,13 +51,6 @@ nsWebNavigationInfo::IsTypeSupported(const nsACString& aType,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// We want to claim that the type for SWF movies is unsupported,
|
||||
// so that the internal SWF player's stream converter will get used.
|
||||
if (aType.LowerCaseEqualsLiteral("application/x-shockwave-flash") &&
|
||||
nsContentUtils::IsSWFPlayerEnabled()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
const nsCString& flatType = PromiseFlatCString(aType);
|
||||
nsresult rv = IsTypeSupportedInternal(flatType, aIsTypeSupported);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -31,9 +31,7 @@ struct PropertyValuePair
|
||||
// (string).
|
||||
nsCSSValue mValue;
|
||||
|
||||
// The specified value when using the Servo backend. However, even when
|
||||
// using the Servo backend, we still fill in |mValue| in the case where we
|
||||
// fail to parse the value since we use it to store the original string.
|
||||
// The specified value when using the Servo backend.
|
||||
RefPtr<RawServoDeclarationBlock> mServoDeclarationBlock;
|
||||
|
||||
bool operator==(const PropertyValuePair&) const;
|
||||
|
@ -1032,8 +1032,8 @@ MakePropertyValuePair(nsCSSPropertyID aProperty, const nsAString& aStringValue,
|
||||
|
||||
if (servoDeclarationBlock) {
|
||||
result.mServoDeclarationBlock = servoDeclarationBlock.forget();
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
nsCSSValue value;
|
||||
@ -1067,13 +1067,6 @@ MakePropertyValuePair(nsCSSPropertyID aProperty, const nsAString& aStringValue,
|
||||
"The shorthand property of a token stream should be initialized"
|
||||
" to unknown");
|
||||
value.SetTokenStreamValue(tokenStream);
|
||||
} else {
|
||||
// If we succeeded in parsing with Gecko, but not Servo the animation is
|
||||
// not going to work since, for the purposes of animation, we're going to
|
||||
// ignore |mValue| when the backend is Servo.
|
||||
NS_WARNING_ASSERTION(aDocument->GetStyleBackendType() !=
|
||||
StyleBackendType::Servo,
|
||||
"Gecko succeeded in parsing where Servo failed");
|
||||
}
|
||||
|
||||
result.mValue = value;
|
||||
|
@ -1,11 +1,11 @@
|
||||
pref(dom.animations-api.core.enabled,true) load 1239889-1.html
|
||||
pref(dom.animations-api.core.enabled,true) load 1244595-1.html
|
||||
pref(dom.animations-api.core.enabled,true) load 1216842-1.html # bug 1334036
|
||||
pref(dom.animations-api.core.enabled,true) load 1216842-2.html # bug 1334036
|
||||
pref(dom.animations-api.core.enabled,true) load 1216842-1.html
|
||||
pref(dom.animations-api.core.enabled,true) load 1216842-2.html
|
||||
pref(dom.animations-api.core.enabled,true) load 1216842-3.html
|
||||
pref(dom.animations-api.core.enabled,true) load 1216842-4.html
|
||||
pref(dom.animations-api.core.enabled,true) load 1216842-5.html # bug 1334036
|
||||
pref(dom.animations-api.core.enabled,true) load 1216842-6.html # bug 1334036
|
||||
pref(dom.animations-api.core.enabled,true) load 1216842-5.html
|
||||
pref(dom.animations-api.core.enabled,true) load 1216842-6.html
|
||||
pref(dom.animations-api.core.enabled,true) load 1272475-1.html
|
||||
pref(dom.animations-api.core.enabled,true) load 1272475-2.html
|
||||
pref(dom.animations-api.core.enabled,true) load 1278485-1.html
|
||||
@ -22,7 +22,7 @@ skip-if(stylo) pref(dom.animations-api.core.enabled,true) load 1325193-1.html #
|
||||
skip-if(stylo) pref(dom.animations-api.core.enabled,true) load 1330190-1.html # bug 1311257
|
||||
skip-if(stylo) pref(dom.animations-api.core.enabled,true) load 1330190-2.html # bug 1311257
|
||||
skip-if(stylo) pref(dom.animations-api.core.enabled,true) load 1330513-1.html # bug 1311257
|
||||
skip-if(stylo) pref(dom.animations-api.core.enabled,true) load 1333539-1.html
|
||||
skip-if(stylo) pref(dom.animations-api.core.enabled,true) load 1333539-2.html
|
||||
pref(dom.animations-api.core.enabled,true) load 1333539-1.html
|
||||
pref(dom.animations-api.core.enabled,true) load 1333539-2.html
|
||||
skip-if(stylo) pref(dom.animations-api.core.enabled,true) load 1333418-1.html # bug 1311257
|
||||
pref(dom.animations-api.core.enabled,true) load 1343589-1.html
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/FunctionBinding.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
@ -6768,20 +6768,6 @@ nsContentUtils::IsPDFJSEnabled()
|
||||
return NS_SUCCEEDED(rv) && canConvert;
|
||||
}
|
||||
|
||||
bool
|
||||
nsContentUtils::IsSWFPlayerEnabled()
|
||||
{
|
||||
nsCOMPtr<nsIStreamConverterService> convServ =
|
||||
do_GetService("@mozilla.org/streamConverters;1");
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
bool canConvert = false;
|
||||
if (convServ) {
|
||||
rv = convServ->CanConvert("application/x-shockwave-flash",
|
||||
"text/html", &canConvert);
|
||||
}
|
||||
return NS_SUCCEEDED(rv) && canConvert;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIDocumentLoaderFactory>
|
||||
nsContentUtils::FindInternalContentViewer(const nsACString& aType,
|
||||
ContentViewerType* aLoaderType)
|
||||
@ -10153,13 +10139,6 @@ nsContentUtils::HtmlObjectContentTypeForMIMEType(const nsCString& aMIMEType,
|
||||
return nsIObjectLoadingContent::TYPE_DOCUMENT;
|
||||
}
|
||||
|
||||
// Faking support of the SWF content as a document for EMBED tags
|
||||
// when internal SWF player is enabled.
|
||||
if (aMIMEType.LowerCaseEqualsLiteral("application/x-shockwave-flash") &&
|
||||
IsSWFPlayerEnabled()) {
|
||||
return nsIObjectLoadingContent::TYPE_DOCUMENT;
|
||||
}
|
||||
|
||||
if (HtmlObjectContentSupportsDocument(aMIMEType, aContent)) {
|
||||
return nsIObjectLoadingContent::TYPE_DOCUMENT;
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user