@freedomofpress/webcat 0.0.0-stage → 3.0.1
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/Readme.md +45 -0
- package/data/block.json +101 -0
- package/data/list.json +80 -0
- package/dist/hooks/content.js +1 -0
- package/dist/lib/browser/chrome.d.ts +86 -0
- package/dist/lib/browser/chrome.js +138 -0
- package/dist/lib/browser/kvstore.d.ts +70 -0
- package/dist/lib/browser/kvstore.js +241 -0
- package/dist/lib/browser/permissions.d.ts +113 -0
- package/dist/lib/browser/permissions.js +182 -0
- package/dist/lib/browser/requests.d.ts +145 -0
- package/dist/lib/browser/requests.js +292 -0
- package/dist/lib/browser/scripting.d.ts +19 -0
- package/dist/lib/browser/scripting.js +92 -0
- package/dist/lib/browser/sync.d.ts +68 -0
- package/dist/lib/browser/sync.js +114 -0
- package/dist/lib/browser/utils.d.ts +5 -0
- package/dist/lib/browser/utils.js +11 -0
- package/dist/lib/config.d.ts +45 -0
- package/dist/lib/config.js +45 -0
- package/dist/lib/validator_set.d.ts +4 -0
- package/dist/lib/validator_set.js +20 -0
- package/dist/lib/webcat/cache.d.ts +200 -0
- package/dist/lib/webcat/cache.js +308 -0
- package/dist/lib/webcat/canonicalize.d.ts +1 -0
- package/dist/lib/webcat/canonicalize.js +58 -0
- package/dist/lib/webcat/db.d.ts +30 -0
- package/dist/lib/webcat/db.js +131 -0
- package/dist/lib/webcat/encoding.d.ts +8 -0
- package/dist/lib/webcat/encoding.js +57 -0
- package/dist/lib/webcat/handler.d.ts +26 -0
- package/dist/lib/webcat/handler.js +419 -0
- package/dist/lib/webcat/hookbuilder.d.ts +47 -0
- package/dist/lib/webcat/hookbuilder.js +170 -0
- package/dist/lib/webcat/interfaces/bundle.d.ts +46 -0
- package/dist/lib/webcat/interfaces/bundle.js +8 -0
- package/dist/lib/webcat/interfaces/database.d.ts +68 -0
- package/dist/lib/webcat/interfaces/database.js +1 -0
- package/dist/lib/webcat/interfaces/errors.d.ts +451 -0
- package/dist/lib/webcat/interfaces/errors.js +109 -0
- package/dist/lib/webcat/interfaces/log.d.ts +14 -0
- package/dist/lib/webcat/interfaces/log.js +10 -0
- package/dist/lib/webcat/interfaces/originstate.d.ts +40 -0
- package/dist/lib/webcat/interfaces/originstate.js +1 -0
- package/dist/lib/webcat/interfaces/requeststate.d.ts +10 -0
- package/dist/lib/webcat/interfaces/requeststate.js +1 -0
- package/dist/lib/webcat/logger.d.ts +64 -0
- package/dist/lib/webcat/logger.js +112 -0
- package/dist/lib/webcat/originstate.d.ts +45 -0
- package/dist/lib/webcat/originstate.js +302 -0
- package/dist/lib/webcat/parsers.d.ts +21 -0
- package/dist/lib/webcat/parsers.js +36 -0
- package/dist/lib/webcat/request.d.ts +11 -0
- package/dist/lib/webcat/request.js +78 -0
- package/dist/lib/webcat/resources.d.ts +3 -0
- package/dist/lib/webcat/resources.js +41 -0
- package/dist/lib/webcat/response.d.ts +39 -0
- package/dist/lib/webcat/response.js +394 -0
- package/dist/lib/webcat/ui.d.ts +70 -0
- package/dist/lib/webcat/ui.js +282 -0
- package/dist/lib/webcat/updater.d.ts +115 -0
- package/dist/lib/webcat/updater.js +296 -0
- package/dist/lib/webcat/utils.d.ts +8 -0
- package/dist/lib/webcat/utils.js +74 -0
- package/dist/lib/webcat/validators.d.ts +16 -0
- package/dist/lib/webcat/validators.js +457 -0
- package/dist/lib/webcat.d.ts +11 -0
- package/dist/lib/webcat.js +130 -0
- package/icons/dark/webcat-error.SVG +1 -0
- package/icons/dark/webcat-ok.SVG +1 -0
- package/icons/dark/webcat.SVG +1 -0
- package/icons/light/webcat-error.SVG +1 -0
- package/icons/light/webcat-ok.SVG +1 -0
- package/icons/light/webcat.SVG +1 -0
- package/package.json +72 -4
- package/pages/error.css +9 -0
- package/pages/error.html +70 -0
- package/pages/error.js +51 -0
- package/pages/popup.css +16 -0
- package/pages/popup.html +14 -0
- package/pages/popup.js +48 -0
- package/README.md +0 -3
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name);
|
|
2
|
+
var __typeError = (msg) => {
|
|
3
|
+
throw TypeError(msg);
|
|
4
|
+
};
|
|
5
|
+
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
6
|
+
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
7
|
+
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
8
|
+
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
|
|
9
|
+
var __using = (stack, value, async) => {
|
|
10
|
+
if (value != null) {
|
|
11
|
+
if (typeof value !== "object" && typeof value !== "function") __typeError("Object expected");
|
|
12
|
+
var dispose, inner;
|
|
13
|
+
if (async) dispose = value[__knownSymbol("asyncDispose")];
|
|
14
|
+
if (dispose === void 0) {
|
|
15
|
+
dispose = value[__knownSymbol("dispose")];
|
|
16
|
+
if (async) inner = dispose;
|
|
17
|
+
}
|
|
18
|
+
if (typeof dispose !== "function") __typeError("Object not disposable");
|
|
19
|
+
if (inner) dispose = function() {
|
|
20
|
+
try {
|
|
21
|
+
inner.call(this);
|
|
22
|
+
} catch (e) {
|
|
23
|
+
return Promise.reject(e);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
stack.push([async, dispose, value]);
|
|
27
|
+
} else if (async) {
|
|
28
|
+
stack.push([async]);
|
|
29
|
+
}
|
|
30
|
+
return value;
|
|
31
|
+
};
|
|
32
|
+
var __callDispose = (stack, error, hasError) => {
|
|
33
|
+
var E = typeof SuppressedError === "function" ? SuppressedError : function(e, s, m, _) {
|
|
34
|
+
return _ = Error(m), _.name = "SuppressedError", _.error = e, _.suppressed = s, _;
|
|
35
|
+
};
|
|
36
|
+
var fail = (e) => error = hasError ? new E(e, error, "An error was suppressed during disposal") : (hasError = true, e);
|
|
37
|
+
var next = (it) => {
|
|
38
|
+
while (it = stack.pop()) {
|
|
39
|
+
try {
|
|
40
|
+
var result = it[1] && it[1].call(it[2]);
|
|
41
|
+
if (it[0]) return Promise.resolve(result).then(next, (e) => (fail(e), next()));
|
|
42
|
+
} catch (e) {
|
|
43
|
+
fail(e);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (hasError) throw error;
|
|
47
|
+
};
|
|
48
|
+
return next();
|
|
49
|
+
};
|
|
50
|
+
var _mutex, _namespace, _store;
|
|
51
|
+
import permissions from "./permissions.js";
|
|
52
|
+
import { Mutex } from "./sync.js";
|
|
53
|
+
var __create = Object.create;
|
|
54
|
+
var __defProp = Object.defineProperty;
|
|
55
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
56
|
+
var __knownSymbol2 = (name, symbol) => (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name);
|
|
57
|
+
var __typeError2 = (msg) => {
|
|
58
|
+
throw TypeError(msg);
|
|
59
|
+
};
|
|
60
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
61
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
62
|
+
var __decoratorStart = (base) => [, , , __create(null)];
|
|
63
|
+
var __decoratorStrings = ["class", "method", "getter", "setter", "accessor", "field", "value", "get", "set"];
|
|
64
|
+
var __expectFn = (fn) => fn !== void 0 && typeof fn !== "function" ? __typeError2("Function expected") : fn;
|
|
65
|
+
var __decoratorContext = (kind, name, done, metadata, fns) => ({ kind: __decoratorStrings[kind], name, metadata, addInitializer: (fn) => done._ ? __typeError2("Already initialized") : fns.push(__expectFn(fn || null)) });
|
|
66
|
+
var __decoratorMetadata = (array, target) => __defNormalProp(target, __knownSymbol2("metadata"), array[3]);
|
|
67
|
+
var __runInitializers = (array, flags, self, value) => {
|
|
68
|
+
for (var i = 0, fns = array[flags >> 1], n = fns && fns.length; i < n; i++) fns[i].call(self);
|
|
69
|
+
return value;
|
|
70
|
+
};
|
|
71
|
+
var __decorateElement = (array, flags, name, decorators, target, extra) => {
|
|
72
|
+
var it, done, ctx, k = flags & 7, p = false;
|
|
73
|
+
var j = 0;
|
|
74
|
+
var extraInitializers = array[j] || (array[j] = []);
|
|
75
|
+
var desc = k && (target = target.prototype, k < 5 && (k > 3 || !p) && __getOwnPropDesc(target, name));
|
|
76
|
+
__name(target, name);
|
|
77
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
78
|
+
ctx = __decoratorContext(k, name, done = {}, array[3], extraInitializers);
|
|
79
|
+
it = (0, decorators[i])(target, ctx), done._ = 1;
|
|
80
|
+
__expectFn(it) && (target = it);
|
|
81
|
+
}
|
|
82
|
+
return __decoratorMetadata(array, target), desc && __defProp(target, name, desc), p ? k ^ 4 ? extra : desc : target;
|
|
83
|
+
};
|
|
84
|
+
var _KVStore_decorators, _init;
|
|
85
|
+
_KVStore_decorators = [permissions.require("storage")];
|
|
86
|
+
class KVStore {
|
|
87
|
+
/**
|
|
88
|
+
* Reads a persisted value.
|
|
89
|
+
*
|
|
90
|
+
* @param key The key to read.
|
|
91
|
+
* @param area The name of the {@link browser.storage.StorageArea | storage area} to read from.
|
|
92
|
+
* @returns A Promise that resolves to the value read.
|
|
93
|
+
*/
|
|
94
|
+
async get(key, area = "local") {
|
|
95
|
+
const item = await browser.storage[area].get(key);
|
|
96
|
+
return item[key];
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Stores values.
|
|
100
|
+
*
|
|
101
|
+
* @param items An object consisting of one or more key/value pairs to store.
|
|
102
|
+
* @param area The name of the {@link browser.storage.StorageArea | storage area} to use.
|
|
103
|
+
*/
|
|
104
|
+
async set(items, area = "local") {
|
|
105
|
+
return browser.storage[area].set(items);
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Clears all values whose key matches the specified prefix.
|
|
109
|
+
*
|
|
110
|
+
* @param prefix The prefix to match against.
|
|
111
|
+
* @param area The name of the {@link browser.storage.StorageArea | storage area} to use.
|
|
112
|
+
*/
|
|
113
|
+
async clear(prefix = "", area = "local") {
|
|
114
|
+
const keys = await this.getKeys(prefix, area);
|
|
115
|
+
return browser.storage[area].remove(keys);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Retrieves a list of stored keys matching the specified prefix.
|
|
119
|
+
*
|
|
120
|
+
* @param prefix The prefix to match against.
|
|
121
|
+
* @param area The name of the {@link browser.storage.StorageArea | storage area} to read from.
|
|
122
|
+
* @returns A Promise that resolves to an array of matching keys.
|
|
123
|
+
*/
|
|
124
|
+
async getKeys(prefix = "", area = "local") {
|
|
125
|
+
let keys;
|
|
126
|
+
if (browser.storage[area]["getKeys"]) {
|
|
127
|
+
keys = await browser.storage[area].getKeys();
|
|
128
|
+
} else {
|
|
129
|
+
keys = Object.keys(await browser.storage[area].get(null));
|
|
130
|
+
}
|
|
131
|
+
return keys.filter((key) => key.startsWith(`${prefix}`));
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Clears a single persisted value.
|
|
135
|
+
*
|
|
136
|
+
* @param key The key to clear.
|
|
137
|
+
* @param area The name of the {@link browser.storage.StorageArea | storage area} to use.
|
|
138
|
+
*/
|
|
139
|
+
async remove(key, area = "local") {
|
|
140
|
+
return browser.storage[area].remove(key);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
_init = __decoratorStart();
|
|
144
|
+
KVStore = __decorateElement(_init, 0, "KVStore", _KVStore_decorators, KVStore);
|
|
145
|
+
__runInitializers(_init, 1, KVStore);
|
|
146
|
+
const _NamespacedKVStore = class _NamespacedKVStore {
|
|
147
|
+
/**
|
|
148
|
+
* @param namespace The namespace prefix to use for this store.
|
|
149
|
+
* @param store A backing {@link KVStore} instance to use for persistence.
|
|
150
|
+
*/
|
|
151
|
+
constructor(namespace, store = new KVStore()) {
|
|
152
|
+
__privateAdd(this, _mutex, new Mutex());
|
|
153
|
+
__privateAdd(this, _namespace);
|
|
154
|
+
__privateAdd(this, _store);
|
|
155
|
+
__privateSet(this, _namespace, namespace);
|
|
156
|
+
__privateSet(this, _store, store);
|
|
157
|
+
}
|
|
158
|
+
async get(key, area = "local") {
|
|
159
|
+
var _stack = [];
|
|
160
|
+
try {
|
|
161
|
+
const _lock = __using(_stack, await __privateGet(this, _mutex).acquire());
|
|
162
|
+
const namespacedKey = `${__privateGet(this, _namespace)}:${key}`;
|
|
163
|
+
return await __privateGet(this, _store).get(namespacedKey, area);
|
|
164
|
+
} catch (_) {
|
|
165
|
+
var _error = _, _hasError = true;
|
|
166
|
+
} finally {
|
|
167
|
+
__callDispose(_stack, _error, _hasError);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
async set(items, area = "local") {
|
|
171
|
+
var _stack = [];
|
|
172
|
+
try {
|
|
173
|
+
const _lock = __using(_stack, await __privateGet(this, _mutex).acquire());
|
|
174
|
+
const namespacedItems = {};
|
|
175
|
+
for (const key in items) {
|
|
176
|
+
namespacedItems[`${__privateGet(this, _namespace)}:${key}`] = items[key];
|
|
177
|
+
}
|
|
178
|
+
return await __privateGet(this, _store).set(namespacedItems, area);
|
|
179
|
+
} catch (_) {
|
|
180
|
+
var _error = _, _hasError = true;
|
|
181
|
+
} finally {
|
|
182
|
+
__callDispose(_stack, _error, _hasError);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
async clear(prefix = "", area = "local") {
|
|
186
|
+
var _stack = [];
|
|
187
|
+
try {
|
|
188
|
+
const _lock = __using(_stack, await __privateGet(this, _mutex).acquire());
|
|
189
|
+
return await __privateGet(this, _store).clear(`${__privateGet(this, _namespace)}:${prefix}`, area);
|
|
190
|
+
} catch (_) {
|
|
191
|
+
var _error = _, _hasError = true;
|
|
192
|
+
} finally {
|
|
193
|
+
__callDispose(_stack, _error, _hasError);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
async getKeys(prefix = "", area = "local") {
|
|
197
|
+
var _stack = [];
|
|
198
|
+
try {
|
|
199
|
+
const _lock = __using(_stack, await __privateGet(this, _mutex).acquire());
|
|
200
|
+
const namespacedKeys = await __privateGet(this, _store).getKeys(
|
|
201
|
+
`${__privateGet(this, _namespace)}:${prefix}`,
|
|
202
|
+
area
|
|
203
|
+
);
|
|
204
|
+
return namespacedKeys.map(
|
|
205
|
+
(key) => key.substring(__privateGet(this, _namespace).length + 1)
|
|
206
|
+
);
|
|
207
|
+
} catch (_) {
|
|
208
|
+
var _error = _, _hasError = true;
|
|
209
|
+
} finally {
|
|
210
|
+
__callDispose(_stack, _error, _hasError);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
async remove(key, area) {
|
|
214
|
+
var _stack = [];
|
|
215
|
+
try {
|
|
216
|
+
const _lock = __using(_stack, await __privateGet(this, _mutex).acquire());
|
|
217
|
+
const namespacedKey = `${__privateGet(this, _namespace)}:${key}`;
|
|
218
|
+
return await __privateGet(this, _store).remove(namespacedKey, area);
|
|
219
|
+
} catch (_) {
|
|
220
|
+
var _error = _, _hasError = true;
|
|
221
|
+
} finally {
|
|
222
|
+
__callDispose(_stack, _error, _hasError);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Creates a new subnamespace within this namespace.
|
|
227
|
+
*
|
|
228
|
+
* @param namespace A new namespace prefix to append to the existing prefix.
|
|
229
|
+
*/
|
|
230
|
+
namespace(namespace) {
|
|
231
|
+
return new _NamespacedKVStore(namespace, this);
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
_mutex = new WeakMap();
|
|
235
|
+
_namespace = new WeakMap();
|
|
236
|
+
_store = new WeakMap();
|
|
237
|
+
let NamespacedKVStore = _NamespacedKVStore;
|
|
238
|
+
export {
|
|
239
|
+
KVStore,
|
|
240
|
+
NamespacedKVStore
|
|
241
|
+
};
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The subject of a permission check. Typically a class or a method, but may
|
|
3
|
+
* also be a function or any object with a name property.
|
|
4
|
+
*/
|
|
5
|
+
export interface Subject {
|
|
6
|
+
/** The name of the subject. */
|
|
7
|
+
name: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* The `permissionerror` event. Notifies the consumer of a missing permission.
|
|
11
|
+
*/
|
|
12
|
+
export declare class PermissionErrorEvent extends Event {
|
|
13
|
+
/**
|
|
14
|
+
* The subject of the missing permission passed to the decorator returned by
|
|
15
|
+
* {@link PermissionChecker.require}.
|
|
16
|
+
*/
|
|
17
|
+
readonly subject: Subject;
|
|
18
|
+
/**
|
|
19
|
+
* The missing permission, as declared via {@link PermissionChecker.require}.
|
|
20
|
+
*/
|
|
21
|
+
readonly permission: string;
|
|
22
|
+
/** @internal */
|
|
23
|
+
constructor(subject: Subject, permission: string);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The `permissionrestored` event. Notifies the consumer of a required
|
|
27
|
+
* permission gained by a subject.
|
|
28
|
+
*/
|
|
29
|
+
export declare class PermissionRestoredEvent extends Event {
|
|
30
|
+
/** The subject that required the permission. */
|
|
31
|
+
readonly subject: Subject;
|
|
32
|
+
/**
|
|
33
|
+
* The required permission, as declared via
|
|
34
|
+
* {@link PermissionChecker.require}.
|
|
35
|
+
*/
|
|
36
|
+
readonly permission: string;
|
|
37
|
+
/** @internal */
|
|
38
|
+
constructor(subject: Subject, permission: string);
|
|
39
|
+
}
|
|
40
|
+
export interface PermissionChecker {
|
|
41
|
+
/** @group Methods */
|
|
42
|
+
addEventListener: EventTarget["addEventListener"] & ((type: "permissionerror", callback: (event: PermissionErrorEvent) => void) => void) & ((type: "permissionrestored", callback: (event: PermissionRestoredEvent) => void) => void);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Checks extension permissions and triggers warnings for missing ones. For
|
|
46
|
+
* an example, {@link PermissionChecker.require}.
|
|
47
|
+
*/
|
|
48
|
+
export declare class PermissionChecker extends EventTarget {
|
|
49
|
+
#private;
|
|
50
|
+
constructor();
|
|
51
|
+
/**
|
|
52
|
+
* Creates a decorator that checks for an extension permission. For a class
|
|
53
|
+
* or method that requires multiple permissions, use multiple decorators.
|
|
54
|
+
*
|
|
55
|
+
* Permissions are checked at declaration time, not at instantiation or call
|
|
56
|
+
* time. Permission checks are asynchronous, best-effort, and do not block
|
|
57
|
+
* any code from running.
|
|
58
|
+
*
|
|
59
|
+
* Permission warnings in the console may be suppressed by calling
|
|
60
|
+
* {@link PermissionErrorEvent.preventDefault}.
|
|
61
|
+
*
|
|
62
|
+
* @param permission The extension permission to require. May be either a
|
|
63
|
+
* {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions#api_permissions | named permission}
|
|
64
|
+
* or a {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Match_patterns | match pattern}
|
|
65
|
+
* for a {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/host_permissions | host permission}.
|
|
66
|
+
* @returns
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* import permissions from "@freedomofpress/webcat/browser/permissions";
|
|
70
|
+
*
|
|
71
|
+
* @permissions.require("webRequest")
|
|
72
|
+
* @permissions.require("webRequestBlocking")
|
|
73
|
+
* @permissions.require("https://example.com/*")
|
|
74
|
+
* class ExampleBlocker {
|
|
75
|
+
* ...
|
|
76
|
+
* }
|
|
77
|
+
*/
|
|
78
|
+
require(permission: string): (subject: Subject) => void;
|
|
79
|
+
/**
|
|
80
|
+
* Reads the required permissions for a subject. If subject is omitted,
|
|
81
|
+
* reads the required permissions across all subjects.
|
|
82
|
+
*
|
|
83
|
+
* @param subject The subject of the permissions.
|
|
84
|
+
* @returns The set of permissions declared for the subject via
|
|
85
|
+
* {@link require}, or if no subject is given, permissions across all
|
|
86
|
+
* subjects.
|
|
87
|
+
*/
|
|
88
|
+
getRequired(subject?: Subject): Set<string>;
|
|
89
|
+
/**
|
|
90
|
+
* Reads the missing permissions for a subject. If subject is omitted, reads
|
|
91
|
+
* the missing permissions across all subjects.
|
|
92
|
+
*
|
|
93
|
+
* @param subject The subject of the permissions.
|
|
94
|
+
* @returns The set of missing permissions required by the subject via
|
|
95
|
+
* {@link require}, or if no subject is given, missing permissions across
|
|
96
|
+
* all subjects.
|
|
97
|
+
*/
|
|
98
|
+
getMissing(subject?: Subject): Set<string>;
|
|
99
|
+
/**
|
|
100
|
+
* Checks the permissions of a given subject.
|
|
101
|
+
*
|
|
102
|
+
* @param subject The subject of the permissions.
|
|
103
|
+
* @returns A Promise that resolves to true if the subject has all the
|
|
104
|
+
* permissions required.
|
|
105
|
+
*/
|
|
106
|
+
check(subject: Subject): Promise<boolean>;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* The default {@link PermissionChecker} instance. For an example, see
|
|
110
|
+
* {@link PermissionChecker.require}.
|
|
111
|
+
*/
|
|
112
|
+
declare const _default: PermissionChecker;
|
|
113
|
+
export default _default;
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
var __typeError = (msg) => {
|
|
2
|
+
throw TypeError(msg);
|
|
3
|
+
};
|
|
4
|
+
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
5
|
+
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
6
|
+
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
7
|
+
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
|
|
8
|
+
var _requirements, _missing, _PermissionChecker_instances, checkOne_fn, handleAdded_fn, handleRemoved_fn;
|
|
9
|
+
class PermissionErrorEvent extends Event {
|
|
10
|
+
/** @internal */
|
|
11
|
+
constructor(subject, permission) {
|
|
12
|
+
super("permissionerror", { cancelable: true });
|
|
13
|
+
this.subject = subject;
|
|
14
|
+
this.permission = permission;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
class PermissionRestoredEvent extends Event {
|
|
18
|
+
/** @internal */
|
|
19
|
+
constructor(subject, permission) {
|
|
20
|
+
super("permissionrestored", { cancelable: true });
|
|
21
|
+
this.subject = subject;
|
|
22
|
+
this.permission = permission;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
class PermissionChecker extends EventTarget {
|
|
26
|
+
constructor() {
|
|
27
|
+
super();
|
|
28
|
+
__privateAdd(this, _PermissionChecker_instances);
|
|
29
|
+
__privateAdd(this, _requirements, /* @__PURE__ */ new Map());
|
|
30
|
+
__privateAdd(this, _missing, /* @__PURE__ */ new Map());
|
|
31
|
+
browser.permissions.onAdded.addListener(__privateMethod(this, _PermissionChecker_instances, handleAdded_fn).bind(this));
|
|
32
|
+
browser.permissions.onRemoved.addListener(__privateMethod(this, _PermissionChecker_instances, handleRemoved_fn).bind(this));
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Creates a decorator that checks for an extension permission. For a class
|
|
36
|
+
* or method that requires multiple permissions, use multiple decorators.
|
|
37
|
+
*
|
|
38
|
+
* Permissions are checked at declaration time, not at instantiation or call
|
|
39
|
+
* time. Permission checks are asynchronous, best-effort, and do not block
|
|
40
|
+
* any code from running.
|
|
41
|
+
*
|
|
42
|
+
* Permission warnings in the console may be suppressed by calling
|
|
43
|
+
* {@link PermissionErrorEvent.preventDefault}.
|
|
44
|
+
*
|
|
45
|
+
* @param permission The extension permission to require. May be either a
|
|
46
|
+
* {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions#api_permissions | named permission}
|
|
47
|
+
* or a {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Match_patterns | match pattern}
|
|
48
|
+
* for a {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/host_permissions | host permission}.
|
|
49
|
+
* @returns
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* import permissions from "@freedomofpress/webcat/browser/permissions";
|
|
53
|
+
*
|
|
54
|
+
* @permissions.require("webRequest")
|
|
55
|
+
* @permissions.require("webRequestBlocking")
|
|
56
|
+
* @permissions.require("https://example.com/*")
|
|
57
|
+
* class ExampleBlocker {
|
|
58
|
+
* ...
|
|
59
|
+
* }
|
|
60
|
+
*/
|
|
61
|
+
require(permission) {
|
|
62
|
+
return (subject) => {
|
|
63
|
+
let requirements = __privateGet(this, _requirements).get(subject);
|
|
64
|
+
if (!requirements) {
|
|
65
|
+
requirements = /* @__PURE__ */ new Set();
|
|
66
|
+
__privateGet(this, _requirements).set(subject, requirements);
|
|
67
|
+
}
|
|
68
|
+
requirements.add(permission);
|
|
69
|
+
__privateMethod(this, _PermissionChecker_instances, checkOne_fn).call(this, subject, permission);
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Reads the required permissions for a subject. If subject is omitted,
|
|
74
|
+
* reads the required permissions across all subjects.
|
|
75
|
+
*
|
|
76
|
+
* @param subject The subject of the permissions.
|
|
77
|
+
* @returns The set of permissions declared for the subject via
|
|
78
|
+
* {@link require}, or if no subject is given, permissions across all
|
|
79
|
+
* subjects.
|
|
80
|
+
*/
|
|
81
|
+
getRequired(subject) {
|
|
82
|
+
if (subject) {
|
|
83
|
+
return new Set(__privateGet(this, _requirements).get(subject));
|
|
84
|
+
}
|
|
85
|
+
return __privateGet(this, _requirements).values().reduce((all, permissions2) => {
|
|
86
|
+
return all.union(permissions2);
|
|
87
|
+
}, /* @__PURE__ */ new Set());
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Reads the missing permissions for a subject. If subject is omitted, reads
|
|
91
|
+
* the missing permissions across all subjects.
|
|
92
|
+
*
|
|
93
|
+
* @param subject The subject of the permissions.
|
|
94
|
+
* @returns The set of missing permissions required by the subject via
|
|
95
|
+
* {@link require}, or if no subject is given, missing permissions across
|
|
96
|
+
* all subjects.
|
|
97
|
+
*/
|
|
98
|
+
getMissing(subject) {
|
|
99
|
+
if (subject) {
|
|
100
|
+
return new Set(__privateGet(this, _missing).get(subject));
|
|
101
|
+
}
|
|
102
|
+
return __privateGet(this, _missing).values().reduce((all, missing) => {
|
|
103
|
+
return all.union(missing);
|
|
104
|
+
}, /* @__PURE__ */ new Set());
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Checks the permissions of a given subject.
|
|
108
|
+
*
|
|
109
|
+
* @param subject The subject of the permissions.
|
|
110
|
+
* @returns A Promise that resolves to true if the subject has all the
|
|
111
|
+
* permissions required.
|
|
112
|
+
*/
|
|
113
|
+
async check(subject) {
|
|
114
|
+
const requirements = __privateGet(this, _requirements).get(subject) ?? /* @__PURE__ */ new Set();
|
|
115
|
+
const checks = Array.from(requirements).map(
|
|
116
|
+
(r) => __privateMethod(this, _PermissionChecker_instances, checkOne_fn).call(this, subject, r)
|
|
117
|
+
);
|
|
118
|
+
const results = await Promise.all(checks);
|
|
119
|
+
return results.every((ok) => ok);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
_requirements = new WeakMap();
|
|
123
|
+
_missing = new WeakMap();
|
|
124
|
+
_PermissionChecker_instances = new WeakSet();
|
|
125
|
+
checkOne_fn = async function(subject, permission) {
|
|
126
|
+
const permissions2 = new Array();
|
|
127
|
+
const origins = new Array();
|
|
128
|
+
if (permission.includes("://") || permission === "<all_urls>") {
|
|
129
|
+
origins.push(permission);
|
|
130
|
+
} else {
|
|
131
|
+
permissions2.push(permission);
|
|
132
|
+
}
|
|
133
|
+
return browser.permissions.contains({ permissions: permissions2, origins }).then((ok) => {
|
|
134
|
+
if (ok) {
|
|
135
|
+
const missing = __privateGet(this, _missing).get(subject);
|
|
136
|
+
if (missing) {
|
|
137
|
+
if (missing.delete(permission)) {
|
|
138
|
+
const event = new PermissionRestoredEvent(subject, permission);
|
|
139
|
+
this.dispatchEvent(event);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
} else {
|
|
143
|
+
let missing = __privateGet(this, _missing).get(subject);
|
|
144
|
+
if (!missing) {
|
|
145
|
+
missing = /* @__PURE__ */ new Set();
|
|
146
|
+
__privateGet(this, _missing).set(subject, missing);
|
|
147
|
+
}
|
|
148
|
+
if (!missing.has(permission)) {
|
|
149
|
+
missing.add(permission);
|
|
150
|
+
const event = new PermissionErrorEvent(subject, permission);
|
|
151
|
+
this.dispatchEvent(event);
|
|
152
|
+
if (!event.defaultPrevented) {
|
|
153
|
+
console.warn(
|
|
154
|
+
"Extension permission requirements not fulfilled for %s. The '%s' permission is required.",
|
|
155
|
+
subject.name,
|
|
156
|
+
permission
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return ok;
|
|
162
|
+
});
|
|
163
|
+
};
|
|
164
|
+
handleAdded_fn = function() {
|
|
165
|
+
for (const [subject, set] of __privateGet(this, _missing)) {
|
|
166
|
+
if (set.size > 0) {
|
|
167
|
+
this.check(subject);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
handleRemoved_fn = function() {
|
|
172
|
+
for (const [subject, _] of __privateGet(this, _requirements)) {
|
|
173
|
+
this.check(subject);
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
const permissions = new PermissionChecker();
|
|
177
|
+
export {
|
|
178
|
+
PermissionChecker,
|
|
179
|
+
PermissionErrorEvent,
|
|
180
|
+
PermissionRestoredEvent,
|
|
181
|
+
permissions as default
|
|
182
|
+
};
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/** @internal */
|
|
2
|
+
export declare class RequestDetailsBase {
|
|
3
|
+
#private;
|
|
4
|
+
/**
|
|
5
|
+
* Resolved when the request completes or rejected if a network error occurs.
|
|
6
|
+
*/
|
|
7
|
+
readonly completed: Promise<void>;
|
|
8
|
+
constructor();
|
|
9
|
+
/** @internal */
|
|
10
|
+
complete(): void;
|
|
11
|
+
/** @internal */
|
|
12
|
+
fail(): void;
|
|
13
|
+
}
|
|
14
|
+
/** @interface */
|
|
15
|
+
export type BeforeRequestDetails = RequestDetailsBase & browser.webRequest._OnBeforeRequestDetails;
|
|
16
|
+
/** @interface */
|
|
17
|
+
export type BeforeHeadersDetails = BeforeRequestDetails & browser.webRequest._OnBeforeSendHeadersDetails;
|
|
18
|
+
/** @interface */
|
|
19
|
+
export type HeadersReceivedDetails = BeforeHeadersDetails & browser.webRequest._OnHeadersReceivedDetails;
|
|
20
|
+
/** @interface */
|
|
21
|
+
export type ErrorOccurredDetails = BeforeRequestDetails & browser.webRequest._OnErrorOccurredDetails;
|
|
22
|
+
/** @interface */
|
|
23
|
+
export type CompletedDetails = HeadersReceivedDetails & browser.webRequest._OnCompletedDetails;
|
|
24
|
+
export type RequestDetails = BeforeHeadersDetails | BeforeHeadersDetails | HeadersReceivedDetails | ErrorOccurredDetails | CompletedDetails;
|
|
25
|
+
declare const dispose: typeof Symbol.dispose;
|
|
26
|
+
/**
|
|
27
|
+
* The response of a single listener to a blocking {@link RequestEvent},
|
|
28
|
+
* created with {@link RequestEvent.createBlockingResponse}. Implements the
|
|
29
|
+
* {@link Disposable} interface. A new BlockingResponse cancels the request;
|
|
30
|
+
* a listener signals successful completion by setting {@link cancel} to
|
|
31
|
+
* false, either by assigning to it directly or with the {@link set} method.
|
|
32
|
+
* A listener must create it with a
|
|
33
|
+
* {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/using using declaration}
|
|
34
|
+
* before its first await expression; the response is reported on disposal.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* handler.addEventListener("beforeheaders", async (event) => {
|
|
38
|
+
* using blockingResponse = event.createBlockingResponse();
|
|
39
|
+
* await doSomething(event.details);
|
|
40
|
+
* blockingResponse.cancel = false;
|
|
41
|
+
* });
|
|
42
|
+
*/
|
|
43
|
+
export declare class BlockingResponse implements browser.webRequest.BlockingResponse, Disposable {
|
|
44
|
+
#private;
|
|
45
|
+
/**
|
|
46
|
+
* Whether to cancel the request. Defaults to true, so that a listener that
|
|
47
|
+
* throws, or never completes its checks, cancels the request. Set to false
|
|
48
|
+
* to signal successful completion.
|
|
49
|
+
*/
|
|
50
|
+
cancel: boolean | undefined;
|
|
51
|
+
redirectUrl?: string | undefined;
|
|
52
|
+
upgradeToSecure?: boolean | undefined;
|
|
53
|
+
requestHeaders?: browser.webRequest.HttpHeaders | undefined;
|
|
54
|
+
responseHeaders?: browser.webRequest.HttpHeaders | undefined;
|
|
55
|
+
authCredentials?: browser.webRequest._BlockingResponseAuthCredentials | undefined;
|
|
56
|
+
constructor(details?: RequestDetails);
|
|
57
|
+
/**
|
|
58
|
+
* Implements the {@link Disposable} interface.
|
|
59
|
+
*/
|
|
60
|
+
[dispose](): void;
|
|
61
|
+
/**
|
|
62
|
+
* @returns A Promise that resolves to this BlockingResponse after disposal.
|
|
63
|
+
*/
|
|
64
|
+
ready(): Promise<BlockingResponse>;
|
|
65
|
+
/**
|
|
66
|
+
* @param value An object whose properties are copied to this BlockingResponse.
|
|
67
|
+
*/
|
|
68
|
+
set(value: browser.webRequest.BlockingResponse): void;
|
|
69
|
+
/**
|
|
70
|
+
* Sets the response header `name` to `value`, replacing any existing
|
|
71
|
+
* occurrences. Starts from the response's original headers, so the rest
|
|
72
|
+
* pass through unchanged.
|
|
73
|
+
*/
|
|
74
|
+
setHeader(name: string, value: string): void;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Event type for events dispatched by RequestHandlers.
|
|
78
|
+
*/
|
|
79
|
+
export declare class RequestEvent<T extends RequestDetails> extends Event {
|
|
80
|
+
#private;
|
|
81
|
+
/**
|
|
82
|
+
* Details of the request this event concerns.
|
|
83
|
+
*/
|
|
84
|
+
readonly details: T;
|
|
85
|
+
/** @internal */
|
|
86
|
+
constructor(type: string, details: T);
|
|
87
|
+
/**
|
|
88
|
+
* Creates a {@link BlockingResponse} for this event. Each listener creates
|
|
89
|
+
* its own before its first await expression, so that listeners respond
|
|
90
|
+
* independently of each other; see {@link ready} for how the responses are
|
|
91
|
+
* combined.
|
|
92
|
+
*
|
|
93
|
+
* @returns A new BlockingResponse that cancels the request unless the
|
|
94
|
+
* listener sets {@link BlockingResponse.cancel} to false.
|
|
95
|
+
*/
|
|
96
|
+
createBlockingResponse(): BlockingResponse;
|
|
97
|
+
/**
|
|
98
|
+
* Awaits all BlockingResponses created for this event and merges them into
|
|
99
|
+
* a single response. If any of them cancels the request, so does the
|
|
100
|
+
* result; otherwise, their other properties are combined. With no
|
|
101
|
+
* BlockingResponses, the request proceeds unchanged.
|
|
102
|
+
*
|
|
103
|
+
* @returns A Promise that resolves to the merged response.
|
|
104
|
+
* @internal
|
|
105
|
+
*/
|
|
106
|
+
ready(): Promise<browser.webRequest.BlockingResponse>;
|
|
107
|
+
}
|
|
108
|
+
export interface RequestHandler extends EventTarget {
|
|
109
|
+
/** @group Methods */
|
|
110
|
+
addEventListener: EventTarget["addEventListener"] & ((type: "beforerequest", callback: (event: RequestEvent<BeforeRequestDetails>) => void) => void) & ((type: "beforeheaders", callback: (event: RequestEvent<BeforeHeadersDetails>) => void) => void) & ((type: "headersreceived", callback: (event: RequestEvent<HeadersReceivedDetails>) => void) => void) & ((type: "erroroccurred", callback: (event: RequestEvent<ErrorOccurredDetails>) => void) => void) & ((type: "completed", callback: (event: RequestEvent<CompletedDetails>) => void) => void);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Handles web requests and responses for specific FQDNs. Manages the entire
|
|
114
|
+
* lifecycle of a request and aggregates details such as request headers and
|
|
115
|
+
* response headers to make them available in later stages.
|
|
116
|
+
*/
|
|
117
|
+
export declare class RequestHandler extends EventTarget {
|
|
118
|
+
#private;
|
|
119
|
+
/**
|
|
120
|
+
* Binds the handler to the given list of FQDNs. When called, the handler
|
|
121
|
+
* starts handling requests for the FQDNs in the list and stops handling
|
|
122
|
+
* requests for any previously bound FQDNs that are not in the new list.
|
|
123
|
+
*
|
|
124
|
+
* @param fqdns A list of fully-qualified domain names to bind to.
|
|
125
|
+
*/
|
|
126
|
+
bind(fqdns: string[]): void;
|
|
127
|
+
/** @internal */
|
|
128
|
+
protected getListenerOptions(fqdns: string[], type: "beforerequest"): [browser.webRequest.RequestFilter, browser.webRequest.OnBeforeRequestOptions[]];
|
|
129
|
+
/** @internal */
|
|
130
|
+
protected getListenerOptions(fqdns: string[], type: "beforeheaders"): [browser.webRequest.RequestFilter, browser.webRequest.OnBeforeSendHeadersOptions[]];
|
|
131
|
+
/** @internal */
|
|
132
|
+
protected getListenerOptions(fqdns: string[], type: "headersreceived"): [browser.webRequest.RequestFilter, browser.webRequest.OnHeadersReceivedOptions[]];
|
|
133
|
+
/** @internal */
|
|
134
|
+
protected getListenerOptions(fqdns: string[], type: "erroroccurred" | "completed"): [browser.webRequest.RequestFilter];
|
|
135
|
+
/**
|
|
136
|
+
* Returns a tuple consisting of a request filter and an optional options
|
|
137
|
+
* array, used when registering webRequest listeners. Overriding this method
|
|
138
|
+
* allows changing the registration behavior.
|
|
139
|
+
*
|
|
140
|
+
* @param fqdns Fully-qualified domain names to handle requests for.
|
|
141
|
+
* @param type The type of event to handle.
|
|
142
|
+
*/
|
|
143
|
+
protected getListenerOptions(fqdns: string[], type: string): [browser.webRequest.RequestFilter] | [browser.webRequest.RequestFilter, (browser.webRequest.OnBeforeRequestOptions[] | browser.webRequest.OnBeforeSendHeadersOptions[] | browser.webRequest.OnHeadersReceivedOptions[])];
|
|
144
|
+
}
|
|
145
|
+
export {};
|