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

This commit is contained in:
Gijs Kruitbosch 2015-01-23 17:55:56 +00:00
Родитель 9342641ce7
Коммит 5c2d5eb30c
4 изменённых файлов: 197 добавлений и 47 удалений

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

@ -1506,16 +1506,21 @@ var gApplicationsPane = {
}
// Create a menu item for selecting a local application.
let canOpenWithOtherApp = true;
#ifdef XP_WIN
// On Windows, selecting an application to open another application
// 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");
if (handlerInfo.type != executableType)
canOpenWithOtherApp = handlerInfo.type != executableType;
#endif
if (canOpenWithOtherApp)
{
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");
menuItem.setAttribute("label", label);
menuItem.setAttribute("tooltiptext", label);
@ -1527,7 +1532,10 @@ var gApplicationsPane = {
let menuItem = document.createElement("menuseparator");
menuPopup.appendChild(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"));
menuPopup.appendChild(menuItem);
}
@ -1700,20 +1708,23 @@ var gApplicationsPane = {
var typeItem = this._list.selectedItem;
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",
"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) {
@ -1762,17 +1773,20 @@ var gApplicationsPane = {
params.filename = 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",
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
let winTitle = this._prefsBundle.getString("fpTitleChooseApp");
let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);

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

@ -10,6 +10,8 @@ support-files =
[browser_bug795764_cachedisabled.js]
[browser_bug1018066_resetScrollPosition.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_bug388287.js]
[browser_healthreport.js]

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

@ -0,0 +1,110 @@
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);
}
function promisePopupEvent(popup, ev) {
return new Promise((resolve, reject) => {
popup.addEventListener(ev, () => {
popup.removeEventListener(ev, arguments.callee);
resolve();
}, false);
});
}
add_task(function*() {
setupFakeHandler();
yield openPreferencesViaOpenPreferencesAPI("applications", null, {leaveOpen: true});
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"));
let popup = list.firstChild;
let popupShownPromise = promisePopupEvent(popup, "popupshown");
list.boxObject.openMenu(true);
yield popupShownPromise;
let dialogLoadedPromise = promiseLoadSubDialog("chrome://global/content/appPicker.xul");
let popupHiddenPromise = promisePopupEvent(popup, "popuphidden");
let chooseItem = popup.querySelector(".choose-app-item");
chooseItem.click();
popup.hidePopup(); // Not clear why we need to do this manually, but we do. :-\
yield popupHiddenPromise;
let dialog = yield dialogLoadedPromise;
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"));
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:
popup = list.firstChild;
popupShownPromise = promisePopupEvent(popup, "popupshown");
list.boxObject.openMenu(true);
yield popupShownPromise;
dialogLoadedPromise = promiseLoadSubDialog("chrome://browser/content/preferences/applicationManager.xul");
popupHiddenPromise = promisePopupEvent(popup, "popuphidden");
let manageItem = popup.querySelector(".manage-app-item");
manageItem.click();
popup.hidePopup();
yield popupHiddenPromise;
dialog = yield dialogLoadedPromise;
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);
});

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

@ -39,35 +39,38 @@ function open_preferences(aCallback) {
}
function openAndLoadSubDialog(aURL, aFeatures = null, aParams = null, aClosingCallback = null) {
let dialog = content.gSubDialog.open(aURL, aFeatures, aParams, aClosingCallback);
let deferred = Promise.defer();
let promise = promiseLoadSubDialog(aURL);
content.gSubDialog.open(aURL, aFeatures, aParams, aClosingCallback);
return promise;
}
content.gSubDialog._frame.addEventListener("load", function load(aEvent) {
if (aEvent.target.contentWindow.location == "about:blank")
return;
content.gSubDialog._frame.removeEventListener("load", load);
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);
ise(content.gSubDialog._frame.contentWindow.location.toString(), aURL,
"Check the proper URL is loaded");
ise(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 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);
// 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);
}
}
}
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;
}
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();
});
}