Creating cookies from background page - javascript

I have a background script in my extension that creates a context menu item and handles it. When it is clicked, a cookie is created with specific details. Here is the source for that file:
script.js
function createC() {
var x = 1;
var y = 2;
//Create Cookie
document.cookie = document.URL + "=" + " " + x + " " + y + " ; " + 4102444799;
console.log("Cookie Created.");
}
chrome.contextMenus.create({
title: "Create Cookie",
contexts:["all"],
onclick: createC,
});
Obviously the variables used in it are for testing. When I run document.cookie; in the console, the cookie does not appear. I have tried using the chrome.cookies API and had the same issue.
Does the cookie not appear because it is created in the background script? I am trying to set it on the current tab the user is on, not the background page itself.
manifest.json
{
"manifest_version": 2,
"name": "MyExtension",
"description": "Do stuff",
"version": "0.1",
"icons": { "16": "icon.png",
"48": "icon.png",
"128": "icon.png" },
"options_page": "options.html",
"permissions": [
"tabs", "<all_urls>", "contextMenus", "cookies"
],
"background": {
"scripts": ["script.js"]
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["nav.js"]
}
]
}

In background script, 'document' is not for the current page, but for the extension background page(chrome-extension://[your extension id]/bacground.html). So, you can't use 'document.cookie', you need to try chrome.cookies.get like this:
/**
* Create cookie for the special page
* #param {Object<key, value>} detail
* #param {Function=} opt_callback
*/
function createCookie(detail, opt_callback) {
chrome.cookies.set(detail, opt_callback);
}

You need to use javascript code in specific tab if you want to use the document the current page instead of background.html.
This can be done by function executeScript, your syntax is :
chrome.tabs.executeScript( tabId, details, callback )
chrome.tabs.executeScript( MyTabIdNumberMandatoryInYourCase, MyScriptCodeInLineOrUrl, MyCallbackOptional )
tabId matches the ID of the active tab page, background.js file is executed under the main background.html, then you need to pass the correct ID if you do not pass it, and hopefully it will execute the background.html as the active tab.
All WebRequest events, has a variable called details and she carries a tabid value, and you access it via details.tabId, below is a code that I use in one of my extensions already created.
var onCompletedExecuteScriptDetails = {
// You can run all the code in the inline form,
// rather than using the parameter "file", use the "code" parameter, but is very ugly,
// is much more elegant to use the "file" mode
// my-script.js is a file with code to create cookie
file : "my-script.js"
};
var onCompletedExecuteScript = function ( details ) {
chrome.tabs.executeScript( details.tabId, onCompletedExecuteScriptDetails );
};
var onCompletedCallback = function ( details ) {
document.addEventListener( 'DOMContentLoaded', onCompletedExecuteScript( details ) );
};
var onCompletedFilter = {
urls : [
"http://*/*",
"https://*/*"
]
};
chrome.webRequest.onCompleted.addListener( onCompletedCallback, onCompletedFilter, onCompletedInfo );
executeScript

I ended up using:
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
if (changeInfo.url != null) {
url = changeInfo.url;
}
});

This is what I ended up doing.
In manifest.json:
"permissions": [
"cookies",
"*://*.target_website.com/",
"*://*/_generated_background_page.html"
]
In background.js
chrome.cookies.set({
"name": "cookie's name",
"url": "the URL you want to apply the cookies to",
"value": "cookie's value"
}, function(cookie) {
if (chrome.extension.lastError) {
console.log(chrome.extension.lastError);
}
if (chrome.runtime.lastError) {
console.log(chrome.runtime.lastError);
}
});

Related

Problems with asynchronous calls in chrome extension

