Getting variables outside executeScript in chrome extension - javascript

I am trying to code a chrome extension, and I have a background.html with this code:
var x = "test";
function tabChanged(id, info, tab){
if(info.status == 'complete'){
chrome.tabs.executeScript(id, {code:"try{alert(x);}catch(e){alert(e);}"}, null);
}
}
chrome.tabs.onUpdated.addListener(tabChanged);
chrome.tabs.getAllInWindow(null,function(tabs){
for(var index=0; index < tabs.length; index++){
chrome.tabs.executeScript(tabs[index].id, {code:"try{alert(x);}catch(e){alert(e);}"}, null);
}
});
But variable "x" is always undefined inside executeScript.
How can I get/set x from executeScript? Without using messaging.

Content scripts executes in context of web page. See Content Scripts section in Chrome docs for more information.
If you want to pass string variable from background page to chrome.tabs.executeScript you must do something like this:
var x = "test";
chrome.tabs.executeScript(id, {code:"var x = '"+x+"'; try{alert(x);}catch(e){alert(e);}"},null);
If you want to modify variable, you have only one way - messaging:
var x = 1;
console.log('x=' + x);
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
console.log(request);
if(request.command == 'setVar') {
window[request.name] = request.data;
}
});
chrome.browserAction.onClicked.addListener(function() {
var code = "chrome.extension.sendRequest({command: 'setVar', name: 'x', data: 2});";
chrome.tabs.executeScript(null, {code:code});
window.setTimeout(function(){console.log('x=' + x);}, 1000);
});

For chrome Chrome 92+, you can use args
chrome.tabs.query({active: true, currentWindow: true}).then(([tab])=>{
const para = "Hello world!!!"
chrome.scripting.executeScript({
target: {tabId: tab.id},
function: (args) => {
alert(args)
},
args: [para]
})
})
or you can use the chrome.storage
{
"manifest_version": 3,
"permissions": [
"storage",
"activeTab",
"scripting"
]
}
chrome.storage.sync.set({msg: "hello world"})
chrome.tabs.query({active: true, currentWindow: true}).then(([tab])=>{
chrome.scripting.executeScript({
target: {tabId: tab.id},
function: () => {
chrome.storage.sync.get(['msg'], ({msg})=> {
console.log(`${msg}`)
alert(`Command: ${msg}`)
})
}
})
})
Update for pass functions in args is OK?
You can't
Neither Storage nor Args, they both can't accept the function parameter.
Example:
const myObj = {
msg: "Hi",
myNum: 1,
myFunc: ()=>{return "hi"},
myFunc2: function() {return ""}
}
chrome.storage.sync.set({
msg: "my storage msg",
myObj,
})
chrome.tabs.query({active: true, currentWindow: true}).then(([tab])=>{
chrome.scripting.executeScript({
target: {tabId: tab.id},
function: (para1, para2MyObj) => {
console.log(para1) // Hello
console.log(JSON.stringify(para2MyObj)) // {"msg":"Hi","myNum":1} // myFunc, myFunc2 are missing. You can't get the variable if its type is function.
chrome.storage.sync.get(['msg', "myObj"], ({msg, myObj})=> {
console.log(`${msg}`) // "my storage msg"
console.log(JSON.stringify(myObj)) // {"msg":"Hi","myNum":1}
alert(`Command: ${msg}`)
})
},
args: ["Hello", myObj]
})
})

The reason your variable is undefined is because you are referencing your variable inside of a string so you can just simply do this:
var yourVar = "your variable"
//define your variable
chrome.tabs.executeScript({code: 'Your code here' + yourVar + ';}'})
//then format it like this ({code: "Your code as a string" + your variable + "code"})
and if you want to change the variable later than just do the same thing but with your new variable, it's pretty straight forward

Related

Unable to persist state of my chrome extension between tab reloads and tab changes

