Bug 754304 - make in-content preferences linkable via URL. r=mattn

This commit is contained in:
Jared Wein 2014-06-19 16:12:52 -04:00
parent 7fa51b688f
commit 8242d9a4cc
7 changed files with 113 additions and 50 deletions

View File

@ -38,11 +38,11 @@ function checkPreferences(prefsWin) {
}
// Same as the other one, but for in-content preferences
function checkInContentPreferences(win) {
let sel = win.history.state;
let doc = win.document;
let sel = doc.getElementById("categories").selectedItems[0].id;
let tab = doc.getElementById("advancedPrefs").selectedTab.id;
is(gBrowser.currentURI.spec, "about:preferences", "about:preferences loaded");
is(sel, "paneAdvanced", "Advanced pane was selected");
is(gBrowser.currentURI.spec, "about:preferences#advanced", "about:preferences loaded");
is(sel, "category-advanced", "Advanced pane was selected");
is(tab, "networkTab", "Network tab is selected");
// all good, we are done.
win.close();
@ -75,7 +75,9 @@ function test() {
let newTabBrowser = gBrowser.getBrowserForTab(gBrowser.selectedTab);
newTabBrowser.addEventListener("Initialized", function PrefInit() {
newTabBrowser.removeEventListener("Initialized", PrefInit, true);
checkInContentPreferences(newTabBrowser.contentWindow);
executeSoon(function() {
checkInContentPreferences(newTabBrowser.contentWindow);
})
}, true);
}
});

View File

