Skip to content

Commit 3e9d5a8

Browse files
committed
hook xhr + fetch
1 parent 5b102cc commit 3e9d5a8

File tree

3 files changed

+172
-137
lines changed

3 files changed

+172
-137
lines changed

scripts/_test.js

Lines changed: 24 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
import { UfsGlobal } from "./content-scripts/ufs_global.js";
2-
import { fetchGraphQl } from "./fb_GLOBAL.js";
2+
import {
3+
hookFetch,
4+
hookXHR,
5+
CANCEL_FETCH,
6+
CANCEL_XHR,
7+
cancelKey,
8+
} from "./libs/ajax-hook/index.js";
39

410
export default {
511
icon: "",
@@ -13,6 +19,7 @@ export default {
1319
},
1420

1521
popupScript: {
22+
// selenium automation get album's images
1623
_onClick: async () => {
1724
const { openWebAndRunScript } = await import("./helpers/utils.js");
1825

@@ -170,97 +177,6 @@ export default {
170177
}
171178
},
172179

173-
// sync element position accross all tabs
174-
_onDocumentStart: (details) => {
175-
console.log(details);
176-
177-
const div = document.createElement("div");
178-
div.id = "ufs-test";
179-
div.innerHTML = `
180-
<style>
181-
#ufs-test {
182-
position: fixed;
183-
background-color: #f1f1f1;
184-
border: 1px solid #d3d3d3;
185-
text-align: center;
186-
z-index: 999999999;
187-
top: 0;
188-
left: 0;
189-
}
190-
191-
#ufs-testheader {
192-
padding: 10px;
193-
cursor: move;
194-
z-index: 10;
195-
background-color: #2196F3;
196-
color: #fff;
197-
}
198-
</style>
199-
<div id="ufs-testheader">Click here to move</div>
200-
<p>Move</p>
201-
<p>this</p>
202-
<p>DIV</p>`;
203-
document.documentElement.appendChild(div);
204-
205-
window.ufs_test = (x, y) => {
206-
div.style.top = y + "px";
207-
div.style.left = x + "px";
208-
};
209-
210-
// Make the DIV element draggable:
211-
dragElement(div, (x, y) => {
212-
console.log(x, y);
213-
chrome.runtime.sendMessage({ action: "ufs-test", data: { x, y } });
214-
});
215-
216-
function dragElement(elmnt, onMoved) {
217-
var pos1 = 0,
218-
pos2 = 0,
219-
pos3 = 0,
220-
pos4 = 0;
221-
if (document.getElementById(elmnt.id + "header")) {
222-
// if present, the header is where you move the DIV from:
223-
document.getElementById(elmnt.id + "header").onmousedown =
224-
dragMouseDown;
225-
} else {
226-
// otherwise, move the DIV from anywhere inside the DIV:
227-
elmnt.onmousedown = dragMouseDown;
228-
}
229-
230-
function dragMouseDown(e) {
231-
e = e || window.event;
232-
e.preventDefault();
233-
// get the mouse cursor position at startup:
234-
pos3 = e.clientX;
235-
pos4 = e.clientY;
236-
document.onmouseup = closeDragElement;
237-
// call a function whenever the cursor moves:
238-
document.onmousemove = elementDrag;
239-
}
240-
241-
function elementDrag(e) {
242-
e = e || window.event;
243-
e.preventDefault();
244-
// calculate the new cursor position:
245-
pos1 = pos3 - e.clientX;
246-
pos2 = pos4 - e.clientY;
247-
pos3 = e.clientX;
248-
pos4 = e.clientY;
249-
// set the element's new position:
250-
elmnt.style.top = elmnt.offsetTop - pos2 + "px";
251-
elmnt.style.left = elmnt.offsetLeft - pos1 + "px";
252-
}
253-
254-
function closeDragElement() {
255-
// stop moving when mouse button is released:
256-
document.onmouseup = null;
257-
document.onmousemove = null;
258-
259-
onMoved?.(parseInt(elmnt.style.left), parseInt(elmnt.style.top));
260-
}
261-
}
262-
},
263-
264180
// text size in KB
265181
_onClick: () => {
266182
function formatSize(size, fixed = 0) {
@@ -346,9 +262,23 @@ export default {
346262
},
347263

348264
pageScript: {
349-
_onClick: () => {
350-
fetchGraphQl();
265+
onDocumentStart: () => {
266+
// hookFetch({
267+
// onBefore: (url, options) => {
268+
// console.log("onBefore", url, options);
269+
// },
270+
// });
271+
// const unregister = hookXHR({
272+
// onBefore: (...args) => {
273+
// console.log("before", args);
274+
// },
275+
// onAfter: (...args) => {
276+
// console.log("-> after", args);
277+
// },
278+
// });
351279
},
280+
281+
// download album
352282
_onClick: async () => {
353283
(async () => {
354284
function getGroupId() {
@@ -785,50 +715,8 @@ export default {
785715
})();
786716
},
787717
},
788-
789-
backgroundScript: {
790-
// sync element position accross all tabs
791-
_onDocumentStart: (details, context) => {
792-
const cachedPos = context.getCache("ufs-test", { x: 0, y: 0 });
793-
updatePos(details.tabId, cachedPos.x, cachedPos.y);
794-
},
795-
_runtime: {
796-
onMessage: ({ request, sender, sendResponse }, context) => {
797-
if (request.action === "ufs-test" && request.data) {
798-
context.setCache("ufs-test", request.data);
799-
chrome.tabs.query({}, (tabs) => {
800-
for (let tab of tabs) {
801-
try {
802-
updatePos(tab.id, request.data.x, request.data.y);
803-
} catch (e) {}
804-
}
805-
});
806-
}
807-
},
808-
},
809-
},
810718
};
811719

812-
function updatePos(tabId, x, y) {
813-
chrome.scripting.executeScript({
814-
target: {
815-
tabId: tabId,
816-
},
817-
func: (x, y) => {
818-
let interval = setInterval(() => {
819-
if (typeof window.ufs_test == "function") {
820-
window.ufs_test?.(x, y);
821-
clearInterval(interval);
822-
clearTimeout(timeout);
823-
}
824-
}, 100);
825-
826-
let timeout = setTimeout(() => clearInterval(interval), 10000);
827-
},
828-
args: [x, y],
829-
});
830-
}
831-
832720
const backup = () => {
833721
(() => {
834722
// modify window.fetch

scripts/libs/ajax-hook/index.js

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
export const cancelKey = "_ufs_cancel_";
2+
3+
function hook({ onBefore, onAfter, onBeforeArr, onAfterArr } = {}) {
4+
const beforeId = randId();
5+
const afterId = randId();
6+
7+
if (typeof onBefore === "function")
8+
onBeforeArr.push({ fn: onBefore, id: beforeId });
9+
if (typeof onAfter === "function")
10+
onAfterArr.push({ fn: onAfter, id: afterId });
11+
12+
return () => {
13+
let beforeIndex = onBeforeArr.findIndex((e) => e.id === beforeId);
14+
let afterIndex = onAfterArr.findIndex((e) => e.id === afterId);
15+
16+
if (beforeIndex !== -1) onBeforeArr.splice(beforeIndex, 1);
17+
if (afterIndex !== -1) onAfterArr.splice(afterIndex, 1);
18+
};
19+
}
20+
21+
function randId() {
22+
return Math.random().toString(36).slice(2);
23+
}
24+
25+
// ============ FETCH ============
26+
const onBeforeFetchFn = [];
27+
const onAfterFetchFn = [];
28+
let readyFetch = false;
29+
export const CANCEL_FETCH = {
30+
options: { [cancelKey]: true },
31+
};
32+
33+
function initFetch() {
34+
const originalFetch = window.fetch;
35+
window.fetch = async function (url, options) {
36+
let request = { url, options };
37+
for (let { fn } of onBeforeFetchFn)
38+
request = fn(request.url, request.options) || request;
39+
if (request?.options?.[cancelKey]) return null;
40+
41+
let response = await originalFetch(...request);
42+
for (let { fn } of onAfterFetchFn)
43+
response = fn(request.url, request.options, response) || response;
44+
45+
return response;
46+
};
47+
}
48+
49+
export function hookFetch({ onBefore, onAfter } = {}) {
50+
if (!readyFetch) {
51+
initFetch();
52+
readyFetch = true;
53+
}
54+
return hook({
55+
onBefore,
56+
onAfter,
57+
onBeforeArr: onBeforeFetchFn,
58+
onAfterArr: onAfterFetchFn,
59+
});
60+
}
61+
62+
/* hookFetch example
63+
hookFetch({
64+
onBefore: (url, options) => {
65+
console.log(url, options);
66+
return CANCEL_FETCH;
67+
},
68+
onAfter: (url, options, response) => {
69+
console.log(url, options, response);
70+
return res;
71+
},
72+
});
73+
*/
74+
75+
// =========== XHR ============
76+
const onBeforeXHRFn = [];
77+
const onAfterXHRFn = [];
78+
let readyXhr = false;
79+
80+
export const CANCEL_XHR = {
81+
[cancelKey]: true,
82+
};
83+
84+
function initXhr() {
85+
const originalXMLHttpRequest = window.XMLHttpRequest;
86+
window.XMLHttpRequest = new Proxy(originalXMLHttpRequest, {
87+
construct(target, args) {
88+
const instance = new target(...args);
89+
90+
const open = instance.open;
91+
instance.open = function (method, url, m, y, f) {
92+
this._method = method;
93+
this._url = url;
94+
return open.apply(this, arguments);
95+
};
96+
97+
const send = instance.send;
98+
instance.send = function (dataSend) {
99+
this.dataSend = dataSend;
100+
101+
for (let { fn } of onBeforeXHRFn)
102+
dataSend = fn(this._url, this._method, dataSend) || dataSend;
103+
104+
if (dataSend?.[cancelKey]) return null;
105+
106+
return send.apply(this, arguments);
107+
};
108+
109+
// TODO verify
110+
instance.onreadystatechange = function () {
111+
if (this.readyState === 4 && this.status === 200) {
112+
for (let { fn } of onAfterXHRFn)
113+
fn(this._url, this._method, this.dataSend, this.responseText);
114+
}
115+
};
116+
117+
return instance;
118+
},
119+
});
120+
}
121+
122+
export function hookXHR({ onBefore, onAfter } = {}) {
123+
if (!readyXhr) {
124+
initXhr();
125+
readyFetch = true;
126+
}
127+
return hook({
128+
onBefore,
129+
onAfter,
130+
onBeforeArr: onBeforeXHRFn,
131+
onAfterArr: onAfterXHRFn,
132+
});
133+
}
134+
135+
/* hookXHR example
136+
hookXHR({
137+
onBefore: (url, method, dataSend) => {
138+
console.log({ url, method, dataSend });
139+
return dataSend;
140+
// return CANCEL_XHR;
141+
},
142+
onAfter: (url, method, dataSend, response) => {
143+
console.log({ url, method, dataSend, response });
144+
return res;
145+
},
146+
});
147+
*/

working_note.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## 30/05/2024 - ?
44

5-
- [ ] check linux compatible
5+
- [ ] check linux compatible -> relative path in manifest + file name camelcase
66

77
- [ ] modify responseText xhr <https://stackoverflow.com/a/37532556/23648002>
88

0 commit comments

Comments
 (0)