Access stack trace from content script and pass it to background script - javascript

I am creating a Firefox extension, where I want to get the stack trace each time a network request is sent. Currently, I inject a content script to access the stack but cannot get the content script to send the stack trace back to background script. Specifically, I listen for a message in content script (from background script) with browser.runtime.onMessage.addListener and call my code in the content script to get me the stack trace but it seems that when I am inside the browser.runtime.onMessage.addListener I cannot call JS methods that I injected with the content script. Any ideas on how I can get the stack trace when a network request is initiated?
background.js:
browser.webRequest.onBeforeSendHeaders.addListener(
function (details) {
if (details.tabId == -1) {
return;
}
browser.tabs.sendMessage(details.tabId, { content: details.url });
},
{
urls: [
"http://*/*",
"https://*/*",
],
},
["requestHeaders", "blocking"]
);
content_script.js
function getPageScript() {
return "function codeToInject() {console.trace();} codeToInject();";
}
function insertScript(text) {
var parent = document.documentElement,
script = document.createElement('script');
script.text = text;
script.async = false;
parent.insertBefore(script, parent.firstChild);
}
browser.runtime.onMessage.addListener(returnStack);
function returnStack() {
insertScript(getPageScript());
}
manifest.json
{
"manifest_version": 2,
"name": "call-stack-retrieval",
"version": "0.0",
"background": {
"persistent": true,
"scripts": [
"background.js"
]
},
"content_scripts": [{
"all_frames": true,
"js": [
"content_script.js"
],
"match_about_blank": false,
"matches": [
"<all_urls>"
],
"run_at": "document_start"
}],
"permissions": [
"tabs",
"<all_urls>",
"contextMenus",
"webRequest",
"webRequestBlocking",
"webNavigation",
"storage",
"unlimitedStorage",
"notifications"
]
}

Related

why is chrome failing to load my custom extension with error "Service worker registration failed. Status code: 10"?

I am trying to load my custom extension in chrome, but I'm getting an error and the service worker is marked as "inactive"
This is my manifest file contents (removed sensitive paths):
{
"name": "Quicker",
"version": "1.0",
"description": "Automation quick actions performer",
"manifest_version": 3,
"permissions": [
"storage",
"activeTab",
"tabs",
"notifications",
"background",
"management"
],
"content_scripts": [
{
"matches": [
"..."
],
"js": [
"jquery-3.4.1.min.js",
"contentScript.js"
],
"run_at": "document_end"
},
{
"matches": [
"..."
],
"css": [
"jenkinsStyle.css"
],
"run_at": "document_end"
}
],
"action": {
"default_popup": "popup.html"
},
"background": {
"service_worker": "background.js"
},
"web_accessible_resources": [
{
"resources": [
"..."
],
"matches": [
"<all_urls>"
]
}
],
"icons": {
"128": "autoCog.png"
}
}
I've tried resetting chrome, updating, reinstalling. I've also tried to load the background file in a try/catch block and to load an empty background file all attempts yield the above state.

Chrome extension, send message from panel.js to content script

I'm trying to intercept youtube requests response from a devtool panel and send it to the content or background script of a Chrome extension. but I can't get it to work.
There is loads of exemple online but most of them use Manifest V2 and I really want to make it work on V3.
I don't know which method to use for sending messages to the content or background script from the panel.js, nor do I know how to listen for incoming messages from the panel in those scripts.
And I don't know if I need to add more permissions in my manifest for this to work :
{
"manifest_version": 3,
"name": "Already Seen",
"version": "1",
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["jquery-3.6.0.min.js", "content.js"],
"css": ["avatar.css"]
}
],
"devtools_page" : "devtools.html",
"action": {
"default_icon": "icon.png"
},
"background": {
"service_worker": "background.js"
},
"permissions": ["identity", "storage", "tabs", "webRequest"],
"host_permissions": ["https://www.youtube.com/", "https://youtube.com/"],
"externally_connectable": {
"matches": ["https://youtube.com/*"]
},
"oauth2": {
"client_id": "***************",
"scopes": [
"https://www.googleapis.com/auth/userinfo.email",
"https://www.googleapis.com/auth/userinfo.profile"
]
}
}
devtools.html
<script src="devtools.js"></script>
devtools.js
chrome.devtools.panels.create("Already Seen", "icon.png", 'panel.html');
panel.html
<html>
<body>
<script src="panel.js"></script>
</body>
</html>
panel.js
chrome.devtools.network.onRequestFinished.addListener((request) => {
request.getContent((body) => {
if (!request.request || !request.request.url) return;
// I NEED TO SEND THE MESSAGE HERE TO BACKGROUND.JS OR CONTENT.JS
});
});
I found another way of doing this by using the chrome.debbuger in the background script but it shows "... started debugging this browser" on top of every pages.

Javascript - code injected multiple times on specific website

I would like to know why and how to fix:
My code is being injected a few times while being o specific website, can't find why.
It should be injected only when visiting a specific url (it can be different for example tickets/*****).
manifest.json
{
"manifest_version": 2,
"name": "ext",
"version": "1.619",
"description": "Does things:)",
"background": {
"scripts": ["background.js"]
},
"content_scripts": [
{
"matches": ["https://www.example.com/agent/tickets/*"],
"js": ["foreground.js"]
}
],
"permissions": [
"tabs",
"activeTab",
"http://*/",
"https://*/"
]
}
background.js
chrome.tabs.onUpdated.addListener(function(id, info, tab){
/*if (tab.status !== "complete"){
return;
}*/
if(tab.url.indexOf("tickets") != -1){
console.log("injected");
chrome.tabs.executeScript(tab.id, {"file": "foreground.js"});
}
});

