Sorry for my english, i will do my best.
I need to create an extension where the popup contains a field and a button.
The goal is that once the button is clicked, a new window opens (another website) and you have to send the popin field information in this new window.
There is my manifest.json
{
"name": "Webrelief extension",
"version": "1",
"browser_action":
{
"default_icon": "webrelief.ico",
"default_popup": "popup.html",
"default_title": "Webrelief extension - Iello"
},
"background":
{
"scripts": ["background.js"],
"persistent": true
},
"content_scripts": [
{
"run_at": "document_end",
"matches": [
"https://www.iello.pro/iello-c102x3259540",
"https://www.google.com/"
],
"js": ["jquery.min.js","content.js"]
}
],
"permissions": ["tabs","activeTab","<all_urls>"],
"manifest_version": 2,
"content_security_policy": "script-src 'self' https://www.iello.pro/iello-c102x3259540; object-src 'self'"
}
My background.js
$('#validate').on('click',function(activeTab){
var newURL = "https://www.iello.pro/iello-c102x3259540";
chrome.tabs.create(
{
url: newURL
}, function() {
chrome.tabs.query({active: false, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[tabs.length - 1].id, {greeting: "hello"}, function(response) { // tabs[tabs.length - 1] to get the new windows ? I'm not sure
console.log(response);
});
});
}
);
});
My content.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
console.log(sender.tab ?
"from a content script:" + sender.tab.url :
"from the extension");
if (request.greeting == "hello")
sendResponse({farewell: "goodbye"});
});
And my popup.html
<!doctype html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Webrelief Extension</title>
<link href="css/main.css" rel="stylesheet">
</head>
<body>
<img width="400px" src="webrelief_logo.svg" alt="Bannière webrelief">
<hr>
<div>
<textarea placeholder="Veuillez saisir le json ici ..." name="json" id="json_iello" cols="30" rows="10"></textarea>
</div>
<button id="validate">Go !</button>
<script src="background.js"></script>
</body>
</html>
Currently if I press the button, my new window opens, but I do not receive the message on the new window.
Can you tell me my mistakes
Thanks !
There are three principal issues here.
There isn't really a good duplicate of this question (this is the closest candidate), but the main issue you're having is timing.
After opening a tab, the callback of create
is called before the page is sufficiently loaded. Your content script may simply not be there yet to listen to the message. With document_end
timing, it's almost certainly not the case.
The only safe way to do it is to reverse the communication: let the content script request the data, so that way you know it's ready.
This leads to the next issue..
When you create a tab that is focused, this causes the popup to lose focus and close.
When that happens, the script that was running there is terminated - as if you closed a tab with the page.
So the rest of your code isn't even run (regardless of the previous issue). You have two options here:
You could create a tab with active: false
set. This doesn't lose focus, so the popup stays active, but is less convenient for the user, though you can still make it active after that.
As an unrelated note, you shouldn't query
when functions like tabs.create
explicitly return a tab
object in their callback.
Better option: you should delegate the opening-then-communication to your background page. It is immune to the effect of popup closure and is generally better suited as a "communication router".
Which brings us to the last problem..
You declared a background.js
script in the manifest as the background script. What does that mean?
It means that a separate, invisible, empty page is created and loaded with that script running.
If you include a background.js
script in other places in the extension, it won't be "that" instance of the script. It will be an independent copy running and subject to all limitations of its new context.
Very strong advice: do not attempt to reuse whole scripts in your code. It's fine to have some shared code (say, utils.js
holding some common functions, and included before respective scripts), but take care to call your scripts descriptively and separate code.
To interact with the "real" background page, you'll need to send messages (with chrome.runtime.sendMessage
).
Putting it all together, your logic should be:
popup.js
script), listen for your UI event.chrome.storage
) the user data.chrome.storage
, or request it (via runtime.sendMessage
) from the background page.There's a concern that your content script is launched every time the target page opens, even when you don't want to use the user data. You could either implement some mechanism to only use the data once (e.g. clear / flag it after use) or only inject the content script programmatically (though you again will have timing issues to deal with after tabs.create
)