@ohos-ports/cross-storage 1.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +176 -0
- package/README.md +325 -0
- package/dist/client.js +465 -0
- package/dist/client.min.js +11 -0
- package/dist/hub.js +279 -0
- package/dist/hub.min.js +11 -0
- package/lib/client.js +629 -0
- package/lib/hub.js +299 -0
- package/lib/index.js +4 -0
- package/package.json +41 -0
package/lib/hub.js
ADDED
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
;(function(root) {
|
|
2
|
+
var CrossStorageHub = {};
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* In Node.js/OHOS in-process mode, _storage holds a localStorage-compatible
|
|
6
|
+
* object. When set, all hub methods use this instead of window.localStorage.
|
|
7
|
+
*
|
|
8
|
+
* @private
|
|
9
|
+
*/
|
|
10
|
+
CrossStorageHub._storage = null;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Returns the active storage backend. Uses _storage if set (in-process mode),
|
|
14
|
+
* otherwise falls back to window.localStorage (browser mode).
|
|
15
|
+
*
|
|
16
|
+
* @private
|
|
17
|
+
* @returns {object} localStorage-compatible storage
|
|
18
|
+
*/
|
|
19
|
+
CrossStorageHub._getStorage = function() {
|
|
20
|
+
if (CrossStorageHub._storage) {
|
|
21
|
+
return CrossStorageHub._storage;
|
|
22
|
+
}
|
|
23
|
+
return window.localStorage;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Accepts an array of objects with two keys: origin and allow. The value
|
|
28
|
+
* of origin is expected to be a RegExp, and allow, an array of strings.
|
|
29
|
+
* The cross storage hub is then initialized to accept requests from any of
|
|
30
|
+
* the matching origins, allowing access to the associated lists of methods.
|
|
31
|
+
* Methods may include any of: get, set, del, getKeys and clear. A 'ready'
|
|
32
|
+
* message is sent to the parent window once complete.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* // Subdomain can get, but only root domain can set and del
|
|
36
|
+
* CrossStorageHub.init([
|
|
37
|
+
* {origin: /\.example.com$/, allow: ['get']},
|
|
38
|
+
* {origin: /:(www\.)?example.com$/, allow: ['get', 'set', 'del']}
|
|
39
|
+
* ]);
|
|
40
|
+
*
|
|
41
|
+
* @param {array} permissions An array of objects with origin and allow
|
|
42
|
+
*/
|
|
43
|
+
CrossStorageHub.init = function(permissions) {
|
|
44
|
+
// In-process mode: skip browser checks
|
|
45
|
+
if (CrossStorageHub._storage) {
|
|
46
|
+
CrossStorageHub._permissions = permissions || [];
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
var available = true;
|
|
51
|
+
|
|
52
|
+
// Return if localStorage is unavailable, or third party
|
|
53
|
+
// access is disabled
|
|
54
|
+
try {
|
|
55
|
+
if (!window.localStorage) available = false;
|
|
56
|
+
} catch (e) {
|
|
57
|
+
available = false;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (!available) {
|
|
61
|
+
try {
|
|
62
|
+
return window.parent.postMessage('cross-storage:unavailable', '*');
|
|
63
|
+
} catch (e) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
CrossStorageHub._permissions = permissions || [];
|
|
69
|
+
CrossStorageHub._installListener();
|
|
70
|
+
window.parent.postMessage('cross-storage:ready', '*');
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Installs the necessary listener for the window message event. Accommodates
|
|
75
|
+
* IE8 and up.
|
|
76
|
+
*
|
|
77
|
+
* @private
|
|
78
|
+
*/
|
|
79
|
+
CrossStorageHub._installListener = function() {
|
|
80
|
+
var listener = CrossStorageHub._listener;
|
|
81
|
+
if (window.addEventListener) {
|
|
82
|
+
window.addEventListener('message', listener, false);
|
|
83
|
+
} else {
|
|
84
|
+
window.attachEvent('onmessage', listener);
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* The message handler for all requests posted to the window. It ignores any
|
|
90
|
+
* messages having an origin that does not match the originally supplied
|
|
91
|
+
* pattern. Given a JSON object with one of get, set, del or getKeys as the
|
|
92
|
+
* method, the function performs the requested action and returns its result.
|
|
93
|
+
*
|
|
94
|
+
* @param {MessageEvent} message A message to be processed
|
|
95
|
+
*/
|
|
96
|
+
CrossStorageHub._listener = function(message) {
|
|
97
|
+
var origin, targetOrigin, request, method, error, result, response;
|
|
98
|
+
|
|
99
|
+
// postMessage returns the string "null" as the origin for "file://"
|
|
100
|
+
origin = (message.origin === 'null') ? 'file://' : message.origin;
|
|
101
|
+
|
|
102
|
+
// Handle polling for a ready message
|
|
103
|
+
if (message.data === 'cross-storage:poll') {
|
|
104
|
+
return window.parent.postMessage('cross-storage:ready', message.origin);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Ignore the ready message when viewing the hub directly
|
|
108
|
+
if (message.data === 'cross-storage:ready') return;
|
|
109
|
+
|
|
110
|
+
// Check whether message.data is a valid json
|
|
111
|
+
try {
|
|
112
|
+
request = JSON.parse(message.data);
|
|
113
|
+
} catch (err) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Check whether request.method is a string
|
|
118
|
+
if (!request || typeof request.method !== 'string') {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
method = request.method.split('cross-storage:')[1];
|
|
123
|
+
|
|
124
|
+
if (!method) {
|
|
125
|
+
return;
|
|
126
|
+
} else if (!CrossStorageHub._permitted(origin, method)) {
|
|
127
|
+
error = 'Invalid permissions for ' + method;
|
|
128
|
+
} else {
|
|
129
|
+
try {
|
|
130
|
+
result = CrossStorageHub['_' + method](request.params);
|
|
131
|
+
} catch (err) {
|
|
132
|
+
error = err.message;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
response = JSON.stringify({
|
|
137
|
+
id: request.id,
|
|
138
|
+
error: error,
|
|
139
|
+
result: result
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
// postMessage requires that the target origin be set to "*" for "file://"
|
|
143
|
+
targetOrigin = (origin === 'file://') ? '*' : origin;
|
|
144
|
+
|
|
145
|
+
window.parent.postMessage(response, targetOrigin);
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Returns a boolean indicating whether or not the requested method is
|
|
150
|
+
* permitted for the given origin. The argument passed to method is expected
|
|
151
|
+
* to be one of 'get', 'set', 'del' or 'getKeys'.
|
|
152
|
+
*
|
|
153
|
+
* @param {string} origin The origin for which to determine permissions
|
|
154
|
+
* @param {string} method Requested action
|
|
155
|
+
* @returns {bool} Whether or not the request is permitted
|
|
156
|
+
*/
|
|
157
|
+
CrossStorageHub._permitted = function(origin, method) {
|
|
158
|
+
var available, i, entry, match;
|
|
159
|
+
|
|
160
|
+
available = ['get', 'set', 'del', 'clear', 'getKeys'];
|
|
161
|
+
if (!CrossStorageHub._inArray(method, available)) {
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
for (i = 0; i < CrossStorageHub._permissions.length; i++) {
|
|
166
|
+
entry = CrossStorageHub._permissions[i];
|
|
167
|
+
if (!(entry.origin instanceof RegExp) || !(entry.allow instanceof Array)) {
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
match = entry.origin.test(origin);
|
|
172
|
+
if (match && CrossStorageHub._inArray(method, entry.allow)) {
|
|
173
|
+
return true;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return false;
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Sets a key to the specified value.
|
|
182
|
+
*
|
|
183
|
+
* @param {object} params An object with key and value
|
|
184
|
+
*/
|
|
185
|
+
CrossStorageHub._set = function(params) {
|
|
186
|
+
CrossStorageHub._getStorage().setItem(params.key, params.value);
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Accepts an object with an array of keys for which to retrieve their values.
|
|
191
|
+
* Returns a single value if only one key was supplied, otherwise it returns
|
|
192
|
+
* an array. Any keys not set result in a null element in the resulting array.
|
|
193
|
+
*
|
|
194
|
+
* @param {object} params An object with an array of keys
|
|
195
|
+
* @returns {*|*[]} Either a single value, or an array
|
|
196
|
+
*/
|
|
197
|
+
CrossStorageHub._get = function(params) {
|
|
198
|
+
var storage, result, i, value;
|
|
199
|
+
|
|
200
|
+
storage = CrossStorageHub._getStorage();
|
|
201
|
+
result = [];
|
|
202
|
+
|
|
203
|
+
for (i = 0; i < params.keys.length; i++) {
|
|
204
|
+
try {
|
|
205
|
+
value = storage.getItem(params.keys[i]);
|
|
206
|
+
} catch (e) {
|
|
207
|
+
value = null;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
result.push(value);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return (result.length > 1) ? result : result[0];
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Deletes all keys specified in the array found at params.keys.
|
|
218
|
+
*
|
|
219
|
+
* @param {object} params An object with an array of keys
|
|
220
|
+
*/
|
|
221
|
+
CrossStorageHub._del = function(params) {
|
|
222
|
+
var storage = CrossStorageHub._getStorage();
|
|
223
|
+
for (var i = 0; i < params.keys.length; i++) {
|
|
224
|
+
storage.removeItem(params.keys[i]);
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Clears localStorage.
|
|
230
|
+
*/
|
|
231
|
+
CrossStorageHub._clear = function() {
|
|
232
|
+
CrossStorageHub._getStorage().clear();
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Returns an array of all keys stored in localStorage.
|
|
237
|
+
*
|
|
238
|
+
* @returns {string[]} The array of keys
|
|
239
|
+
*/
|
|
240
|
+
CrossStorageHub._getKeys = function(params) {
|
|
241
|
+
var i, length, keys, storage;
|
|
242
|
+
|
|
243
|
+
storage = CrossStorageHub._getStorage();
|
|
244
|
+
keys = [];
|
|
245
|
+
length = storage.length;
|
|
246
|
+
|
|
247
|
+
for (i = 0; i < length; i++) {
|
|
248
|
+
keys.push(storage.key(i));
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
return keys;
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Returns whether or not a value is present in the array. Consists of an
|
|
256
|
+
* alternative to extending the array prototype for indexOf, since it's
|
|
257
|
+
* unavailable for IE8.
|
|
258
|
+
*
|
|
259
|
+
* @param {*} value The value to find
|
|
260
|
+
* @parma {[]*} array The array in which to search
|
|
261
|
+
* @returns {bool} Whether or not the value was found
|
|
262
|
+
*/
|
|
263
|
+
CrossStorageHub._inArray = function(value, array) {
|
|
264
|
+
for (var i = 0; i < array.length; i++) {
|
|
265
|
+
if (value === array[i]) return true;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
return false;
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* A cross-browser version of Date.now compatible with IE8 that avoids
|
|
273
|
+
* modifying the Date object.
|
|
274
|
+
*
|
|
275
|
+
* @return {int} The current timestamp in milliseconds
|
|
276
|
+
*/
|
|
277
|
+
CrossStorageHub._now = function() {
|
|
278
|
+
if (typeof Date.now === 'function') {
|
|
279
|
+
return Date.now();
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
return new Date().getTime();
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Export for various environments.
|
|
287
|
+
*/
|
|
288
|
+
if (typeof module !== 'undefined' && module.exports) {
|
|
289
|
+
module.exports = CrossStorageHub;
|
|
290
|
+
} else if (typeof exports !== 'undefined') {
|
|
291
|
+
exports.CrossStorageHub = CrossStorageHub;
|
|
292
|
+
} else if (typeof define === 'function' && define.amd) {
|
|
293
|
+
define([], function() {
|
|
294
|
+
return CrossStorageHub;
|
|
295
|
+
});
|
|
296
|
+
} else {
|
|
297
|
+
root.CrossStorageHub = CrossStorageHub;
|
|
298
|
+
}
|
|
299
|
+
}(typeof global !== 'undefined' ? global : this));
|
package/lib/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ohos-ports/cross-storage",
|
|
3
|
+
"version": "1.0.0-beta.0",
|
|
4
|
+
"description": "Cross domain local storage",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"local",
|
|
7
|
+
"storage",
|
|
8
|
+
"cross",
|
|
9
|
+
"domain"
|
|
10
|
+
],
|
|
11
|
+
"main": "lib/index.js",
|
|
12
|
+
"author": "Daniel St. Jules <danielst.jules@gmail.com>",
|
|
13
|
+
"license": "Apache-2.0",
|
|
14
|
+
"homepage": "https://github.com/zendesk/cross-storage",
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "https://github.com/ohos-ports/ohos-ports.git",
|
|
18
|
+
"directory": "ports/cross-storage/1.0.0"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"connect": "^2.25.7",
|
|
22
|
+
"expect.js": "^0.3.1",
|
|
23
|
+
"gulp": "*",
|
|
24
|
+
"gulp-header": "^1.1.1",
|
|
25
|
+
"gulp-jshint": "^1.8.4",
|
|
26
|
+
"gulp-rename": "^1.2.0",
|
|
27
|
+
"gulp-rimraf": "^0.1.0",
|
|
28
|
+
"gulp-uglify": "^0.3.1",
|
|
29
|
+
"serve-static": "^1.5.3",
|
|
30
|
+
"zuul": "~3.10.1"
|
|
31
|
+
},
|
|
32
|
+
"scripts": {
|
|
33
|
+
"test": "node test/ohos-test.js",
|
|
34
|
+
"saucetest": "./node_modules/.bin/zuul --ui mocha-bdd -- test/test.js"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {},
|
|
37
|
+
"files": [
|
|
38
|
+
"lib/",
|
|
39
|
+
"dist/"
|
|
40
|
+
]
|
|
41
|
+
}
|