I had this idea for a new chrome extension:
It should create a linking QR code for the currently open website, displayed in the popup.html which can be easily scanned with the smartphone. If you watch a video on YouTube, the current time of the video should be also embedded in the QR code, which makes it possible to continue watching the video directly in the YouTube app on the smartphone.
So far so good. But now I have the following problem:
This extension works fine on all websites. Only on Youtube there seems to be a problem with the asynchrony of the onmessage listener and the sending of the message to the contentScript (requesting the current time of the viewed YouTube video).
In the debugging console I get the following errors:
Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist.
... getting this after trying to execute line 7 of background.js
Error handling response: TypeError: Cannot read property 'videoTime' of undefined
at chrome-extension://...../background.js:8:70
... getting this after trying to execute line 8 of background.js
popup.js
$(function() {
chrome.runtime.sendMessage({text: 'sendURL'}, function(response) {
$('#qr-code').attr('src', getQRCodeImgURL(response.url));
});
});
function getQRCodeImgURL(url) {
var qrCodeURL = new URL('http://api.qrserver.com/v1/create-qr-code/');
qrCodeURL.searchParams.set('data', encodeURI(url));
qrCodeURL.searchParams.set('size', '200x200');
return qrCodeURL;
}
background.js
chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
if (message.text == 'sendURL') {
chrome.tabs.query({active: true, /* lastFocusedWindow: true */}, function (tabs) {
var currentURL = new URL(tabs[0].url);
if (currentURL.href.indexOf('youtube.com/watch?v=') >= 0) { // if current website is youtube
chrome.tabs.sendMessage(tabs[0].id, { text: 'sendVideoTime' }, function (response) {
const ytVideoTime = timeStringToSeconds(response.videoTime);
var ytURL = new URL('https://youtu.be/');
ytURL.pathname = '/' + currentURL.searchParams.get('v');
ytURL.searchParams.set('t', ytVideoTime);
currentURL = ytURL;
sendResponse({ url: currentURL.href });
});
} else {
sendResponse({ url: currentURL.href });
}
});
}
return true;
});
function timeStringToSeconds(timeString) {
var seconds = 0;
var hms = timeString.split(':');
if (hms.length == 3) {
seconds = parseInt(hms[0])/* hours */ * 60 /* minutes per hour */ * 60 /* seconds per minute */;
hms.shift(); /* remove first element, for accessing first element in next step (also if hms doesnt is in this hh:mm:ss format) */
}
return seconds + (parseInt(hms[0]) * 60) /* seconds per minute */ + parseInt(hms[1]) /* seconds */;
}
contentScript.js
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
if (message.text == 'sendVideoTime') {
const time = document.evaluate('//*[#id="movie_player"]/div[27]/div[2]/div[1]/div[1]/span[1]', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue.textContent;
sendResponse({videoTime: time});
}
return true;
});
manifest.json
{
"manifest_version": 2,
"name": "URL-QR-Code-Creator",
"version": "1.0",
"description": "This extension creates a linking QR code for the currently open website, which can be easily scanned with the smartphone. If you watch a video on the YouTube website, the current time of the video is also embedded in the QR code, which makes it possible to continue watching the video directly in the YouTube app on the smartphone.",
"icons": {
"16": "images/qr-code-16px.png",
"32": "images/qr-code-32px.png",
"48": "images/qr-code-48px.png",
"64": "images/qr-code-64px.png",
"128": "images/qr-code-128px.png"
},
"browser_action": {
"default_icon": {
"16": "images/qr-code-16px.png",
"32": "images/qr-code-32px.png",
"48": "images/qr-code-48px.png",
"64": "images/qr-code-64px.png",
"128": "images/qr-code-128px.png"
},
"default_title": "show QR-Code",
"default_popup": "popup.html"
},
"background": {
"scripts": [
"background.js"
],
"persistant": false
},
"content_scripts": [
{
"matches": ["*://www.youtube.com/watch?v=*"],
"js": ["contentScript.js"]
}
],
"permissions": [
"activeTab",
"tabs"
]
}
I did it!
At first I said goodbye to the idea of regulating access to the youtube DOM via an extra content script.
So I deleted contentScript.js and deleted it from manifest.json.
Now I simply accessed the DOM using the chrome.tabs.executeScript method in the background.js file and got the result using the callback function. Quite simply - without having to send messages around all the time.

chrome extension not work after load new data

