зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1111540 - setting app in about:preferences should also work on Windows, r=jaws
This commit is contained in:
Родитель
9342641ce7
Коммит
5c2d5eb30c
|
@ -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();
|
||||
});
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче