PageSourceSearch

https://maketime.online/lib/hub.js

js maketime.online collected 2026-09-24 14:05:44 UTC 7,785 bytes, 269 lines download raw bytes

vendor: 7,785 bytes, lines 1-269
1;(function(root) {
2  var CrossStorageHub = {};
3
4  /**
5   * Accepts an array of objects with two keys: origin and allow. The value
6   * of origin is expected to be a RegExp, and allow, an array of strings.
7   * The cross storage hub is then initialized to accept requests from any of
8   * the matching origins, allowing access to the associated lists of methods.
9   * Methods may include any of: get, set, del, getKeys and clear. A 'ready'
10   * message is sent to the parent window once complete.
11   *
12   * @example
13   * // Subdomain can get, but only root domain can set and del
14   * CrossStorageHub.init([
15   *   {origin: /\.example.com$/,        allow: ['get']},
16   *   {origin: /:(www\.)?example.com$/, allow: ['get', 'set', 'del']}
17   * ]);
18   *
19   * @param {array} permissions An array of objects with origin and allow
20   */
21  CrossStorageHub.init = function(permissions) {
22    var available = true;
23
24    // Return if localStorage is unavailable, or third party
25    // access is disabled
26    try {
27      if (!window.localStorage) available = false;
28    } catch (e) {
29      available = false;
30    }
31
32    if (!available) {
33      try {
34        return window.parent.postMessage('cross-storage:unavailable', '*');
35      } catch (e) {
36        return;
37      }
38    }
39
40    CrossStorageHub._permissions = permissions || [];
41    CrossStorageHub._installListener();
42    window.parent.postMessage('cross-storage:ready', '*');
43  };
44
45  /**
46   * Installs the necessary listener for the window message event. Accommodates
47   * IE8 and up.
48   *
49   * @private
50   */
51  CrossStorageHub._installListener = function() {
52    var listener = CrossStorageHub._listener;
53    if (window.addEventListener) {
54      window.addEventListener('message', listener, false);
55    } else {
56      window.attachEvent('onmessage', listener);
57    }
58  };
59
60  /**
61   * The message handler for all requests posted to the window. It ignores any
62   * messages having an origin that does not match the originally supplied
63   * pattern. Given a JSON object with one of get, set, del or getKeys as the
64   * method, the function performs the requested action and returns its result.
65   *
66   * @param {MessageEvent} message A message to be processed
67   */
68  CrossStorageHub._listener = function(message) {
69    var origin, targetOrigin, request, method, error, result, response;
70
71    // postMessage returns the string "null" as the origin for "file://"
72    origin = (message.origin === 'null') ? 'file://' : message.origin;
73
74    // Handle polling for a ready message
75    if (message.data === 'cross-storage:poll') {
76      return window.parent.postMessage('cross-storage:ready', message.origin);
77    }
78
79    // Ignore the ready message when viewing the hub directly
80    if (message.data === 'cross-storage:ready') return;
81
82    // Check whether message.data is a valid json
83    try {
84      request = JSON.parse(message.data);
85    } catch (err) {
86      return;
87    }
88
89    // Check whether request.method is a string
90    if (!request || typeof request.method !== 'string') {
91      return;
92    }
93
94    method = request.method.split('cross-storage:')[1];
95
96    if (!method) {
97      return;
98    } else if (!CrossStorageHub._permitted(origin, method)) {
99      error = 'Invalid permissions for ' + method;
100    } else {
101      try {
102        result = CrossStorageHub['_' + method](request.params);
103      } catch (err) {
104        error = err.message;
105      }
106    }
107
108    response = JSON.stringify({
109      id: request.id,
110      error: error,
111      result: result
112    });
113
114    // postMessage requires that the target origin be set to "*" for "file://"
115    targetOrigin = (origin === 'file://') ? '*' : origin;
116
117    window.parent.postMessage(response, targetOrigin);
118  };
119
120  /**
121   * Returns a boolean indicating whether or not the requested method is
122   * permitted for the given origin. The argument passed to method is expected
123   * to be one of 'get', 'set', 'del' or 'getKeys'.
124   *
125   * @param   {string} origin The origin for which to determine permissions
126   * @param   {string} method Requested action
127   * @returns {bool}   Whether or not the request is permitted
128   */
129  CrossStorageHub._permitted = function(origin, method) {
130    var available, i, entry, match;
131
132    available = ['get', 'set', 'del', 'clear', 'getKeys'];
133    if (!CrossStorageHub._inArray(method, available)) {
134      return false;
135    }
136
137    for (i = 0; i < CrossStorageHub._permissions.length; i++) {
138      entry = CrossStorageHub._permissions[i];
139      if (!(entry.origin instanceof RegExp) || !(entry.allow instanceof Array)) {
140        continue;
141      }
142
143      match = entry.origin.test(origin);
144      if (match && CrossStorageHub._inArray(method, entry.allow)) {
145        return true;
146      }
147    }
148
149    return false;
150  };
151
152  /**
153   * Sets a key to the specified value.
154   *
155   * @param {object} params An object with key and value
156   */
157  CrossStorageHub._set = function(params) {
158    window.localStorage.setItem(params.key, params.value);
159  };
160
161  /**
162   * Accepts an object with an array of keys for which to retrieve their values.
163   * Returns a single value if only one key was supplied, otherwise it returns
164   * an array. Any keys not set result in a null element in the resulting array.
165   *
166   * @param   {object} params An object with an array of keys
167   * @returns {*|*[]}  Either a single value, or an array
168   */
169  CrossStorageHub._get = function(params) {
170    var storage, result, i, value;
171
172    storage = window.localStorage;
173    result = [];
174
175    for (i = 0; i < params.keys.length; i++) {
176      try {
177        value = storage.getItem(params.keys[i]);
178      } catch (e) {
179        value = null;
180      }
181
182      result.push(value);
183    }
184
185    return (result.length > 1) ? result : result[0];
186  };
187
188  /**
189   * Deletes all keys specified in the array found at params.keys.
190   *
191   * @param {object} params An object with an array of keys
192   */
193  CrossStorageHub._del = function(params) {
194    for (var i = 0; i < params.keys.length; i++) {
195      window.localStorage.removeItem(params.keys[i]);
196    }
197  };
198
199  /**
200   * Clears localStorage.
201   */
202  CrossStorageHub._clear = function() {
203    window.localStorage.clear();
204  };
205
206  /**
207   * Returns an array of all keys stored in localStorage.
208   *
209   * @returns {string[]} The array of keys
210   */
211  CrossStorageHub._getKeys = function(params) {
212    var i, length, keys;
213
214    keys = [];
215    length = window.localStorage.length;
216
217    for (i = 0; i < length; i++) {
218      keys.push(window.localStorage.key(i));
219    }
220
221    return keys;
222  };
223
224  /**
225   * Returns whether or not a value is present in the array. Consists of an
226   * alternative to extending the array prototype for indexOf, since it's
227   * unavailable for IE8.
228   *
229   * @param   {*}    value The value to find
230   * @parma   {[]*}  array The array in which to search
231   * @returns {bool} Whether or not the value was found
232   */
233  CrossStorageHub._inArray = function(value, array) {
234    for (var i = 0; i < array.length; i++) {
235      if (value === array[i]) return true;
236    }
237
238    return false;
239  };
240
241  /**
242   * A cross-browser version of Date.now compatible with IE8 that avoids
243   * modifying the Date object.
244   *
245   * @return {int} The current timestamp in milliseconds
246   */
247  CrossStorageHub._now = function() {
248    if (typeof Date.now === 'function') {
249      return Date.now();
250    }
251
252    return new Date().getTime();
253  };
254
255  /**
256   * Export for various environments.
257   */
258  if (typeof module !== 'undefined' && module.exports) {
259    module.exports = CrossStorageHub;
260  } else if (typeof exports !== 'undefined') {
261    exports.CrossStorageHub = CrossStorageHub;
262  } else if (typeof define === 'function' && define.amd) {
263    define([], function() {
264      return CrossStorageHub;
265    });
266  } else {
267    root.CrossStorageHub = CrossStorageHub;
268  }
269}(this));

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.