Bug 1111540 - setting app in about:preferences should also work on Windows, r=jaws

--HG--
extra : rebase_source : 05e101a18517676c5c4f8835cf88c91b0406c413
This commit is contained in:
Gijs Kruitbosch 2015-01-23 17:55:56 +00:00
parent aa60e627f2
commit b59232dc0f
4 changed files with 179 additions and 47 deletions

View File

@ -1506,16 +1506,21 @@ var gApplicationsPane = {
} }
// Create a menu item for selecting a local application. // Create a menu item for selecting a local application.
let canOpenWithOtherApp = true;
#ifdef XP_WIN #ifdef XP_WIN
// On Windows, selecting an application to open another application // On Windows, selecting an application to open another application
// would be meaningless so we special case executables. // would be meaningless so we special case executables.
var executableType = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService) let executableType = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService)
.getTypeFromExtension("exe"); .getTypeFromExtension("exe");
if (handlerInfo.type != executableType) canOpenWithOtherApp = handlerInfo.type != executableType;
#endif #endif
if (canOpenWithOtherApp)
{ {
let menuItem = document.createElement("menuitem"); let menuItem = document.createElement("menuitem");
menuItem.setAttribute("oncommand", "gApplicationsPane.chooseApp(event)"); menuItem.className = "choose-app-item";
menuItem.addEventListener("command", function(e) {
gApplicationsPane.chooseApp(e);
});
let label = this._prefsBundle.getString("useOtherApp"); let label = this._prefsBundle.getString("useOtherApp");
menuItem.setAttribute("label", label); menuItem.setAttribute("label", label);
menuItem.setAttribute("tooltiptext", label); menuItem.setAttribute("tooltiptext", label);
@ -1527,7 +1532,10 @@ var gApplicationsPane = {
let menuItem = document.createElement("menuseparator"); let menuItem = document.createElement("menuseparator");
menuPopup.appendChild(menuItem); menuPopup.appendChild(menuItem);
menuItem = document.createElement("menuitem"); menuItem = document.createElement("menuitem");
menuItem.setAttribute("oncommand", "gApplicationsPane.manageApp(event)"); menuItem.className = "manage-app-item";
menuItem.addEventListener("command", function(e) {
gApplicationsPane.manageApp(e);
});
menuItem.setAttribute("label", this._prefsBundle.getString("manageApp")); menuItem.setAttribute("label", this._prefsBundle.getString("manageApp"));
menuPopup.appendChild(menuItem); menuPopup.appendChild(menuItem);
} }
@ -1700,20 +1708,23 @@ var gApplicationsPane = {
var typeItem = this._list.selectedItem; var typeItem = this._list.selectedItem;
var handlerInfo = this._handledTypes[typeItem.type]; var handlerInfo = this._handledTypes[typeItem.type];
let onComplete = () => {
// Rebuild the actions menu so that we revert to the previous selection,
// or "Always ask" if the previous default application has been removed
this.rebuildActionsMenu();
// update the richlistitem too. Will be visible when selecting another row
typeItem.setAttribute("actionDescription",
this._describePreferredAction(handlerInfo));
if (!this._setIconClassForPreferredAction(handlerInfo, typeItem)) {
typeItem.setAttribute("actionIcon",
this._getIconURLForPreferredAction(handlerInfo));
}
};
gSubDialog.open("chrome://browser/content/preferences/applicationManager.xul", gSubDialog.open("chrome://browser/content/preferences/applicationManager.xul",
"resizable=no", handlerInfo); "resizable=no", handlerInfo, onComplete);
// Rebuild the actions menu so that we revert to the previous selection,
// or "Always ask" if the previous default application has been removed
this.rebuildActionsMenu();
// update the richlistitem too. Will be visible when selecting another row
typeItem.setAttribute("actionDescription",
this._describePreferredAction(handlerInfo));
if (!this._setIconClassForPreferredAction(handlerInfo, typeItem)) {
typeItem.setAttribute("actionIcon",
this._getIconURLForPreferredAction(handlerInfo));
}
}, },
chooseApp: function(aEvent) { chooseApp: function(aEvent) {
@ -1762,17 +1773,20 @@ var gApplicationsPane = {
params.filename = null; params.filename = null;
params.handlerApp = null; params.handlerApp = null;
let onAppSelected = () => {
if (this.isValidHandlerApp(params.handlerApp)) {
handlerApp = params.handlerApp;
// Add the app to the type's list of possible handlers.
handlerInfo.addPossibleApplicationHandler(handlerApp);
}
chooseAppCallback(handlerApp);
};
gSubDialog.open("chrome://global/content/appPicker.xul", gSubDialog.open("chrome://global/content/appPicker.xul",
null, params); null, params, onAppSelected);
if (this.isValidHandlerApp(params.handlerApp)) {
handlerApp = params.handlerApp;
// Add the app to the type's list of possible handlers.
handlerInfo.addPossibleApplicationHandler(handlerApp);
}
chooseAppCallback(handlerApp);
#else #else
let winTitle = this._prefsBundle.getString("fpTitleChooseApp"); let winTitle = this._prefsBundle.getString("fpTitleChooseApp");
let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker); let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);

View File

@ -10,6 +10,8 @@ support-files =
[browser_bug795764_cachedisabled.js] [browser_bug795764_cachedisabled.js]
[browser_bug1018066_resetScrollPosition.js] [browser_bug1018066_resetScrollPosition.js]
[browser_bug1020245_openPreferences_to_paneContent.js] [browser_bug1020245_openPreferences_to_paneContent.js]
[browser_change_app_handler.js]
run-if = os == "win" # This test tests the windows-specific app selection dialog, so can't run on non-Windows
[browser_connection.js] [browser_connection.js]
[browser_connection_bug388287.js] [browser_connection_bug388287.js]
[browser_healthreport.js] [browser_healthreport.js]

View File

@ -0,0 +1,92 @@
let gMimeSvc = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
let gHandlerSvc = Cc["@mozilla.org/uriloader/handler-service;1"].getService(Ci.nsIHandlerService);
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");
chooseItem.click();
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");
manageItem.click();
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);
});