I developed a chrome extension which generates a custom message for me from skype on clicking it. It works fine on page load and when I scroll down and load more connection to send message extension stop work on it.
{
"name": "Page Redder",
"description": "Make the current page red",
"version": "2.0",
"content_scripts": [
{
"run_at" :"document_end",
"matches": ["<all_urls>"],
"js": ["jquery.js","script.js"]
}
],
"permissions": [
"activeTab"
],
"background": {
"scripts": ["background.js"],
"persistent": true
},
"browser_action": {
"default_title": "Make this page red"
},
"manifest_version": 2
}
jquery file
$(document).ready(function(){
$('.mn-person-card__person-btn-ext').click(function(){
var name = $(this).attr('aria-label');
name = name.replace("Send message to ","");
var dummyContent = "Hello " + name + ", \n\nThanks for staying connected with me on LinkedIn.";
$('body').append("<textarea id='absdfjalskjdf'></textarea>");
document.getElementById('absdfjalskjdf').innerHTML = dummyContent;
var dummy =$('#absdfjalskjdf').select()
document.execCommand("Copy");
$('#absdfjalskjdf').remove();
});
});
$(document).on('change', function(){
$('.mn-person-card__person-btn-ext').click(function(){
alert("asldfkjaldfj");
var name = $(this).attr('aria-label');
name = name.replace("Send message to ","");
var dummyContent = "Hello " + name + ", \n\nThanks for staying connected with me on LinkedIn.";
$('body').append("<textarea id='absdfjalskjdf'></textarea>");
document.getElementById('absdfjalskjdf').innerHTML = dummyContent;
var dummy =$('#absdfjalskjdf').select()
document.execCommand("Copy");
$('#absdfjalskjdf').remove();
});
});
When I open all my connection, first loaded connections are work successfully but when load some more connections that time it stop to work. Please help me to make it possible.

How to get selected text in the background script from the active tab (after a hotkey)?

