notifications.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  4. "use strict";
  5. module.metadata = {
  6. "stability": "stable"
  7. };
  8. const { Cc, Ci, Cr } = require("chrome");
  9. const apiUtils = require("./deprecated/api-utils");
  10. const errors = require("./deprecated/errors");
  11. const { isString, isUndefined, instanceOf } = require('./lang/type');
  12. const { URL } = require('./url');
  13. const NOTIFICATION_DIRECTIONS = ["auto", "ltr", "rtl"];
  14. try {
  15. let alertServ = Cc["@mozilla.org/alerts-service;1"].
  16. getService(Ci.nsIAlertsService);
  17. // The unit test sets this to a mock notification function.
  18. var notify = alertServ.showAlertNotification.bind(alertServ);
  19. }
  20. catch (err) {
  21. // An exception will be thrown if the platform doesn't provide an alert
  22. // service, e.g., if Growl is not installed on OS X. In that case, use a
  23. // mock notification function that just logs to the console.
  24. notify = notifyUsingConsole;
  25. }
  26. exports.notify = function notifications_notify(options) {
  27. let valOpts = validateOptions(options);
  28. let clickObserver = !valOpts.onClick ? null : {
  29. observe: function notificationClickObserved(subject, topic, data) {
  30. if (topic === "alertclickcallback")
  31. errors.catchAndLog(valOpts.onClick).call(exports, valOpts.data);
  32. }
  33. };
  34. function notifyWithOpts(notifyFn) {
  35. notifyFn(valOpts.iconURL, valOpts.title, valOpts.text, !!clickObserver,
  36. valOpts.data, clickObserver, valOpts.tag, valOpts.dir, valOpts.lang);
  37. }
  38. try {
  39. notifyWithOpts(notify);
  40. }
  41. catch (err if err instanceof Ci.nsIException &&
  42. err.result == Cr.NS_ERROR_FILE_NOT_FOUND) {
  43. console.warn("The notification icon named by " + valOpts.iconURL +
  44. " does not exist. A default icon will be used instead.");
  45. delete valOpts.iconURL;
  46. notifyWithOpts(notify);
  47. }
  48. catch (err) {
  49. notifyWithOpts(notifyUsingConsole);
  50. }
  51. };
  52. function notifyUsingConsole(iconURL, title, text) {
  53. title = title ? "[" + title + "]" : "";
  54. text = text || "";
  55. let str = [title, text].filter(function (s) s).join(" ");
  56. console.log(str);
  57. }
  58. function validateOptions(options) {
  59. return apiUtils.validateOptions(options, {
  60. data: {
  61. is: ["string", "undefined"]
  62. },
  63. iconURL: {
  64. is: ["string", "undefined", "object"],
  65. ok: function(value) {
  66. return isUndefined(value) || isString(value) || (value instanceof URL);
  67. },
  68. msg: "`iconURL` must be a string or an URL instance."
  69. },
  70. onClick: {
  71. is: ["function", "undefined"]
  72. },
  73. text: {
  74. is: ["string", "undefined", "number"]
  75. },
  76. title: {
  77. is: ["string", "undefined", "number"]
  78. },
  79. tag: {
  80. is: ["string", "undefined", "number"]
  81. },
  82. dir: {
  83. is: ["string", "undefined"],
  84. ok: function(value) {
  85. return isUndefined(value) || ~NOTIFICATION_DIRECTIONS.indexOf(value);
  86. },
  87. msg: '`dir` option must be one of: "auto", "ltr" or "rtl".'
  88. },
  89. lang: {
  90. is: ["string", "undefined"]
  91. }
  92. });
  93. }