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
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.
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.
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"});
}
});
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);
});
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.