1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
'use strict';
{
let listenersMap = new Map();
let backlog = new Set();
let stopAndReload = beforeReloading => {
debug("Should I reload? %o, now: %s", performance.now())
if (location.href === "about:blank" || performance.now() > 10000 ) {
debug("Won't reload.");
return;
}
stop();
setTimeout(() => {
debug("Reloading...");
if (typeof beforeReloading === "function") {
beforeReloading();
}
location.reload();
}, 1000)
};
let ns = {
debug: true, // DEV_ONLY
get embeddingDocument() {
delete this.embeddingDocument;
return this.embeddingDocument = CSP.isEmbedType(document.contentType);
},
on(eventName, listener) {
let listeners = listenersMap.get(eventName);
if (!listeners) listenersMap.set(eventName, listeners = new Set());
listeners.add(listener);
if (backlog.has(eventName)) this.fire(eventName, listener);
},
detach(eventName, listener) {
let listeners = listenersMap.get(eventName);
if (listeners) listeners.delete(listener);
},
fire(eventName, listener = null) {
if (listener) {
listener({type:eventName, source: this});
return;
}
let listeners = listenersMap.get(eventName);
if (listeners) {
for (let l of listeners) {
this.fire(eventName, l);
}
}
backlog.add(eventName);
},
fetchPolicy() {
debug(`Fetching policy from document %s, readyState %s, content %s`,
document.URL, document.readyState, document.documentElement.outerHTML);
let url = document.URL;
let isFileUrl = url.startsWith("file:");
if (isFileUrl) {
let cookie = "noscript.startupFileReloaded=true";
if (!document.cookie.split(/\s*;\s*/).includes(cookie)) {
stopAndReload(() => document.cookie = cookie);
}
}
let policy = browser.runtime.sendSyncMessage(
{id: "fetchPolicy", url, contextUrl: url});
debug("Fetched %o, readyState %s", policy, document.readyState);
if (!policy) {
debug("Could not fetch policy!");
if (isFileUrl && !sessionStorage.__noScriptFallbackReload__) {
sessionStorage.__noScriptFallbackReload__ = "true";
stopAndReload();
}
// let's try asynchronously
(async () => {
this.setup(await Messages.send("fetchPolicy", {url, contextUrl: url}));
})();
return false;
} else if (policy.fallback) {
stopAndReload();
}
this.setup(policy);
return true;
},
setup(policy) {
debug("%s, %s, %o", document.URL, document.readyState, policy);
this.policy = policy;
if (!policy.permissions || policy.unrestricted) {
this.allows = () => true;
this.capabilities = Object.assign(
new Set(["script"]), { has() { return true; } });
} else {
let perms = policy.permissions;
this.capabilities = new Set(perms.capabilities);
new DocumentCSP(document).apply(this.capabilities, this.embeddingDocument);
}
this.canScript = this.allows("script");
this.fire("capabilities");
},
policy: null,
allows(cap) {
return this.capabilities && this.capabilities.has(cap);
},
getWindowName() {
return window.name;
}
};
if (this.ns) {
this.ns.merge(ns);
} else {
this.ns = ns;
}
}
|