I'm trying to get the selected text from a web page after a hotkey like for example Ctrl+SHIFT+Number. I'm starting with the code from Firefox help.
The manifest.json:
{
"description": "Native messaging example extension",
"manifest_version": 2,
"name": "Native messaging example",
"version": "1.0",
"icons": {
"48": "icons/message.svg"
},
"applications": {
"gecko": {
"id": "ping_pong#example.org",
"strict_min_version": "50.0"
}
},
"background": {
"scripts": ["background.js"]
},
"commands": {
"toggle-feature": {
"suggested_key": {
"default": "Ctrl+Shift+Y",
"linux": "Ctrl+Shift+0"
},
"description": "Send a 'toggle-feature' event"
}
},
"browser_action": {
"default_icon": "icons/message.svg"
},
"permissions": ["nativeMessaging"]
}
The JavaScript file:
/*
On startup, connect to the "ping_pong" app.
*/
var port = browser.runtime.connectNative("ping_pong");
/*
Listen for messages from the app.
*/
port.onMessage.addListener((response) => {
console.log("Received: " + response);
});
/*
On a click on the browser action, send the app a message.
*/
browser.browserAction.onClicked.addListener(() => {
console.log("Sending: ping");
port.postMessage("ping");
});
browser.commands.onCommand.addListener(function(command) {
if (command == "toggle-feature") {
console.log("toggling the feature!");
text1 = window.getSelection();
console.log(text1);
}
});
The debugger says:
Selection { anchorNode: null, anchorOffset: 0, focusNode: null,
focusOffset: 0, isCollapsed: true, rangeCount: 0, caretBidiLevel: null
}
The messaging works, the hotkey works, but I can't get the selected text. Is there another method which I need to use? I tried a lot of code all yesterday, but I didn't find how to do it. Sometimes I have another error from the debugger, but I can never get the selected text. It is a problem of focus? It is crazy!
I read the code from other add-ons. It seems they use that method but maybe it is in a popup window?
I'm on Debian Stretch, and Firefox 56. I tried on 2 computers.
To get the selected text you must use a content script. Given that you are initiating getting the selected text from a hotkey defined with a manifest.json commands, you're best off using tabs.executeScript() to inject the needed code when the user presses the hotkey.
The following adapts the code you have in the question to do only the portion which is defining the hotkey and adds getting the selection (based on the code in Get the Highlighted/Selected text) using tabs.executeScript() to inject into all frames in the activeTab.
It is possible for the user to have made a selection in each existing iframe. You will need to determine how you want to handle that. The code below gets the selection from each iframe. However, it currently discards all but the last selection found (the first result is the main frame). You may want to notify the user when they have selections in multiple frames. Note that Chrome does not permit selecting text in multiple frames, but Firefox does.
The following code is tested in both Firefox and Chrome.
manifest.json:
{
"description": "Get selected text upon hotkey",
"manifest_version": 2,
"name": "Hotkey: get selected text",
"version": "1.0",
"icons": {
"48": "icon.png"
},
"background": {
"scripts": ["background.js"]
},
"commands": {
"get-selected-text": {
"suggested_key": {
"default": "Ctrl+Shift+Y",
"linux": "Ctrl+Shift+0"
},
"description": "Get the selected text from the active tab."
}
},
"permissions": [
"activeTab"
]
}
background.js:
chrome.commands.onCommand.addListener(function (command) {
if (command == "get-selected-text") {
chrome.tabs.executeScript({
code: '(' + getSelectionText.toString() + ')()',
//We should inject into all frames, because the user could have made their
// selection within any frame, or in multiple frames.
allFrames: true,
matchAboutBlank: true
}, function (results) {
selectedText = results.reduce(function (sum, value) {
//This checks all the results from the different frames to get the one
// which actually had a selection.
if (value) {
if (sum) {
//You will need to decide how you want to handle it when the user
// has things selected in more than one frame. This case is
// definitely possible (easy to demonstrate).
console.log('Selections have been made in multiple frames:');
console.log('Had:', sum, ':: found additional:', value);
}
// Currently, we just discard what was obtained first (which will be
// the main frame). You may want to concatenate the strings, but
// then you need to determine which comes first. Reasonably, that
// means determining where the iframe is located on the page with
// respect to any other selection the user has made. You may want
// to just inform the user that they need to make only one
// selection.
return value;
}
return sum;
}, '');
console.log('selectedText:', selectedText);
})
}
});
//The following code to get the selection is from an answer to "Get the
// Highlighted/Selected text" on Stack Overflow, available at:
// https://stackoverflow.com/a/5379408
// The answer is copyright 2011-2017 by Tim Down and Makyen. It is
// licensed under CC BY-SA 3.0, available at
// https://creativecommons.org/licenses/by-sa/3.0/
function getSelectionText() {
var text = "";
var activeEl = document.activeElement;
var activeElTagName = activeEl ? activeEl.tagName.toLowerCase() : null;
if (
(activeElTagName == "textarea") || (activeElTagName == "input" &&
/^(?:text|search|password|tel|url)$/i.test(activeEl.type)) &&
(typeof activeEl.selectionStart == "number")
) {
text = activeEl.value.slice(activeEl.selectionStart, activeEl.selectionEnd);
} else if (window.getSelection) {
text = window.getSelection().toString();
}
return text;
}
I found a solution:
I select the text from any webpage, and I have the text in the background.js and after I can do what I want with the text. In my specific case, I use an external program (in python) to receive the selected text.
Manifest.json
{
"description": "Native messaging + Hotkey + content-script messaging",
"manifest_version": 2,
"name": "getSelectedTextFromHotkey",
"version": "1.0",
"icons": {
"48": "icons/message.svg"
},
"applications": {
"gecko": {
"id": "gettext#example.org",
"strict_min_version": "50.0"
}
},
"background": {
"scripts": ["background.js"]
},
"commands": {
"toggle-feature": {
"suggested_key": {
"default": "Ctrl+Shift+4",
"linux": "Ctrl+Shift+5"
},
"description": "Send the selected text"
}
},
"browser_action": {
"default_icon": "icons/message.svg"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content-script.js"]
}
],
"permissions": [ "<all_urls>","nativeMessaging","webRequest"]
}
Background.js
var port = browser.runtime.connectNative("gettext");
browser.runtime.onConnect.addListener(connected);
port.onMessage.addListener((response) => {
console.log("Received: " + response);
});
function onExecuted(result) {
console.log(`We executed`);
}
function onError(error) {
console.log(`Error: ${error}`);
}
browser.commands.onCommand.addListener(function(command) {
if (command == "toggle-feature") {
console.log("toggling the feature!");
var executing = browser.tabs.executeScript({ file: "/content-script.js", allFrames: false });
executing.then(onExecuted, onError);
}
});
var portFromCS;
function connected(p) {
portFromCS = p;
portFromCS.onMessage.addListener(function(m) {
console.log("message selected:")
console.log(m);
console.log("Sending: ping");
port.postMessage("ping");
});
}
content-script.js
// content-script.js
var selectedText = getSelection().toString();
var myPort = browser.runtime.connect({name:"port-from-cs"});
myPort.postMessage(selectedText);
gettext.json
{
"name": "gettext",
"description": "Native messaging + Hotkey + content-script messaging",
"path": "/home/marie/web-ext/gettext.py",
"type": "stdio",
"allowed_extensions": [ "gettext#example.org" ]
}
gettext.py
#!/usr/bin/python -u
# Note that running python with the `-u` flag is required on Windows,
# in order to ensure that stdin and stdout are opened in binary, rather
# than text, mode.
import sys, json, struct
# Read a message from stdin and decode it.
def getMessage():
rawLength = sys.stdin.read(4)
if len(rawLength) == 0:
sys.exit(0)
messageLength = struct.unpack('#I', rawLength)[0]
message = sys.stdin.read(messageLength)
return json.loads(message)
# Encode a message for transmission, given its content.
def encodeMessage(messageContent):
encodedContent = json.dumps(messageContent)
encodedLength = struct.pack('#I', len(encodedContent))
return {'length': encodedLength, 'content': encodedContent}
# Send an encoded message to stdout.
def sendMessage(encodedMessage):
sys.stdout.write(encodedMessage['length'])
sys.stdout.write(encodedMessage['content'])
sys.stdout.flush()
# BE CAREFUL, NEVER USE THE CONSOLE in the loop ! it stops the connection!!!
while True:
receivedMessage = getMessage()
if (receivedMessage == "ping"):
sendMessage(encodeMessage("pong"))
It seems to work well on Firefox.

