Can not modify request headers via chrome extension - google-chrome

My main aim is to modify the origin header to some specific origin, but I am unable to modify any header of the request.
I tried with onBeforeSendHeaders event listener with extraHeaders option
chrome.webRequest.onBeforeSendHeaders.addListener((details) => {
for (var i = 0; i < details.requestHeaders.length; ++i) {
if (details.requestHeaders[i].name.toLowerCase() === 'origin') {
details.requestHeaders[i].value = "https://bar.com"
break;
}
}
console.log(details);
return { requestHeaders: details.requestHeaders };
}, {
urls: [
"https://*.foo.com/*"
]
}, ['extraHeaders', 'requestHeaders']);
Later I also tried changing the user-agent header with the code provided in the documentation - https://developer.chrome.com/docs/extensions/reference/webRequest/#examples
but none of it worked, headers are getting changed in the logged object but
then I logged the headers with onSendHeaders event listener with this code
chrome.webRequest.onSendHeaders.addListener((details) => {
console.log("Header sent", details)
}, {
urls: [
"https://*.foo.com/*"
]
}, ['extraHeaders', 'requestHeaders']);
and it shows none of the headers changed.
I am not using any other extension (disabled all).
I am using manifest version 3 and I have these permissions
"permissions": [
"tabs",
"scripting",
"webRequest"
],
"host_permissions": [
"https://*.foo.com/*",
"https://*.bar.com/*"
]
My Browser : Version 92.0.4515.159 (Official Build) (64-bit)
My OS: Linux Mint 20.1 Ulyssa
Any help will be much appreciated. Thank you

Related

Why Chrome DevTools Network shows no response?

I've been trying to fetch some url using Devtools 'copy as fetch' but I can see no response. If I try replay xhr, it will work. It's strange since it doesn't work for this particular site, but if I try 'copy as fetch' on some others it does bring a result.
What I'm trying to do is grab the response body and display it some other way (it's a schedling software, and I'm trying to modify the way it displays the calendar view since it displays everything together).
I have an extension that enables me to modify XMLHttpRequest so I can get the response of any XHR, but since the first async executes before I inject the script, then I'm always missing the first one.
I plan on using chrome webRequest to stop the first one and fetch it again.
manifest.json
{
"name": "jobber",
"version": "2.0",
"description": "Build an Extension!",
"manifest_version": 2,
"permissions": [
"webNavigation",
"webRequest",
"*://secure.name.com/*"
],
"content_scripts": [{
"matches": ["*://secure.name.com/calendar*"],
"js": ["contents.js"],
"run-at": "document_start"
}],
"externally_connectable": {
"matches": ["*://secure.name.com/calendar*"]
},
"background": {
"scripts": ["background.js"]
}
}
contents.js
(function () {
'use strict';
let s = document.createElement("script");
s.textContent = overloadXHR();
document.head.insertBefore(s, document.head.children[0]);
s = document.createElement("script");
s.textContent = displayCalendar;
document.head.insertBefore(s, document.head.children[0]);
})();
function overloadXHR() {
const text = `
console.log(\`overriding: \${Date.now()}\`);
const rawOpen = XMLHttpRequest.prototype.open;
let json = [];
(function(){
XMLHttpRequest.prototype.open = function () {
this.addEventListener("readystatechange", e => {
if (/secure.name.com.calendar.*?calendar=true/i.test(this.responseURL)) {
if ((this.status == 200) && (this.readyState == 4)) {
console.log(this.readyState);
try {
json = JSON.parse(this.response);
window.setTimeout(() => (window.displayCalendar({json}))({json}), 1000);
}
catch (e) { console.log(e); }
}
}
});
rawOpen.apply(this, arguments);
}
}())
`;
return text;
}
function displayCalendar({ json }) {
// do something
}
I tried POST requests too. I could see that they would work, but no response given tho.
original request:
copy as fetch
copy as fetch response
copy as fetch timing