I am trying to create a pretty simple chrome extension that enables me to navigate the browser back and forward using horizontal scrolling. I want to be able to enable and disable the extension; however I want the state to persist when the tab changes (whether the active tab is a new url or a new tab is launched).
Here is my current code that partially works for only the active tab:
manifest.json:
{
"name": "SwipeNav",
"action": {},
"manifest_version": 3,
"version": "0.1",
"description": "Navigates browser forward and back with 2 finger swiping",
"permissions": [
"activeTab",
"scripting",
"tabs",
"alarms"
],
"background": {
"service_worker": "background.js"
}
}
background.js
function twoFingerBack() {
console.log("Enabling 2 finger scrolling");
let timer;
window.addEventListener("wheel", function(event) {
clearTimeout(timer);
if (Math.abs(event.deltaX) > Math.abs(event.deltaY)) {
timer = setTimeout(function() {
if (event.deltaX > 0) {
history.back();
} else if (event.deltaX < 0) {
history.forward();
}
}, 200);
}
});
}
function removeExt() {
console.log("Disabling 2 finger scrolling");
window.removeEventListener("wheel", removeExt)
}
let enabled = true;
chrome.action.onClicked.addListener((tab) => {
enabled = !enabled;
if (enabled) {
if (!tab.url.includes("chrome://")) {
chrome.scripting.executeScript({
target: { tabId: tab.id },
function: twoFingerBack
});
}
} else {
if (!tab.url.includes("chrome://")) {
chrome.scripting.executeScript({
target: { tabId: tab.id },
function: removeExt
});
}
}
});
I have read that I can use chrome.tabs.onActivated however I could not get this to work at all. Not sure if that is the right path.
Any help is appreciated...thanks!
Save the state in storage. Since localStorage is not available in a service worker you can use chrome.storage.local.
Register/unregister the content script, so it runs automatically next time the tab is loaded.
Process all tabs using executeScript to apply the changes to the currently loaded pages.
Use a global function for the wheel listener and use its name in removeEventListener.
// manifest.json
Add "storage" inside "permissions"
Add "host_permissions": ["<all_urls>"]
// background.js
chrome.action.onClicked.addListener(async (tab) => {
let {enabled} = await chrome.storage.local.get('enabled');
enabled = !enabled;
chrome.storage.local.set({enabled});
await chrome.scripting.unregisterContentScripts({ids: ['foo']}).catch(() => {});
if (enabled) {
chrome.scripting.registerContentScripts([{
id: 'foo',
js: ['content.js'],
matches: ['<all_urls>'],
runAt: 'document_start',
}]);
}
const execOpts = enabled ? {files: ['content.js']} : {func: removeExt};
const tabs = (await chrome.tabs.query({}))
.sort(t => t.active ? -1 : 0); // processing the active tab(s) first
for (const {id} of tabs) {
chrome.scripting.executeScript({target: {tabId: id}, ...execOpts})
.catch(() => {});
}
});
function removeExt() {
console.log('Disabling');
// onWheel is the name of the global function used in content.js
if (typeof onWheel === 'function') removeEventListener('wheel', onWheel);
}
// content.js
console.log('Enabling');
if (typeof onWheel !== 'function') (() => {
let timer;
window.onWheel = e => {
clearTimeout(timer);
const x = e.deltaX;
if (x && Math.abs(x) > Math.abs(e.deltaY)) {
timer = setTimeout(() => x > 0 ? history.back() : history.forward(), 200);
}
};
addEventListener('wheel', onWheel);
})();

Context menu not reponding for first click

