I'm creating a Chrome extension exclusively for personal use. I need it to watch over any requests made to https://www.instagram.com/api/graphql and log the response (that is, forward it to another script that does that). I am very new to Chrome Extension development, so please forgive me any noob mistakes.
Currently it seems that I'm able to fetch the response; console.log also prints out the response fine. However, I'm stuck at the CSP errors (Content Security Policy), and it won't forward the response it gathered to my script (currently on localhost).
What I have so far, a mixture of copy-pasting stuff from all around, but I understand what it does. I just don't understand what I have to do to make it do what I want :
manifest.json
{
"manifest_version": 3,
"name": "BytE IG",
"description": "BytE Instagram checker",
"version": "1.3",
"content_security_policy": {
"extension_pages": "script-src 'self' http://localhost; object-src 'self' script-src-elem 'self'"
},
"background": {
"service_worker": "background.js"
},
"host_permissions": [
"*://*/*"
],
"permissions": [
"activeTab",
"tabs",
"webRequest"
],
"content_scripts": [
{
"matches": ["*://*.instagram.com/direct/*"],
"run_at": "document_start",
"js": ["inject.js"]
}
],
"web_accessible_resources": [
{
"resources": ["injected.js"],
"matches": ["*://*.instagram.com/*"]
}
]
}
background.js
chrome.webRequest.onCompleted.addListener(
(details) => {
const url = new URL(details.url);
console.log('caught request' + url);
},
{
urls: "https://*.instagram.com/api/graphql*"
}
);
inject.js
var s = document.createElement('script');
s.src = chrome.runtime.getURL('injected.js');
s.onload = function() {
this.remove();
};
(document.head || document.documentElement).appendChild(s);
injected.js
(function(xhr) {
var XHR = XMLHttpRequest.prototype;
var open = XHR.open;
var send = XHR.send;
var setRequestHeader = XHR.setRequestHeader;
XHR.open = function(method, url) {
this._method = method;
this._url = url;
this._requestHeaders = {};
this._startTime = (new Date()).toISOString();
return open.apply(this, arguments);
};
XHR.setRequestHeader = function(header, value) {
this._requestHeaders[header] = value;
return setRequestHeader.apply(this, arguments);
};
XHR.send = function(postData) {
this.addEventListener('load', function() {
var endTime = (new Date()).toISOString();
var myUrl = this._url ? this._url.toLowerCase() : this._url;
if(myUrl) {
if (postData) {
if (typeof postData === 'string') {
try {
// here you get the REQUEST HEADERS, in JSON format, so you can also use JSON.parse
this._requestHeaders = postData;
} catch(err) {
console.log('Request Header JSON decode failed, transfer_encoding field could be base64');
console.log(err);
}
} else if (typeof postData === 'object' || typeof postData === 'array' || typeof postData === 'number' || typeof postData === 'boolean') {
// do something if you need
}
}
// here you get the RESPONSE HEADERS
var responseHeaders = this.getAllResponseHeaders();
if ( this.responseType != 'blob' && this.responseText) {
// responseText is string or null
try {
// here you get RESPONSE TEXT (BODY), in JSON format, so you can use JSON.parse
var arr = this.responseText;
// printing url, request headers, response headers, response body, to console
// building your form values
var data = new URLSearchParams();
data.set('ig', arr);
// send to the endpoint
fetch("http://localhost:1608/ig.php", {
method: 'POST',
mode: 'no-cors',
cache: 'no-cache',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: data
}).then(function(response) {
// check the response object for result
// ...
});
} catch(err) {
console.log("Error in responseType try catch");
console.log(err);
}
}
}
});
return send.apply(this, arguments);
};
})(XMLHttpRequest);
Instead of getting a nice little JSON to ig.php, I get:
injected.js:62 Refused to connect to 'http://localhost:1608/ig.php' because it violates the document's Content Security Policy. (anonymous) @ injected.js:62 injected.js:62 Refused to connect to 'http://localhost:1608/ig.php' because it violates the document's Content Security Policy. (anonymous) @ injected.js:62 injected.js:62 Refused to connect to 'http://localhost:1608/ig.php' because it violates the document's Content Security Policy. (anonymous) @ injected.js:62 injected.js:62 Refused to connect to 'http://localhost:1608/ig.php' because it violates the document's Content Security Policy. (anonymous) @ injected.js:62 injected.js:62 Refused to connect to 'http://localhost:1608/ig.php' because it violates the document's Content Security Policy.
Edit:
I also tried using a FQDN instead of localhost, with an SSL certificate. No luck.