How to executeScript for webRequest event onBeforeRequest in Google Chrome Extension - google-chrome

Following Chrome Extension Manifest V3 rule I want to create an extension, that listens to particular network request and, for startes, just log them to the console of the currently opened tab (later I want to add custom script and styles to the page in the current tab).
For this I try to utilize chrome.scripting.executeScript.
When I implement the sample from https://github.com/GoogleChrome/chrome-extensions-samples/blob/main/examples/page-redder/manifest.json it works like expected for the chrome.action.onClicked listener.
As soon as I try to execute a script within the chrome.webRequest.onBeforeRequest listener, this error pops up:
Error in event handler: TypeError: Error in invocation of
scripting.executeScript(scripting.ScriptInjection injection, optional
function callback): Error at parameter 'injection': Error at property
'target': Missing required property 'tabId'.
at chrome.webRequest.onBeforeRequest.addListener.urls ()
Missing required property tabId? I assume it has to do with the lifecycle, but I cannot figure out what to do. This is my manifest:
{
"name": "Getting Started Example",
"description": "Build an Extension!",
"version": "1.0",
"manifest_version": 3,
"background": {
"service_worker": "background.js",
"matches": [ "<all_urls>"]
},
"host_permissions": [
"<all_urls>"
],
"permissions": [
"activeTab",
"tabs",
"webRequest",
"webNavigation",
"management",
"scripting"
]
}
And this is my script, I just slightly modified the "redden"-example:
function reddenPage(url) {
console.log(url);
}
chrome.webRequest.onBeforeRequest.addListener((tab) => {
chrome.scripting.executeScript({
target: { tabId: tab.id },
function: reddenPage,
args: [tab.url],
});
},
{urls: ["*://*.google.com/*"]},
[]);

I don't know exactly why, but the script from Github seems not work. This is how it works:
It's not only a couple of changed brackets, look at tab instead of (tab), but also tab.tabId instead of tab.id:
chrome.webRequest.onBeforeRequest.addListener(tab => {
chrome.scripting.executeScript(
{
target: { tabId: tab.tabId },
function: reddenPage,
args: [details.url],
},
() => { console.log('ZZZ') });
}, {
urls: ['<all_urls>']
});

Related

Can `content_scripts` detect if a `command` is set?

My extension currently uses the [esc] key to perform an action.
This is done in the content-script, using addEventListener('keydown').
I'd like the user to be able to choose a different shortcut.
I've updated to Manifest V3, and added a new "commands" key, i.e.
{
...
"manifest_version": 3,
"background": {
"service_worker": "background.js"
},
"content_scripts": [ {
"js": [ "screenshot.js" ],
"matches": [ "http://*/*", "https://*/*" ]
}],
"commands": {
"stop-animations": {
"description": "Stop Animations"
}
}
}
I've updated background.js to use chrome.commands.onCommand, and this works well.
But, how can I get my content-script to determine if the user has set their own shortcut?
Because I should not listen to the 'keydown' event to check if they have pressed the [esc] key.
I've tried using chrome.commands.getAll(), but this method is only available at install time.
A partial option would be to use something like browser.storage to set a simple boolean "custom-command-set" to true whenever onCommand is used, but I cannot think of a way to switch it off again if the user deletes the shortcut command (i.e. they want to go back to using the [esc] key).
At the moment I don't have a toolbar icon (action default_popup), or any other UI, and I'd prefer to not add one just to provide a custom way to set the shortcut.
Content scripts can't call chrome.commands.getAll() directly, so they need to send a message to the service worker. The SW calls chrome.commands.getAll() and sends the result back to the content script.
manifest.json
{
"manifest_version": 3,
"name": "chrome.commands.getAll",
"version": "1.0.0",
"background": {
"service_worker": "background.js"
},
"content_scripts": [
{
"js": [ "content_script.js" ],
"matches": [ "*://*/*" ]
}
],
"commands": {
"test": {
"description": "Test"
}
},
"permissions": ["commands"]
}
background.js
function commands_on_command(command) {
console.log("on_command", command);
}
function runtime_on_message(message, sender, sendResponse) {
if (message == "get_all_commands") {
chrome.commands.getAll()
.then(commands => {
console.log("background.js", "runtime_on_message", commands);
sendResponse(commands);
});
return true; // https://developer.chrome.com/docs/extensions/mv3/messaging/#simple
}
else {
console.log("background.js", "runtime_on_message", "unknown command");
sendResponse("unknown command");
}
}
chrome.commands.onCommand.addListener(commands_on_command);
chrome.runtime.onMessage.addListener(runtime_on_message);
content_script.js
(async () => {
let response = await chrome.runtime.sendMessage("get_all_commands");
console.log("content_script.js", response);
})();

how i can fix error about chrome extension