View File

@ -39,35 +39,38 @@ function open_preferences(aCallback) {
} }
function openAndLoadSubDialog(aURL, aFeatures = null, aParams = null, aClosingCallback = null) { function openAndLoadSubDialog(aURL, aFeatures = null, aParams = null, aClosingCallback = null) {
let dialog = content.gSubDialog.open(aURL, aFeatures, aParams, aClosingCallback); let promise = promiseLoadSubDialog(aURL);
let deferred = Promise.defer(); content.gSubDialog.open(aURL, aFeatures, aParams, aClosingCallback);
return promise;
}
content.gSubDialog._frame.addEventListener("load", function load(aEvent) { function promiseLoadSubDialog(aURL) {
if (aEvent.target.contentWindow.location == "about:blank") return new Promise((resolve, reject) => {
return; content.gSubDialog._frame.addEventListener("load", function load(aEvent) {
content.gSubDialog._frame.removeEventListener("load", load); if (aEvent.target.contentWindow.location == "about:blank")
return;
content.gSubDialog._frame.removeEventListener("load", load);
ise(content.gSubDialog._frame.contentWindow.location.toString(), aURL, ise(content.gSubDialog._frame.contentWindow.location.toString(), aURL,
"Check the proper URL is loaded"); "Check the proper URL is loaded");
// Check visibility // Check visibility
is_element_visible(content.gSubDialog._overlay, "Overlay is visible"); is_element_visible(content.gSubDialog._overlay, "Overlay is visible");
// Check that stylesheets were injected // Check that stylesheets were injected
let expectedStyleSheetURLs = content.gSubDialog._injectedStyleSheets.slice(0); let expectedStyleSheetURLs = content.gSubDialog._injectedStyleSheets.slice(0);
for (let styleSheet of content.gSubDialog._frame.contentDocument.styleSheets) { for (let styleSheet of content.gSubDialog._frame.contentDocument.styleSheets) {
let i = expectedStyleSheetURLs.indexOf(styleSheet.href); let i = expectedStyleSheetURLs.indexOf(styleSheet.href);
if (i >= 0) { if (i >= 0) {
info("found " + styleSheet.href); info("found " + styleSheet.href);
expectedStyleSheetURLs.splice(i, 1); expectedStyleSheetURLs.splice(i, 1);
}
} }
} ise(expectedStyleSheetURLs.length, 0, "All expectedStyleSheetURLs should have been found");
ise(expectedStyleSheetURLs.length, 0, "All expectedStyleSheetURLs should have been found");
deferred.resolve(dialog); resolve(content.gSubDialog._frame.contentWindow);
});
}); });
return deferred.promise;
} }
/** /**
@ -139,3 +142,24 @@ function openPreferencesViaOpenPreferencesAPI(aPane, aAdvancedTab, aOptions) {
return deferred.promise; 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();
});
}