Google Chrome - passing a variable to an extension

Currently I'm trying to pass an array from the context_script into my popup.html on a button click from the extension. However there have been complications which I can't seem to solve on my own, almost every single one of the implementation methods in SO and other sites don't seem to work out.
All I really need is to simply pass a single list from the context, into the JavaScript page that handles the extensions HTML interface.
background.js
"use strict";
function Master() {
firebase.initializeApp(config);
this.time = 0;
this.http_usage = this.get_http();
this.https_usage = this.get_https();
this.todays_usage = this.get_today_sites();
chrome.runtime.onMessage.addListener(function(message,sender,sendResponce) {
sendResponce("Hello world");
});
this.init();
}
manifest.json
{
"name": "Statistics",
"description": "Saves time and visitation data.",
"version": "1.0",
"manifest_version": 2,
"permissions": [
"activeTab",
"tabs",
"http://*/*",
"https://*/*",
"clipboardRead",
"clipboardWrite",
"background"
],
"content_scripts": [
{
"matches": [
"*://*/*"
],
"js": [
"config.js",
"firebase.js",
"background.js"
],
"css": [
"styles.css"
]
}
],
"browser_action": {
"default_title": "Statistics",
"default_popup": "popup.html"
}
}
popup.js
function get_data(){
let data = []
chrome.runtime.sendMessage({data:"giblist"}, function (responce) {
console.log(responce);
...
});
}
document.addEventListener('DOMContentLoaded', function () {
console.log("Loaded page");
firebase.initializeApp(config);
document.getElementById("showStatistics").addEventListener("click", get_data);
});

chrome extension: run script after page has finished loading javascript

this is not firing at all when the page finishes loading. Basically when I click the browser action button, it will trigger it on, and on page load, it will run a script. In my background.js
var toggle = false;
chrome.browserAction.onClicked.addListener(function(tab) {
toggle = !toggle;
if(toggle){
chrome.browserAction.setIcon({path: "icons/logo.png", tabId:tab.id});
// chrome.tabs.executeScript(tab.id, {file:"SCRIPT.user.js"});
chrome.tabs.executeScript(tab.id, {code:"alert('aaxxxbbaa')"});
}
else{
chrome.browserAction.setIcon({path: "icons/icon48.png", tabId:tab.id});
chrome.tabs.executeScript(tab.id, {code:"alert('bbdxdb')"});
}
});
var filter = {'url': [
{hostSuffix: '*', pathPrefix: ''},
{hostSuffix: '*', pathPrefix: ''}
]};
chrome.webNavigation.onDOMContentLoaded.addListener(function(tab){
if (toggle)
chrome.tabs.executeScript(tab.id,{code:"alert('loaded')"});
},filter);
I've also tried to set it in the manifest
{
"name": "Tool",
"version": "0.0.1",
"manifest_version": 2,
"description": "Te",
"homepage_url": "",
"icons": {
"16": "icons/logo.png",
"48": "icons/logo.png",
"128": "icons/logo.png"
},
"default_locale": "en",
"background": {
"page": "src/bg/background.html",
"persistent": true
},
"browser_action": {
"default_icon": "icons/logo.png",
"default_title": "browser action demo"
},
"permissions": [
"<all_urls>"
],
"content_scripts": [
{
"run_at": "document_end",
"matches": [
"https://www.google.ca/*"
],
"css": [
"src/inject/inject.css"
]
},
{
"run_at": "document_end",
"matches": [
"https://www.google.ca/*"
],
"js": [
"src/inject/inject.js"
]
}
]
}
and in my inject.js
chrome.extension.sendMessage({}, function(response) {
var readyStateCheckInterval = setInterval(function() {
if (document.readyState === "complete") {
clearInterval(readyStateCheckInterval);
// ----------------------------------------------------------
// This part of the script triggers when page is done loading
console.log("Hello. This message was sent from scripts/inject.js");
// ----------------------------------------------------------
}
}, 10);
});
window.addEventListener ("load", myMain, false);
function myMain (evt) {
console.log('aaann');
var jsInitChecktimer = setInterval (checkForJS_Finish, 111);
function checkForJS_Finish () {
if ( typeof SOME_GLOBAL_VAR != "undefined"
|| document.querySelector ("SOME_INDICATOR_NODE_css_SELECTOR")
) {
clearInterval (jsInitChecktimer);
// DO YOUR STUFF HERE.
console.log('hi');
}
}
}
In your manifest file, you have duplicate content scripts, one with CSS and one with JS. It should look like this:
"content_scripts": [
{
"run_at": "document_end",
"matches": [
"https://www.google.ca/*"
],
"js": [
"src/inject/inject.js"
],
"css": [
"src/inject/inject.css"
]
}
]
Also, if you want it to match other urls, you will need to add them specifically, or use
"matches": ["<all_urls>"]
As for your proposed background script, that is essentially re-inventing the concept of content scripts, and it may not be in your best interest. I suggest sticking with the content script route.

Categories