Bug 864895 - Catch exceptions from PopupNotification callbacks. r=MattN

This commit is contained in:
Sankha Narayan Guria 2013-06-01 08:22:16 +05:30
Родитель b808ef7069
Коммит ce12070342
2 изменённых файлов: 130 добавлений и 8 удалений

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

@ -155,6 +155,54 @@ function basicNotification() {
}
}
function errorNotification() {
var self = this;
this.browser = gBrowser.selectedBrowser;
this.id = "test-notification-" + gTestIndex;
this.message = "This is popup notification " + this.id + " from test " + gTestIndex;
this.anchorID = null;
this.mainAction = {
label: "Main Action",
accessKey: "M",
callback: function () {
self.mainActionClicked = true;
throw new Error("Oops!");
}
};
this.secondaryActions = [
{
label: "Secondary Action",
accessKey: "S",
callback: function () {
self.secondaryActionClicked = true;
throw new Error("Oops!");
}
}
];
this.options = {
eventCallback: function (eventName) {
switch (eventName) {
case "dismissed":
self.dismissalCallbackTriggered = true;
break;
case "showing":
self.showingCallbackTriggered = true;
break;
case "shown":
self.shownCallbackTriggered = true;
break;
case "removed":
self.removedCallbackTriggered = true;
break;
}
}
};
this.addOptions = function(options) {
for (let [name, value] in Iterator(options))
self.options[name] = value;
}
}
var wrongBrowserNotificationObject = new basicNotification();
var wrongBrowserNotification;
@ -831,7 +879,69 @@ var tests = [
});
}
},
{ // Test #29 - Existing popup notification shouldn't disappear when adding a dismissed notification
{ // Test #29 - Popup Notifications should catch exceptions from callbacks
run: function () {
let callbackCount = 0;
this.testNotif1 = new basicNotification();
this.testNotif1.message += " 1";
showNotification(this.testNotif1);
this.testNotif1.options.eventCallback = function (eventName) {
info("notifyObj1.options.eventCallback: " + eventName);
if (eventName == "dismissed") {
throw new Error("Oops 1!");
if (++callbackCount == 2) {
executeSoon(goNext);
}
}
};
this.testNotif2 = new basicNotification();
this.testNotif2.message += " 2";
this.testNotif2.id += "-2";
this.testNotif2.options.eventCallback = function (eventName) {
info("notifyObj2.options.eventCallback: " + eventName);
if (eventName == "dismissed") {
throw new Error("Oops 2!");
if (++callbackCount == 2) {
executeSoon(goNext);
}
}
};
showNotification(this.testNotif2);
},
onShown: function (popup) {
is(popup.childNodes.length, 2, "two notifications are shown");
dismissNotification(popup);
},
onHidden: function () {}
},
{ // Test #30 - Popup Notifications main actions should catch exceptions from callbacks
run: function () {
this.testNotif = new errorNotification();
showNotification(this.testNotif);
},
onShown: function (popup) {
checkPopup(popup, this.testNotif);
triggerMainCommand(popup);
},
onHidden: function (popup) {
ok(this.testNotif.mainActionClicked, "main action has been triggered");
}
},
{ // Test #31 - Popup Notifications secondary actions should catch exceptions from callbacks
run: function () {
this.testNotif = new errorNotification();
showNotification(this.testNotif);
},
onShown: function (popup) {
checkPopup(popup, this.testNotif);
triggerSecondaryCommand(popup, 0);
},
onHidden: function (popup) {
ok(this.testNotif.secondaryActionClicked, "secondary action has been triggered");
}
},
{ // Test #32 - Existing popup notification shouldn't disappear when adding a dismissed notification
run: function () {
this.notifyObj1 = new basicNotification();
this.notifyObj1.id += "_1";
@ -862,7 +972,7 @@ var tests = [
this.notification2.remove();
}
},
{ // Test #30 - Showing should be able to modify the popup data
{ // Test #33 - Showing should be able to modify the popup data
run: function() {
this.notifyObj = new basicNotification();
var normalCallback = this.notifyObj.options.eventCallback;

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

@ -4,9 +4,9 @@
this.EXPORTED_SYMBOLS = ["PopupNotifications"];
var Cc = Components.classes, Ci = Components.interfaces;
var Cc = Components.classes, Ci = Components.interfaces, Cu = Components.utils;
Components.utils.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/Services.jsm");
const NOTIFICATION_EVENT_DISMISSED = "dismissed";
const NOTIFICATION_EVENT_REMOVED = "removed";
@ -748,8 +748,12 @@ PopupNotifications.prototype = {
},
_fireCallback: function PopupNotifications_fireCallback(n, event) {
if (n.options.eventCallback)
n.options.eventCallback.call(n, event);
try {
if (n.options.eventCallback)
n.options.eventCallback.call(n, event);
} catch (error) {
Cu.reportError(error);
}
},
_onPopupHidden: function PopupNotifications_onPopupHidden(event) {
@ -817,7 +821,11 @@ PopupNotifications.prototype = {
timeSinceShown + "ms");
return;
}
notification.mainAction.callback.call();
try {
notification.mainAction.callback.call();
} catch(error) {
Cu.reportError(error);
}
this._remove(notification);
this._update();
@ -829,7 +837,11 @@ PopupNotifications.prototype = {
throw "menucommand target has no associated action/notification";
event.stopPropagation();
target.action.callback.call();
try {
target.action.callback.call();
} catch(error) {
Cu.reportError(error);
}
this._remove(target.notification);
this._update();