I am building an extension in which content script is injected on context menu click. This functionality is working. Now the problem I am facing is that, the first click on context menu is not working.
Now the problem I am facing is that, the first click on context menu is not working. Is this a bug?.
background.js
on_message = async(message, sender, sendResponse) => {
console.log("bg.on_message");
sendResponse("from bg");
chrome.storage.local.get("list_url", function (data) {
if (typeof data.list_url != "undefined") {
urls = data.list_url
}
});
chrome.storage.local.get("list_ip", function (data) {
if (typeof data.list_ip != "undefined") {
ips = data.list_ip
}
});
chrome.storage.local.get("list_hash", function (data) {
if (typeof data.list_hash != "undefined") {
hashes = data.list_hash;
}
});
if (hashes){
hash_report = await createHashReport(hashes)
hash_table = await createHashTable(hash_report)
await chrome.storage.local.set({
"scanHash": true,
"hash_table": hash_table
}, () => {});
}
if (ips){
ip_report = await createIpReport(ips)
ip_table = await createIpTable(ip_report)
await chrome.storage.local.set({
"scanIp": true,
"ip_table": ip_table
}, () => {});
}
if (urls){
url_report = await createUrlReport(urls)
url_table = await createUrlTable(url_report)
await chrome.storage.local.set({
"scanUrl": true,
"url_table": url_table
}, () => {});
}
if ( hashes.length>0 || urls.length>0 || ips.length>0 ){
chrome.windows.create({url: "output.html", type: "popup", height:1000, width:1000});
}
}
chrome.runtime.onMessage.addListener(on_message);
genericOnClick = async () => {
// Inject the payload.js script into the current tab after the backdround has loaded
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
chrome.scripting.executeScript({
target: { tabId: tabs[0].id },
files: ["payload.js"]
},() => chrome.runtime.lastError);
});
}
// create context menu
chrome.runtime.onInstalled.addListener(() => {
chrome.contextMenus.create({
id: 'scrapper',
"title": "Scrapper",
"contexts": ["all"]
});
});
chrome.contextMenus.onClicked.addListener(genericOnClick);
payload.js
function extract() {
htmlInnerText = document.documentElement.innerText;
url_exp = /[-a-zA-Z0-9#:%_\+.~#?&//=]{2,256}\.[a-z]{2,4}\b(\/[-a-zA-Z0-9#:%_\+.~#?&//=]*)?/gi;
regex = new RegExp(url_exp)
list_url = htmlInnerText.match(url_exp)
ip_exp = /\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/;
list_ip = htmlInnerText.match(ip_exp)
hash_exp = /\b[A-Fa-f0-9]{32}\b|\b[A-Fa-f0-9]{40}\b|\b[A-Fa-f0-9]{64}\b/g
list_hash = htmlInnerText.match(hash_exp)
await chrome.storage.local.set({ list_url: removeEmails(removeDuplicates(list_url)), list_ip: removeDuplicates(list_ip), list_hash: removeDuplicates(list_hash) });
}
chrome.runtime.sendMessage( extract());
Assuming that "removeEmails" and "removeDuplicates" are synchronous functions (only you know this), the chrome.storage.local.set method instead returns a promise. Basically you send a message to the background hoping that it can read the updated values of list_url, list_ip and list_hash, when instead it has those available before the storage.local.set (so it won't find anything on the first round).
I thought you'd already figured it out yourself with my clue.
Add await keyword before each chrome.storage.local.set

Chrome extension - Uncaught TypeError: Cannot read properties of undefined (reading 'sendMessage')

I am trying to send a message from injected code to background.js.
ContentScript.js
var g = document.createElement('script');
g.src = chrome.runtime.getURL('/js/buttonclick.js');
g.onload = function() {
this.remove();
};
(document.head || document.documentElement).appendChild(g);
buttonclick.js
var qsb = document.createElement("button");
document.body.appendChild(qsb);
qsb.addEventListener("click", submitT);
function submitT(e) {
opSubmit('T'); // opSubmit() is a function in a webpage, it is why I injected this code
window.onbeforeunload = null;
window.scrollTo(0, 0);
chrome.runtime.sendMessage({text: "hey"}, function(response) {
});
}
background.js
chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) {
console.log("Received %o from %o, frame", msg, sender.tab, sender.frameId);
sendResponse("Gotcha!");
chrome.action.setBadgeText( { text: 'X', tabId: sender.tab.id} );
chrome.action.setBadgeBackgroundColor( { color: '#ef5350', tabId: sender.tab.id} );
setTimeout(function () {
chrome.tabs.query({currentWindow: true, active: true}, function(tabs){
uu = tabs[0].url;
tt = uu.indexOf(e);
vv = uu.indexOf(c);
if (tt != -1 || vv != -1) {
chrome.scripting.executeScript({
target: {tabId: sender.tab.id, allFrames: true},
files: ['/js/inject.js']
});
chrome.action.setBadgeText( { text: 'O', tabId: sender.tab.id} );
chrome.action.setBadgeBackgroundColor( { color: 'green', tabId: sender.tab.id} );
};
});
}, 4000);
});
However, when I run it, I get this error in console:
Uncaught TypeError: Cannot read properties of undefined (reading 'sendMessage')
Is it because I tried to execute sendMessage in an injected code? Then how can I change my code so that it will properly send Message?
Alternatively, sendMessage works fine if I call it from content script directly. Is there any way conten script can recognize button click from my injected button(qsb)? I tried adding
qsb.id = "qsb1"
in buttonclick.js and
document.getElementid("qsb1")
in contentscript.js but it can't recognize my button and instead returns null.
Thanks!
Okay, I did it with the latter method. I just added window.onload = function() to make my buttons load first and then used getElementid. It recognized my button correctly.