Message callback returns a value infrequently - Chrome Extension

I'm building a chrome extension which communicates with a nodejs server through websockets. The point of it is to track browsing history with content. It all seems to work, but occasionally (30% of the time) the callback in a function passed to onMessage.addListener doesn't fire correctly. Let me show you the code:
background.js
var socket = io('http://localhost:3000/');
var tabLoad = function (tab) {
socket.emit('page load', tab);
};
var tabUpdate = function (tabid, changeinfo, tab) {
var url = tab.url;
if (url !== undefined && changeinfo.status == "complete") {
tab.user_agent = navigator.userAgent;
tab.description = '';
tab.content = '';
socket.emit('insert', tab);
}
};
socket.on('inserted', function(page){
socket.emit('event', 'Requesting page content\n');
//page = {tab: page, id: docs._id};
chrome.tabs.sendMessage(page.tab_id, {requested: "content", page: page}, function(data) {
socket.emit('content', data);
});
});
try {
chrome.tabs.onCreated.addListener(tabLoad);
chrome.tabs.onUpdated.addListener(tabUpdate);
} catch(e) {
alert('Error in background.js: ' + e.message);
}
content script - public.js
var messageHandler = function(request, sender, sendContent) {
if (request.requested == "content") {
var html = document.getElementsByTagName('html')[0].innerHTML;
var data = {
content: html,
page: request.page
};
sendContent(data);
return true;
}
};
chrome.extension.onMessage.addListener(messageHandler);
The problem is that sometimes data in sendContent is undefined, while sometimes it is alright. Any ideas how to debug this or what i'm doing wrong?
I've tried replacing document.getElementsByTagName('html')[0].innerHTML with a hardcoded 'test' string, but that didn't help.
Pages like youtube/wikipedia seem to never work, while facebook/google works.
Edit: The sendContent callback does fire 100% of the time it's just that the data passed to it is undefined.
Edit: Here's the manifest file
{
"manifest_version": 2,
"name": "Socket test",
"description": "sockets are cool",
"version": "1.0",
"permissions": [
"http://st-api.localhost/",
"http://localhost:3000/",
"tabs",
"background",
"history",
"idle",
"notifications"
],
"content_scripts": [{
"matches": ["*://*/"],
"js": ["public/public.js"]
//"run_at": "document_start"
}],
//"browser_action": {
// "default_icon": "logo.png",
// "default_popup": "index.html"
//},
"background": {
//"page" : "background.html",
"scripts": ["socket-io.js", "background.js"],
"persistent": true
}
}
First off, your understanding that sendContent is executed 100% of the time is wrong.
As established in the comments, the sendMessage callback also gets executed when there was an error; and this error is, in your case, "Receiving end does not exist"
The error lies in your manifest declaration of the content script. A match pattern "*://*/" will only match top-level pages on http and https URIs. I.e. http://example.com/ will match, while http://example.com/test will not.
The easiest fix is "*://*/*", but I would recommend the universal match pattern "<all_urls>".
With that fixed, there are still a couple of improvements to your code.
Replace chrome.extension.onMessage (which is deprecated) and use chrome.runtime.onMessage
Modify the sendMessage part to be more resilient, by checking for chrome.runtime.lastError. Despite the wide permission, Chrome still won't inject any content scripts into some pages (e.g. chrome:// pages, Chrome Web Store)
Make sure you use "run_at" : "document_start" in your content script, to make sure onUpdated with "complete" is not fired before your script is ready.

