forked from greasemonkey/greasemonkey
-
Notifications
You must be signed in to change notification settings - Fork 1
/
on-user-script-xhr.js
122 lines (106 loc) · 3.19 KB
/
on-user-script-xhr.js
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
121
122
/*
This file is responsible for providing the GM.xmlHttpRequest API method. It
listens for a connection on a Port, and
*/
// Private implementation.
(function() {
function onUserScriptXhr(port) {
if (port.name != 'UserScriptXhr') return;
let xhr = new XMLHttpRequest();
port.onMessage.addListener(msg => {
switch (msg.name) {
case 'open': open(xhr, msg.details, port); break;
default:
console.warn('UserScriptXhr port un-handled message name:', msg.name);
}
});
}
chrome.runtime.onConnect.addListener(onUserScriptXhr);
function open(xhr, d, port) {
function xhrEventHandler(src, event) {
console.log('xhr event;', src, event);
var responseState = {
context: d.context || null,
finalUrl: null,
lengthComputable: null,
loaded: null,
readyState: xhr.readyState,
response: xhr.response,
responseHeaders: null,
responseText: null,
responseXML: null,
status: null,
statusText: null,
total: null
};
try {
responseState.responseText = xhr.responseText;
} catch (e) {
// Some response types don't have .responseText (but do have e.g. blob
// .response). Ignore.
}
var responseXML = null;
try {
responseXML = xhr.responseXML;
} catch (e) {
// Ignore failure. At least in responseType blob case, this access fails.
}
switch (event.type) {
case "progress":
responseState.lengthComputable = evt.lengthComputable;
responseState.loaded = evt.loaded;
responseState.total = evt.total;
break;
case "error":
console.log('error event?', event);
break;
default:
if (4 != xhr.readyState) break;
responseState.responseHeaders = xhr.getAllResponseHeaders();
responseState.status = xhr.status;
responseState.statusText = xhr.statusText;
break;
}
port.postMessage(
{src: src, type: event.type, responseState: responseState});
}
[
'abort', 'error', 'load', 'loadend', 'loadstart', 'progress',
'readystatechange', 'timeout'
].forEach(v => {
if (d['on' + v]) {
xhr.addEventListener(v, xhrEventHandler.bind(null, 'down'));
}
});
[
'abort', 'error', 'load', 'loadend', 'progress', 'timeout'
].forEach(v => {
if (d.upload['on' + v]) {
xhr.upload.addEventListener(v, xhrEventHandler.bind(null, 'up'));
}
});
xhr.open(d.method, d.url, !d.synchronous, d.user || '', d.password || '');
xhr.mozBackgroundRequest = !!d.mozBackgroundRequest;
d.overrideMimeType && xhr.overrideMimeType(d.overrideMimeType);
d.responseType && (xhr.responseType = d.responseType);
d.timeout && (xhr.timeout = d.timeout);
if (d.headers) {
for (var prop in d.headers) {
if (Object.prototype.hasOwnProperty.call(d.headers, prop)) {
xhr.setRequestHeader(prop, d.headers[prop]);
}
}
}
var body = d.data || null;
if (d.binary && (body !== null)) {
var bodyLength = body.length;
var bodyData = new Uint8Array(bodyLength);
for (var i = 0; i < bodyLength; i++) {
bodyData[i] = body.charCodeAt(i) & 0xff;
}
xhr.send(new Blob([bodyData]));
} else {
xhr.send(body);
}
}
})();