The base .eslintrc is essentially a merge of the root Toolkit .eslintrc and the devtools .eslintrc, with some minor changes to match our prevalent style. For the most enforces the coding styles that we've been using most consistently. There are a couple of significant differences, though: * The rule for opening brace alignment can only be applied globally, and doesn't make exceptions for top-level functions. I chose to turn it on, and change the brace style of existing top-level functions that violated it, since the rule seemed worth using, and that's the direction most Toolkit JS code has been headed anyway. * The rule for switch/case statements requires an added indentation level for case statements. Most of our switch statements did not use an extra level of indentation, and I initially wrote the rule to enforce that style, until I came across case statements that used blocks, and required the extra indentation level for sanity.
149 lines
4.1 KiB
JavaScript
149 lines
4.1 KiB
JavaScript
"use strict";
|
|
|
|
var { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
|
|
|
Cu.import("resource://gre/modules/ExtensionUtils.jsm");
|
|
var {
|
|
EventManager,
|
|
ignoreEvent,
|
|
runSafe,
|
|
} = ExtensionUtils;
|
|
|
|
// WeakMap[Extension -> Set[Notification]]
|
|
var notificationsMap = new WeakMap();
|
|
|
|
// WeakMap[Extension -> Set[callback]]
|
|
var notificationCallbacksMap = new WeakMap();
|
|
|
|
// Manages a notification popup (notifications API) created by the extension.
|
|
function Notification(extension, id, options) {
|
|
this.extension = extension;
|
|
this.id = id;
|
|
this.options = options;
|
|
|
|
let imageURL;
|
|
if (options.iconUrl) {
|
|
imageURL = this.extension.baseURI.resolve(options.iconUrl);
|
|
}
|
|
|
|
try {
|
|
let svc = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService);
|
|
svc.showAlertNotification(imageURL,
|
|
options.title,
|
|
options.message,
|
|
false, // textClickable
|
|
this.id,
|
|
this,
|
|
this.id);
|
|
} catch (e) {
|
|
// This will fail if alerts aren't available on the system.
|
|
}
|
|
}
|
|
|
|
Notification.prototype = {
|
|
clear() {
|
|
try {
|
|
let svc = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService);
|
|
svc.closeAlert(this.id);
|
|
} catch (e) {
|
|
// This will fail if the OS doesn't support this function.
|
|
}
|
|
notificationsMap.get(this.extension).delete(this);
|
|
},
|
|
|
|
observe(subject, topic, data) {
|
|
if (topic != "alertfinished") {
|
|
return;
|
|
}
|
|
|
|
for (let callback in notificationCallbacksMap.get(this.extension)) {
|
|
callback(this);
|
|
}
|
|
|
|
notificationsMap.get(this.extension).delete(this);
|
|
},
|
|
};
|
|
|
|
/* eslint-disable mozilla/balanced-listeners */
|
|
extensions.on("startup", (type, extension) => {
|
|
notificationsMap.set(extension, new Set());
|
|
notificationCallbacksMap.set(extension, new Set());
|
|
});
|
|
|
|
extensions.on("shutdown", (type, extension) => {
|
|
for (let notification of notificationsMap.get(extension)) {
|
|
notification.clear();
|
|
}
|
|
notificationsMap.delete(extension);
|
|
notificationCallbacksMap.delete(extension);
|
|
});
|
|
/* eslint-enable mozilla/balanced-listeners */
|
|
|
|
var nextId = 0;
|
|
|
|
extensions.registerPrivilegedAPI("notifications", (extension, context) => {
|
|
return {
|
|
notifications: {
|
|
create: function(...args) {
|
|
let notificationId, options, callback;
|
|
if (args.length == 1) {
|
|
options = args[0];
|
|
} else {
|
|
[notificationId, options, callback] = args;
|
|
}
|
|
|
|
if (!notificationId) {
|
|
notificationId = nextId++;
|
|
}
|
|
|
|
// FIXME: Lots of options still aren't supported, especially
|
|
// buttons.
|
|
let notification = new Notification(extension, notificationId, options);
|
|
notificationsMap.get(extension).add(notification);
|
|
|
|
if (callback) {
|
|
runSafe(context, callback, notificationId);
|
|
}
|
|
},
|
|
|
|
clear: function(notificationId, callback) {
|
|
let notifications = notificationsMap.get(extension);
|
|
let cleared = false;
|
|
for (let notification of notifications) {
|
|
if (notification.id == notificationId) {
|
|
notification.clear();
|
|
cleared = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (callback) {
|
|
runSafe(context, callback, cleared);
|
|
}
|
|
},
|
|
|
|
getAll: function(callback) {
|
|
let notifications = notificationsMap.get(extension);
|
|
notifications = notifications.map(notification => notification.id);
|
|
runSafe(context, callback, notifications);
|
|
},
|
|
|
|
onClosed: new EventManager(context, "notifications.onClosed", fire => {
|
|
let listener = notification => {
|
|
// FIXME: Support the byUser argument.
|
|
fire(notification.id, true);
|
|
};
|
|
|
|
notificationCallbacksMap.get(extension).add(listener);
|
|
return () => {
|
|
notificationCallbacksMap.get(extension).delete(listener);
|
|
};
|
|
}).api(),
|
|
|
|
// FIXME
|
|
onButtonClicked: ignoreEvent(context, "notifications.onButtonClicked"),
|
|
onClicked: ignoreEvent(context, "notifications.onClicked"),
|
|
},
|
|
};
|
|
});
|