Capturing media files from XHR
Use PerformanceObserver
.
What's the point? There are some browser extensions to capture media existing already. Are they bad?
Konf, yes this is true.
However:
- Not all browsers have access to extensions.
- Most browsers support userscripts.
- Regardless to the above, capturing media is needed for Tobacco Cinema so video be displayed.
In order to avoid script execution, ads and any other distraction, Tobacco Cinema is loded immediately (it is set to run at document-start
), so it is not possible to copy an object or video element because the original page has never been loaded.
- It might be possible by parsing the document, yet it might involve unwanted scripts which would cause to unwanted popups and ads.
The purpose of Tobacco Cinema is to avoid distractions so user won't be enticed to watch another video and hopefully find a nice lady (or gentlemen, if user is a woman) to get married.
This is why this thread was started.
I've made an example of any requests interception. I'm not sure that is what you need or if it works with browsers without access to extensions, but here you are:
// ==UserScript==
// @name xhrs intercept example
// @description xhrs intercept example
// @author Konf
// @namespace https://greasyfork.org/users/424058
// @version -1
// @match *://*/*
// @run-at document-start
// @grant unsafeWindow
// ==/UserScript==
(function() {
'use strict';
const IDS_LENGTH = 6; // should be replaced to uuid
const oldFetch = unsafeWindow.fetch;
const oldXMLHttpRequest = unsafeWindow.XMLHttpRequest;
// these should never throw an error, use try..catch somewhere
const hooks = {
fetch: {
handleArgs: (fetchId, args) => {
console.log(`fetch: args of ${fetchId}`, args);
},
handleResult: (fetchId, response) => {
console.log(`fetch: result of ${fetchId}`, response);
},
},
xhr: {
handleArgs: (xhrId, args) => {
console.log(`xhr: args of ${xhrId}`, args);
},
handleResult: (xhrId, onloadEvent, xhr) => {
console.log(`xhr: result of ${xhrId}`, xhr);
},
},
}
unsafeWindow.fetch = function(...args) {
const fetchPromise = oldFetch(...args);
const id = makeId(IDS_LENGTH); // should be replaced to uuid
hooks.fetch.handleArgs(id, args);
fetchPromise.then(r => hooks.fetch.handleResult(id, r));
return fetchPromise;
}
unsafeWindow.XMLHttpRequest = function(...args) {
const xhr = new oldXMLHttpRequest();
let xhrOpen = xhr.open.bind(xhr);
let xhrOnload;
const id = makeId(IDS_LENGTH); // should be replaced to uuid
xhr.onload = (ev) => {
hooks.xhr.handleResult(id, ev, xhr);
if (xhrOnload) return xhrOnload(...args);
}
Object.defineProperty(xhr, 'onload', {
get: () => xhrOnload,
set: (value) => (xhrOnload = value),
});
Object.defineProperty(xhr, 'open', {
get() {
return (...args) => {
hooks.xhr.handleArgs(id, args);
return xhrOpen(...args);
};
},
set: (value) => (xhrOpen = value),
});
return xhr;
}
// utils ---------------------------------------------------
// should be replaced to uuid
function makeId(length) {
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
let id = "";
for (let i = 0; i < length; i++) {
id += chars.charAt(Math.floor(Math.random() * chars.length));
}
return id;
}
})();
Hello
Me and my friends have made a script that fetches media from DOM, but capturing media from XHR was not handled yet.
As more and more websites send media from XHR it is important for us to begin working on capturing media from XHR.
Please help or even join us.
Thank you