I have written a simple extension just to learn how it works.
Manifest V3:
{ "name": "Sample",
"version": "1.0",
"manifest_version": 3,
"action": {
"default_name": "Sample",
"default_popup": "popup.html"
},
"background": {
"service_worker": "background.js"
},
"permissions": ["tabs", "storage", "activeTab", "clipboardRead", "scripting"],
"host_permissions": ["http://*/", "file://*/*", "https://*/", "*://*/*"]
}
popup.html:
.....
.....
<button id='getInfo' >GET</button>
.....
.....
popup.js:
....
document.getElementById("getInfo").addEventListener("click", function() {
chrome.tabs.query(
{active: true, currentWindow: true},
(tabs) => {
chrome.scripting.executeScript({
target: {tabId: tabs[0].id},
file: ['func.js'],
});
});
}
func.js:
alert("extension sample")
When i press the button 'GET' i receive an error in extension manager page.
The error says: "Error handling response: TypeError: Error in invocation of scripting.executeScript(scripting.ScriptInjection injection, optional function callback): Error at parameter 'injection': Unexpected property: 'file'."
I have tried with function instead of the file and it works.
How i can fix this error? Thank you.
chrome.scripting.executeScript does not have file property.
You should use files property.
Search for "executeScript" in the official Google documentation below to see the sample.
https://developer.chrome.com/docs/extensions/reference/scripting/

Chrome - Message passing - From popup click to context script on specific tab

Can you tell me why the following code is not working. Here is my code :
Popup.js (not a backgorund script) :
chrome.tabs.create({url: url}, function(tab) {
chrome.tabs.executeScript(tab.id, {file: 'connect.js', allFrames:true}, function() {
chrome.tabs.sendMessage(tab.id, 'whatever value; String, object, whatever');
});
});
content script :
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
console.log(message);
// Handle message.
// In this example, message === 'whatever value; String, object, whatever'
});
And my manifest :
{
"name": "AN App",
"version": "1.0",
"description": "To connect",
"permissions": [
"storage",
"activeTab",
"tabs",
"https://*/*"],
"browser_action": {
"default_popup": "popup.html"
},
"content_scripts": [{
"matches": ["https://*/*"],
"js": ["connect.js"]
}],
/*
"background": {
"scripts": ["background.js"]
},*/
"manifest_version": 2
}
I don't understand, the console debug in the tab do not display anything...
I also try from the popup to the background and then from the background to the tab but nothing happen neither (I'm quite new at chrome extension so I hope u can help me)
Thanks,
Regards
Martin
I found the solution. When I call chrome.tabs.create from the JS inside the popup it closes the code running in the popup and the message is never sent.
So instead of calling the chrome.tabs.create inside the JS linked to the popup, I just send a message to the background script, the background script call chrome.tabs.create (like this it runs in background and the code do not stop from executing).
And then the message function works correctly like chrome doc says.
Martin

Chrome Extension Notifications Not Appearing

I've been trying to develop a chrome extension that creates notifications after certain periods of time. I've been using both chrome.alarms and chrome.notifications to accomplish this, but I cannot get notifications to appear, even when creating them from the console. I also don't get any errors from runtime.lastError in the callback. I do know for certain that the alarm listener and callback are being executed.
manifest.json
{
"manifest_version": 2,
"name": "notifications",
"version": "0.0",
"browser_action": {
"default_popup": "popup.html"
},
"background": {
"scripts": ["notifications.js"],
"persistent": false
},
"permissions": [
"alarms",
"storage",
"notifications"
],
"web_accessible_resources": [
"mascot48.png"
]
}
notifications.js
function resetTimer(id, minutes) {
chrome.alarms.create(id,{delayInMinutes: minutes});
}
chrome.alarms.onAlarm.addListener((alarm) => {
console.log('alarm!');
chrome.notifications.create('reminder', {
type: 'basic',
iconUrl: 'mascot48.png',
title: 'Dont forget!',
message: 'You have things to do'
}, function(notificationId) {
console.log(chrome.runtime.lastError);
});
});
Is there anything clear that I'm getting wrong?
EDIT: For clarity, notifications.js is my events page, the popup page is the one that runs the code to start the alarms.

Chrome extension executescript into external drive file

I have created an extension that uses the executescript api to inject a piece of code (shown below) that basically on window.onbeforeunload confirms they want to close the page. I have the script working, and by using the file://*/* permission, got it to inject on file URLs. However, when testing it on a flash game I downloaded, the script didn't inject. The URL was externalfile:drive-randomtext/root/SWFNAME.swf. I tried adding externalfile://*/* in the permissions but got the following error message: There were warnings when trying to install this extension: Permission 'externalfile://*/*' is unknown or URL pattern is malformed. Is there an external file permission, or another way to do this?
Manifest.json:
{
"name": "name",
"short_name": "name",
"version": "3.6",
"manifest_version": 2,
"description": "Desc",
"permissions": [
"storage",
"http://*/",
"https://*/",
"tabs",
"activeTab",
"webNavigation",
"*://*/*",
"file://*/*"
],
"page_action": {
"default_icon": "logo.png"
},
"background": {
"scripts": ["disabled.js"]
}
}
Script that gets executed:
(hotkey-binding code too long, can be found here)
Mousetrap.bind('ctrl+m', function(e) {
window.onbeforeunload = confirmExit;function confirmExit(){alert('confirm exit is being called');return'Close page?';}
alert('Enabled');
return false;
});
Mousetrap.bind('ctrl+q', function(e) {
location.reload();
return false;
});