Chrome Extension Modify FormData - google-chrome

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.

Related

How to read a cookie in chrome extension to make sure user is logged in on my website

I have a user who will log in to my website using credentials (Not google Oauth). Once he is logged in, I want to check if he is logged in on my website using the chrome extension.
Manifest.json
"host_permissions": [
"*://*.mydomain.com/"
],
"permissions": [
"storage",
"cookies"
],
background.js
function getCookies(domain, name, callback) {
chrome.cookies.get({"url": domain, "name": name}, function(cookie) {
if(callback) {
callback(cookie.value);
}
});
}
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
getCookies("mydomain.com", "my_cookie_name", function (cookie_value) {
chrome.extension.getBackgroundPage().console.log(cookie_value)
});
})
Content Script
This sends messages to background.js
chrome.runtime.sendMessage({text, style, platform, isBig: Boolean(element)}, function (response) {
updateInput(response, element);
})
I don't see any log output here. Anything I am doing wrong?

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({});
}
});

LinkedIn not reading JSON request

Trying to 'share' on LinkedIn: https://developer.linkedin.com/docs/share-on-linkedin
Which is basically a POST to 'https://api.linkedin.com/v1/people/~/shares?format=json'
in its simplest form is with json:
{
"comment": "Check out developer.linkedin.com! http://linkd.in/1FC2PyG",
"visibility": {
"code": "anyone"
}
}
This requires setting http headers:
Content-Type: application/json
x-li-format: json
I'm trying to do this using OAuth.io, but LinkedIn seems to be still reading the body in XML.
See my example here: https://jsfiddle.net/Lv3jtpkb/2/
I get the following error from it:
Invalid xml {Element 'share#http://api.linkedin.com/v1' with element-only content type cannot have text content.}
I have checked if from OAuth.io server to LinkedIn API endpoint the headers specified here at frontend were somehow altered and can confirm that they have not been.
You're almost there. There are 2 errors.
Your data are formatted as a JS object. The method you're using doesn't seem to be converting the object to JSON automatically.
This line of code isn't doing anything, and is causing exceptions:
.then(user => { console.log("next:",user) })
Remove it.
Working code snippet:
$('#linkedin-button').on('click', function() {
// Initialize with your OAuth.io app public key
OAuth.initialize('A5oDtHv-oUEVlR7q7hDolXxC7RE');
alert('init');
OAuth.popup('linkedin2').then(linkedin => {
alert('logged in');
linkedin.post({
url: "/v1/people/~/shares?format=json",
data: JSON.stringify({
"comment": "Hello world!",
"visibility": {
"code": "anyone"
}
}),
headers: {
"x-li-format": "json",
"Content-Type": "application/json"
}
}).then(data => {
console.log("success:", data);
}).fail(err => { console.log("err:",err) });
})
})
Success in console:

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}"