@ -488,32 +488,36 @@ function openPreferences(paneID, extraArgs)
}
}
// This function is duplicated from preferences.js.
function internalPrefCategoryNameToFriendlyName(aName) {
return (aName || "").replace(/^pane./, function(toReplace) { return toReplace[4].toLowerCase(); });
}
if (getBoolPref("browser.preferences.inContent")) {
let win = Services.wm.getMostRecentWindow("navigator:browser");
if (!win) {
return;
}
let newLoad = !win.switchToTabHavingURI("about:preferences", true);
let friendlyCategoryName = internalPrefCategoryNameToFriendlyName(paneID);
let preferencesURL = "about:preferences" +
(friendlyCategoryName ? "#" + friendlyCategoryName : "");
let newLoad = !win.switchToTabHavingURI(preferencesURL, true, undefined, true);
let browser = win.gBrowser.selectedBrowser;
function switchToPane() {
if (paneID) {
browser.contentWindow.selectCategory(paneID);
}
switchToAdvancedSubPane(browser.contentDocument);
}
if (newLoad) {
Services.obs.addObserver(function advancedPaneLoadedObs(prefWin, topic, data) {
if (prefWin != browser.contentWindow) {
return;
}
Services.obs.removeObserver(advancedPaneLoadedObs, "advanced-pane-loaded");
switchToPane();
switchToAdvancedSubPane(browser.contentDocument);
}, "advanced-pane-loaded", false);
} else {
switchToPane();
if (paneID) {
browser.contentWindow.gotoPref(paneID);
}
switchToAdvancedSubPane(browser.contentDocument);
}
} else {
var instantApply = getBoolPref("browser.preferences.instantApply", false);

View File

@ -71,9 +71,6 @@ var gAdvancedPane = {
#endif
this.updateActualCacheSize();
this.updateActualAppCacheSize();
// Notify observers that the UI is now ready
Services.obs.notifyObservers(window, "advanced-pane-loaded", null);
},
/**

View File

@ -12,6 +12,8 @@ const Cr = Components.results;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
let gLastHash = "";
addEventListener("DOMContentLoaded", function onLoad() {
removeEventListener("DOMContentLoaded", onLoad);
init_all();
@ -42,21 +44,45 @@ function init_all() {
this.removeAttribute("keyboard-navigation");
});
if (document.getElementById("category-general").selected) {
gotoPref("paneGeneral");
}
window.addEventListener("hashchange", onHashChange);
gotoPref();
// Wait until initialization of all preferences are complete before
// notifying observers that the UI is now ready.
Services.obs.notifyObservers(window, "advanced-pane-loaded", null);
}
function selectCategory(name) {
function onHashChange() {
gotoPref();
}
function gotoPref(aCategory) {
let categories = document.getElementById("categories");
let item = categories.querySelector(".category[value=" + name + "]");
categories.selectedItem = item;
gotoPref(name);
}
const kDefaultCategoryInternalName = categories.firstElementChild.value;
let hash = document.location.hash;
let category = aCategory || hash.substr(1) || kDefaultCategoryInternalName;
category = friendlyPrefCategoryNameToInternalName(category);
function gotoPref(page) {
window.history.replaceState(page, document.title);
search(page, "data-category");
// Updating the hash (below) or changing the selected category
// will re-enter gotoPref.
if (gLastHash == category)
return;
let item = categories.querySelector(".category[value=" + category + "]");
if (!item) {
category = kDefaultCategoryInternalName;
item = categories.querySelector(".category[value=" + category + "]");
}
let newHash = internalPrefCategoryNameToFriendlyName(category);
if (gLastHash || category != kDefaultCategoryInternalName) {
document.location.hash = newHash;
}
// Need to set the gLastHash before setting categories.selectedItem since
// the categories 'select' event will re-enter the gotoPref codepath.
gLastHash = category;
categories.selectedItem = item;
window.history.replaceState(category, document.title);
search(category, "data-category");
}
function search(aQuery, aAttribute) {
@ -74,3 +100,14 @@ function helpButtonCommand() {
.getAttribute("helpTopic");
openHelpLink(helpTopic);
}
function friendlyPrefCategoryNameToInternalName(aName) {
if (aName.startsWith("pane"))
return aName;
return "pane" + aName.substring(0,1).toUpperCase() + aName.substr(1);
}
// This function is duplicated inside of utilityOverlay.js's openPreferences.
function internalPrefCategoryNameToFriendlyName(aName) {
return (aName || "").replace(/^pane./, function(toReplace) { return toReplace[4].toLowerCase(); });
}

View File

@ -1,25 +1,59 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
add_task(function test() {
waitForExplicitFinish();
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 openPreferencesViaOpenPreferencesAPI(aPane, aAdvancedTab) {
let deferred = Promise.defer();
gBrowser.selectedTab = gBrowser.addTab("about:blank");
openPreferences("paneContent");
let newTabBrowser = gBrowser.getBrowserForTab(gBrowser.selectedTab);
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 sel = gBrowser.contentWindow.history.state;
is(sel, "paneContent", "Content pane was selected");
deferred.resolve();
let win = gBrowser.contentWindow;
let selectedPane = win.history.state;
let doc = win.document;
let selectedAdvancedTab = aAdvancedTab && doc.getElementById("advancedPrefs").selectedTab.id;
gBrowser.removeCurrentTab();
deferred.resolve({selectedPane: selectedPane, selectedAdvancedTab: selectedAdvancedTab});
});
}, true);
yield deferred.promise;
return deferred.promise;
}
finish();
});
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;
}

View File

@ -37,7 +37,7 @@ function test() {
function runTest(win) {
win.gotoPref("applications");
var sel = win.history.state;
ok(sel == "applications", "Specified pane was opened");
is(sel, "paneApplications", "Specified pane was opened");
var rbox = win.document.getElementById("handlersView");
ok(rbox, "handlersView is present");

View File

@ -26,17 +26,6 @@ function runTest(win) {
}
}
//Test if tabs pane is opened correctly
win.gotoPref("paneTabs");
for (let element of elements) {
let attributeValue = element.getAttribute("data-category");
if (attributeValue == "paneTabs") {
is_element_visible(element, "Tab elements should be visible");
} else {
is_element_hidden(element, "Non-Tab elements should be hidden");
}
}
//Test if content pane is opened correctly
win.gotoPref("paneContent");
for (let element of elements) {