Same messages being passed more that once while switching tabs fast : Chrome extension issue

I am currently new to building the chrome extension. However I have started to build a chrome extension that scrapes a webpage and stores the data in the google spreadsheet.
Here is my manifest.json:
"manifest_version": 2,
"version": "0.0.1",
"name": "A listener check",
"description": "Understanding the working of listeners in the application",
"content_scripts": [
{
"matches": [
"https://some.website.com/projects/*",
"http://some.website.com/projects/*"
],
"js": [
"content.js"
],
"all_frames": true,
"run_at": "document_end"
},
{
"matches": [
"https://embedded_website.net/*",
"https://embedded_website_2.net/*"
],
"js": [
"demeter.js"
],
"all_frames": true,
"run_at": "document_end"
}
],
"background":{
"scripts": [
"background.js"
]
},
"browser_action": {
"default_popup": "popup/popup.html"
},
"permissions": [
"tabs",
"background",
"management",
"storage"
]
}
Here is my background.js file
const loadedTabs = [];
const switchedTabs = [];
function updatedCallbackFunction(tabId, changeInfo, tab) {
const message = {
action: "load_page",
changeInfo: changeInfo,
tab: tab,
allowLoad: 1,
state: "loaded"
}
if (!loadedTabs.includes(tab.id))
loadedTabs.push(tab.id);
if (changeInfo.status === 'complete') {
chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
chrome.tabs.sendMessage(tab.id, message);
});
}
}
function tabActivatedCallbackFunction(activeInfo) {
const message = {
action: "load_page",
activeInfo: activeInfo,
state: "switched",
allowLoad: 1
}
console.log(`Switched Tabs : ${switchedTabs}`)
if (!switchedTabs.includes(activeInfo.tabId) ) {
switchedTabs.push(activeInfo.tabId);
chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
chrome.tabs.sendMessage(activeInfo.tabId, message);
});
}
}
async function backgroundRuntimeCallbackFunction(message, sender, sendResponse) {
switch (message.action) {
case "unload":
console.log('Wrong page loaded');
break;
case "listen":
console.log('Investigating current page');
chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
chrome.tabs.sendMessage(tabs[0].id, {action: "load_page"});
})
break;
case "demeter_page_direct":
console.log('Going to demeter page');
chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
chrome.tabs.sendMessage(tabs[0].id, {...message, action: 'demeter_page_load'});
});
break;
case "wait_for_page_load":
console.log('Waiting for demeter page load');
chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
chrome.tabs.sendMessage(tabs[0].id, {...message, action: 'demeter_page_load'});
});
break;
case "upload_google_sheet":
console.log('Updating to google sheet');
const {action, allowLoad, QApresent, ...googleSheetData} = message;
console.log(googleSheetData);
googleSheetData.hitlink = googleSheetData.hitlink.substring(0, googleSheetData.hitlink.lastIndexOf('&'));
const options = {
method: 'post',
headers: {
'Content-type': 'application/json'
},
body: JSON.stringify(googleSheetData)
}
const response = await fetch('my_backend_app.com/url_to_fetch', options);
const responseBody = await response.json();
console.log(responseBody);
const boxUpdateMessage = {
...message,
action: "load_page",
allowLoad: 0
};
chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
chrome.tabs.sendMessage(tabs[0].id, boxUpdateMessage);
});
break;
}
}
// creating the functions to get the listeners
function tabUpdateFunction() {
if (chrome.tabs.onUpdated.hasListener(updatedCallbackFunction)) {
console.log('The onupdated listener is already there so removing it!');
chrome.tabs.onUpdated.removeListener(updatedCallbackFunction);
}
// adding the onupdated listener again
console.log('No overhead update function');
chrome.tabs.onUpdated.addListener(updatedCallbackFunction);
}
function tabSwitchFunction() {
if (chrome.tabs.onActivated.hasListener(tabActivatedCallbackFunction)) {
console.log('The tab switch function already there so removing it');
chrome.tabs.onActivated.removeListener(tabActivatedCallbackFunction);
}
console.log('No overhead switch function');
chrome.tabs.onActivated.addListener(tabActivatedCallbackFunction);
}
function backgroundRuntimeFunction() {
console.log(`backgroundRuntimeFunction : ${chrome.runtime.onMessage.hasListener(backgroundRuntimeCallbackFunction)}`);
chrome.runtime.onMessage.removeListener(backgroundRuntimeCallbackFunction);
if (chrome.runtime.onMessage.hasListener(backgroundRuntimeCallbackFunction)) {
chrome.runtime.onMessage.removeListener(backgroundRuntimeCallbackFunction);
}
chrome.runtime.onMessage.addListener(backgroundRuntimeCallbackFunction);
}
// calling the functions
tabUpdateFunction();
tabSwitchFunction();
backgroundRuntimeFunction();
Here is content.js
function getDetails(msg) {
// extract info
return {
action: 'demeter_page_direct',
// more info
};
}
function contentRuntimeCallback(message, sender, sendResponse) {
switch (message.action) {
case "load_page":
const delimiterMessage = getDetails(message);
if (delimiterMessage.title) {
const returnBtnForms = document.getElementsByClassName('force-inline');
for (let returnBtnForm of returnBtnForms) {
returnBtnForm.addEventListener('submit', (e) => {
console.log('Return btn was clicked!');
e.preventDefault();
delimiterMessage.return = 1;
delimiterMessage.allowLoad = 0;
chrome.runtime.sendMessage(delimiterMessage);
})
}
chrome.runtime.sendMessage(delimiterMessage);
}
else {
chrome.runtime.sendMessage({...delimiterMessage, action: 'unload'});
}
break;
}
}
function contentRuntimeCheck() {
if (chrome.runtime.onMessage.hasListener(contentRuntimeCallback))
chrome.runtime.onMessage.removeListener(contentRuntimeCallback);
chrome.runtime.onMessage.addListener(contentRuntimeCallback);
}
contentRuntimeCheck();
and demeter.js
function demeterRuntimeCallbackFunction(message, sender, sendResponse) {
switch (message.action) {
case "demeter_page_load":
if (message.hittitle.includes("specifictitle")) {
const svgParentContainer = document.getElementById('SVG_PARENT_CONTAINER');
if (!svgParentContainer) {
console.log('svg container loading!');
chrome.runtime.sendMessage({...message, action: 'wait_for_page_load'});
break;
} else {
// counting the total number of boxes
const totalBoxes = svgParentContainer.querySelectorAll('rect').length;
// when page loads for the first time
if (message.allowLoad === 1) {
if (message.changeInfo)
console.log('Updated info done');
else if (message.currentTabInfo)
console.log('In port 1');
console.log(`still allowing to load`);
message.allowLoad = 0;
const finalSheetUploadMessage = {
...message,
action: 'upload_google_sheet',
boxcount: totalBoxes
}
chrome.runtime.sendMessage(finalSheetUploadMessage);
break;
} else if (message.return === 1) {
console.log('In port 2');
const finalSheetUploadMessage = {
...message,
hitqueue: message.hitqueue - 1,
action: 'upload_google_sheet',
boxcount: totalBoxes
}
chrome.runtime.sendMessage(finalSheetUploadMessage);
break;
} else {
console.log('In port 3');
const saveBtn = document.querySelector("[aria-label='save']");
const submitBtn = document.querySelector('[aria-label="submit"]');
console.log(submitBtn);
if (saveBtn) {
saveBtn.addEventListener('click', function (e) {
console.log('Save button clicked');
const totalBoxes = svgParentContainer.querySelectorAll('rect').length;
const finalSheetUploadMessage = {
...message,
action: 'upload_google_sheet',
boxcount: totalBoxes
};
chrome.runtime.sendMessage(finalSheetUploadMessage);
});
}
if (submitBtn) {
console.log(submitBtn);
const totalBoxes = svgParentContainer.querySelectorAll('rect').length;
submitBtn.addEventListener('click', (e) => {
const sheetUpdateMessage = {
...message,
action: 'upload_google_sheet',
boxcount: totalBoxes,
submit: 1,
return: 0
}
console.log('Submit btn was clicked');
chrome.runtime.sendMessage(sheetUpdateMessage);
});
break;
}
break;
}
}
}
}
}
if (chrome.runtime.onMessage.hasListener(demeterRuntimeCallbackFunction))
chrome.runtime.onMessage.removeListener(demeterRuntimeCallbackFunction);
chrome.runtime.onMessage.addListener(demeterRuntimeCallbackFunction);
Working
The website i am scraping has an embedded website inside it as an iframe, so I created another content script for it. What i did was scraped details on the original webpage, then sent those details to the embedded webpage to extract further information there and then I am clustering those information and uploading to my google sheet
here is my workflow
content.js -> background.js -> demeter.js -> upload_google_sheet
I have kept allowload = 1 for automatically update the google sheet once all the page loads. Since several instances of the webpage can be open so I tried to implement tab switch event. So that the extension starts firing messages again from scratch once tab switch happens.
Problem
I open let say 3 tabs of the website and rapidly switch tabs among them. I get quite a large number of duplicate rows. I did a lot in tracking and removing listeners. But I really can't find the exact solution or approach to solving this. I want that after rapid switching of tabs. I get the information on the current tab only and no information from other tabs.
Since I am very new to stack overflow. Pardon my long question.