chrome.webRequest not working?

I'm trying to implement the chrome.webRequest API in my extension but for some reason it's just not working no matter what I do. Can someone post an example of usage? or correct my mistakes? Basically what I'm trying to do is to intercept the recieved headers from a response.
This is an implementation for onBeforeSendHeaders but I'd like to use OnHeadersRecieved as well
:
var requestFilter = {
urls: [ "<all_urls>" ]
},
// The 'extraInfoSpec' parameter modifies how Chrome calls your
// listener function. 'requestHeaders' ensures that the 'details'
// object has a key called 'requestHeaders' containing the headers,
// and 'blocking' ensures that the object your function returns is
// used to overwrite the headers
extraInfoSpec = ['requestHeaders','blocking'],
// Chrome will call your listener function in response to every
// HTTP request
handler = function( details ) {
alert(details);
var headers = details.requestHeaders,
blockingResponse = {};
// Each header parameter is stored in an array. Since Chrome
// makes no guarantee about the contents/order of this array,
// you'll have to iterate through it to find for the
// 'User-Agent' element
for( var i = 0, l = headers.length; i < l; ++i ) {
if( headers[i].name == 'User-Agent' ) {
headers[i].value = '>>> Your new user agent string here <<<';
break;
}
// If you want to modify other headers, this is the place to
// do it. Either remove the 'break;' statement and add in more
// conditionals or use a 'switch' statement on 'headers[i].name'
}
blockingResponse.requestHeaders = headers;
return blockingResponse;
};
chrome.webRequest.onBeforeSendHeaders.addListener( handler, requestFilter, extraInfoSpec );
this is my manifest file:
{
"background_page": "iRBackground.html",
"browser_action": {
"default_icon": "Off.png",
"popup": "iRMenu.html"
},
"content_scripts": [ {
"js": [ "Content.js" ],
"matches": [ "http://*/*" ],
"run_at": "document_start"
} ],
"description": "***",
"icons": {
"128": "On128x128.png",
"16": "On.png",
"48": "On48x48.png"
},
"key": "****",
"manifest_version": 2,
"name": "***",
"permissions": [ "tabs", "notifications", "unlimitedStorage", "webRequest", “webRequestBlocking”, “<all_urls>”],
"update_url": "***/Chrome/UpdateVersion.xml",
"version": "1.3"
}
the error I get from Chrome is: Uncaught TypeError: Cannot read property 'onBeforeSendHeaders' of undefined
Anyone see anything wrong??? thanks
Well for an example of usage I can give you this working code. I wrote it this way because the other way seems backwards to me but that is just my personal preference, they should both work the same.
Manifest
{
"name": "Chrome webrequest test",
"version": "0.1",
"description": "A test for webrequest",
"manifest_version": 2,
"permissions": [
"<all_urls>","webRequest","webRequestBlocking"
],
"background": {
"scripts": ["bgp.js"],
"persistent": true
}
}
bgp.js
chrome.webRequest.onBeforeSendHeaders.addListener(function(details){
//console.log(JSON.stringify(details));
var headers = details.requestHeaders,
blockingResponse = {};
// Each header parameter is stored in an array. Since Chrome
// makes no guarantee about the contents/order of this array,
// you'll have to iterate through it to find for the
// 'User-Agent' element
for( var i = 0, l = headers.length; i < l; ++i ) {
if( headers[i].name == 'User-Agent' ) {
headers[i].value = '>>> Your new user agent string here <<<';
console.log(headers[i].value);
break;
}
// If you want to modify other headers, this is the place to
// do it. Either remove the 'break;' statement and add in more
// conditionals or use a 'switch' statement on 'headers[i].name'
}
blockingResponse.requestHeaders = headers;
return blockingResponse;
},
{urls: [ "<all_urls>" ]},['requestHeaders','blocking']);
I just fixed this in my extension here: https://github.com/devinrhode2/tweet-bar
What I needed to do was use chrome.webRequest.onBeforeSendHeaders.addListener, but that also meant adding in the webRequest, webRequestBlocking permissions.. would be better to use declarativeWebRequest, but this project isn't that important to me.
Key things:
manifest.json "background": { "persistent": true,
"permissions": [ "webRequest", "webRequestBlocking",
When you make these changes in the manifest.json, you should actually consider re-installing the extension just to make sure the change is being picked up.
This is my filter code. Yours should not be identical. See the docs here https://developer.chrome.com/extensions/webRequest
chrome.webRequest.onBeforeSendHeaders.addListener((req) => {
console.log('onBeforeSendHeaders');
req.requestHeaders.forEach(function(header, index){
console.log(header.name+':', header.value);
if (headers[header.name.toLowerCase()]) {
console.log('set header:'+header.name, 'to:'+headers[header.name.toLowerCase()]);
req.requestHeaders[index].value = headers[header.name.toLowerCase()]
}
})
return {requestHeaders: req.requestHeaders};
},{
urls: ['https://twitter.com/i/tweet/create'],
types: ["xmlhttprequest"]
},[
'blocking',
'requestHeaders'
]);
I also added these headers to my xhr request, which doesn't hurt, makes you appear more similar to the normal site:
//add headers:
var headers = {
'content-type': 'application/x-www-form-urlencoded',
accept: 'application/json, text/javascript, */*; q=0.01',
origin: 'https://twitter.com',
referer: 'https://twitter.com/',
'x-requested-with': 'XMLHttpRequest'
};
console.log('change')
Object.keys(headers).forEach((header) => {
postXhr.setRequestHeader(header, headers[header]);
})
Add the required permissions for the extension in manifest.json, you might not need webRequestBlocking depending on what u want to do.
...
"permissions": [
"<all_urls>","webRequest","webRequestBlocking"
],"background": {
"scripts": ["background.js"],
"persistent": true
}
...
After adding the required permissions for your extension in the manifest.json file, make sure you click on the update button and if that does not work or the browser does not have an update button then reinstall the extension.
Here is the manifest config
"permissions": [
"webRequestBlocking"
,"webRequest"
,"http://*.beibei.com/*"
],
"background" : {
"page" : "xxx.html",
"persistent" : true
}
Here is the javascript demo code
$( function() {
// add event listners
chrome.webRequest.onBeforeRequest.addListener(
function(details) {
console.log('onBeforeRequest', details);
},
{urls: ["http://www.beibei.com/"]},
[]
);
chrome.webRequest.onBeforeSendHeaders.addListener(
function(details) {
console.log('onBeforeSendHeaders', details);
},
{urls: ["http://www.beibei.com/"]},
["requestHeaders"]
);
chrome.webRequest.onCompleted.addListener(
function(details) {
console.log('onCompleted', details);
},
{urls: ["http://www.beibei.com/"]},
[]
);
// do a GET request, so that relative events will be fired, need jquery here
$.get('http://www.beibei.com/');
});

Categories