Receiving Error in Chrome Extension: Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist

I'm trying to create a very simple Chrome extension that will allow me to highlight a word on a webpage, right click to open the context menu, and then search it on a database called Whitaker's Words by simply appending the word to the search URL. I'm continuing to receive
"Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist."
as an error every time I run the code and attempt to use the context menu.
At the moment, I have already taken the steps to disable all other extensions and I attempted to use the port documentation on the Chrome Messaging Docs but I wasn't able to resolve the issue that way.
background.js
chrome.contextMenus.create({
title: "Search Whitaker's Words",
contexts: ["selection"]
});
chrome.contextMenus.onClicked.addListener(function() {
chrome.runtime.sendMessage({ method: "getSelection" }, function (response) {
sendToWW(response.data);
});
});
function sendToWW(selectedText) {
var serviceCall = 'http://archives.nd.edu/cgi-bin/wordz.pl?keyword=' + selectedText;
chrome.tabs.create({ url: serviceCall });
}
Here, I create a context menu and when the menu item is clicked, I send a message to the context script asking for the highlighted selection. I then return this to another function in background.js that will create a new tab with the search query.
content.js
chrome.runtime.onMessage.addListener(function (message) {
if (message.method === "getSelection"){
var word = window.getSelection().toString().trim();
console.log(word);
chrome.runtime.sendMessage({ data: word });
}
else
chrome.runtime.sendMessage({}); // snub them.
});
I listen here for the message and then take a selection from the window, trim, and send it back.
manifest.json
{
"manifest_version": 2,
"name": "Latinate",
"version": "0.1",
"description": "Aid in Latin translation using Whitaker's Words",
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": [
"jquery-3.4.1.min.js",
"content.js"
]
}
],
"background": {
"scripts": [
"background.js"
]
},
"permissions": [
"contextMenus",
"tabs"
],
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
}
}
Any and all help would be appreciated! I've tried nearly everything I could find that seemed to apply.
The error message says there is no message listener on the other side. And indeed there is none because a message listener is a function registered with chrome.runtime.onMessage.addListener - in your extension only the content script has such a listener.
Instead of sending a new message back, send the response using sendResponse function which is passed as a parameter to the onMessage listener
(see also the messaging tutorial).
Another problem is that to send a message to a tab you need to use a different method: chrome.tabs.sendMessage with a tab id as the first parameter.
background script:
chrome.contextMenus.onClicked.addListener((info, tab) => {
chrome.tabs.sendMessage(tab.id, {method: 'getSelection'}, response => {
sendToWW(response.data);
});
});
content script:
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.method === 'getSelection') {
var word = window.getSelection().toString().trim();
console.log(word);
sendResponse({ data: word });
} else {
sendResponse({});
}
});

How to route all in matchCondition ?

