summaryrefslogtreecommitdiffstats
path: root/browser/components/preferences/in-content/tests
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/preferences/in-content/tests')
-rw-r--r--browser/components/preferences/in-content/tests/.eslintrc.js7
-rw-r--r--browser/components/preferences/in-content/tests/browser.ini43
-rw-r--r--browser/components/preferences/in-content/tests/browser_advanced_update.js158
-rw-r--r--browser/components/preferences/in-content/tests/browser_basic_rebuild_fonts_test.js76
-rw-r--r--browser/components/preferences/in-content/tests/browser_bug1018066_resetScrollPosition.js24
-rw-r--r--browser/components/preferences/in-content/tests/browser_bug1020245_openPreferences_to_paneContent.js43
-rw-r--r--browser/components/preferences/in-content/tests/browser_bug1184989_prevent_scrolling_when_preferences_flipped.js92
-rw-r--r--browser/components/preferences/in-content/tests/browser_bug1184989_prevent_scrolling_when_preferences_flipped.xul33
-rw-r--r--browser/components/preferences/in-content/tests/browser_bug410900.js46
-rw-r--r--browser/components/preferences/in-content/tests/browser_bug705422.js144
-rw-r--r--browser/components/preferences/in-content/tests/browser_bug731866.js52
-rw-r--r--browser/components/preferences/in-content/tests/browser_bug795764_cachedisabled.js52
-rw-r--r--browser/components/preferences/in-content/tests/browser_change_app_handler.js98
-rw-r--r--browser/components/preferences/in-content/tests/browser_connection.js99
-rw-r--r--browser/components/preferences/in-content/tests/browser_connection_bug388287.js125
-rw-r--r--browser/components/preferences/in-content/tests/browser_cookies_exceptions.js348
-rw-r--r--browser/components/preferences/in-content/tests/browser_defaultbrowser_alwayscheck.js103
-rw-r--r--browser/components/preferences/in-content/tests/browser_healthreport.js62
-rw-r--r--browser/components/preferences/in-content/tests/browser_homepages_filter_aboutpreferences.js20
-rw-r--r--browser/components/preferences/in-content/tests/browser_notifications_do_not_disturb.js44
-rw-r--r--browser/components/preferences/in-content/tests/browser_permissions_urlFieldHidden.js45
-rw-r--r--browser/components/preferences/in-content/tests/browser_privacypane_1.js18
-rw-r--r--browser/components/preferences/in-content/tests/browser_privacypane_3.js17
-rw-r--r--browser/components/preferences/in-content/tests/browser_privacypane_4.js25
-rw-r--r--browser/components/preferences/in-content/tests/browser_privacypane_5.js17
-rw-r--r--browser/components/preferences/in-content/tests/browser_privacypane_8.js26
-rw-r--r--browser/components/preferences/in-content/tests/browser_proxy_backup.js65
-rw-r--r--browser/components/preferences/in-content/tests/browser_sanitizeOnShutdown_prefLocked.js37
-rw-r--r--browser/components/preferences/in-content/tests/browser_searchsuggestions.js43
-rw-r--r--browser/components/preferences/in-content/tests/browser_security.js130
-rw-r--r--browser/components/preferences/in-content/tests/browser_subdialogs.js293
-rw-r--r--browser/components/preferences/in-content/tests/browser_telemetry.js52
-rw-r--r--browser/components/preferences/in-content/tests/head.js165
-rw-r--r--browser/components/preferences/in-content/tests/privacypane_tests_perwindow.js330
-rw-r--r--browser/components/preferences/in-content/tests/subdialog.xul27
-rw-r--r--browser/components/preferences/in-content/tests/subdialog2.xul27
36 files changed, 2986 insertions, 0 deletions
diff --git a/browser/components/preferences/in-content/tests/.eslintrc.js b/browser/components/preferences/in-content/tests/.eslintrc.js
new file mode 100644
index 000000000..7c8021192
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/.eslintrc.js
@@ -0,0 +1,7 @@
+"use strict";
+
+module.exports = {
+ "extends": [
+ "../../../../../testing/mochitest/browser.eslintrc.js"
+ ]
+};
diff --git a/browser/components/preferences/in-content/tests/browser.ini b/browser/components/preferences/in-content/tests/browser.ini
new file mode 100644
index 000000000..6cba02599
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser.ini
@@ -0,0 +1,43 @@
+[DEFAULT]
+support-files =
+ head.js
+ privacypane_tests_perwindow.js
+
+[browser_advanced_update.js]
+[browser_basic_rebuild_fonts_test.js]
+[browser_bug410900.js]
+[browser_bug705422.js]
+[browser_bug731866.js]
+[browser_bug795764_cachedisabled.js]
+[browser_bug1018066_resetScrollPosition.js]
+[browser_bug1020245_openPreferences_to_paneContent.js]
+[browser_bug1184989_prevent_scrolling_when_preferences_flipped.js]
+support-files =
+ browser_bug1184989_prevent_scrolling_when_preferences_flipped.xul
+[browser_change_app_handler.js]
+skip-if = os != "win" # This test tests the windows-specific app selection dialog, so can't run on non-Windows
+[browser_connection.js]
+[browser_connection_bug388287.js]
+[browser_cookies_exceptions.js]
+[browser_defaultbrowser_alwayscheck.js]
+[browser_healthreport.js]
+skip-if = true || !healthreport # Bug 1185403 for the "true"
+[browser_homepages_filter_aboutpreferences.js]
+[browser_notifications_do_not_disturb.js]
+[browser_permissions_urlFieldHidden.js]
+[browser_proxy_backup.js]
+[browser_privacypane_1.js]
+[browser_privacypane_3.js]
+[browser_privacypane_4.js]
+[browser_privacypane_5.js]
+[browser_privacypane_8.js]
+[browser_sanitizeOnShutdown_prefLocked.js]
+[browser_searchsuggestions.js]
+[browser_security.js]
+[browser_subdialogs.js]
+support-files =
+ subdialog.xul
+ subdialog2.xul
+[browser_telemetry.js]
+# Skip this test on Android as FHR and Telemetry are separate systems there.
+skip-if = !healthreport || !telemetry || (os == 'linux' && debug) || (os == 'android')
diff --git a/browser/components/preferences/in-content/tests/browser_advanced_update.js b/browser/components/preferences/in-content/tests/browser_advanced_update.js
new file mode 100644
index 000000000..e9d0e8652
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser_advanced_update.js
@@ -0,0 +1,158 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const { classes: Cc, interfaces: Ci, manager: Cm, utils: Cu, results: Cr } = Components;
+
+Cu.import('resource://gre/modules/XPCOMUtils.jsm');
+
+const uuidGenerator = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator);
+
+const mockUpdateManager = {
+ contractId: "@mozilla.org/updates/update-manager;1",
+
+ _mockClassId: uuidGenerator.generateUUID(),
+
+ _originalClassId: "",
+
+ _originalFactory: null,
+
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIUpdateManager]),
+
+ createInstance: function(outer, iiD) {
+ if (outer) {
+ throw Cr.NS_ERROR_NO_AGGREGATION;
+ }
+ return this.QueryInterface(iiD);
+ },
+
+ register: function () {
+ let registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
+ if (!registrar.isCIDRegistered(this._mockClassId)) {
+ this._originalClassId = registrar.contractIDToCID(this.contractId);
+ this._originalFactory = Cm.getClassObject(Cc[this.contractId], Ci.nsIFactory);
+ registrar.unregisterFactory(this._originalClassId, this._originalFactory);
+ registrar.registerFactory(this._mockClassId, "Unregister after testing", this.contractId, this);
+ }
+ },
+
+ unregister: function () {
+ let registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
+ registrar.unregisterFactory(this._mockClassId, this);
+ registrar.registerFactory(this._originalClassId, "", this.contractId, this._originalFactory);
+ },
+
+ get updateCount() {
+ return this._updates.length;
+ },
+
+ getUpdateAt: function (index) {
+ return this._updates[index];
+ },
+
+ _updates: [
+ {
+ name: "Firefox Developer Edition 49.0a2",
+ statusText: "The Update was successfully installed",
+ buildID: "20160728004010",
+ type: "minor",
+ installDate: 1469763105156,
+ detailsURL: "https://www.mozilla.org/firefox/aurora/"
+ },
+ {
+ name: "Firefox Developer Edition 43.0a2",
+ statusText: "The Update was successfully installed",
+ buildID: "20150929004011",
+ type: "minor",
+ installDate: 1443585886224,
+ detailsURL: "https://www.mozilla.org/firefox/aurora/"
+ },
+ {
+ name: "Firefox Developer Edition 42.0a2",
+ statusText: "The Update was successfully installed",
+ buildID: "20150920004018",
+ type: "major",
+ installDate: 1442818147544,
+ detailsURL: "https://www.mozilla.org/firefox/aurora/"
+ }
+ ]
+};
+
+function resetPreferences() {
+ Services.prefs.clearUserPref("browser.search.update");
+}
+
+function formatInstallDate(sec) {
+ var date = new Date(sec);
+ const locale = Cc["@mozilla.org/chrome/chrome-registry;1"]
+ .getService(Ci.nsIXULChromeRegistry)
+ .getSelectedLocale("global", true);
+ const dtOptions = { year: 'numeric', month: 'long', day: 'numeric',
+ hour: 'numeric', minute: 'numeric', second: 'numeric' };
+ return date.toLocaleString(locale, dtOptions);
+}
+
+registerCleanupFunction(resetPreferences);
+
+add_task(function*() {
+ yield openPreferencesViaOpenPreferencesAPI("advanced", "updateTab", { leaveOpen: true });
+ resetPreferences();
+ Services.prefs.setBoolPref("browser.search.update", false);
+
+ let doc = gBrowser.selectedBrowser.contentDocument;
+ let enableSearchUpdate = doc.getElementById("enableSearchUpdate");
+ is_element_visible(enableSearchUpdate, "Check search update preference is visible");
+
+ // Ensure that the update pref dialog reflects the actual pref value.
+ ok(!enableSearchUpdate.checked, "Ensure search updates are disabled");
+ Services.prefs.setBoolPref("browser.search.update", true);
+ ok(enableSearchUpdate.checked, "Ensure search updates are enabled");
+
+ gBrowser.removeCurrentTab();
+});
+
+add_task(function*() {
+ mockUpdateManager.register();
+
+ yield openPreferencesViaOpenPreferencesAPI("advanced", "updateTab", { leaveOpen: true });
+ let doc = gBrowser.selectedBrowser.contentDocument;
+
+ let showBtn = doc.getElementById("showUpdateHistory");
+ let dialogOverlay = doc.getElementById("dialogOverlay");
+
+ // Test the dialog window opens
+ is(dialogOverlay.style.visibility, "", "The dialog should be invisible");
+ showBtn.doCommand();
+ yield promiseLoadSubDialog("chrome://mozapps/content/update/history.xul");
+ is(dialogOverlay.style.visibility, "visible", "The dialog should be visible");
+
+ let dialogFrame = doc.getElementById("dialogFrame");
+ let frameDoc = dialogFrame.contentDocument;
+ let updates = frameDoc.querySelectorAll("update");
+
+ // Test the update history numbers are correct
+ is(updates.length, mockUpdateManager.updateCount, "The update count is incorrect.");
+
+ // Test the updates are displayed correctly
+ let update = null;
+ let updateData = null;
+ for (let i = 0; i < updates.length; ++i) {
+ update = updates[i];
+ updateData = mockUpdateManager.getUpdateAt(i);
+
+ is(update.name, updateData.name + " (" + updateData.buildID + ")", "Wrong update name");
+ is(update.type, updateData.type == "major" ? "New Version" : "Security Update", "Wrong update type");
+ is(update.installDate, formatInstallDate(updateData.installDate), "Wrong update installDate");
+ is(update.detailsURL, updateData.detailsURL, "Wrong update detailsURL");
+ is(update.status, updateData.statusText, "Wrong update status");
+ }
+
+ // Test the dialog window closes
+ let closeBtn = doc.getElementById("dialogClose");
+ closeBtn.doCommand();
+ is(dialogOverlay.style.visibility, "", "The dialog should be invisible");
+
+ mockUpdateManager.unregister();
+ gBrowser.removeCurrentTab();
+});
diff --git a/browser/components/preferences/in-content/tests/browser_basic_rebuild_fonts_test.js b/browser/components/preferences/in-content/tests/browser_basic_rebuild_fonts_test.js
new file mode 100644
index 000000000..32c1bd726
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser_basic_rebuild_fonts_test.js
@@ -0,0 +1,76 @@
+Services.prefs.setBoolPref("browser.preferences.instantApply", true);
+
+registerCleanupFunction(function() {
+ Services.prefs.clearUserPref("browser.preferences.instantApply");
+});
+
+add_task(function*() {
+ yield openPreferencesViaOpenPreferencesAPI("paneContent", null, {leaveOpen: true});
+ let doc = gBrowser.contentDocument;
+ var langGroup = Services.prefs.getComplexValue("font.language.group", Ci.nsIPrefLocalizedString).data
+ is(doc.getElementById("font.language.group").value, langGroup,
+ "Language group should be set correctly.");
+
+ let defaultFontType = Services.prefs.getCharPref("font.default." + langGroup);
+ let fontFamily = Services.prefs.getCharPref("font.name." + defaultFontType + "." + langGroup);
+ let fontFamilyField = doc.getElementById("defaultFont");
+ is(fontFamilyField.value, fontFamily, "Font family should be set correctly.");
+
+ let defaultFontSize = Services.prefs.getIntPref("font.size.variable." + langGroup);
+ let fontSizeField = doc.getElementById("defaultFontSize");
+ is(fontSizeField.value, defaultFontSize, "Font size should be set correctly.");
+
+ doc.getElementById("advancedFonts").click();
+ let win = yield promiseLoadSubDialog("chrome://browser/content/preferences/fonts.xul");
+ doc = win.document;
+
+ // Simulate a dumb font backend.
+ win.FontBuilder._enumerator = {
+ _list: ["MockedFont1", "MockedFont2", "MockedFont3"],
+ EnumerateFonts: function(lang, type, list) {
+ return this._list;
+ },
+ EnumerateAllFonts: function() {
+ return this._list;
+ },
+ getDefaultFont: function() { return null; },
+ getStandardFamilyName: function(name) { return name; },
+ };
+ win.FontBuilder._allFonts = null;
+ win.FontBuilder._langGroupSupported = false;
+
+ let langGroupElement = doc.getElementById("font.language.group");
+ let selectLangsField = doc.getElementById("selectLangs");
+ let serifField = doc.getElementById("serif");
+ let armenian = "x-armn";
+ let western = "x-western";
+
+ langGroupElement.value = armenian;
+ selectLangsField.value = armenian;
+ is(serifField.value, "", "Font family should not be set.");
+
+ langGroupElement.value = western;
+ selectLangsField.value = western;
+
+ // Simulate a font backend supporting language-specific enumeration.
+ // NB: FontBuilder has cached the return value from EnumerateAllFonts(),
+ // so _allFonts will always have 3 elements regardless of subsequent
+ // _list changes.
+ win.FontBuilder._enumerator._list = ["MockedFont2"];
+
+ langGroupElement.value = armenian;
+ selectLangsField.value = armenian;
+ is(serifField.value, "MockedFont2", "Font family should be set.");
+
+ langGroupElement.value = western;
+ selectLangsField.value = western;
+
+ // Simulate a system that has no fonts for the specified language.
+ win.FontBuilder._enumerator._list = [];
+
+ langGroupElement.value = armenian;
+ selectLangsField.value = armenian;
+ is(serifField.value, "", "Font family should not be set.");
+
+ gBrowser.removeCurrentTab();
+});
diff --git a/browser/components/preferences/in-content/tests/browser_bug1018066_resetScrollPosition.js b/browser/components/preferences/in-content/tests/browser_bug1018066_resetScrollPosition.js
new file mode 100644
index 000000000..9d938fdd4
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser_bug1018066_resetScrollPosition.js
@@ -0,0 +1,24 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+var originalWindowHeight;
+registerCleanupFunction(function() {
+ window.resizeTo(window.outerWidth, originalWindowHeight);
+ while (gBrowser.tabs[1])
+ gBrowser.removeTab(gBrowser.tabs[1]);
+});
+
+add_task(function*() {
+ originalWindowHeight = window.outerHeight;
+ window.resizeTo(window.outerWidth, 300);
+ let prefs = yield openPreferencesViaOpenPreferencesAPI("paneApplications", undefined, {leaveOpen: true});
+ is(prefs.selectedPane, "paneApplications", "Applications pane was selected");
+ let mainContent = gBrowser.contentDocument.querySelector(".main-content");
+ mainContent.scrollTop = 50;
+ is(mainContent.scrollTop, 50, "main-content should be scrolled 50 pixels");
+
+ gBrowser.contentWindow.gotoPref("paneGeneral");
+ is(mainContent.scrollTop, 0,
+ "Switching to a different category should reset the scroll position");
+});
+
diff --git a/browser/components/preferences/in-content/tests/browser_bug1020245_openPreferences_to_paneContent.js b/browser/components/preferences/in-content/tests/browser_bug1020245_openPreferences_to_paneContent.js
new file mode 100644
index 000000000..bc2c6d800
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser_bug1020245_openPreferences_to_paneContent.js
@@ -0,0 +1,43 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+Services.prefs.setBoolPref("browser.preferences.instantApply", true);
+
+registerCleanupFunction(function() {
+ Services.prefs.clearUserPref("browser.preferences.instantApply");
+});
+
+add_task(function*() {
+ let prefs = yield openPreferencesViaOpenPreferencesAPI("paneContent");
+ is(prefs.selectedPane, "paneContent", "Content pane was selected");
+ prefs = yield openPreferencesViaOpenPreferencesAPI("advanced", "updateTab");
+ is(prefs.selectedPane, "paneAdvanced", "Advanced pane was selected");
+ is(prefs.selectedAdvancedTab, "updateTab", "The update tab within the advanced prefs should be selected");
+ prefs = yield openPreferencesViaHash("privacy");
+ is(prefs.selectedPane, "panePrivacy", "Privacy pane is selected when hash is 'privacy'");
+ prefs = yield openPreferencesViaOpenPreferencesAPI("nonexistant-category");
+ is(prefs.selectedPane, "paneGeneral", "General pane is selected by default when a nonexistant-category is requested");
+ prefs = yield openPreferencesViaHash("nonexistant-category");
+ is(prefs.selectedPane, "paneGeneral", "General pane is selected when hash is a nonexistant-category");
+ prefs = yield openPreferencesViaHash();
+ is(prefs.selectedPane, "paneGeneral", "General pane is selected by default");
+});
+
+function openPreferencesViaHash(aPane) {
+ let deferred = Promise.defer();
+ gBrowser.selectedTab = gBrowser.addTab("about:preferences" + (aPane ? "#" + aPane : ""));
+ let newTabBrowser = gBrowser.selectedBrowser;
+
+ newTabBrowser.addEventListener("Initialized", function PrefInit() {
+ newTabBrowser.removeEventListener("Initialized", PrefInit, true);
+ newTabBrowser.contentWindow.addEventListener("load", function prefLoad() {
+ newTabBrowser.contentWindow.removeEventListener("load", prefLoad);
+ let win = gBrowser.contentWindow;
+ let selectedPane = win.history.state;
+ gBrowser.removeCurrentTab();
+ deferred.resolve({selectedPane: selectedPane});
+ });
+ }, true);
+
+ return deferred.promise;
+}
diff --git a/browser/components/preferences/in-content/tests/browser_bug1184989_prevent_scrolling_when_preferences_flipped.js b/browser/components/preferences/in-content/tests/browser_bug1184989_prevent_scrolling_when_preferences_flipped.js
new file mode 100644
index 000000000..0972b2de4
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser_bug1184989_prevent_scrolling_when_preferences_flipped.js
@@ -0,0 +1,92 @@
+const ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
+
+add_task(function* () {
+ waitForExplicitFinish();
+
+ const tabURL = getRootDirectory(gTestPath) + "browser_bug1184989_prevent_scrolling_when_preferences_flipped.xul";
+
+ yield BrowserTestUtils.withNewTab({ gBrowser, url: tabURL }, function* (browser) {
+ let doc = browser.contentDocument;
+ let container = doc.getElementById("container");
+
+ // Test button
+ let button = doc.getElementById("button");
+ button.focus();
+ EventUtils.synthesizeKey(" ", {});
+ yield checkPageScrolling(container, "button");
+
+ // Test checkbox
+ let checkbox = doc.getElementById("checkbox");
+ checkbox.focus();
+ EventUtils.synthesizeKey(" ", {});
+ ok(checkbox.checked, "Checkbox is checked");
+ yield checkPageScrolling(container, "checkbox");
+
+ // Test listbox
+ let listbox = doc.getElementById("listbox");
+ let listitem = doc.getElementById("listitem");
+ listbox.focus();
+ EventUtils.synthesizeKey(" ", {});
+ ok(listitem.selected, "Listitem is selected");
+ yield checkPageScrolling(container, "listbox");
+
+ // Test radio
+ let radiogroup = doc.getElementById("radiogroup");
+ radiogroup.focus();
+ EventUtils.synthesizeKey(" ", {});
+ yield checkPageScrolling(container, "radio");
+ });
+
+ yield BrowserTestUtils.withNewTab({ gBrowser, url: "about:preferences#search" }, function* (browser) {
+ let doc = browser.contentDocument;
+ let container = doc.getElementsByClassName("main-content")[0];
+
+ // Test search
+ let engineList = doc.getElementById("engineList");
+ engineList.focus();
+ EventUtils.synthesizeKey(" ", {});
+ is(engineList.view.selection.currentIndex, 0, "Search engineList is selected");
+ EventUtils.synthesizeKey(" ", {});
+ yield checkPageScrolling(container, "search engineList");
+ });
+
+ // Test session restore
+ const CRASH_URL = "about:mozilla";
+ const CRASH_FAVICON = "chrome://branding/content/icon32.png";
+ const CRASH_SHENTRY = {url: CRASH_URL};
+ const CRASH_TAB = {entries: [CRASH_SHENTRY], image: CRASH_FAVICON};
+ const CRASH_STATE = {windows: [{tabs: [CRASH_TAB]}]};
+
+ const TAB_URL = "about:sessionrestore";
+ const TAB_FORMDATA = {url: TAB_URL, id: {sessionData: CRASH_STATE}};
+ const TAB_SHENTRY = {url: TAB_URL};
+ const TAB_STATE = {entries: [TAB_SHENTRY], formdata: TAB_FORMDATA};
+
+ let tab = gBrowser.selectedTab = gBrowser.addTab("about:blank");
+
+ // Fake a post-crash tab
+ ss.setTabState(tab, JSON.stringify(TAB_STATE));
+
+ yield BrowserTestUtils.browserLoaded(tab.linkedBrowser);
+ let doc = tab.linkedBrowser.contentDocument;
+
+ // Make body scrollable
+ doc.body.style.height = (doc.body.clientHeight + 100) + "px";
+
+ let tabList = doc.getElementById("tabList");
+ tabList.focus();
+ EventUtils.synthesizeKey(" ", {});
+ yield checkPageScrolling(doc.documentElement, "session restore");
+
+ gBrowser.removeCurrentTab();
+ finish();
+});
+
+function checkPageScrolling(container, type) {
+ return new Promise(resolve => {
+ setTimeout(() => {
+ is(container.scrollTop, 0, "Page should not scroll when " + type + " flipped");
+ resolve();
+ }, 0);
+ });
+}
diff --git a/browser/components/preferences/in-content/tests/browser_bug1184989_prevent_scrolling_when_preferences_flipped.xul b/browser/components/preferences/in-content/tests/browser_bug1184989_prevent_scrolling_when_preferences_flipped.xul
new file mode 100644
index 000000000..59b644c8f
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser_bug1184989_prevent_scrolling_when_preferences_flipped.xul
@@ -0,0 +1,33 @@
+<?xml version="1.0"?>
+<!--
+ XUL Widget Test for Bug 1184989
+ -->
+<page title="Bug 1184989 Test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+<vbox id="container" style="height: 200px; overflow: auto;">
+ <vbox style="height: 500px;">
+ <hbox>
+ <button id="button" label="button" />
+ </hbox>
+
+ <hbox>
+ <checkbox id="checkbox" label="checkbox" />
+ </hbox>
+
+ <hbox style="height: 50px;">
+ <listbox id="listbox">
+ <listitem id="listitem" label="listitem" />
+ <listitem label="listitem" />
+ </listbox>
+ </hbox>
+
+ <hbox>
+ <radiogroup id="radiogroup">
+ <radio id="radio" label="radio" />
+ </radiogroup>
+ </hbox>
+ </vbox>
+</vbox>
+
+</page>
diff --git a/browser/components/preferences/in-content/tests/browser_bug410900.js b/browser/components/preferences/in-content/tests/browser_bug410900.js
new file mode 100644
index 000000000..5b100966d
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser_bug410900.js
@@ -0,0 +1,46 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+Components.utils.import("resource://gre/modules/PlacesUtils.jsm");
+Components.utils.import("resource://gre/modules/NetUtil.jsm");
+
+function test() {
+ waitForExplicitFinish();
+
+ // Setup a phony handler to ensure the app pane will be populated.
+ var handler = Cc["@mozilla.org/uriloader/web-handler-app;1"].
+ createInstance(Ci.nsIWebHandlerApp);
+ handler.name = "App pane alive test";
+ handler.uriTemplate = "http://test.mozilla.org/%s";
+
+ var extps = Cc["@mozilla.org/uriloader/external-protocol-service;1"].
+ getService(Ci.nsIExternalProtocolService);
+ var info = extps.getProtocolHandlerInfo("apppanetest");
+ info.possibleApplicationHandlers.appendElement(handler, false);
+
+ var hserv = Cc["@mozilla.org/uriloader/handler-service;1"].
+ getService(Ci.nsIHandlerService);
+ hserv.store(info);
+
+ openPreferencesViaOpenPreferencesAPI("applications", null, {leaveOpen: true}).then(
+ () => runTest(gBrowser.selectedBrowser.contentWindow)
+ );
+}
+
+function runTest(win) {
+ var rbox = win.document.getElementById("handlersView");
+ ok(rbox, "handlersView is present");
+
+ var items = rbox && rbox.getElementsByTagName("richlistitem");
+ ok(items && items.length > 0, "App handler list populated");
+
+ var handlerAdded = false;
+ for (let i = 0; i < items.length; i++) {
+ if (items[i].getAttribute('type') == "apppanetest")
+ handlerAdded = true;
+ }
+ ok(handlerAdded, "apppanetest protocol handler was successfully added");
+
+ gBrowser.removeCurrentTab();
+ finish();
+}
diff --git a/browser/components/preferences/in-content/tests/browser_bug705422.js b/browser/components/preferences/in-content/tests/browser_bug705422.js
new file mode 100644
index 000000000..24732083b
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser_bug705422.js
@@ -0,0 +1,144 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function test() {
+ waitForExplicitFinish();
+ // Allow all cookies, then actually set up the test
+ SpecialPowers.pushPrefEnv({"set": [["network.cookie.cookieBehavior", 0]]}, initTest);
+}
+
+function initTest() {
+ const searchTerm = "example";
+ const dummyTerm = "elpmaxe";
+
+ var cm = Components.classes["@mozilla.org/cookiemanager;1"]
+ .getService(Components.interfaces.nsICookieManager);
+
+ // delete all cookies (might be left over from other tests)
+ cm.removeAll();
+
+ // data for cookies
+ var vals = [[searchTerm+".com", dummyTerm, dummyTerm], // match
+ [searchTerm+".org", dummyTerm, dummyTerm], // match
+ [dummyTerm+".com", searchTerm, dummyTerm], // match
+ [dummyTerm+".edu", searchTerm+dummyTerm, dummyTerm], // match
+ [dummyTerm+".net", dummyTerm, searchTerm], // match
+ [dummyTerm+".org", dummyTerm, searchTerm+dummyTerm], // match
+ [dummyTerm+".int", dummyTerm, dummyTerm]]; // no match
+
+ // matches must correspond to above data
+ const matches = 6;
+
+ var ios = Components.classes["@mozilla.org/network/io-service;1"]
+ .getService(Components.interfaces.nsIIOService);
+ var cookieSvc = Components.classes["@mozilla.org/cookieService;1"]
+ .getService(Components.interfaces.nsICookieService);
+ var v;
+ // inject cookies
+ for (v in vals) {
+ let [host, name, value] = vals[v];
+ var cookieUri = ios.newURI("http://"+host, null, null);
+ cookieSvc.setCookieString(cookieUri, null, name+"="+value+";", null);
+ }
+
+ // open cookie manager
+ var cmd = window.openDialog("chrome://browser/content/preferences/cookies.xul",
+ "Browser:Cookies", "", {});
+
+ // when it has loaded, run actual tests
+ cmd.addEventListener("load", function() { executeSoon(function() { runTest(cmd, searchTerm, vals.length, matches); }); }, false);
+}
+
+function isDisabled(win, expectation) {
+ var disabled = win.document.getElementById("removeAllCookies").disabled;
+ is(disabled, expectation, "Remove all cookies button has correct state: "+(expectation?"disabled":"enabled"));
+}
+
+function runTest(win, searchTerm, cookies, matches) {
+ var cm = Components.classes["@mozilla.org/cookiemanager;1"]
+ .getService(Components.interfaces.nsICookieManager);
+
+
+ // number of cookies should match injected cookies
+ var injectedCookies = 0,
+ injectedEnumerator = cm.enumerator;
+ while (injectedEnumerator.hasMoreElements()) {
+ injectedCookies++;
+ injectedEnumerator.getNext();
+ }
+ is(injectedCookies, cookies, "Number of cookies match injected cookies");
+
+ // "delete all cookies" should be enabled
+ isDisabled(win, false);
+
+ // filter cookies and count matches
+ win.gCookiesWindow.setFilter(searchTerm);
+ is(win.gCookiesWindow._view.rowCount, matches, "Correct number of cookies shown after filter is applied");
+
+ // "delete all cookies" should be enabled
+ isDisabled(win, false);
+
+
+ // select first cookie and delete
+ var tree = win.document.getElementById("cookiesList");
+ var deleteButton = win.document.getElementById("removeSelectedCookies");
+ var rect = tree.treeBoxObject.getCoordsForCellItem(0, tree.columns[0], "cell");
+ EventUtils.synthesizeMouse(tree.body, rect.x + rect.width / 2, rect.y + rect.height / 2, {}, win);
+ EventUtils.synthesizeMouseAtCenter(deleteButton, {}, win);
+
+ // count cookies should be matches-1
+ is(win.gCookiesWindow._view.rowCount, matches-1, "Deleted selected cookie");
+
+ // select two adjacent cells and delete
+ EventUtils.synthesizeMouse(tree.body, rect.x + rect.width / 2, rect.y + rect.height / 2, {}, win);
+ var eventObj = {};
+ if (navigator.platform.indexOf("Mac") >= 0)
+ eventObj.metaKey = true;
+ else
+ eventObj.ctrlKey = true;
+ rect = tree.treeBoxObject.getCoordsForCellItem(1, tree.columns[0], "cell");
+ EventUtils.synthesizeMouse(tree.body, rect.x + rect.width / 2, rect.y + rect.height / 2, eventObj, win);
+ EventUtils.synthesizeMouseAtCenter(deleteButton, {}, win);
+
+ // count cookies should be matches-3
+ is(win.gCookiesWindow._view.rowCount, matches-3, "Deleted selected two adjacent cookies");
+
+ // "delete all cookies" should be enabled
+ isDisabled(win, false);
+
+ // delete all cookies and count
+ var deleteAllButton = win.document.getElementById("removeAllCookies");
+ EventUtils.synthesizeMouseAtCenter(deleteAllButton, {}, win);
+ is(win.gCookiesWindow._view.rowCount, 0, "Deleted all matching cookies");
+
+ // "delete all cookies" should be disabled
+ isDisabled(win, true);
+
+ // clear filter and count should be cookies-matches
+ win.gCookiesWindow.setFilter("");
+ is(win.gCookiesWindow._view.rowCount, cookies-matches, "Unmatched cookies remain");
+
+ // "delete all cookies" should be enabled
+ isDisabled(win, false);
+
+ // delete all cookies and count should be 0
+ EventUtils.synthesizeMouseAtCenter(deleteAllButton, {}, win);
+ is(win.gCookiesWindow._view.rowCount, 0, "Deleted all cookies");
+
+ // check that datastore is also at 0
+ var remainingCookies = 0,
+ remainingEnumerator = cm.enumerator;
+ while (remainingEnumerator.hasMoreElements()) {
+ remainingCookies++;
+ remainingEnumerator.getNext();
+ }
+ is(remainingCookies, 0, "Zero cookies remain");
+
+ // "delete all cookies" should be disabled
+ isDisabled(win, true);
+
+ // clean up
+ win.close();
+ finish();
+}
+
diff --git a/browser/components/preferences/in-content/tests/browser_bug731866.js b/browser/components/preferences/in-content/tests/browser_bug731866.js
new file mode 100644
index 000000000..c1031d412
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser_bug731866.js
@@ -0,0 +1,52 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+Components.utils.import("resource://gre/modules/PlacesUtils.jsm");
+Components.utils.import("resource://gre/modules/NetUtil.jsm");
+
+function test() {
+ waitForExplicitFinish();
+ open_preferences(runTest);
+}
+
+var gElements;
+
+function checkElements(expectedPane) {
+ for (let element of gElements) {
+ // keyset and preferences elements fail is_element_visible checks because they are never visible.
+ // special-case the drmGroup item because its visibility depends on pref + OS version
+ if (element.nodeName == "keyset" ||
+ element.nodeName == "preferences" ||
+ element.id === "drmGroup") {
+ continue;
+ }
+ let attributeValue = element.getAttribute("data-category");
+ let suffix = " (id=" + element.id + ")";
+ if (attributeValue == "pane" + expectedPane) {
+ is_element_visible(element, expectedPane + " elements should be visible" + suffix);
+ } else {
+ is_element_hidden(element, "Elements not in " + expectedPane + " should be hidden" + suffix);
+ }
+ }
+}
+
+function runTest(win) {
+ is(gBrowser.currentURI.spec, "about:preferences", "about:preferences loaded");
+
+ let tab = win.document;
+ gElements = tab.getElementById("mainPrefPane").children;
+
+ let panes = [
+ "General", "Search", "Content", "Applications",
+ "Privacy", "Security", "Sync", "Advanced",
+ ];
+
+ for (let pane of panes) {
+ win.gotoPref("pane" + pane);
+ checkElements(pane);
+ }
+
+ gBrowser.removeCurrentTab();
+ win.close();
+ finish();
+}
diff --git a/browser/components/preferences/in-content/tests/browser_bug795764_cachedisabled.js b/browser/components/preferences/in-content/tests/browser_bug795764_cachedisabled.js
new file mode 100644
index 000000000..21f92db8d
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser_bug795764_cachedisabled.js
@@ -0,0 +1,52 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+Components.utils.import("resource://gre/modules/PlacesUtils.jsm");
+Components.utils.import("resource://gre/modules/NetUtil.jsm");
+
+function test() {
+ waitForExplicitFinish();
+
+ let prefs = [
+ "browser.cache.offline.enable",
+ "browser.cache.disk.enable",
+ "browser.cache.memory.enable",
+ ];
+
+ registerCleanupFunction(function() {
+ for (let pref of prefs) {
+ Services.prefs.clearUserPref(pref);
+ }
+ });
+
+ for (let pref of prefs) {
+ Services.prefs.setBoolPref(pref, false);
+ }
+
+ open_preferences(runTest);
+}
+
+function runTest(win) {
+ is(gBrowser.currentURI.spec, "about:preferences", "about:preferences loaded");
+
+ let tab = win.document;
+ let elements = tab.getElementById("mainPrefPane").children;
+
+ // Test if advanced pane is opened correctly
+ win.gotoPref("paneAdvanced");
+ for (let element of elements) {
+ if (element.nodeName == "preferences") {
+ continue;
+ }
+ let attributeValue = element.getAttribute("data-category");
+ if (attributeValue == "paneAdvanced") {
+ is_element_visible(element, "Advanced elements should be visible");
+ } else {
+ is_element_hidden(element, "Non-Advanced elements should be hidden");
+ }
+ }
+
+ gBrowser.removeCurrentTab();
+ win.close();
+ finish();
+}
diff --git a/browser/components/preferences/in-content/tests/browser_change_app_handler.js b/browser/components/preferences/in-content/tests/browser_change_app_handler.js
new file mode 100644
index 000000000..f66cdfd37
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser_change_app_handler.js
@@ -0,0 +1,98 @@
+var gMimeSvc = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
+var gHandlerSvc = Cc["@mozilla.org/uriloader/handler-service;1"].getService(Ci.nsIHandlerService);
+
+SimpleTest.requestCompleteLog();
+
+function setupFakeHandler() {
+ let info = gMimeSvc.getFromTypeAndExtension("text/plain", "foo.txt");
+ ok(info.possibleLocalHandlers.length, "Should have at least one known handler");
+ let handler = info.possibleLocalHandlers.queryElementAt(0, Ci.nsILocalHandlerApp);
+
+ let infoToModify = gMimeSvc.getFromTypeAndExtension("text/x-test-handler", null);
+ infoToModify.possibleApplicationHandlers.appendElement(handler, false);
+
+ gHandlerSvc.store(infoToModify);
+}
+
+add_task(function*() {
+ setupFakeHandler();
+ yield openPreferencesViaOpenPreferencesAPI("applications", null, {leaveOpen: true});
+ info("Preferences page opened on the applications pane.");
+ let win = gBrowser.selectedBrowser.contentWindow;
+
+ let container = win.document.getElementById("handlersView");
+ let ourItem = container.querySelector("richlistitem[type='text/x-test-handler']");
+ ok(ourItem, "handlersView is present");
+ ourItem.scrollIntoView();
+ container.selectItem(ourItem);
+ ok(ourItem.selected, "Should be able to select our item.");
+
+ let list = yield waitForCondition(() => win.document.getAnonymousElementByAttribute(ourItem, "class", "actionsMenu"));
+ info("Got list after item was selected");
+
+ let chooseItem = list.firstChild.querySelector(".choose-app-item");
+ let dialogLoadedPromise = promiseLoadSubDialog("chrome://global/content/appPicker.xul");
+ let cmdEvent = win.document.createEvent("xulcommandevent");
+ cmdEvent.initCommandEvent("command", true, true, win, 0, false, false, false, false, null);
+ chooseItem.dispatchEvent(cmdEvent);
+
+ let dialog = yield dialogLoadedPromise;
+ info("Dialog loaded");
+
+ let dialogDoc = dialog.document;
+ let dialogList = dialogDoc.getElementById("app-picker-listbox");
+ dialogList.selectItem(dialogList.firstChild);
+ let selectedApp = dialogList.firstChild.handlerApp;
+ dialogDoc.documentElement.acceptDialog();
+
+ // Verify results are correct in mime service:
+ let mimeInfo = gMimeSvc.getFromTypeAndExtension("text/x-test-handler", null);
+ ok(mimeInfo.preferredApplicationHandler.equals(selectedApp), "App should be set as preferred.");
+
+ // Check that we display this result:
+ list = yield waitForCondition(() => win.document.getAnonymousElementByAttribute(ourItem, "class", "actionsMenu"));
+ info("Got list after item was selected");
+ ok(list.selectedItem, "Should have a selected item");
+ ok(mimeInfo.preferredApplicationHandler.equals(list.selectedItem.handlerApp),
+ "App should be visible as preferred item.");
+
+
+ // Now try to 'manage' this list:
+ dialogLoadedPromise = promiseLoadSubDialog("chrome://browser/content/preferences/applicationManager.xul");
+
+ let manageItem = list.firstChild.querySelector(".manage-app-item");
+ cmdEvent = win.document.createEvent("xulcommandevent");
+ cmdEvent.initCommandEvent("command", true, true, win, 0, false, false, false, false, null);
+ manageItem.dispatchEvent(cmdEvent);
+
+ dialog = yield dialogLoadedPromise;
+ info("Dialog loaded the second time");
+
+ dialogDoc = dialog.document;
+ dialogList = dialogDoc.getElementById("appList");
+ let itemToRemove = dialogList.querySelector('listitem[label="' + selectedApp.name + '"]');
+ dialogList.selectItem(itemToRemove);
+ let itemsBefore = dialogList.children.length;
+ dialogDoc.getElementById("remove").click();
+ ok(!itemToRemove.parentNode, "Item got removed from DOM");
+ is(dialogList.children.length, itemsBefore - 1, "Item got removed");
+ dialogDoc.documentElement.acceptDialog();
+
+ // Verify results are correct in mime service:
+ mimeInfo = gMimeSvc.getFromTypeAndExtension("text/x-test-handler", null);
+ ok(!mimeInfo.preferredApplicationHandler, "App should no longer be set as preferred.");
+
+ // Check that we display this result:
+ list = yield waitForCondition(() => win.document.getAnonymousElementByAttribute(ourItem, "class", "actionsMenu"));
+ ok(list.selectedItem, "Should have a selected item");
+ ok(!list.selectedItem.handlerApp,
+ "No app should be visible as preferred item.");
+
+ gBrowser.removeCurrentTab();
+});
+
+registerCleanupFunction(function() {
+ let infoToModify = gMimeSvc.getFromTypeAndExtension("text/x-test-handler", null);
+ gHandlerSvc.remove(infoToModify);
+});
+
diff --git a/browser/components/preferences/in-content/tests/browser_connection.js b/browser/components/preferences/in-content/tests/browser_connection.js
new file mode 100644
index 000000000..50438aed1
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser_connection.js
@@ -0,0 +1,99 @@
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+Components.utils.import("resource://gre/modules/Services.jsm");
+Components.utils.import("resource://gre/modules/Task.jsm");
+
+function test() {
+ waitForExplicitFinish();
+
+ // network.proxy.type needs to be backed up and restored because mochitest
+ // changes this setting from the default
+ let oldNetworkProxyType = Services.prefs.getIntPref("network.proxy.type");
+ registerCleanupFunction(function() {
+ Services.prefs.setIntPref("network.proxy.type", oldNetworkProxyType);
+ Services.prefs.clearUserPref("network.proxy.no_proxies_on");
+ Services.prefs.clearUserPref("browser.preferences.instantApply");
+ });
+
+ let connectionURL = "chrome://browser/content/preferences/connection.xul";
+
+ /*
+ The connection dialog alone won't save onaccept since it uses type="child",
+ so it has to be opened as a sub dialog of the main pref tab.
+ Open the main tab here.
+ */
+ open_preferences(Task.async(function* tabOpened(aContentWindow) {
+ is(gBrowser.currentURI.spec, "about:preferences", "about:preferences loaded");
+ let dialog = yield openAndLoadSubDialog(connectionURL);
+ let dialogClosingPromise = waitForEvent(dialog.document.documentElement, "dialogclosing");
+
+ ok(dialog, "connection window opened");
+ runConnectionTests(dialog);
+ dialog.document.documentElement.acceptDialog();
+
+ let dialogClosingEvent = yield dialogClosingPromise;
+ ok(dialogClosingEvent, "connection window closed");
+ // runConnectionTests will have changed this pref - make sure it was
+ // sanitized correctly when the dialog was accepted
+ is(Services.prefs.getCharPref("network.proxy.no_proxies_on"),
+ ".a.com,.b.com,.c.com", "no_proxies_on pref has correct value");
+ gBrowser.removeCurrentTab();
+ finish();
+ }));
+}
+
+// run a bunch of tests on the window containing connection.xul
+function runConnectionTests(win) {
+ let doc = win.document;
+ let networkProxyNone = doc.getElementById("networkProxyNone");
+ let networkProxyNonePref = doc.getElementById("network.proxy.no_proxies_on");
+ let networkProxyTypePref = doc.getElementById("network.proxy.type");
+
+ // make sure the networkProxyNone textbox is formatted properly
+ is(networkProxyNone.getAttribute("multiline"), "true",
+ "networkProxyNone textbox is multiline");
+ is(networkProxyNone.getAttribute("rows"), "2",
+ "networkProxyNone textbox has two rows");
+
+ // check if sanitizing the given input for the no_proxies_on pref results in
+ // expected string
+ function testSanitize(input, expected, errorMessage) {
+ networkProxyNonePref.value = input;
+ win.gConnectionsDialog.sanitizeNoProxiesPref();
+ is(networkProxyNonePref.value, expected, errorMessage);
+ }
+
+ // change this pref so proxy exceptions are actually configurable
+ networkProxyTypePref.value = 1;
+ is(networkProxyNone.disabled, false, "networkProxyNone textbox is enabled");
+
+ testSanitize(".a.com", ".a.com",
+ "sanitize doesn't mess up single filter");
+ testSanitize(".a.com, .b.com, .c.com", ".a.com, .b.com, .c.com",
+ "sanitize doesn't mess up multiple comma/space sep filters");
+ testSanitize(".a.com\n.b.com", ".a.com,.b.com",
+ "sanitize turns line break into comma");
+ testSanitize(".a.com,\n.b.com", ".a.com,.b.com",
+ "sanitize doesn't add duplicate comma after comma");
+ testSanitize(".a.com\n,.b.com", ".a.com,.b.com",
+ "sanitize doesn't add duplicate comma before comma");
+ testSanitize(".a.com,\n,.b.com", ".a.com,,.b.com",
+ "sanitize doesn't add duplicate comma surrounded by commas");
+ testSanitize(".a.com, \n.b.com", ".a.com, .b.com",
+ "sanitize doesn't add comma after comma/space");
+ testSanitize(".a.com\n .b.com", ".a.com, .b.com",
+ "sanitize adds comma before space");
+ testSanitize(".a.com\n\n\n;;\n;\n.b.com", ".a.com,.b.com",
+ "sanitize only adds one comma per substring of bad chars");
+ testSanitize(".a.com,,.b.com", ".a.com,,.b.com",
+ "duplicate commas from user are untouched");
+ testSanitize(".a.com\n.b.com\n.c.com,\n.d.com,\n.e.com",
+ ".a.com,.b.com,.c.com,.d.com,.e.com",
+ "sanitize replaces things globally");
+
+ // will check that this was sanitized properly after window closes
+ networkProxyNonePref.value = ".a.com;.b.com\n.c.com";
+}
diff --git a/browser/components/preferences/in-content/tests/browser_connection_bug388287.js b/browser/components/preferences/in-content/tests/browser_connection_bug388287.js
new file mode 100644
index 000000000..5a348876e
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser_connection_bug388287.js
@@ -0,0 +1,125 @@
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+Components.utils.import("resource://gre/modules/Services.jsm");
+Components.utils.import("resource://gre/modules/Task.jsm");
+
+function test() {
+ waitForExplicitFinish();
+ const connectionURL = "chrome://browser/content/preferences/connection.xul";
+ let closeable = false;
+ let finalTest = false;
+
+ // The changed preferences need to be backed up and restored because this mochitest
+ // changes them setting from the default
+ let oldNetworkProxyType = Services.prefs.getIntPref("network.proxy.type");
+ registerCleanupFunction(function() {
+ Services.prefs.setIntPref("network.proxy.type", oldNetworkProxyType);
+ Services.prefs.clearUserPref("network.proxy.share_proxy_settings");
+ for (let proxyType of ["http", "ssl", "ftp", "socks"]) {
+ Services.prefs.clearUserPref("network.proxy." + proxyType);
+ Services.prefs.clearUserPref("network.proxy." + proxyType + "_port");
+ if (proxyType == "http") {
+ continue;
+ }
+ Services.prefs.clearUserPref("network.proxy.backup." + proxyType);
+ Services.prefs.clearUserPref("network.proxy.backup." + proxyType + "_port");
+ }
+ });
+
+ /*
+ The connection dialog alone won't save onaccept since it uses type="child",
+ so it has to be opened as a sub dialog of the main pref tab.
+ Open the main tab here.
+ */
+ open_preferences(Task.async(function* tabOpened(aContentWindow) {
+ let dialog, dialogClosingPromise;
+ let doc, proxyTypePref, sharePref, httpPref, httpPortPref, ftpPref, ftpPortPref;
+
+ // Convenient function to reset the variables for the new window
+ function* setDoc() {
+ if (closeable) {
+ let dialogClosingEvent = yield dialogClosingPromise;
+ ok(dialogClosingEvent, "Connection dialog closed");
+ }
+
+ if (finalTest) {
+ gBrowser.removeCurrentTab();
+ finish();
+ return;
+ }
+
+ dialog = yield openAndLoadSubDialog(connectionURL);
+ dialogClosingPromise = waitForEvent(dialog.document.documentElement, "dialogclosing");
+
+ doc = dialog.document;
+ proxyTypePref = doc.getElementById("network.proxy.type");
+ sharePref = doc.getElementById("network.proxy.share_proxy_settings");
+ httpPref = doc.getElementById("network.proxy.http");
+ httpPortPref = doc.getElementById("network.proxy.http_port");
+ ftpPref = doc.getElementById("network.proxy.ftp");
+ ftpPortPref = doc.getElementById("network.proxy.ftp_port");
+ }
+
+ // This batch of tests should not close the dialog
+ yield setDoc();
+
+ // Testing HTTP port 0 with share on
+ proxyTypePref.value = 1;
+ sharePref.value = true;
+ httpPref.value = "localhost";
+ httpPortPref.value = 0;
+ doc.documentElement.acceptDialog();
+
+ // Testing HTTP port 0 + FTP port 80 with share off
+ sharePref.value = false;
+ ftpPref.value = "localhost";
+ ftpPortPref.value = 80;
+ doc.documentElement.acceptDialog();
+
+ // Testing HTTP port 80 + FTP port 0 with share off
+ httpPortPref.value = 80;
+ ftpPortPref.value = 0;
+ doc.documentElement.acceptDialog();
+
+ // From now on, the dialog should close since we are giving it legitimate inputs.
+ // The test will timeout if the onbeforeaccept kicks in erroneously.
+ closeable = true;
+
+ // Both ports 80, share on
+ httpPortPref.value = 80;
+ ftpPortPref.value = 80;
+ doc.documentElement.acceptDialog();
+
+ // HTTP 80, FTP 0, with share on
+ yield setDoc();
+ proxyTypePref.value = 1;
+ sharePref.value = true;
+ ftpPref.value = "localhost";
+ httpPref.value = "localhost";
+ httpPortPref.value = 80;
+ ftpPortPref.value = 0;
+ doc.documentElement.acceptDialog();
+
+ // HTTP host empty, port 0 with share on
+ yield setDoc();
+ proxyTypePref.value = 1;
+ sharePref.value = true;
+ httpPref.value = "";
+ httpPortPref.value = 0;
+ doc.documentElement.acceptDialog();
+
+ // HTTP 0, but in no proxy mode
+ yield setDoc();
+ proxyTypePref.value = 0;
+ sharePref.value = true;
+ httpPref.value = "localhost";
+ httpPortPref.value = 0;
+
+ // This is the final test, don't spawn another connection window
+ finalTest = true;
+ doc.documentElement.acceptDialog();
+ yield setDoc();
+ }));
+}
diff --git a/browser/components/preferences/in-content/tests/browser_cookies_exceptions.js b/browser/components/preferences/in-content/tests/browser_cookies_exceptions.js
new file mode 100644
index 000000000..89313d736
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser_cookies_exceptions.js
@@ -0,0 +1,348 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+requestLongerTimeout(2);
+
+function test() {
+ waitForExplicitFinish();
+ requestLongerTimeout(3);
+ testRunner.runTests();
+}
+
+var testRunner = {
+
+ tests:
+ [
+ {
+ test: function(params) {
+ params.url.value = "test.com";
+ params.btnAllow.doCommand();
+ is(params.tree.view.rowCount, 1, "added exception shows up in treeview");
+ is(params.tree.view.getCellText(0, params.nameCol), "http://test.com",
+ "origin name should be set correctly");
+ is(params.tree.view.getCellText(0, params.statusCol), params.allowText,
+ "permission text should be set correctly");
+ params.btnApplyChanges.doCommand();
+ },
+ observances: [{ type: "cookie", origin: "http://test.com", data: "added",
+ capability: Ci.nsIPermissionManager.ALLOW_ACTION }],
+ },
+ {
+ test: function(params) {
+ params.url.value = "test.com";
+ params.btnBlock.doCommand();
+ is(params.tree.view.getCellText(0, params.nameCol), "http://test.com",
+ "origin name should be set correctly");
+ is(params.tree.view.getCellText(0, params.statusCol), params.denyText,
+ "permission should change to deny in UI");
+ params.btnApplyChanges.doCommand();
+ },
+ observances: [{ type: "cookie", origin: "http://test.com", data: "changed",
+ capability: Ci.nsIPermissionManager.DENY_ACTION }],
+ },
+ {
+ test: function(params) {
+ params.url.value = "test.com";
+ params.btnAllow.doCommand();
+ is(params.tree.view.getCellText(0, params.nameCol), "http://test.com",
+ "origin name should be set correctly");
+ is(params.tree.view.getCellText(0, params.statusCol), params.allowText,
+ "permission should revert back to allow");
+ params.btnApplyChanges.doCommand();
+ },
+ observances: [{ type: "cookie", origin: "http://test.com", data: "changed",
+ capability: Ci.nsIPermissionManager.ALLOW_ACTION }],
+ },
+ {
+ test: function(params) {
+ params.url.value = "test.com";
+ params.btnRemove.doCommand();
+ is(params.tree.view.rowCount, 0, "exception should be removed");
+ params.btnApplyChanges.doCommand();
+ },
+ observances: [{ type: "cookie", origin: "http://test.com", data: "deleted" }],
+ },
+ {
+ expectPermObservancesDuringTestFunction: true,
+ test: function(params) {
+ let uri = params.ioService.newURI("http://test.com", null, null);
+ params.pm.add(uri, "popup", Ci.nsIPermissionManager.DENY_ACTION);
+ is(params.tree.view.rowCount, 0, "adding unrelated permission should not change display");
+ params.btnApplyChanges.doCommand();
+ },
+ observances: [{ type: "popup", origin: "http://test.com", data: "added",
+ capability: Ci.nsIPermissionManager.DENY_ACTION }],
+ cleanUp: function(params) {
+ let uri = params.ioService.newURI("http://test.com", null, null);
+ params.pm.remove(uri, "popup");
+ },
+ },
+ {
+ test: function(params) {
+ params.url.value = "https://test.com:12345";
+ params.btnAllow.doCommand();
+ is(params.tree.view.rowCount, 1, "added exception shows up in treeview");
+ is(params.tree.view.getCellText(0, params.nameCol), "https://test.com:12345",
+ "origin name should be set correctly");
+ is(params.tree.view.getCellText(0, params.statusCol), params.allowText,
+ "permission text should be set correctly");
+ params.btnApplyChanges.doCommand();
+ },
+ observances: [{ type: "cookie", origin: "https://test.com:12345", data: "added",
+ capability: Ci.nsIPermissionManager.ALLOW_ACTION }],
+ },
+ {
+ test: function(params) {
+ params.url.value = "https://test.com:12345";
+ params.btnBlock.doCommand();
+ is(params.tree.view.getCellText(0, params.nameCol), "https://test.com:12345",
+ "origin name should be set correctly");
+ is(params.tree.view.getCellText(0, params.statusCol), params.denyText,
+ "permission should change to deny in UI");
+ params.btnApplyChanges.doCommand();
+ },
+ observances: [{ type: "cookie", origin: "https://test.com:12345", data: "changed",
+ capability: Ci.nsIPermissionManager.DENY_ACTION }],
+ },
+ {
+ test: function(params) {
+ params.url.value = "https://test.com:12345";
+ params.btnAllow.doCommand();
+ is(params.tree.view.getCellText(0, params.nameCol), "https://test.com:12345",
+ "origin name should be set correctly");
+ is(params.tree.view.getCellText(0, params.statusCol), params.allowText,
+ "permission should revert back to allow");
+ params.btnApplyChanges.doCommand();
+ },
+ observances: [{ type: "cookie", origin: "https://test.com:12345", data: "changed",
+ capability: Ci.nsIPermissionManager.ALLOW_ACTION }],
+ },
+ {
+ test: function(params) {
+ params.url.value = "https://test.com:12345";
+ params.btnRemove.doCommand();
+ is(params.tree.view.rowCount, 0, "exception should be removed");
+ params.btnApplyChanges.doCommand();
+ },
+ observances: [{ type: "cookie", origin: "https://test.com:12345", data: "deleted" }],
+ },
+ {
+ test: function(params) {
+ params.url.value = "localhost:12345";
+ params.btnAllow.doCommand();
+ is(params.tree.view.rowCount, 1, "added exception shows up in treeview");
+ is(params.tree.view.getCellText(0, params.nameCol), "http://localhost:12345",
+ "origin name should be set correctly");
+ is(params.tree.view.getCellText(0, params.statusCol), params.allowText,
+ "permission text should be set correctly");
+ params.btnApplyChanges.doCommand();
+ },
+ observances: [{ type: "cookie", origin: "http://localhost:12345", data: "added",
+ capability: Ci.nsIPermissionManager.ALLOW_ACTION }],
+ },
+ {
+ test: function(params) {
+ params.url.value = "localhost:12345";
+ params.btnBlock.doCommand();
+ is(params.tree.view.getCellText(0, params.nameCol), "http://localhost:12345",
+ "origin name should be set correctly");
+ is(params.tree.view.getCellText(0, params.statusCol), params.denyText,
+ "permission should change to deny in UI");
+ params.btnApplyChanges.doCommand();
+ },
+ observances: [{ type: "cookie", origin: "http://localhost:12345", data: "changed",
+ capability: Ci.nsIPermissionManager.DENY_ACTION }],
+ },
+ {
+ test: function(params) {
+ params.url.value = "localhost:12345";
+ params.btnAllow.doCommand();
+ is(params.tree.view.getCellText(0, params.nameCol), "http://localhost:12345",
+ "origin name should be set correctly");
+ is(params.tree.view.getCellText(0, params.statusCol), params.allowText,
+ "permission should revert back to allow");
+ params.btnApplyChanges.doCommand();
+ },
+ observances: [{ type: "cookie", origin: "http://localhost:12345", data: "changed",
+ capability: Ci.nsIPermissionManager.ALLOW_ACTION }],
+ },
+ {
+ test: function(params) {
+ params.url.value = "localhost:12345";
+ params.btnRemove.doCommand();
+ is(params.tree.view.rowCount, 0, "exception should be removed");
+ params.btnApplyChanges.doCommand();
+ },
+ observances: [{ type: "cookie", origin: "http://localhost:12345", data: "deleted" }],
+ },
+ {
+ expectPermObservancesDuringTestFunction: true,
+ test(params) {
+ for (let URL of ["http://a", "http://z", "http://b"]) {
+ let URI = params.ioService.newURI(URL, null, null);
+ params.pm.add(URI, "cookie", Ci.nsIPermissionManager.ALLOW_ACTION);
+ }
+
+ is(params.tree.view.rowCount, 3, "Three permissions should be present");
+ is(params.tree.view.getCellText(0, params.nameCol), "http://a",
+ "site should be sorted. 'a' should be first");
+ is(params.tree.view.getCellText(1, params.nameCol), "http://b",
+ "site should be sorted. 'b' should be second");
+ is(params.tree.view.getCellText(2, params.nameCol), "http://z",
+ "site should be sorted. 'z' should be third");
+
+ // Sort descending then check results in cleanup since sorting isn't synchronous.
+ EventUtils.synthesizeMouseAtCenter(params.doc.getElementById("siteCol"), {},
+ params.doc.defaultView);
+ params.btnApplyChanges.doCommand();
+ },
+ observances: [{ type: "cookie", origin: "http://a", data: "added",
+ capability: Ci.nsIPermissionManager.ALLOW_ACTION },
+ { type: "cookie", origin: "http://z", data: "added",
+ capability: Ci.nsIPermissionManager.ALLOW_ACTION },
+ { type: "cookie", origin: "http://b", data: "added",
+ capability: Ci.nsIPermissionManager.ALLOW_ACTION }],
+ cleanUp(params) {
+ is(params.tree.view.getCellText(0, params.nameCol), "http://z",
+ "site should be sorted. 'z' should be first");
+ is(params.tree.view.getCellText(1, params.nameCol), "http://b",
+ "site should be sorted. 'b' should be second");
+ is(params.tree.view.getCellText(2, params.nameCol), "http://a",
+ "site should be sorted. 'a' should be third");
+
+ for (let URL of ["http://a", "http://z", "http://b"]) {
+ let uri = params.ioService.newURI(URL, null, null);
+ params.pm.remove(uri, "cookie");
+ }
+ },
+ },
+ ],
+
+ _currentTest: -1,
+
+ runTests: function() {
+ this._currentTest++;
+
+ info("Running test #" + (this._currentTest + 1) + "\n");
+ let that = this;
+ let p = this.runCurrentTest(this._currentTest + 1);
+ p.then(function() {
+ if (that._currentTest == that.tests.length - 1) {
+ finish();
+ }
+ else {
+ that.runTests();
+ }
+ });
+ },
+
+ runCurrentTest: function(testNumber) {
+ return new Promise(function(resolve, reject) {
+
+ let helperFunctions = {
+ windowLoad: function(win) {
+ let doc = win.document;
+ let params = {
+ doc,
+ tree: doc.getElementById("permissionsTree"),
+ nameCol: doc.getElementById("permissionsTree").treeBoxObject.columns.getColumnAt(0),
+ statusCol: doc.getElementById("permissionsTree").treeBoxObject.columns.getColumnAt(1),
+ url: doc.getElementById("url"),
+ btnAllow: doc.getElementById("btnAllow"),
+ btnBlock: doc.getElementById("btnBlock"),
+ btnApplyChanges: doc.getElementById("btnApplyChanges"),
+ btnRemove: doc.getElementById("removePermission"),
+ pm: Cc["@mozilla.org/permissionmanager;1"]
+ .getService(Ci.nsIPermissionManager),
+ ioService: Cc["@mozilla.org/network/io-service;1"]
+ .getService(Ci.nsIIOService),
+ allowText: win.gPermissionManager._getCapabilityString(
+ Ci.nsIPermissionManager.ALLOW_ACTION),
+ denyText: win.gPermissionManager._getCapabilityString(
+ Ci.nsIPermissionManager.DENY_ACTION),
+ allow: Ci.nsIPermissionManager.ALLOW_ACTION,
+ deny: Ci.nsIPermissionManager.DENY_ACTION,
+ };
+
+ let permObserver = {
+ observe: function(aSubject, aTopic, aData) {
+ if (aTopic != "perm-changed")
+ return;
+
+ if (testRunner.tests[testRunner._currentTest].observances.length == 0) {
+ // Should fail here as we are not expecting a notification, but we don't.
+ // See bug 1063410.
+ return;
+ }
+
+ let permission = aSubject.QueryInterface(Ci.nsIPermission);
+ let expected = testRunner.tests[testRunner._currentTest].observances.shift();
+
+ is(aData, expected.data, "type of message should be the same");
+ for (let prop of ["type", "capability"]) {
+ if (expected[prop])
+ is(permission[prop], expected[prop],
+ "property: \"" + prop + "\" should be equal");
+ }
+
+ if (expected.origin) {
+ is(permission.principal.origin, expected.origin,
+ "property: \"origin\" should be equal");
+ }
+
+ os.removeObserver(permObserver, "perm-changed");
+
+ let test = testRunner.tests[testRunner._currentTest];
+ if (!test.expectPermObservancesDuringTestFunction) {
+ if (test.cleanUp) {
+ test.cleanUp(params);
+ }
+
+ gBrowser.removeCurrentTab();
+ resolve();
+ }
+ },
+ };
+
+ let os = Cc["@mozilla.org/observer-service;1"]
+ .getService(Ci.nsIObserverService);
+
+ os.addObserver(permObserver, "perm-changed", false);
+
+ if (testRunner._currentTest == 0) {
+ is(params.tree.view.rowCount, 0, "no cookie exceptions");
+ }
+
+ try {
+ let test = testRunner.tests[testRunner._currentTest];
+ test.test(params);
+ if (test.expectPermObservancesDuringTestFunction) {
+ if (test.cleanUp) {
+ test.cleanUp(params);
+ }
+
+ gBrowser.removeCurrentTab();
+ resolve();
+ }
+ } catch (ex) {
+ ok(false, "exception while running test #" +
+ testNumber + ": " + ex);
+ }
+ },
+ };
+
+ openPreferencesViaOpenPreferencesAPI("panePrivacy", null, {leaveOpen: true}).then(function() {
+ let doc = gBrowser.contentDocument;
+ let historyMode = doc.getElementById("historyMode");
+ historyMode.value = "custom";
+ historyMode.doCommand();
+ doc.getElementById("cookieExceptions").doCommand();
+
+ let subDialogURL = "chrome://browser/content/preferences/permissions.xul";
+ promiseLoadSubDialog(subDialogURL).then(function(win) {
+ helperFunctions.windowLoad(win);
+ });
+ });
+ });
+ },
+};
diff --git a/browser/components/preferences/in-content/tests/browser_defaultbrowser_alwayscheck.js b/browser/components/preferences/in-content/tests/browser_defaultbrowser_alwayscheck.js
new file mode 100644
index 000000000..b30b6d9e2
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser_defaultbrowser_alwayscheck.js
@@ -0,0 +1,103 @@
+"use strict";
+
+const CHECK_DEFAULT_INITIAL = Services.prefs.getBoolPref("browser.shell.checkDefaultBrowser");
+
+add_task(function* clicking_make_default_checks_alwaysCheck_checkbox() {
+ yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:preferences");
+
+ yield test_with_mock_shellservice({isDefault: false}, function*() {
+ let setDefaultPane = content.document.getElementById("setDefaultPane");
+ Assert.equal(setDefaultPane.selectedIndex, "0",
+ "The 'make default' pane should be visible when not default");
+ let alwaysCheck = content.document.getElementById("alwaysCheckDefault");
+ Assert.ok(!alwaysCheck.checked, "Always Check is unchecked by default");
+ Assert.ok(!Services.prefs.getBoolPref("browser.shell.checkDefaultBrowser"),
+ "alwaysCheck pref should be false by default in test runs");
+
+ let setDefaultButton = content.document.getElementById("setDefaultButton");
+ setDefaultButton.click();
+ content.window.gMainPane.updateSetDefaultBrowser();
+
+ yield ContentTaskUtils.waitForCondition(() => alwaysCheck.checked,
+ "'Always Check' checkbox should get checked after clicking the 'Set Default' button");
+
+ Assert.ok(alwaysCheck.checked,
+ "Clicking 'Make Default' checks the 'Always Check' checkbox");
+ Assert.ok(Services.prefs.getBoolPref("browser.shell.checkDefaultBrowser"),
+ "Checking the checkbox should set the pref to true");
+ Assert.ok(alwaysCheck.disabled,
+ "'Always Check' checkbox is locked with default browser and alwaysCheck=true");
+ Assert.equal(setDefaultPane.selectedIndex, "1",
+ "The 'make default' pane should not be visible when default");
+ Assert.ok(Services.prefs.getBoolPref("browser.shell.checkDefaultBrowser"),
+ "checkDefaultBrowser pref is now enabled");
+ });
+
+ gBrowser.removeCurrentTab();
+ Services.prefs.clearUserPref("browser.shell.checkDefaultBrowser");
+});
+
+add_task(function* clicking_make_default_checks_alwaysCheck_checkbox() {
+ Services.prefs.lockPref("browser.shell.checkDefaultBrowser");
+ yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:preferences");
+
+ yield test_with_mock_shellservice({isDefault: false}, function*() {
+ let setDefaultPane = content.document.getElementById("setDefaultPane");
+ Assert.equal(setDefaultPane.selectedIndex, "0",
+ "The 'make default' pane should be visible when not default");
+ let alwaysCheck = content.document.getElementById("alwaysCheckDefault");
+ Assert.ok(alwaysCheck.disabled, "Always Check is disabled when locked");
+ Assert.ok(alwaysCheck.checked,
+ "Always Check is checked because defaultPref is true and pref is locked");
+ Assert.ok(Services.prefs.getBoolPref("browser.shell.checkDefaultBrowser"),
+ "alwaysCheck pref should ship with 'true' by default");
+
+ let setDefaultButton = content.document.getElementById("setDefaultButton");
+ setDefaultButton.click();
+ content.window.gMainPane.updateSetDefaultBrowser();
+
+ yield ContentTaskUtils.waitForCondition(() => setDefaultPane.selectedIndex == "1",
+ "Browser is now default");
+
+ Assert.ok(alwaysCheck.checked,
+ "'Always Check' is still checked because it's locked");
+ Assert.ok(alwaysCheck.disabled,
+ "'Always Check is disabled because it's locked");
+ Assert.ok(Services.prefs.getBoolPref("browser.shell.checkDefaultBrowser"),
+ "The pref is locked and so doesn't get changed");
+ });
+
+ Services.prefs.unlockPref("browser.shell.checkDefaultBrowser");
+ gBrowser.removeCurrentTab();
+});
+
+registerCleanupFunction(function() {
+ Services.prefs.unlockPref("browser.shell.checkDefaultBrowser");
+ Services.prefs.setBoolPref("browser.shell.checkDefaultBrowser", CHECK_DEFAULT_INITIAL);
+});
+
+function* test_with_mock_shellservice(options, testFn) {
+ yield ContentTask.spawn(gBrowser.selectedBrowser, options, function*(options) {
+ let doc = content.document;
+ let win = doc.defaultView;
+ win.oldShellService = win.getShellService();
+ let mockShellService = {
+ _isDefault: false,
+ isDefaultBrowser() {
+ return this._isDefault;
+ },
+ setDefaultBrowser() {
+ this._isDefault = true;
+ },
+ };
+ win.getShellService = function() {
+ return mockShellService;
+ }
+ mockShellService._isDefault = options.isDefault;
+ win.gMainPane.updateSetDefaultBrowser();
+ });
+
+ yield ContentTask.spawn(gBrowser.selectedBrowser, null, testFn);
+
+ Services.prefs.setBoolPref("browser.shell.checkDefaultBrowser", CHECK_DEFAULT_INITIAL);
+}
diff --git a/browser/components/preferences/in-content/tests/browser_healthreport.js b/browser/components/preferences/in-content/tests/browser_healthreport.js
new file mode 100644
index 000000000..bbfae9707
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser_healthreport.js
@@ -0,0 +1,62 @@
+/* Any copyright is dedicated to the Public Domain.
+* http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const FHR_UPLOAD_ENABLED = "datareporting.healthreport.uploadEnabled";
+
+function runPaneTest(fn) {
+ open_preferences((win) => {
+ let doc = win.document;
+ win.gotoPref("paneAdvanced");
+ let advancedPrefs = doc.getElementById("advancedPrefs");
+ let tab = doc.getElementById("dataChoicesTab");
+ advancedPrefs.selectedTab = tab;
+ fn(win, doc);
+ });
+}
+
+function test() {
+ waitForExplicitFinish();
+ resetPreferences();
+ registerCleanupFunction(resetPreferences);
+ runPaneTest(testBasic);
+}
+
+function testBasic(win, doc) {
+ is(Services.prefs.getBoolPref(FHR_UPLOAD_ENABLED), true,
+ "Health Report upload enabled on app first run.");
+
+ let checkbox = doc.getElementById("submitHealthReportBox");
+ ok(checkbox);
+ is(checkbox.checked, true, "Health Report checkbox is checked on app first run.");
+
+ checkbox.checked = false;
+ checkbox.doCommand();
+ is(Services.prefs.getBoolPref(FHR_UPLOAD_ENABLED), false,
+ "Unchecking checkbox opts out of FHR upload.");
+
+ checkbox.checked = true;
+ checkbox.doCommand();
+ is(Services.prefs.getBoolPref(FHR_UPLOAD_ENABLED), true,
+ "Checking checkbox allows FHR upload.");
+
+ win.close();
+ Services.prefs.lockPref(FHR_UPLOAD_ENABLED);
+ runPaneTest(testUploadDisabled);
+}
+
+function testUploadDisabled(win, doc) {
+ ok(Services.prefs.prefIsLocked(FHR_UPLOAD_ENABLED), "Upload enabled flag is locked.");
+ let checkbox = doc.getElementById("submitHealthReportBox");
+ is(checkbox.getAttribute("disabled"), "true", "Checkbox is disabled if upload flag is locked.");
+ Services.prefs.unlockPref(FHR_UPLOAD_ENABLED);
+
+ win.close();
+ finish();
+}
+
+function resetPreferences() {
+ Services.prefs.clearUserPref(FHR_UPLOAD_ENABLED);
+}
+
diff --git a/browser/components/preferences/in-content/tests/browser_homepages_filter_aboutpreferences.js b/browser/components/preferences/in-content/tests/browser_homepages_filter_aboutpreferences.js
new file mode 100644
index 000000000..366454fcc
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser_homepages_filter_aboutpreferences.js
@@ -0,0 +1,20 @@
+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});
+ let doc = gBrowser.contentDocument;
+ is(gBrowser.currentURI.spec, "about:preferences#general",
+ "#general should be in the URI for about:preferences");
+ let oldHomepagePref = Services.prefs.getCharPref("browser.startup.homepage");
+
+ let useCurrent = doc.getElementById("useCurrent");
+ useCurrent.click();
+
+ is(gBrowser.tabs.length, 3, "Three tabs should be open");
+ is(Services.prefs.getCharPref("browser.startup.homepage"), "about:blank|about:home",
+ "about:blank and about:home should be the only homepages set");
+
+ Services.prefs.setCharPref("browser.startup.homepage", oldHomepagePref);
+ yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
+ yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
+});
diff --git a/browser/components/preferences/in-content/tests/browser_notifications_do_not_disturb.js b/browser/components/preferences/in-content/tests/browser_notifications_do_not_disturb.js
new file mode 100644
index 000000000..68f9653f6
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser_notifications_do_not_disturb.js
@@ -0,0 +1,44 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+
+registerCleanupFunction(function() {
+ while (gBrowser.tabs[1])
+ gBrowser.removeTab(gBrowser.tabs[1]);
+});
+
+add_task(function*() {
+ let prefs = yield openPreferencesViaOpenPreferencesAPI("paneContent", undefined, {leaveOpen: true});
+ is(prefs.selectedPane, "paneContent", "Content pane was selected");
+
+ let doc = gBrowser.contentDocument;
+ let notificationsDoNotDisturbRow = doc.getElementById("notificationsDoNotDisturbRow");
+ if (notificationsDoNotDisturbRow.hidden) {
+ todo(false, "Do not disturb is not available on this platform");
+ return;
+ }
+
+ let alertService;
+ try {
+ alertService = Cc["@mozilla.org/alerts-service;1"]
+ .getService(Ci.nsIAlertsService)
+ .QueryInterface(Ci.nsIAlertsDoNotDisturb);
+ } catch (ex) {
+ ok(true, "Do not disturb is not available on this platform: " + ex.message);
+ return;
+ }
+
+ let checkbox = doc.getElementById("notificationsDoNotDisturb");
+ ok(!checkbox.checked, "Checkbox should not be checked by default");
+ ok(!alertService.manualDoNotDisturb, "Do not disturb should be off by default");
+
+ let checkboxChanged = waitForEvent(checkbox, "command")
+ checkbox.click();
+ yield checkboxChanged;
+ ok(alertService.manualDoNotDisturb, "Do not disturb should be enabled when checked");
+
+ checkboxChanged = waitForEvent(checkbox, "command")
+ checkbox.click();
+ yield checkboxChanged;
+ ok(!alertService.manualDoNotDisturb, "Do not disturb should be disabled when unchecked");
+});
diff --git a/browser/components/preferences/in-content/tests/browser_permissions_urlFieldHidden.js b/browser/components/preferences/in-content/tests/browser_permissions_urlFieldHidden.js
new file mode 100644
index 000000000..d9253735a
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser_permissions_urlFieldHidden.js
@@ -0,0 +1,45 @@
+"use strict";
+
+const PERMISSIONS_URL = "chrome://browser/content/preferences/permissions.xul";
+
+add_task(function* urlFieldVisibleForPopupPermissions(finish) {
+ yield openPreferencesViaOpenPreferencesAPI("paneContent", null, {leaveOpen: true});
+ let win = gBrowser.selectedBrowser.contentWindow;
+ let doc = win.document;
+ let popupPolicyCheckbox = doc.getElementById("popupPolicy");
+ ok(!popupPolicyCheckbox.checked, "popupPolicyCheckbox should be unchecked by default");
+ popupPolicyCheckbox.click();
+ let popupPolicyButton = doc.getElementById("popupPolicyButton");
+ ok(popupPolicyButton, "popupPolicyButton found");
+ let dialogPromise = promiseLoadSubDialog(PERMISSIONS_URL);
+ popupPolicyButton.click();
+ let dialog = yield dialogPromise;
+ ok(dialog, "dialog loaded");
+
+ let urlLabel = dialog.document.getElementById("urlLabel");
+ ok(!urlLabel.hidden, "urlLabel should be visible when one of block/session/allow visible");
+ let url = dialog.document.getElementById("url");
+ ok(!url.hidden, "url should be visible when one of block/session/allow visible");
+
+ popupPolicyCheckbox.click();
+ gBrowser.removeCurrentTab();
+});
+
+add_task(function* urlFieldHiddenForNotificationPermissions() {
+ yield openPreferencesViaOpenPreferencesAPI("paneContent", null, {leaveOpen: true});
+ let win = gBrowser.selectedBrowser.contentWindow;
+ let doc = win.document;
+ let notificationsPolicyButton = doc.getElementById("notificationsPolicyButton");
+ ok(notificationsPolicyButton, "notificationsPolicyButton found");
+ let dialogPromise = promiseLoadSubDialog(PERMISSIONS_URL);
+ notificationsPolicyButton.click();
+ let dialog = yield dialogPromise;
+ ok(dialog, "dialog loaded");
+
+ let urlLabel = dialog.document.getElementById("urlLabel");
+ ok(urlLabel.hidden, "urlLabel should be hidden as requested");
+ let url = dialog.document.getElementById("url");
+ ok(url.hidden, "url should be hidden as requested");
+
+ gBrowser.removeCurrentTab();
+});
diff --git a/browser/components/preferences/in-content/tests/browser_privacypane_1.js b/browser/components/preferences/in-content/tests/browser_privacypane_1.js
new file mode 100644
index 000000000..0df60c6ac
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser_privacypane_1.js
@@ -0,0 +1,18 @@
+let loader = Cc["@mozilla.org/moz/jssubscript-loader;1"].
+ getService(Ci.mozIJSSubScriptLoader);
+
+let rootDir = getRootDirectory(gTestPath);
+let jar = getJar(rootDir);
+if (jar) {
+ let tmpdir = extractJarToTmp(jar);
+ rootDir = "file://" + tmpdir.path + '/';
+}
+loader.loadSubScript(rootDir + "privacypane_tests_perwindow.js", this);
+
+run_test_subset([
+ test_pane_visibility,
+ test_dependent_elements,
+ test_dependent_cookie_elements,
+ test_dependent_clearonclose_elements,
+ test_dependent_prefs,
+]);
diff --git a/browser/components/preferences/in-content/tests/browser_privacypane_3.js b/browser/components/preferences/in-content/tests/browser_privacypane_3.js
new file mode 100644
index 000000000..8fe6f0825
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser_privacypane_3.js
@@ -0,0 +1,17 @@
+let loader = Cc["@mozilla.org/moz/jssubscript-loader;1"].
+ getService(Ci.mozIJSSubScriptLoader);
+let rootDir = getRootDirectory(gTestPath);
+let jar = getJar(rootDir);
+if (jar) {
+ let tmpdir = extractJarToTmp(jar);
+ rootDir = "file://" + tmpdir.path + '/';
+}
+loader.loadSubScript(rootDir + "privacypane_tests_perwindow.js", this);
+
+run_test_subset([
+ test_custom_retention("rememberHistory", "remember"),
+ test_custom_retention("rememberHistory", "custom"),
+ test_custom_retention("rememberForms", "remember"),
+ test_custom_retention("rememberForms", "custom"),
+ test_historymode_retention("remember", "remember"),
+]);
diff --git a/browser/components/preferences/in-content/tests/browser_privacypane_4.js b/browser/components/preferences/in-content/tests/browser_privacypane_4.js
new file mode 100644
index 000000000..b7ef3deda
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser_privacypane_4.js
@@ -0,0 +1,25 @@
+requestLongerTimeout(2);
+
+let loader = Cc["@mozilla.org/moz/jssubscript-loader;1"].
+ getService(Ci.mozIJSSubScriptLoader);
+let rootDir = getRootDirectory(gTestPath);
+let jar = getJar(rootDir);
+if (jar) {
+ let tmpdir = extractJarToTmp(jar);
+ rootDir = "file://" + tmpdir.path + '/';
+}
+loader.loadSubScript(rootDir + "privacypane_tests_perwindow.js", this);
+let runtime = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime);
+
+run_test_subset([
+ test_custom_retention("acceptCookies", "remember"),
+ test_custom_retention("acceptCookies", "custom"),
+ test_custom_retention("acceptThirdPartyMenu", "remember", "visited"),
+ test_custom_retention("acceptThirdPartyMenu", "custom", "always"),
+ test_custom_retention("keepCookiesUntil", "remember", 1),
+ test_custom_retention("keepCookiesUntil", "custom", 2),
+ test_custom_retention("keepCookiesUntil", "custom", 0),
+ test_custom_retention("alwaysClear", "remember"),
+ test_custom_retention("alwaysClear", "custom"),
+ test_historymode_retention("remember", "remember"),
+]);
diff --git a/browser/components/preferences/in-content/tests/browser_privacypane_5.js b/browser/components/preferences/in-content/tests/browser_privacypane_5.js
new file mode 100644
index 000000000..a07530010
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser_privacypane_5.js
@@ -0,0 +1,17 @@
+let loader = Cc["@mozilla.org/moz/jssubscript-loader;1"].
+ getService(Ci.mozIJSSubScriptLoader);
+let rootDir = getRootDirectory(gTestPath);
+let jar = getJar(rootDir);
+if (jar) {
+ let tmpdir = extractJarToTmp(jar);
+ rootDir = "file://" + tmpdir.path + '/';
+}
+loader.loadSubScript(rootDir + "privacypane_tests_perwindow.js", this);
+
+run_test_subset([
+ test_locbar_suggestion_retention("history", true),
+ test_locbar_suggestion_retention("bookmark", true),
+ test_locbar_suggestion_retention("openpage", false),
+ test_locbar_suggestion_retention("history", true),
+ test_locbar_suggestion_retention("history", false),
+]);
diff --git a/browser/components/preferences/in-content/tests/browser_privacypane_8.js b/browser/components/preferences/in-content/tests/browser_privacypane_8.js
new file mode 100644
index 000000000..756b19a2f
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser_privacypane_8.js
@@ -0,0 +1,26 @@
+let loader = Cc["@mozilla.org/moz/jssubscript-loader;1"].
+ getService(Ci.mozIJSSubScriptLoader);
+let rootDir = getRootDirectory(gTestPath);
+let jar = getJar(rootDir);
+if (jar) {
+ let tmpdir = extractJarToTmp(jar);
+ rootDir = "file://" + tmpdir.path + '/';
+}
+loader.loadSubScript(rootDir + "privacypane_tests_perwindow.js", this);
+
+run_test_subset([
+ // history mode should be initialized to remember
+ test_historymode_retention("remember", undefined),
+
+ // history mode should remain remember; toggle acceptCookies checkbox
+ test_custom_retention("acceptCookies", "remember"),
+
+ // history mode should now be custom; set history mode to dontremember
+ test_historymode_retention("dontremember", "custom"),
+
+ // history mode should remain custom; set history mode to remember
+ test_historymode_retention("remember", "custom"),
+
+ // history mode should now be remember
+ test_historymode_retention("remember", "remember"),
+]);
diff --git a/browser/components/preferences/in-content/tests/browser_proxy_backup.js b/browser/components/preferences/in-content/tests/browser_proxy_backup.js
new file mode 100644
index 000000000..3ad24c7ec
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser_proxy_backup.js
@@ -0,0 +1,65 @@
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+Components.utils.import("resource://gre/modules/Services.jsm");
+Components.utils.import("resource://gre/modules/Task.jsm");
+
+function test() {
+ waitForExplicitFinish();
+
+ // network.proxy.type needs to be backed up and restored because mochitest
+ // changes this setting from the default
+ let oldNetworkProxyType = Services.prefs.getIntPref("network.proxy.type");
+ registerCleanupFunction(function() {
+ Services.prefs.setIntPref("network.proxy.type", oldNetworkProxyType);
+ Services.prefs.clearUserPref("browser.preferences.instantApply");
+ Services.prefs.clearUserPref("network.proxy.share_proxy_settings");
+ for (let proxyType of ["http", "ssl", "ftp", "socks"]) {
+ Services.prefs.clearUserPref("network.proxy." + proxyType);
+ Services.prefs.clearUserPref("network.proxy." + proxyType + "_port");
+ if (proxyType == "http") {
+ continue;
+ }
+ Services.prefs.clearUserPref("network.proxy.backup." + proxyType);
+ Services.prefs.clearUserPref("network.proxy.backup." + proxyType + "_port");
+ }
+ });
+
+ let connectionURL = "chrome://browser/content/preferences/connection.xul";
+
+ // Set a shared proxy and a SOCKS backup
+ Services.prefs.setIntPref("network.proxy.type", 1);
+ Services.prefs.setBoolPref("network.proxy.share_proxy_settings", true);
+ Services.prefs.setCharPref("network.proxy.http", "example.com");
+ Services.prefs.setIntPref("network.proxy.http_port", 1200);
+ Services.prefs.setCharPref("network.proxy.socks", "example.com");
+ Services.prefs.setIntPref("network.proxy.socks_port", 1200);
+ Services.prefs.setCharPref("network.proxy.backup.socks", "127.0.0.1");
+ Services.prefs.setIntPref("network.proxy.backup.socks_port", 9050);
+
+ /*
+ The connection dialog alone won't save onaccept since it uses type="child",
+ so it has to be opened as a sub dialog of the main pref tab.
+ Open the main tab here.
+ */
+ open_preferences(Task.async(function* tabOpened(aContentWindow) {
+ is(gBrowser.currentURI.spec, "about:preferences", "about:preferences loaded");
+ let dialog = yield openAndLoadSubDialog(connectionURL);
+ let dialogClosingPromise = waitForEvent(dialog.document.documentElement, "dialogclosing");
+
+ ok(dialog, "connection window opened");
+ dialog.document.documentElement.acceptDialog();
+
+ let dialogClosingEvent = yield dialogClosingPromise;
+ ok(dialogClosingEvent, "connection window closed");
+
+ // The SOCKS backup should not be replaced by the shared value
+ is(Services.prefs.getCharPref("network.proxy.backup.socks"), "127.0.0.1", "Shared proxy backup shouldn't be replaced");
+ is(Services.prefs.getIntPref("network.proxy.backup.socks_port"), 9050, "Shared proxy port backup shouldn't be replaced");
+
+ gBrowser.removeCurrentTab();
+ finish();
+ }));
+}
diff --git a/browser/components/preferences/in-content/tests/browser_sanitizeOnShutdown_prefLocked.js b/browser/components/preferences/in-content/tests/browser_sanitizeOnShutdown_prefLocked.js
new file mode 100644
index 000000000..6b587e036
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser_sanitizeOnShutdown_prefLocked.js
@@ -0,0 +1,37 @@
+"use strict";
+
+function switchToCustomHistoryMode(doc) {
+ // Select the last item in the menulist.
+ let menulist = doc.getElementById("historyMode");
+ menulist.focus();
+ EventUtils.sendKey("UP");
+}
+
+function testPrefStateMatchesLockedState() {
+ let win = gBrowser.contentWindow;
+ let doc = win.document;
+ switchToCustomHistoryMode(doc);
+
+ let checkbox = doc.getElementById("alwaysClear");
+ let preference = doc.getElementById("privacy.sanitize.sanitizeOnShutdown");
+ is(checkbox.disabled, preference.locked, "Always Clear checkbox should be enabled when preference is not locked.");
+
+ gBrowser.removeCurrentTab();
+}
+
+add_task(function setup() {
+ registerCleanupFunction(function resetPreferences() {
+ Services.prefs.unlockPref("privacy.sanitize.sanitizeOnShutdown");
+ });
+});
+
+add_task(function* test_preference_enabled_when_unlocked() {
+ yield openPreferencesViaOpenPreferencesAPI("panePrivacy", undefined, {leaveOpen: true});
+ testPrefStateMatchesLockedState();
+});
+
+add_task(function* test_preference_disabled_when_locked() {
+ Services.prefs.lockPref("privacy.sanitize.sanitizeOnShutdown");
+ yield openPreferencesViaOpenPreferencesAPI("panePrivacy", undefined, {leaveOpen: true});
+ testPrefStateMatchesLockedState();
+});
diff --git a/browser/components/preferences/in-content/tests/browser_searchsuggestions.js b/browser/components/preferences/in-content/tests/browser_searchsuggestions.js
new file mode 100644
index 000000000..0185a23b9
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser_searchsuggestions.js
@@ -0,0 +1,43 @@
+var original = Services.prefs.getBoolPref("browser.search.suggest.enabled");
+
+registerCleanupFunction(() => {
+ Services.prefs.setBoolPref("browser.search.suggest.enabled", original);
+});
+
+// Open with suggestions enabled
+add_task(function*() {
+ Services.prefs.setBoolPref("browser.search.suggest.enabled", true);
+
+ yield openPreferencesViaOpenPreferencesAPI("search", undefined, { leaveOpen: true });
+
+ let doc = gBrowser.selectedBrowser.contentDocument;
+ let urlbarBox = doc.getElementById("urlBarSuggestion");
+ ok(!urlbarBox.disabled, "Checkbox should be enabled");
+
+ Services.prefs.setBoolPref("browser.search.suggest.enabled", false);
+
+ ok(urlbarBox.disabled, "Checkbox should be disabled");
+
+ gBrowser.removeCurrentTab();
+});
+
+// Open with suggestions disabled
+add_task(function*() {
+ Services.prefs.setBoolPref("browser.search.suggest.enabled", false);
+
+ yield openPreferencesViaOpenPreferencesAPI("search", undefined, { leaveOpen: true });
+
+ let doc = gBrowser.selectedBrowser.contentDocument;
+ let urlbarBox = doc.getElementById("urlBarSuggestion");
+ ok(urlbarBox.disabled, "Checkbox should be disabled");
+
+ Services.prefs.setBoolPref("browser.search.suggest.enabled", true);
+
+ ok(!urlbarBox.disabled, "Checkbox should be enabled");
+
+ gBrowser.removeCurrentTab();
+});
+
+add_task(function*() {
+ Services.prefs.setBoolPref("browser.search.suggest.enabled", original);
+});
diff --git a/browser/components/preferences/in-content/tests/browser_security.js b/browser/components/preferences/in-content/tests/browser_security.js
new file mode 100644
index 000000000..e6eb2a91d
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser_security.js
@@ -0,0 +1,130 @@
+const PREFS = [
+ "browser.safebrowsing.phishing.enabled",
+ "browser.safebrowsing.malware.enabled",
+
+ "browser.safebrowsing.downloads.enabled",
+
+ "browser.safebrowsing.downloads.remote.block_potentially_unwanted",
+ "browser.safebrowsing.downloads.remote.block_uncommon"
+];
+
+let originals = PREFS.map(pref => [pref, Services.prefs.getBoolPref(pref)])
+let originalMalwareTable = Services.prefs.getCharPref("urlclassifier.malwareTable");
+registerCleanupFunction(function() {
+ originals.forEach(([pref, val]) => Services.prefs.setBoolPref(pref, val))
+ Services.prefs.setCharPref("urlclassifier.malwareTable", originalMalwareTable);
+});
+
+// test the safebrowsing preference
+add_task(function*() {
+ function* checkPrefSwitch(val1, val2) {
+ Services.prefs.setBoolPref("browser.safebrowsing.phishing.enabled", val1);
+ Services.prefs.setBoolPref("browser.safebrowsing.malware.enabled", val2);
+
+ yield openPreferencesViaOpenPreferencesAPI("security", undefined, { leaveOpen: true });
+
+ let doc = gBrowser.selectedBrowser.contentDocument;
+ let checkbox = doc.getElementById("enableSafeBrowsing");
+ let blockDownloads = doc.getElementById("blockDownloads");
+ let blockUncommon = doc.getElementById("blockUncommonUnwanted");
+ let checked = checkbox.checked;
+ is(checked, val1 && val2, "safebrowsing preference is initialized correctly");
+ // should be disabled when checked is false (= pref is turned off)
+ 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
+ EventUtils.synthesizeMouseAtCenter(checkbox, {}, gBrowser.selectedBrowser.contentWindow);
+
+ // check that both settings are now turned on or off
+ is(Services.prefs.getBoolPref("browser.safebrowsing.phishing.enabled"), !checked,
+ "safebrowsing.enabled is set correctly");
+ is(Services.prefs.getBoolPref("browser.safebrowsing.malware.enabled"), !checked,
+ "safebrowsing.malware.enabled is set correctly");
+
+ // check if the other checkboxes have updated
+ checked = checkbox.checked;
+ is(blockDownloads.hasAttribute("disabled"), !checked, "block downloads checkbox is set correctly");
+ is(blockUncommon.hasAttribute("disabled"), !checked || !blockDownloads.checked, "block uncommon checkbox is set correctly");
+
+ yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
+ }
+
+ yield checkPrefSwitch(true, true);
+ yield checkPrefSwitch(false, true);
+ yield checkPrefSwitch(true, false);
+ yield checkPrefSwitch(false, false);
+});
+
+// test the download protection preference
+add_task(function*() {
+ function* checkPrefSwitch(val) {
+ Services.prefs.setBoolPref("browser.safebrowsing.downloads.enabled", val);
+
+ yield openPreferencesViaOpenPreferencesAPI("security", undefined, { leaveOpen: true });
+
+ let doc = gBrowser.selectedBrowser.contentDocument;
+ let checkbox = doc.getElementById("blockDownloads");
+ let blockUncommon = doc.getElementById("blockUncommonUnwanted");
+ let checked = checkbox.checked;
+ is(checked, val, "downloads preference is initialized correctly");
+ // 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
+ EventUtils.synthesizeMouseAtCenter(checkbox, {}, gBrowser.selectedBrowser.contentWindow);
+
+ // check that setting is now turned on or off
+ is(Services.prefs.getBoolPref("browser.safebrowsing.downloads.enabled"), !checked,
+ "safebrowsing.downloads preference is set correctly");
+
+ // check if the uncommon warning checkbox has updated
+ is(blockUncommon.hasAttribute("disabled"), val, "block uncommon checkbox is set correctly");
+
+ yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
+ }
+
+ yield checkPrefSwitch(true);
+ yield checkPrefSwitch(false);
+});
+
+// test the unwanted/uncommon software warning preference
+add_task(function*() {
+ function* checkPrefSwitch(val1, val2) {
+ 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 });
+
+ 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
+ EventUtils.synthesizeMouseAtCenter(checkbox, {}, gBrowser.selectedBrowser.contentWindow);
+
+ // check that both settings are now turned on or off
+ is(Services.prefs.getBoolPref("browser.safebrowsing.downloads.remote.block_potentially_unwanted"), !checked,
+ "block_potentially_unwanted is set correctly");
+ is(Services.prefs.getBoolPref("browser.safebrowsing.downloads.remote.block_uncommon"), !checked,
+ "block_uncommon is set correctly");
+
+ // when the preference is on, the malware table should include these ids
+ let malwareTable = Services.prefs.getCharPref("urlclassifier.malwareTable").split(",");
+ is(malwareTable.includes("goog-unwanted-shavar"), !checked,
+ "malware table doesn't include goog-unwanted-shavar");
+ is(malwareTable.includes("test-unwanted-simple"), !checked,
+ "malware table doesn't include test-unwanted-simple");
+ let sortedMalware = malwareTable.slice(0);
+ sortedMalware.sort();
+ Assert.deepEqual(malwareTable, sortedMalware, "malware table has been sorted");
+
+ yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
+ }
+
+ yield* checkPrefSwitch(true, true);
+ yield* checkPrefSwitch(false, true);
+ yield* checkPrefSwitch(true, false);
+ yield* checkPrefSwitch(false, false);
+});
diff --git a/browser/components/preferences/in-content/tests/browser_subdialogs.js b/browser/components/preferences/in-content/tests/browser_subdialogs.js
new file mode 100644
index 000000000..ff0c1f8ae
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser_subdialogs.js
@@ -0,0 +1,293 @@
+/* Any copyright is dedicated to the Public Domain.
+* http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+/**
+ * Tests for the sub-dialog infrastructure, not for actual sub-dialog functionality.
+ */
+
+const gDialogURL = getRootDirectory(gTestPath) + "subdialog.xul";
+const gDialogURL2 = getRootDirectory(gTestPath) + "subdialog2.xul";
+
+function* open_subdialog_and_test_generic_start_state(browser, domcontentloadedFn, url = gDialogURL) {
+ let domcontentloadedFnStr = domcontentloadedFn ?
+ "(" + domcontentloadedFn.toString() + ")()" :
+ "";
+ return ContentTask.spawn(browser, {url, domcontentloadedFnStr}, function*(args) {
+ let {url, domcontentloadedFnStr} = args;
+ let rv = { acceptCount: 0 };
+ let win = content.window;
+ let subdialog = win.gSubDialog;
+ subdialog.open(url, null, rv);
+
+ info("waiting for subdialog DOMFrameContentLoaded");
+ yield ContentTaskUtils.waitForEvent(win, "DOMFrameContentLoaded", true);
+ let result;
+ if (domcontentloadedFnStr) {
+ result = eval(domcontentloadedFnStr);
+ }
+
+ info("waiting for subdialog load");
+ yield ContentTaskUtils.waitForEvent(subdialog._frame, "load");
+ info("subdialog window is loaded");
+
+ let expectedStyleSheetURLs = subdialog._injectedStyleSheets.slice(0);
+ for (let styleSheet of subdialog._frame.contentDocument.styleSheets) {
+ let index = expectedStyleSheetURLs.indexOf(styleSheet.href);
+ if (index >= 0) {
+ expectedStyleSheetURLs.splice(index, 1);
+ }
+ }
+
+ Assert.ok(!!subdialog._frame.contentWindow, "The dialog should be non-null");
+ Assert.notEqual(subdialog._frame.contentWindow.location.toString(), "about:blank",
+ "Subdialog URL should not be about:blank");
+ Assert.equal(win.getComputedStyle(subdialog._overlay, "").visibility, "visible",
+ "Overlay should be visible");
+ Assert.equal(expectedStyleSheetURLs.length, 0,
+ "No stylesheets that were expected are missing");
+ return result;
+ });
+}
+
+function* close_subdialog_and_test_generic_end_state(browser, closingFn, closingButton, acceptCount, options) {
+ let dialogclosingPromise = ContentTask.spawn(browser, {closingButton, acceptCount}, function*(expectations) {
+ let win = content.window;
+ let subdialog = win.gSubDialog;
+ let frame = subdialog._frame;
+ info("waiting for dialogclosing");
+ let closingEvent =
+ yield ContentTaskUtils.waitForEvent(frame.contentWindow, "dialogclosing");
+ let closingButton = closingEvent.detail.button;
+ let actualAcceptCount = frame.contentWindow.arguments &&
+ frame.contentWindow.arguments[0].acceptCount;
+
+ info("waiting for about:blank load");
+ yield ContentTaskUtils.waitForEvent(frame, "load");
+
+ Assert.notEqual(win.getComputedStyle(subdialog._overlay, "").visibility, "visible",
+ "overlay is not visible");
+ Assert.equal(frame.getAttribute("style"), "", "inline styles should be cleared");
+ Assert.equal(frame.contentWindow.location.href.toString(), "about:blank",
+ "sub-dialog should be unloaded");
+ Assert.equal(closingButton, expectations.closingButton,
+ "closing event should indicate button was '" + expectations.closingButton + "'");
+ Assert.equal(actualAcceptCount, expectations.acceptCount,
+ "should be 1 if accepted, 0 if canceled, undefined if closed w/out button");
+ });
+
+ if (options && options.runClosingFnOutsideOfContentTask) {
+ yield closingFn();
+ } else {
+ ContentTask.spawn(browser, null, closingFn);
+ }
+
+ yield dialogclosingPromise;
+}
+
+let tab;
+
+add_task(function* test_initialize() {
+ tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:preferences");
+});
+
+add_task(function* check_titlebar_focus_returnval_titlechanges_accepting() {
+ yield open_subdialog_and_test_generic_start_state(tab.linkedBrowser);
+
+ let domtitlechangedPromise = BrowserTestUtils.waitForEvent(tab.linkedBrowser, "DOMTitleChanged");
+ yield ContentTask.spawn(tab.linkedBrowser, null, function*() {
+ let dialog = content.window.gSubDialog._frame.contentWindow;
+ let dialogTitleElement = content.document.getElementById("dialogTitle");
+ Assert.equal(dialogTitleElement.textContent, "Sample sub-dialog",
+ "Title should be correct initially");
+ Assert.equal(dialog.document.activeElement.value, "Default text",
+ "Textbox with correct text is focused");
+ dialog.document.title = "Updated title";
+ });
+
+ info("waiting for DOMTitleChanged event");
+ yield domtitlechangedPromise;
+
+ ContentTask.spawn(tab.linkedBrowser, null, function*() {
+ let dialogTitleElement = content.document.getElementById("dialogTitle");
+ Assert.equal(dialogTitleElement.textContent, "Updated title",
+ "subdialog should have updated title");
+ });
+
+ // Accept the dialog
+ yield close_subdialog_and_test_generic_end_state(tab.linkedBrowser,
+ function() { content.window.gSubDialog._frame.contentDocument.documentElement.acceptDialog(); },
+ "accept", 1);
+});
+
+add_task(function* check_canceling_dialog() {
+ yield open_subdialog_and_test_generic_start_state(tab.linkedBrowser);
+
+ info("canceling the dialog");
+ yield close_subdialog_and_test_generic_end_state(tab.linkedBrowser,
+ function() { content.window.gSubDialog._frame.contentDocument.documentElement.cancelDialog(); },
+ "cancel", 0);
+});
+
+add_task(function* check_reopening_dialog() {
+ yield open_subdialog_and_test_generic_start_state(tab.linkedBrowser);
+ info("opening another dialog which will close the first");
+ yield open_subdialog_and_test_generic_start_state(tab.linkedBrowser, "", gDialogURL2);
+ info("closing as normal");
+ yield close_subdialog_and_test_generic_end_state(tab.linkedBrowser,
+ function() { content.window.gSubDialog._frame.contentDocument.documentElement.acceptDialog(); },
+ "accept", 1);
+});
+
+add_task(function* check_opening_while_closing() {
+ yield open_subdialog_and_test_generic_start_state(tab.linkedBrowser);
+ info("closing");
+ content.window.gSubDialog.close();
+ info("reopening immediately after calling .close()");
+ yield open_subdialog_and_test_generic_start_state(tab.linkedBrowser);
+ yield close_subdialog_and_test_generic_end_state(tab.linkedBrowser,
+ function() { content.window.gSubDialog._frame.contentDocument.documentElement.acceptDialog(); },
+ "accept", 1);
+
+});
+
+add_task(function* window_close_on_dialog() {
+ yield open_subdialog_and_test_generic_start_state(tab.linkedBrowser);
+
+ info("canceling the dialog");
+ yield close_subdialog_and_test_generic_end_state(tab.linkedBrowser,
+ function() { content.window.gSubDialog._frame.contentWindow.window.close(); },
+ null, 0);
+});
+
+add_task(function* click_close_button_on_dialog() {
+ yield open_subdialog_and_test_generic_start_state(tab.linkedBrowser);
+
+ info("canceling the dialog");
+ yield close_subdialog_and_test_generic_end_state(tab.linkedBrowser,
+ function() { return BrowserTestUtils.synthesizeMouseAtCenter("#dialogClose", {}, tab.linkedBrowser); },
+ null, 0, {runClosingFnOutsideOfContentTask: true});
+});
+
+add_task(function* back_navigation_on_subdialog_should_close_dialog() {
+ yield open_subdialog_and_test_generic_start_state(tab.linkedBrowser);
+
+ info("canceling the dialog");
+ yield close_subdialog_and_test_generic_end_state(tab.linkedBrowser,
+ function() { content.window.gSubDialog._frame.goBack(); },
+ null, undefined);
+});
+
+add_task(function* back_navigation_on_browser_tab_should_close_dialog() {
+ yield open_subdialog_and_test_generic_start_state(tab.linkedBrowser);
+
+ info("canceling the dialog");
+ yield close_subdialog_and_test_generic_end_state(tab.linkedBrowser,
+ function() { tab.linkedBrowser.goBack(); },
+ null, undefined, {runClosingFnOutsideOfContentTask: true});
+});
+
+add_task(function* escape_should_close_dialog() {
+ yield open_subdialog_and_test_generic_start_state(tab.linkedBrowser);
+
+ info("canceling the dialog");
+ yield close_subdialog_and_test_generic_end_state(tab.linkedBrowser,
+ function() { return BrowserTestUtils.synthesizeKey("VK_ESCAPE", {}, tab.linkedBrowser); },
+ "cancel", 0, {runClosingFnOutsideOfContentTask: true});
+});
+
+add_task(function* correct_width_and_height_should_be_used_for_dialog() {
+ yield open_subdialog_and_test_generic_start_state(tab.linkedBrowser);
+
+ yield ContentTask.spawn(tab.linkedBrowser, null, function*() {
+ let frameStyle = content.window.gSubDialog._frame.style;
+ Assert.equal(frameStyle.width, "32em",
+ "Width should be set on the frame from the dialog");
+ Assert.equal(frameStyle.height, "5em",
+ "Height should be set on the frame from the dialog");
+ });
+
+ yield close_subdialog_and_test_generic_end_state(tab.linkedBrowser,
+ function() { content.window.gSubDialog._frame.contentWindow.window.close(); },
+ null, 0);
+});
+
+add_task(function* wrapped_text_in_dialog_should_have_expected_scrollHeight() {
+ let oldHeight = yield open_subdialog_and_test_generic_start_state(tab.linkedBrowser, function domcontentloadedFn() {
+ let frame = content.window.gSubDialog._frame;
+ let doc = frame.contentDocument;
+ let oldHeight = doc.documentElement.scrollHeight;
+ doc.documentElement.style.removeProperty("height");
+ doc.getElementById("desc").textContent = `
+ Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque
+ laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi
+ architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas
+ sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione
+ laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi
+ architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas
+ sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione
+ laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi
+ architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas
+ sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione
+ voluptatem sequi nesciunt.`
+ return oldHeight;
+ });
+
+ yield ContentTask.spawn(tab.linkedBrowser, oldHeight, function*(oldHeight) {
+ let frame = content.window.gSubDialog._frame;
+ let docEl = frame.contentDocument.documentElement;
+ Assert.equal(frame.style.width, "32em",
+ "Width should be set on the frame from the dialog");
+ Assert.ok(docEl.scrollHeight > oldHeight,
+ "Content height increased (from " + oldHeight + " to " + docEl.scrollHeight + ").");
+ Assert.equal(frame.style.height, docEl.scrollHeight + "px",
+ "Height on the frame should be higher now");
+ });
+
+ yield close_subdialog_and_test_generic_end_state(tab.linkedBrowser,
+ function() { content.window.gSubDialog._frame.contentWindow.window.close(); },
+ null, 0);
+});
+
+add_task(function* dialog_too_tall_should_get_reduced_in_height() {
+ yield open_subdialog_and_test_generic_start_state(tab.linkedBrowser, function domcontentloadedFn() {
+ let frame = content.window.gSubDialog._frame;
+ frame.contentDocument.documentElement.style.height = '100000px';
+ });
+
+ yield ContentTask.spawn(tab.linkedBrowser, null, function*() {
+ let frame = content.window.gSubDialog._frame;
+ Assert.equal(frame.style.width, "32em", "Width should be set on the frame from the dialog");
+ Assert.ok(parseInt(frame.style.height, 10) < content.window.innerHeight,
+ "Height on the frame should be smaller than window's innerHeight");
+ });
+
+ yield close_subdialog_and_test_generic_end_state(tab.linkedBrowser,
+ function() { content.window.gSubDialog._frame.contentWindow.window.close(); },
+ null, 0);
+});
+
+add_task(function* scrollWidth_and_scrollHeight_from_subdialog_should_size_the_browser() {
+ yield open_subdialog_and_test_generic_start_state(tab.linkedBrowser, function domcontentloadedFn() {
+ let frame = content.window.gSubDialog._frame;
+ frame.contentDocument.documentElement.style.removeProperty("height");
+ frame.contentDocument.documentElement.style.removeProperty("width");
+ });
+
+ yield ContentTask.spawn(tab.linkedBrowser, null, function*() {
+ let frame = content.window.gSubDialog._frame;
+ Assert.ok(frame.style.width.endsWith("px"),
+ "Width (" + frame.style.width + ") should be set to a px value of the scrollWidth from the dialog");
+ Assert.ok(frame.style.height.endsWith("px"),
+ "Height (" + frame.style.height + ") should be set to a px value of the scrollHeight from the dialog");
+ });
+
+ yield close_subdialog_and_test_generic_end_state(tab.linkedBrowser,
+ function() { content.window.gSubDialog._frame.contentWindow.window.close(); },
+ null, 0);
+});
+
+add_task(function* test_shutdown() {
+ gBrowser.removeTab(tab);
+});
diff --git a/browser/components/preferences/in-content/tests/browser_telemetry.js b/browser/components/preferences/in-content/tests/browser_telemetry.js
new file mode 100644
index 000000000..d8139d87a
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser_telemetry.js
@@ -0,0 +1,52 @@
+/* Any copyright is dedicated to the Public Domain.
+* http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const PREF_TELEMETRY_ENABLED = "toolkit.telemetry.enabled";
+
+function runPaneTest(fn) {
+ open_preferences((win) => {
+ let doc = win.document;
+ win.gotoPref("paneAdvanced");
+ let advancedPrefs = doc.getElementById("advancedPrefs");
+ let tab = doc.getElementById("dataChoicesTab");
+ advancedPrefs.selectedTab = tab;
+ fn(win, doc);
+ });
+}
+
+function test() {
+ waitForExplicitFinish();
+ resetPreferences();
+ registerCleanupFunction(resetPreferences);
+ runPaneTest(testTelemetryState);
+}
+
+function testTelemetryState(win, doc) {
+ let fhrCheckbox = doc.getElementById("submitHealthReportBox");
+ Assert.ok(fhrCheckbox.checked, "Health Report checkbox is checked on app first run.");
+
+ let telmetryCheckbox = doc.getElementById("submitTelemetryBox");
+ Assert.ok(!telmetryCheckbox.disabled,
+ "Telemetry checkbox must be enabled if FHR is checked.");
+ Assert.ok(Services.prefs.getBoolPref(PREF_TELEMETRY_ENABLED),
+ "Telemetry must be enabled if the checkbox is ticked.");
+
+ // Uncheck the FHR checkbox and make sure that Telemetry checkbox gets disabled.
+ fhrCheckbox.click();
+
+ Assert.ok(telmetryCheckbox.disabled,
+ "Telemetry checkbox must be disabled if FHR is unchecked.");
+ Assert.ok(!Services.prefs.getBoolPref(PREF_TELEMETRY_ENABLED),
+ "Telemetry must be disabled if the checkbox is unticked.");
+
+ win.close();
+ finish();
+}
+
+function resetPreferences() {
+ Services.prefs.clearUserPref("datareporting.healthreport.uploadEnabled");
+ Services.prefs.clearUserPref(PREF_TELEMETRY_ENABLED);
+}
+
diff --git a/browser/components/preferences/in-content/tests/head.js b/browser/components/preferences/in-content/tests/head.js
new file mode 100644
index 000000000..0ed811e94
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/head.js
@@ -0,0 +1,165 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+Components.utils.import("resource://gre/modules/Promise.jsm");
+
+const kDefaultWait = 2000;
+
+function is_hidden(aElement) {
+ var style = aElement.ownerGlobal.getComputedStyle(aElement);
+ if (style.display == "none")
+ return true;
+ if (style.visibility != "visible")
+ return true;
+
+ // Hiding a parent element will hide all its children
+ if (aElement.parentNode != aElement.ownerDocument)
+ return is_hidden(aElement.parentNode);
+
+ return false;
+}
+
+function is_element_visible(aElement, aMsg) {
+ isnot(aElement, null, "Element should not be null, when checking visibility");
+ ok(!is_hidden(aElement), aMsg);
+}
+
+function is_element_hidden(aElement, aMsg) {
+ isnot(aElement, null, "Element should not be null, when checking visibility");
+ ok(is_hidden(aElement), aMsg);
+}
+
+function open_preferences(aCallback) {
+ gBrowser.selectedTab = gBrowser.addTab("about:preferences");
+ let newTabBrowser = gBrowser.getBrowserForTab(gBrowser.selectedTab);
+ newTabBrowser.addEventListener("Initialized", function () {
+ newTabBrowser.removeEventListener("Initialized", arguments.callee, true);
+ aCallback(gBrowser.contentWindow);
+ }, true);
+}
+
+function openAndLoadSubDialog(aURL, aFeatures = null, aParams = null, aClosingCallback = null) {
+ let promise = promiseLoadSubDialog(aURL);
+ content.gSubDialog.open(aURL, aFeatures, aParams, aClosingCallback);
+ return promise;
+}
+
+function promiseLoadSubDialog(aURL) {
+ return new Promise((resolve, reject) => {
+ content.gSubDialog._frame.addEventListener("load", function load(aEvent) {
+ if (aEvent.target.contentWindow.location == "about:blank")
+ return;
+ content.gSubDialog._frame.removeEventListener("load", load);
+
+ is(content.gSubDialog._frame.contentWindow.location.toString(), aURL,
+ "Check the proper URL is loaded");
+
+ // Check visibility
+ is_element_visible(content.gSubDialog._overlay, "Overlay is visible");
+
+ // Check that stylesheets were injected
+ let expectedStyleSheetURLs = content.gSubDialog._injectedStyleSheets.slice(0);
+ for (let styleSheet of content.gSubDialog._frame.contentDocument.styleSheets) {
+ let i = expectedStyleSheetURLs.indexOf(styleSheet.href);
+ if (i >= 0) {
+ info("found " + styleSheet.href);
+ expectedStyleSheetURLs.splice(i, 1);
+ }
+ }
+ is(expectedStyleSheetURLs.length, 0, "All expectedStyleSheetURLs should have been found");
+
+ resolve(content.gSubDialog._frame.contentWindow);
+ });
+ });
+}
+
+/**
+ * Waits a specified number of miliseconds for a specified event to be
+ * fired on a specified element.
+ *
+ * Usage:
+ * let receivedEvent = waitForEvent(element, "eventName");
+ * // Do some processing here that will cause the event to be fired
+ * // ...
+ * // Now yield until the Promise is fulfilled
+ * yield receivedEvent;
+ * if (receivedEvent && !(receivedEvent instanceof Error)) {
+ * receivedEvent.msg == "eventName";
+ * // ...
+ * }
+ *
+ * @param aSubject the element that should receive the event
+ * @param aEventName the event to wait for
+ * @param aTimeoutMs the number of miliseconds to wait before giving up
+ * @returns a Promise that resolves to the received event, or to an Error
+ */
+function waitForEvent(aSubject, aEventName, aTimeoutMs, aTarget) {
+ let eventDeferred = Promise.defer();
+ let timeoutMs = aTimeoutMs || kDefaultWait;
+ let stack = new Error().stack;
+ let timerID = setTimeout(function wfe_canceller() {
+ aSubject.removeEventListener(aEventName, listener);
+ eventDeferred.reject(new Error(aEventName + " event timeout at " + stack));
+ }, timeoutMs);
+
+ var listener = function (aEvent) {
+ if (aTarget && aTarget !== aEvent.target)
+ return;
+
+ // stop the timeout clock and resume
+ clearTimeout(timerID);
+ eventDeferred.resolve(aEvent);
+ };
+
+ function cleanup(aEventOrError) {
+ // unhook listener in case of success or failure
+ aSubject.removeEventListener(aEventName, listener);
+ return aEventOrError;
+ }
+ aSubject.addEventListener(aEventName, listener, false);
+ return eventDeferred.promise.then(cleanup, cleanup);
+}
+
+function openPreferencesViaOpenPreferencesAPI(aPane, aAdvancedTab, aOptions) {
+ let deferred = Promise.defer();
+ gBrowser.selectedTab = gBrowser.addTab("about:blank");
+ openPreferences(aPane, aAdvancedTab ? {advancedTab: aAdvancedTab} : undefined);
+ let newTabBrowser = gBrowser.selectedBrowser;
+
+ newTabBrowser.addEventListener("Initialized", function PrefInit() {
+ newTabBrowser.removeEventListener("Initialized", PrefInit, true);
+ newTabBrowser.contentWindow.addEventListener("load", function prefLoad() {
+ newTabBrowser.contentWindow.removeEventListener("load", prefLoad);
+ 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: selectedPane, selectedAdvancedTab: selectedAdvancedTab});
+ });
+ }, true);
+
+ return deferred.promise;
+}
+
+function waitForCondition(aConditionFn, aMaxTries=50, aCheckInterval=100) {
+ return new Promise((resolve, reject) => {
+ function tryNow() {
+ tries++;
+ let rv = aConditionFn();
+ if (rv) {
+ resolve(rv);
+ } else if (tries < aMaxTries) {
+ tryAgain();
+ } else {
+ reject("Condition timed out: " + aConditionFn.toSource());
+ }
+ }
+ function tryAgain() {
+ setTimeout(tryNow, aCheckInterval);
+ }
+ let tries = 0;
+ tryAgain();
+ });
+}
diff --git a/browser/components/preferences/in-content/tests/privacypane_tests_perwindow.js b/browser/components/preferences/in-content/tests/privacypane_tests_perwindow.js
new file mode 100644
index 000000000..53c6d7d8a
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/privacypane_tests_perwindow.js
@@ -0,0 +1,330 @@
+function* runTestOnPrivacyPrefPane(testFunc) {
+ info("runTestOnPrivacyPrefPane entered");
+ let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:preferences", true, true);
+ let browser = tab.linkedBrowser;
+ info("loaded about:preferences");
+ browser.contentWindow.gotoPref("panePrivacy");
+ info("viewing privacy pane, executing testFunc");
+ testFunc(browser.contentWindow);
+ yield BrowserTestUtils.removeTab(tab);
+}
+
+function controlChanged(element) {
+ element.doCommand();
+}
+
+// We can only test the panes that don't trigger a preference update
+function test_pane_visibility(win) {
+ let modes = {
+ "remember": "historyRememberPane",
+ "custom": "historyCustomPane"
+ };
+
+ let historymode = win.document.getElementById("historyMode");
+ ok(historymode, "history mode menulist should exist");
+ let historypane = win.document.getElementById("historyPane");
+ ok(historypane, "history mode pane should exist");
+
+ for (let mode in modes) {
+ historymode.value = mode;
+ controlChanged(historymode);
+ is(historypane.selectedPanel, win.document.getElementById(modes[mode]),
+ "The correct pane should be selected for the " + mode + " mode");
+ is_element_visible(historypane.selectedPanel,
+ "Correct pane should be visible for the " + mode + " mode");
+ }
+}
+
+function test_dependent_elements(win) {
+ let historymode = win.document.getElementById("historyMode");
+ ok(historymode, "history mode menulist should exist");
+ let pbautostart = win.document.getElementById("privateBrowsingAutoStart");
+ ok(pbautostart, "the private browsing auto-start checkbox should exist");
+ let controls = [
+ win.document.getElementById("rememberHistory"),
+ win.document.getElementById("rememberForms"),
+ win.document.getElementById("keepUntil"),
+ win.document.getElementById("keepCookiesUntil"),
+ win.document.getElementById("alwaysClear"),
+ ];
+ controls.forEach(function(control) {
+ ok(control, "the dependent controls should exist");
+ });
+ let independents = [
+ win.document.getElementById("acceptCookies"),
+ win.document.getElementById("acceptThirdPartyLabel"),
+ win.document.getElementById("acceptThirdPartyMenu")
+ ];
+ independents.forEach(function(control) {
+ ok(control, "the independent controls should exist");
+ });
+ let cookieexceptions = win.document.getElementById("cookieExceptions");
+ ok(cookieexceptions, "the cookie exceptions button should exist");
+ let keepuntil = win.document.getElementById("keepCookiesUntil");
+ ok(keepuntil, "the keep cookies until menulist should exist");
+ let alwaysclear = win.document.getElementById("alwaysClear");
+ ok(alwaysclear, "the clear data on close checkbox should exist");
+ let rememberhistory = win.document.getElementById("rememberHistory");
+ ok(rememberhistory, "the remember history checkbox should exist");
+ let rememberforms = win.document.getElementById("rememberForms");
+ ok(rememberforms, "the remember forms checkbox should exist");
+ let alwaysclearsettings = win.document.getElementById("clearDataSettings");
+ ok(alwaysclearsettings, "the clear data settings button should exist");
+
+ function expect_disabled(disabled) {
+ controls.forEach(function(control) {
+ is(control.disabled, disabled,
+ control.getAttribute("id") + " should " + (disabled ? "" : "not ") + "be disabled");
+ });
+ is(keepuntil.value, disabled ? 2 : 0,
+ "the keep cookies until menulist value should be as expected");
+ if (disabled) {
+ ok(!alwaysclear.checked,
+ "the clear data on close checkbox value should be as expected");
+ ok(!rememberhistory.checked,
+ "the remember history checkbox value should be as expected");
+ ok(!rememberforms.checked,
+ "the remember forms checkbox value should be as expected");
+ }
+ }
+ function check_independents(expected) {
+ independents.forEach(function(control) {
+ is(control.disabled, expected,
+ control.getAttribute("id") + " should " + (expected ? "" : "not ") + "be disabled");
+ });
+
+ ok(!cookieexceptions.disabled,
+ "the cookie exceptions button should never be disabled");
+ ok(alwaysclearsettings.disabled,
+ "the clear data settings button should always be disabled");
+ }
+
+ // controls should only change in custom mode
+ historymode.value = "remember";
+ controlChanged(historymode);
+ expect_disabled(false);
+ check_independents(false);
+
+ // setting the mode to custom shouldn't change anything
+ historymode.value = "custom";
+ controlChanged(historymode);
+ expect_disabled(false);
+ check_independents(false);
+}
+
+function test_dependent_cookie_elements(win) {
+ let historymode = win.document.getElementById("historyMode");
+ ok(historymode, "history mode menulist should exist");
+ let pbautostart = win.document.getElementById("privateBrowsingAutoStart");
+ ok(pbautostart, "the private browsing auto-start checkbox should exist");
+ let controls = [
+ win.document.getElementById("acceptThirdPartyLabel"),
+ win.document.getElementById("acceptThirdPartyMenu"),
+ win.document.getElementById("keepUntil"),
+ win.document.getElementById("keepCookiesUntil"),
+ ];
+ controls.forEach(function(control) {
+ ok(control, "the dependent cookie controls should exist");
+ });
+ let acceptcookies = win.document.getElementById("acceptCookies");
+ ok(acceptcookies, "the accept cookies checkbox should exist");
+
+ function expect_disabled(disabled) {
+ controls.forEach(function(control) {
+ is(control.disabled, disabled,
+ control.getAttribute("id") + " should " + (disabled ? "" : "not ") + "be disabled");
+ });
+ }
+
+ historymode.value = "custom";
+ controlChanged(historymode);
+ pbautostart.checked = false;
+ controlChanged(pbautostart);
+ expect_disabled(false);
+
+ acceptcookies.checked = false;
+ controlChanged(acceptcookies);
+ expect_disabled(true);
+
+ acceptcookies.checked = true;
+ controlChanged(acceptcookies);
+ expect_disabled(false);
+
+ let accessthirdparty = controls.shift();
+ acceptcookies.checked = false;
+ controlChanged(acceptcookies);
+ expect_disabled(true);
+ ok(accessthirdparty.disabled, "access third party button should be disabled");
+
+ pbautostart.checked = false;
+ controlChanged(pbautostart);
+ expect_disabled(true);
+ ok(accessthirdparty.disabled, "access third party button should be disabled");
+
+ acceptcookies.checked = true;
+ controlChanged(acceptcookies);
+ expect_disabled(false);
+ ok(!accessthirdparty.disabled, "access third party button should be enabled");
+}
+
+function test_dependent_clearonclose_elements(win) {
+ let historymode = win.document.getElementById("historyMode");
+ ok(historymode, "history mode menulist should exist");
+ let pbautostart = win.document.getElementById("privateBrowsingAutoStart");
+ ok(pbautostart, "the private browsing auto-start checkbox should exist");
+ let alwaysclear = win.document.getElementById("alwaysClear");
+ ok(alwaysclear, "the clear data on close checkbox should exist");
+ let alwaysclearsettings = win.document.getElementById("clearDataSettings");
+ ok(alwaysclearsettings, "the clear data settings button should exist");
+
+ function expect_disabled(disabled) {
+ is(alwaysclearsettings.disabled, disabled,
+ "the clear data settings should " + (disabled ? "" : "not ") + "be disabled");
+ }
+
+ historymode.value = "custom";
+ controlChanged(historymode);
+ pbautostart.checked = false;
+ controlChanged(pbautostart);
+ alwaysclear.checked = false;
+ controlChanged(alwaysclear);
+ expect_disabled(true);
+
+ alwaysclear.checked = true;
+ controlChanged(alwaysclear);
+ expect_disabled(false);
+
+ alwaysclear.checked = false;
+ controlChanged(alwaysclear);
+ expect_disabled(true);
+}
+
+function test_dependent_prefs(win) {
+ let historymode = win.document.getElementById("historyMode");
+ ok(historymode, "history mode menulist should exist");
+ let controls = [
+ win.document.getElementById("rememberHistory"),
+ win.document.getElementById("rememberForms"),
+ win.document.getElementById("acceptCookies")
+ ];
+ controls.forEach(function(control) {
+ ok(control, "the micro-management controls should exist");
+ });
+
+ let thirdPartyCookieMenu = win.document.getElementById("acceptThirdPartyMenu");
+ ok(thirdPartyCookieMenu, "the third-party cookie control should exist");
+
+ function expect_checked(checked) {
+ controls.forEach(function(control) {
+ is(control.checked, checked,
+ control.getAttribute("id") + " should " + (checked ? "not " : "") + "be checked");
+ });
+
+ is(thirdPartyCookieMenu.value == "always" || thirdPartyCookieMenu.value == "visited", checked, "third-party cookies should " + (checked ? "not " : "") + "be limited");
+ }
+
+ // controls should be checked in remember mode
+ historymode.value = "remember";
+ controlChanged(historymode);
+ expect_checked(true);
+
+ // even if they're unchecked in custom mode
+ historymode.value = "custom";
+ controlChanged(historymode);
+ thirdPartyCookieMenu.value = "never";
+ controlChanged(thirdPartyCookieMenu);
+ controls.forEach(function(control) {
+ control.checked = false;
+ controlChanged(control);
+ });
+ expect_checked(false);
+ historymode.value = "remember";
+ controlChanged(historymode);
+ expect_checked(true);
+}
+
+function test_historymode_retention(mode, expect) {
+ return function test_historymode_retention_fn(win) {
+ let historymode = win.document.getElementById("historyMode");
+ ok(historymode, "history mode menulist should exist");
+
+ if ((historymode.value == "remember" && mode == "dontremember") ||
+ (historymode.value == "dontremember" && mode == "remember") ||
+ (historymode.value == "custom" && mode == "dontremember")) {
+ return;
+ }
+
+ if (expect !== undefined) {
+ is(historymode.value, expect,
+ "history mode is expected to remain " + expect);
+ }
+
+ historymode.value = mode;
+ controlChanged(historymode);
+ };
+}
+
+function test_custom_retention(controlToChange, expect, valueIncrement) {
+ return function test_custom_retention_fn(win) {
+ let historymode = win.document.getElementById("historyMode");
+ ok(historymode, "history mode menulist should exist");
+
+ if (expect !== undefined) {
+ is(historymode.value, expect,
+ "history mode is expected to remain " + expect);
+ }
+
+ historymode.value = "custom";
+ controlChanged(historymode);
+
+ controlToChange = win.document.getElementById(controlToChange);
+ ok(controlToChange, "the control to change should exist");
+ switch (controlToChange.localName) {
+ case "checkbox":
+ controlToChange.checked = !controlToChange.checked;
+ break;
+ case "textbox":
+ controlToChange.value = parseInt(controlToChange.value) + valueIncrement;
+ break;
+ case "menulist":
+ controlToChange.value = valueIncrement;
+ break;
+ }
+ controlChanged(controlToChange);
+ };
+}
+
+function test_locbar_suggestion_retention(suggestion, autocomplete) {
+ return function(win) {
+ let elem = win.document.getElementById(suggestion + "Suggestion");
+ ok(elem, "Suggest " + suggestion + " checkbox should exist.");
+ elem.click();
+
+ is(Services.prefs.getBoolPref("browser.urlbar.autocomplete.enabled"), autocomplete,
+ "browser.urlbar.autocomplete.enabled pref should be " + autocomplete);
+ };
+}
+
+const gPrefCache = new Map();
+
+function cache_preferences(win) {
+ let prefs = win.document.querySelectorAll("#privacyPreferences > preference");
+ for (let pref of prefs)
+ gPrefCache.set(pref.name, pref.value);
+}
+
+function reset_preferences(win) {
+ let prefs = win.document.querySelectorAll("#privacyPreferences > preference");
+ for (let pref of prefs)
+ pref.value = gPrefCache.get(pref.name);
+}
+
+function run_test_subset(subset) {
+ info("subset: " + Array.from(subset, x => x.name).join(",") + "\n");
+ SpecialPowers.pushPrefEnv({"set": [["browser.preferences.instantApply", true]]});
+
+ let tests = [cache_preferences, ...subset, reset_preferences];
+ for (let test of tests) {
+ add_task(runTestOnPrivacyPrefPane.bind(undefined, test));
+ }
+}
diff --git a/browser/components/preferences/in-content/tests/subdialog.xul b/browser/components/preferences/in-content/tests/subdialog.xul
new file mode 100644
index 000000000..48d297b73
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/subdialog.xul
@@ -0,0 +1,27 @@
+<?xml version="1.0"?>
+
+<!-- Any copyright is dedicated to the Public Domain.
+ - http://creativecommons.org/publicdomain/zero/1.0/ -->
+
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+
+<dialog id="subDialog"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ title="Sample sub-dialog" style="width: 32em; height: 5em;"
+ onload="document.getElementById('textbox').focus();"
+ ondialogaccept="acceptSubdialog();">
+ <script>
+ function acceptSubdialog() {
+ window.arguments[0].acceptCount++;
+ }
+ </script>
+
+ <description id="desc">A sample sub-dialog for testing</description>
+
+ <textbox id="textbox" value="Default text" />
+
+ <separator class="thin"/>
+
+ <button oncommand="close();" icon="close" label="Close" />
+
+</dialog>
diff --git a/browser/components/preferences/in-content/tests/subdialog2.xul b/browser/components/preferences/in-content/tests/subdialog2.xul
new file mode 100644
index 000000000..89803c250
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/subdialog2.xul
@@ -0,0 +1,27 @@
+<?xml version="1.0"?>
+
+<!-- Any copyright is dedicated to the Public Domain.
+ - http://creativecommons.org/publicdomain/zero/1.0/ -->
+
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+
+<dialog id="subDialog"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ title="Sample sub-dialog #2" style="width: 32em; height: 5em;"
+ onload="document.getElementById('textbox').focus();"
+ ondialogaccept="acceptSubdialog();">
+ <script>
+ function acceptSubdialog() {
+ window.arguments[0].acceptCount++;
+ }
+ </script>
+
+ <description id="desc">A sample sub-dialog for testing</description>
+
+ <textbox id="textbox" value="Default text" />
+
+ <separator class="thin"/>
+
+ <button oncommand="close();" icon="close" label="Close" />
+
+</dialog>