xul-app.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  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": "experimental"
  7. };
  8. var { Cc, Ci } = require("chrome");
  9. var appInfo = Cc["@mozilla.org/xre/app-info;1"]
  10. .getService(Ci.nsIXULAppInfo);
  11. var vc = Cc["@mozilla.org/xpcom/version-comparator;1"]
  12. .getService(Ci.nsIVersionComparator);
  13. var ID = exports.ID = appInfo.ID;
  14. var name = exports.name = appInfo.name;
  15. var version = exports.version = appInfo.version;
  16. var platformVersion = exports.platformVersion = appInfo.platformVersion;
  17. // The following mapping of application names to GUIDs was taken from:
  18. //
  19. // https://addons.mozilla.org/en-US/firefox/pages/appversions
  20. //
  21. // Using the GUID instead of the app's name is preferable because sometimes
  22. // re-branded versions of a product have different names: for instance,
  23. // Firefox, Minefield, Iceweasel, and Shiretoko all have the same
  24. // GUID.
  25. // This mapping is duplicated in `app-extensions/bootstrap.js`. They should keep
  26. // in sync, so if you change one, change the other too!
  27. var ids = exports.ids = {
  28. Firefox: "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}",
  29. Mozilla: "{86c18b42-e466-45a9-ae7a-9b95ba6f5640}",
  30. Sunbird: "{718e30fb-e89b-41dd-9da7-e25a45638b28}",
  31. SeaMonkey: "{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}",
  32. Fennec: "{aa3c5121-dab2-40e2-81ca-7ea25febc110}",
  33. Thunderbird: "{3550f703-e582-4d05-9a08-453d09bdfdc6}"
  34. };
  35. function is(name) {
  36. if (!(name in ids))
  37. throw new Error("Unkown Mozilla Application: " + name);
  38. return ID == ids[name];
  39. };
  40. exports.is = is;
  41. function isOneOf(names) {
  42. for (var i = 0; i < names.length; i++)
  43. if (is(names[i]))
  44. return true;
  45. return false;
  46. };
  47. exports.isOneOf = isOneOf;
  48. /**
  49. * Use this to check whether the given version (e.g. xulApp.platformVersion)
  50. * is in the given range. Versions must be in version comparator-compatible
  51. * format. See MDC for details:
  52. * https://developer.mozilla.org/en/XPCOM_Interface_Reference/nsIVersionComparator
  53. */
  54. var versionInRange = exports.versionInRange =
  55. function versionInRange(version, lowInclusive, highExclusive) {
  56. return (vc.compare(version, lowInclusive) >= 0) &&
  57. (vc.compare(version, highExclusive) < 0);
  58. }
  59. const reVersionRange = /^((?:<|>)?=?)?\s*((?:\d+[\S]*)|\*)(?:\s+((?:<|>)=?)?(\d+[\S]+))?$/;
  60. const reOnlyInifinity = /^[<>]?=?\s*[*x]$/;
  61. const reSubInfinity = /\.[*x]/g;
  62. const reHyphenRange = /^(\d+.*?)\s*-\s*(\d+.*?)$/;
  63. const reRangeSeparator = /\s*\|\|\s*/;
  64. const compares = {
  65. "=": function (c) { return c === 0 },
  66. ">=": function (c) { return c >= 0 },
  67. "<=": function (c) { return c <= 0},
  68. "<": function (c) { return c < 0 },
  69. ">": function (c) { return c > 0 }
  70. }
  71. function normalizeRange(range) {
  72. return range
  73. .replace(reOnlyInifinity, "")
  74. .replace(reSubInfinity, ".*")
  75. .replace(reHyphenRange, ">=$1 <=$2")
  76. }
  77. /**
  78. * Compare the versions given, using the comparison operator provided.
  79. * Internal use only.
  80. *
  81. * @example
  82. * compareVersion("1.2", "<=", "1.*") // true
  83. *
  84. * @param {String} version
  85. * A version to compare
  86. *
  87. * @param {String} comparison
  88. * The comparison operator
  89. *
  90. * @param {String} compareVersion
  91. * A version to compare
  92. */
  93. function compareVersion(version, comparison, compareVersion) {
  94. let hasWildcard = compareVersion.indexOf("*") !== -1;
  95. comparison = comparison || "=";
  96. if (hasWildcard) {
  97. switch (comparison) {
  98. case "=":
  99. let zeroVersion = compareVersion.replace(reSubInfinity, ".0");
  100. return versionInRange(version, zeroVersion, compareVersion);
  101. case ">=":
  102. compareVersion = compareVersion.replace(reSubInfinity, ".0");
  103. break;
  104. }
  105. }
  106. let compare = compares[comparison];
  107. return typeof compare === "function" && compare(vc.compare(version, compareVersion));
  108. }
  109. /**
  110. * Returns `true` if `version` satisfies the `versionRange` given.
  111. * If only an argument is passed, is used as `versionRange` and compared against
  112. * `xulApp.platformVersion`.
  113. *
  114. * `versionRange` is either a string which has one or more space-separated
  115. * descriptors, or a range like "fromVersion - toVersion".
  116. * Version range descriptors may be any of the following styles:
  117. *
  118. * - "version" Must match `version` exactly
  119. * - "=version" Same as just `version`
  120. * - ">version" Must be greater than `version`
  121. * - ">=version" Must be greater or equal than `version`
  122. * - "<version" Must be less than `version`
  123. * - "<=version" Must be less or equal than `version`
  124. * - "1.2.x" or "1.2.*" See 'X version ranges' below
  125. * - "*" or "" (just an empty string) Matches any version
  126. * - "version1 - version2" Same as ">=version1 <=version2"
  127. * - "range1 || range2" Passes if either `range1` or `range2` are satisfied
  128. *
  129. * For example, these are all valid:
  130. * - "1.0.0 - 2.9999.9999"
  131. * - ">=1.0.2 <2.1.2"
  132. * - ">1.0.2 <=2.3.4"
  133. * - "2.0.1"
  134. * - "<1.0.0 || >=2.3.1 <2.4.5 || >=2.5.2 <3.0.0"
  135. * - "2.x" (equivalent to "2.*")
  136. * - "1.2.x" (equivalent to "1.2.*" and ">=1.2.0 <1.3.0")
  137. */
  138. function satisfiesVersion(version, versionRange) {
  139. if (arguments.length === 1) {
  140. versionRange = version;
  141. version = appInfo.version;
  142. }
  143. let ranges = versionRange.trim().split(reRangeSeparator);
  144. return ranges.some(function(range) {
  145. range = normalizeRange(range);
  146. // No versions' range specified means that any version satisfies the
  147. // requirements.
  148. if (range === "")
  149. return true;
  150. let matches = range.match(reVersionRange);
  151. if (!matches)
  152. return false;
  153. let [, lowMod, lowVer, highMod, highVer] = matches;
  154. return compareVersion(version, lowMod, lowVer) && (highVer !== undefined
  155. ? compareVersion(version, highMod, highVer)
  156. : true);
  157. });
  158. }
  159. exports.satisfiesVersion = satisfiesVersion;