I'm working on a Azure Functions App and i have some issues with the routes, when I add a matching rule with * inside, it doesn't work anymore. Anyone have an idea of what I'm doing wrong ?
When I uncomment one of the other rules or just change the route of Test Route from /{code} to /{*code}, it fails and gives me the Bad Request response.
My routing file proxies.json
{
"$schema": "http://json.schemastore.org/proxies",
"proxies": {
"Test Route": {
"matchCondition": {
"route": "/{code}"
},
"backendUri": "https://%WEBSITE_HOSTNAME%/api/UrlTester/{code}"
}
//,
//"Let's Encrypt Support" : {
// "matchCondition": {
// "route": "/.well-known/acme-challenge/{*code}"
// },
// "backendUri": "https://%WEBSITE_HOSTNAME%/api/LetsEncrypt/{code}"
//},
//"Domain Redirect": {
// "matchCondition": {
// "route": "/{*shortUrl}"
// },
// "backendUri": "http://%WEBSITE_HOSTNAME%/api/UrlRedirect/{shortUrl}"
//},
//"Api": {
// "matchCondition": {
// "route": "/api/{*path}"
// },
// "backendUri": "http://%WEBSITE_HOSTNAME%/api/{path}"
//}
}
}
I'm using this following fork: https://github.com/duijvelshoff/serverless-url-shortener
And this documentation: https://learn.microsoft.com/en-us/azure/azure-functions/functions-proxies
Thanks.
As per this github issue a catchall {* route redirecting to the same function app will cause a 400 response.
Moving your HTTP triggered functions to a separate function app, and changing the backend URLs will fix your issues.
try something like "route": "id={code}"

Chrome extension sendResponse not working

There are numerous versions of this question, and I have reviewed them and tried many things to the best of my ability without success. I am new to chrome extensions, and I could be missing many things, but I don't know what.
First, I want to point out that I have copied several claimed working examples from various answers, and none of them work for me. I am using Chrome Version 58.0.3029.81 on Windows 7 Professional.
Whether it's my code, or examples I have copied, the code in the content script executes, and calls sendResponse with the correct response. Beyond that, nothing - the specified callback function is never executed.
Here is my current code:
manifest.json
{
"manifest_version": 2,
"name": "TestExtension",
"description": "...",
"version": "1.0",
"content_scripts": [
{
"matches": [
"http://*/*",
"https://*/*"
],
"js": [ "content.js" ]
}
],
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html",
"default_title": "Send a checkpoint request"
},
"permissions": [
"activeTab",
"tabs",
"http://*/*", // allow any host
"https://*/*" // allow any secure host
]
}
popup.js
document.addEventListener('DOMContentLoaded', function ()
{
document.getElementById('extension_form').onsubmit = function ()
{
var elementName = "DataAccessURL";
chrome.tabs.query(
{
active: true,
currentWindow: true
},
function (tabs)
{
chrome.tabs.sendMessage(
tabs[0].id,
{ Method: "GetElement", data: elementName },
function (response)
{
debugger;
console.log("response:Element = " + response.Element);
alert(response.Element);
});
});
};
});
content.js
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse)
{
console.log("In Listener");
if (request.Method && request.Method == "GetElement")
{
var result = "";
var element = request.data;
console.log(element);
var e = document.getElementById(element);
if (e) result = e.innerHTML;
console.log(result);
sendResponse({ Element: result });
return true; // <-- the presence or absence of this line makes no difference
}
});
Any clues would be appreciated. I simply do not understand why my callback is not being called.
User wOxxOm provided this answer in his comments.
In the popup.js example, I am attaching to the form 'onsubmit' event to trigger my code.
I had previously read that if the popup gets closed, it's code would no longer be there to be run. I could not visually tell in my case that, as wOxxOm pointed out, that the submit event reloads the popup. That was disconnecting my code.
In order to prevent the popup from reloading, I needed to prevent the default action on the submit event. I added an 'evt' parameter to accept the event argument to the submit, and called preventDefault as shown below.
document.getElementById('extension_form').onsubmit = function (evt)
{
evt.preventDefault();
...
This allowed the sample to work as expected.
Thanks wOxxOm!

Chrome Extension Modify FormData

chrome.webRequest.onBeforeRequest.addListener(function (details) {
if (details.method === "POST") {
var bodyObj = details['requestBody'];
// I can see/modify bodyObj.formData, but
}
}, {
urls: ["<all_urls>"]
}, [
"blocking", "requestBody"
]););
How can I return a modified formData?
I see from Chrome Extensions's documentation that I can cancel a request, redirect a request, or modify the request headers, but how can I change the formData?
Based on http://crbug.com/91191, it looks like there's only read-only access to POST data for webRequest's onBeforeRequest listeners.
It means we can see what is being sent in a request BODY like this below:
chrome.webRequest.onBeforeRequest.addListener(function (details) {
console.log(details['requestBody']);
}, {
urls: ["<all_urls>"]
}, [
"blocking", "requestBody"
]);
But we can't update it for now.