michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: "use strict"; michael@0: michael@0: module.metadata = { michael@0: "stability": "stable" michael@0: }; michael@0: michael@0: const { Cc, Ci, Cr } = require("chrome"); michael@0: const apiUtils = require("./deprecated/api-utils"); michael@0: const errors = require("./deprecated/errors"); michael@0: const { isString, isUndefined, instanceOf } = require('./lang/type'); michael@0: const { URL } = require('./url'); michael@0: michael@0: const NOTIFICATION_DIRECTIONS = ["auto", "ltr", "rtl"]; michael@0: michael@0: try { michael@0: let alertServ = Cc["@mozilla.org/alerts-service;1"]. michael@0: getService(Ci.nsIAlertsService); michael@0: michael@0: // The unit test sets this to a mock notification function. michael@0: var notify = alertServ.showAlertNotification.bind(alertServ); michael@0: } michael@0: catch (err) { michael@0: // An exception will be thrown if the platform doesn't provide an alert michael@0: // service, e.g., if Growl is not installed on OS X. In that case, use a michael@0: // mock notification function that just logs to the console. michael@0: notify = notifyUsingConsole; michael@0: } michael@0: michael@0: exports.notify = function notifications_notify(options) { michael@0: let valOpts = validateOptions(options); michael@0: let clickObserver = !valOpts.onClick ? null : { michael@0: observe: function notificationClickObserved(subject, topic, data) { michael@0: if (topic === "alertclickcallback") michael@0: errors.catchAndLog(valOpts.onClick).call(exports, valOpts.data); michael@0: } michael@0: }; michael@0: function notifyWithOpts(notifyFn) { michael@0: notifyFn(valOpts.iconURL, valOpts.title, valOpts.text, !!clickObserver, michael@0: valOpts.data, clickObserver, valOpts.tag, valOpts.dir, valOpts.lang); michael@0: } michael@0: try { michael@0: notifyWithOpts(notify); michael@0: } michael@0: catch (err) { michael@0: if (err instanceof Ci.nsIException && err.result == Cr.NS_ERROR_FILE_NOT_FOUND) { michael@0: console.warn("The notification icon named by " + valOpts.iconURL + michael@0: " does not exist. A default icon will be used instead."); michael@0: delete valOpts.iconURL; michael@0: notifyWithOpts(notify); michael@0: } michael@0: else { michael@0: notifyWithOpts(notifyUsingConsole); michael@0: } michael@0: } michael@0: }; michael@0: michael@0: function notifyUsingConsole(iconURL, title, text) { michael@0: title = title ? "[" + title + "]" : ""; michael@0: text = text || ""; michael@0: let str = [title, text].filter(function (s) s).join(" "); michael@0: console.log(str); michael@0: } michael@0: michael@0: function validateOptions(options) { michael@0: return apiUtils.validateOptions(options, { michael@0: data: { michael@0: is: ["string", "undefined"] michael@0: }, michael@0: iconURL: { michael@0: is: ["string", "undefined", "object"], michael@0: ok: function(value) { michael@0: return isUndefined(value) || isString(value) || (value instanceof URL); michael@0: }, michael@0: msg: "`iconURL` must be a string or an URL instance." michael@0: }, michael@0: onClick: { michael@0: is: ["function", "undefined"] michael@0: }, michael@0: text: { michael@0: is: ["string", "undefined", "number"] michael@0: }, michael@0: title: { michael@0: is: ["string", "undefined", "number"] michael@0: }, michael@0: tag: { michael@0: is: ["string", "undefined", "number"] michael@0: }, michael@0: dir: { michael@0: is: ["string", "undefined"], michael@0: ok: function(value) { michael@0: return isUndefined(value) || ~NOTIFICATION_DIRECTIONS.indexOf(value); michael@0: }, michael@0: msg: '`dir` option must be one of: "auto", "ltr" or "rtl".' michael@0: }, michael@0: lang: { michael@0: is: ["string", "undefined"] michael@0: } michael@0: }); michael@0: }