CookieCache.jsm 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. /*******************************************************************************
  2. ηMatrix - a browser extension to black/white list requests.
  3. Copyright (C) 2014-2019 The uMatrix/uBlock Origin authors
  4. Copyright (C) 2019-2022 Alessio Vanni
  5. This program is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation, either version 3 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see {http://www.gnu.org/licenses/}.
  15. Home: https://gitlab.com/vannilla/ematrix
  16. uMatrix Home: https://github.com/gorhill/uMatrix
  17. */
  18. 'use strict';
  19. Components.utils.import('chrome://ematrix/content/lib/UriTools.jsm');
  20. var EXPORTED_SYMBOLS = ['CookieCache', 'CookieUtils'];
  21. var junkyard = [];
  22. var dict = new Map();
  23. var CookieEntry = function (cookie) {
  24. this.usedOn = new Set();
  25. this.init(cookie);
  26. };
  27. CookieEntry.prototype.init = function (cookie) {
  28. this.secure = cookie.secure;
  29. this.session = cookie.session;
  30. this.anySubdomain = cookie.domain.charAt(0) === '.';
  31. this.hostname = this.anySubdomain ? cookie.domain.slice(1) : cookie.domain;
  32. this.domain = UriTools.domainFromHostname(this.hostname) || this.hostname;
  33. this.path = cookie.path;
  34. this.name = cookie.name;
  35. this.value = cookie.value;
  36. this.tstamp = Date.now();
  37. this.usedOn.clear();
  38. return this;
  39. };
  40. CookieEntry.prototype.dispose = function () {
  41. this.hostname = '';
  42. this.domain = '';
  43. this.path = '';
  44. this.name = '';
  45. this.value = '';
  46. this.usedOn.clear();
  47. return this;
  48. };
  49. var CookieUtils = {
  50. keyFromCookie: function (cookie) {
  51. let cb = [];
  52. cb[0] = cookie.secure ? 'https' : 'http';
  53. cb[1] = '://';
  54. cb[2] = cookie.domain.charAt(0) === '.' ?
  55. cookie.domain.slice(1) :
  56. cookie.domain;
  57. cb[3] = cookie.path;
  58. cb[4] = '{';
  59. cb[5] = cookie.session ? 'session' : 'persistent';
  60. cb[6] = '-cookie:';
  61. cb[7] = cookie.name;
  62. cb[8] = '}';
  63. return cb.join('');
  64. },
  65. keyFromURL: function (url, type, name) {
  66. if (typeof url !== 'object') {
  67. throw new Error('Invalid URL parameter');
  68. }
  69. let cb = [];
  70. cb[0] = url.scheme;
  71. cb[1] = '://';
  72. cb[2] = url.hostname;
  73. cb[3] = url.path;
  74. cb[4] = '{';
  75. cb[5] = type;
  76. cb[6] = '-cookie:';
  77. cb[7] = name;
  78. cb[8] = '}';
  79. return cb.join('');
  80. },
  81. urlFromEntry: function (entry) {
  82. if (!entry) {
  83. return '';
  84. }
  85. return (entry.secure ? 'https://' : 'http://')
  86. + entry.hostname
  87. + entry.path;
  88. },
  89. matchDomains: function (key, allHosts) {
  90. let entry = CookieCache.get(key);
  91. if (entry === undefined) {
  92. return false;
  93. }
  94. if (allHosts.indexOf(' '+entry.hostname+' ') < 0) {
  95. if (!entry.anySubdomain) {
  96. return false;
  97. }
  98. if (allHosts.indexOf('.'+entry.hostname+' ') < 0) {
  99. return false;
  100. }
  101. }
  102. return true;
  103. },
  104. };
  105. var CookieCache = {
  106. add: function (cookie) {
  107. let key = CookieUtils.keyFromCookie(cookie);
  108. let value = dict.get(key);
  109. if (value === undefined) {
  110. value = junkyard.pop();
  111. if (value) {
  112. value.init(cookie);
  113. } else {
  114. value = new CookieEntry(cookie);
  115. }
  116. dict.set(key, value);
  117. }
  118. return value;
  119. },
  120. addVector: function (vector) {
  121. for (let i=vector.length-1; i>=0; --i) {
  122. CookieCache.add(vector[i]);
  123. }
  124. },
  125. remove: function (cookie) {
  126. let value = dict.get(cookie);
  127. if (value === undefined) {
  128. return false;
  129. }
  130. dict.delete(cookie);
  131. if (junkyard.length < 25) {
  132. junkyard.push(value.dispose());
  133. }
  134. return true;
  135. },
  136. get: function (key) {
  137. return dict.get(key);
  138. },
  139. keys: function () {
  140. return dict.keys();
  141. }
  142. };