Reputation: 1534
I have an extension where I call
function doScript(window) {
chrome.scripting.executeScript(
{
target: {tabId: window.tabs[0].id},
files: ['myscript.js'],
});
}
myscript.js simply has
alert("Made it")
but I get no alert in my tab.
If I change the tabId to something random like 123
chrome.scripting.executeScript(
{
target: {tabId: 123},
files: ['myscript.js'],
});
then I get an error "Unchecked runtime.lastError: No tab with id: 123"
So it looks like my tabId is right, but for some reason myscript.js is not triggering an alert.
If I mess up the script name like this
chrome.scripting.executeScript(
{
target: {tabId: window.tabs[0].id}},
files: ['ttttttttttt.js'],
});
I get "runtime.lastError: Could not load file: 'ttttttttttt.js'."
I tried looking through the console logs and the only thing I see is this error upon clicking but it looks like a red herring.
"Unchecked runtime.lastError: Cannot access contents of url "". Extension manifest must request permission to access this host." https://github.com/GoogleChrome/web-vitals-extension/issues/54
Here is my manifest
{
"manifest_version": 3,
"name": "pokemon bokemon",
"description": "",
"version": "0.3.0",
"action": {
"default_popup": "popup.html"
},
"icons": {
"16": "icon16.png",
"32": "icon32.png"
},
"permissions": [
"tabs",
"storage",
"scripting",
"activeTab",
"cookies"
],
"host_permissions": [
"*://*/*",
"<all_urls>"
],
"options_page": "options.html"
}
EDIT: Apparently it's a bug in chrome/manifest v3. Opened a bug here: https://bugs.chromium.org/p/chromium/issues/detail?id=1191971
Upvotes: 25
Views: 48996
Reputation: 49150
[For Manifest v3]
You can also execute a function directly instead of passing a file:
Add this line in manifest.json:
"permissions": ["scripting"]
let [tab] = await chrome.tabs.query({ active: true, currentWindow: true })
// Execute script in the current tab
await chrome.scripting.executeScript({
target: { tabId: tab.id },
func: (items) => {
Object.keys(items).forEach((key) => {
localStorage.setItem(key, items[key])
})
},
args: [items] // pass any parameters to function
})
Upvotes: 8
Reputation: 7958
I also encountered the same problem, and I share my experience as follows.
If you use chrome.windows.create
to create a new tab(panel, popup,...) and then call chrome.scripting.executeScript
in the new one. Unfortunately, it will not work.
for example
// popup.js
const targetURL = 'templates/main.html'
chrome.windows.create(
{
focused: true,
url: targetURL,
type: 'popup',
},
(subWindow) => {
}
)
// But you can put the ``chrome.scripting.executeScript``here, which will be fine.
chrome.scripting.executeScript({})
does not work in templates/main.html
<script>
// templates/main.html
chrome.tabs.query({active: true, currentWindow: true}).then(([tab]) => {
chrome.scripting.executeScript(
{
target: {tabId: tab.id},
files: ['myscript.js'],
// function: () => {}, // files or function, both do not work.
})
})
</script>
If you want to communicate with each other, you can try.
chrome.tabs.sendMessage(myTabID, {event: 'myTest'}, ({msg, other})=>{
console.log(msg) // hello
console.log(other) // test
})
chrome.runtime.onMessage.addListener((media, sender, sendResponse) => {
if (media.event === 'myTest') {
sendResponse({msg:"hello", other:"test"})
}
})
If you need a working example, you can refer to one of my repositories.
https://github.com/CarsonSlovoka/chrome/tree/7f1e731/tutorials/extensions/tabs-info
Click the button, and the following log will show some information from the tabs.
Suggested order for your reading:
two parts
sendMessage
onMessage
chrome.tabs.sendMessage
: When you add callback parameters, it will return undefined
.
if you want to handle the error by yourself, you should omit this parameter, which will return the Promise
. exampleUpvotes: 6
Reputation: 800
The problem comes from the fact that the chrome.scripting.executeScript
part is executed too fast.
For instance it starts working if you add a timer of 2 seconds:
const timer = ms => {
function randn_bm(middle_number) {
let u = 0, v = 0;
while(u === 0) u = Math.random(); //Converting [0,1) to (0,1)
while(v === 0) v = Math.random();
let num = Math.sqrt( -2.0 * Math.log( u ) ) * Math.cos( 2.0 * Math.PI * v );
num = num / 10.0 + 0.5; // Translate to 0 -> 1
if (num > 1 || num < 0) return randn_bm() // resample between 0 and 1
return num * 2 * middle_number
}
ms=randn_bm(ms);
console.log(ms)
return new Promise(res => setTimeout(res, ms));
}
You can use this timer like so: await timer(2000)
For sure an async behaviour would be preferable but so you understand why this happens: the script is executed before the new tab completely opened. Therefore the function is never executed.
Upvotes: 2
Reputation: 599
Manifest version 3 Use this:
chrome.tabs.query({currentWindow: true, active: true}, function(tabs){
console.log(tabs[0].url);
console.log(tabs[0].id);
my_tabid=tabs[0].id;
});
alert(my_tabid);
chrome.scripting.executeScript(
{
target: {tabId: my_tabid},
files: ['myscript.js'],
});
Upvotes: 2