Chrome Extension: "No resource with given identifier found" when trying to Network.getResponseBody

I'm writing a Chrome Extension that can get HTTP response for a site. I try to use debugger for getting response body:
var gCurrentTab;
chrome.debugger.onEvent.addListener(function (source, method, params) {
if (gCurrentTab.id != source.tabId) {
return;
}
if (method == "Network.loadingFinished") {
var tabId = source.tabId;
var requestId = params.requestId;
chrome.debugger.sendCommand(
source,
"Network.getResponseBody",
{"requestId": requestId},
function (body) {
console.log(body);
chrome.debugger.detach(source);
});
}
}
);
chrome.webRequest.onBeforeRequest.addListener(function (details) {
var url = details.url;
if (url.indexOf('/mypage') >= 0) {
chrome.tabs.query({
currentWindow: true,
active: true
}, function (tabs) {
gCurrentTab = tabs[0];
chrome.debugger.attach({
tabId: gCurrentTab.id
}, "1.0", function () {
chrome.debugger.sendCommand({
tabId: gCurrentTab.id
}, "Network.enable");
});
});
}
},
{urls: []}, ["requestBody", "blocking"]);
But I always get
Unchecked runtime.lastError while running debugger.sendCommand: {"code":-32000,"message":"No resource with given identifier found"}
at chrome-extension://ikphgobkghdkjkfplgokmapjlbdfeegl/background.js:11:29
error, and the body is undefined.
Does anyone have idea about why this happen? Thanks!
It was because the website sends many responses, and this code will see another request other than I want, then detach the debugger so I can't get the result.
To solve this, just use a single debugger and do not detach it, or only detach when it's safe to.
var gAttached = false;
var gRequests = [];
var gObjects = [];
chrome.debugger.onEvent.addListener(function (source, method, params) {
if (method == "Network.requestWillBeSent") {
// If we see a url need to be handled, push it into index queue
var rUrl = params.request.url;
if (getTarget(rUrl) >= 0) {
gRequests.push(rUrl);
}
}
if (method == "Network.responseReceived") {
// We get its request id here, write it down to object queue
var eUrl = params.response.url;
var target = getTarget(eUrl);
if (target >= 0) {
gObjects.push({
requestId: params.requestId,
target: target,
url: eUrl
});
}
}
if (method == "Network.loadingFinished" && gObjects.length > 0) {
// Pop out the request object from both object queue and request queue
var requestId = params.requestId;
var object = null;
for (var o in gObjects) {
if (requestId == gObjects[o].requestId) {
object = gObjects.splice(o, 1)[0];
break;
}
}
// Usually loadingFinished will be immediately after responseReceived
if (object == null) {
console.log('Failed!!');
return;
}
gRequests.splice(gRequests.indexOf(object.url), 1);
chrome.debugger.sendCommand(
source,
"Network.getResponseBody",
{"requestId": requestId},
function (response) {
if (response) {
dispatch(source.tabId, object.target, JSON.parse(response.body));
} else {
console.log("Empty response for " + object.url);
}
// If we don't have any request waiting for response, re-attach debugger
// since without this step it will lead to memory leak.
if (gRequests.length == 0) {
chrome.debugger.detach({
tabId: source.tabId
}, function () {
chrome.debugger.attach({
tabId: source.tabId
}, "1.0", function () {
chrome.debugger.sendCommand({
tabId: source.tabId
}, "Network.enable");
});
});
}
});
}
}
);
var initialListener = function (details) {
if (gAttached) return; // Only need once at the very first request, so block all following requests
var tabId = details.tabId;
if (tabId > 0) {
gAttached = true;
chrome.debugger.attach({
tabId: tabId
}, "1.0", function () {
chrome.debugger.sendCommand({
tabId: tabId
}, "Network.enable");
});
// Remove self since the debugger is attached already
chrome.webRequest.onBeforeRequest.removeListener(initialListener);
}
};
// Attach debugger on startup
chrome.webRequest.onBeforeRequest.addListener(initialListener, {urls: ["<all_urls>"]}, ["blocking"]);
// Filter if the url is what we want
function getTarget(url) {
for (var i in TARGETS) {
var target = TARGETS[i];
if (url.match(target.url)) {
return i;
}
}
return -1;
}
const TARGETS = [
{url: '/path1', desc: 'target1'},
{url: '/path2', desc: 'target2'}
]
I am facing similar issue. I figured that sendCommand was not executing immediately. I was facing the issue for the requests which are sent before sending "Network.enable" was complete. Try adding completion for
chrome.debugger.sendCommand({
tabId: gCurrentTab.id
}, "Network.enable")

Categories

Resources