0

I am trying to inject content script on context menu click in an extension manifest version 3. I need to check if it is already injected or not. If it is not injected , inject the content script. This condition has to be satisfied. Can anyone help me with this?

We can use

ALREADY_INJECTED_FLAG

but this can be checked only in the content script, so this approach will not work as expected.

payload.js(content script)

function extract() {
 
 htmlInnerText = document.documentElement.innerText;
 url_exp = /[-a-zA-Z0-9@:%_\+.~#?&//=]{2,256}\.[a-z]{2,4}\b(\/[-a-zA-Z0-9@:%_\+.~#?&//=]*)?/gi;
 regex = new RegExp(url_exp)
 list_url = htmlInnerText.match(url_exp)
 ip_exp = /\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/;
 list_ip = htmlInnerText.match(ip_exp)
 hash_exp = /\b[A-Fa-f0-9]{32}\b|\b[A-Fa-f0-9]{40}\b|\b[A-Fa-f0-9]{64}\b/g
 list_hash = htmlInnerText.match(hash_exp)
 chrome.storage.local.set({ list_url: list_url, list_ip: list_ip, list_hash: list_hash });
}
chrome.runtime.sendMessage( extract());

background.js

genericOnClick = async () => {
 // Inject the payload.js script into the current tab after the backdround has loaded
 chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
 chrome.scripting.executeScript({
 target: { tabId: tabs[0].id },
 files: ["payload.js"]
 },() => chrome.runtime.lastError);
 });
 
 // Listen to messages from the payload.js script and create output.
 chrome.runtime.onMessage.addListener(async (message) => {
 
 chrome.storage.local.get("list_url", function (data) {
 if (typeof data.list_url != "undefined") {
 urls = data.list_url
 }
 });
 chrome.storage.local.get("list_ip", function (data) {
 if (typeof data.list_ip != "undefined") {
 ips = data.list_ip
 }
 });
 chrome.storage.local.get("list_hash", function (data) {
 if (typeof data.list_hash != "undefined") {
 hashes = data.list_hash;
 }
 });
 
 if ( hashes.length>0 || urls.length>0 || ips.length>0 ){
 chrome.windows.create({url: "output.html", type: "popup", height:1000, width:1000});
 }
 });
}
4
  • 1
    You can check it inside the content script as shown here. Commented Nov 30, 2022 at 9:23
  • The output html is called from background after getting a message from content script. on my first context menu click I get the output html once. Second time I click, I get the output html twice likewise. If I use this condition mentioned, the output screen will come only once for a webpage . second time you click the context menu , no output. Commented Nov 30, 2022 at 10:41
  • 1
    It means you're not using the example correctly. Please show your code. Commented Nov 30, 2022 at 11:34
  • Code added. Please review Commented Nov 30, 2022 at 12:05

1 Answer 1

1

on my first context menu click I get the output html once. Second time I click, I get the output html twice likewise.

This behavior is caused by a combination of two factors.

First factor

You're calling chrome.runtime.onMessage.addListener() inside genericOnClick(). So every time the user clicks the context menu item, the code adds a new onMessage listener. That wouldn't be a problem if you passed a named function to chrome.runtime.onMessage.addListener(), because a named function can only be registered once for an event.

function on_message(message, sender, sendResponse) {
 console.log("bg.on_message");
 sendResponse("from bg");
}
chrome.runtime.onMessage.addListener(on_message);

Second factor

But you're not registering a named function as the onMessage handler. You're registering an anonymous function. Every click on the context menu item creates and registers a new anonymous function. So after the Nth click on the context menu item, there will be N different onMessage handlers, and each one will open a new window.

Solution

  1. Define the onMessage handler as a named function, as shown above.
  2. Call chrome.runtime.onMessage.addListener() outside of a function.

You don't have to do both 1 and 2. Doing either will solve your problem. But I recommend doing both, because it's cleaner.

answered Nov 30, 2022 at 13:35
Sign up to request clarification or add additional context in comments.

4 Comments

It is working. I have been behind this for days. Thank you
One more query. When we open a webpage, the output.html is opened without context menu click. What can I do restrict output.html coming on load?
@toniajsebastian I learned the hard way that I must know when to stop helping. If I don't, it'll be bad for my mental health. When I read "One more query", followed by very little information, I knew that this point had been reached. Some friendly advice: Don't use the comments to ask additional questions, because your options for formatting text are very limited. Create a new question instead.
@toniajsebastian In your new question, provide an MCVE. If you give people something they can actually run on their computer, you'll drastically increase your chances of getting a helpful answer. I will not answer your new question, but if you put enough time and effort into it, I'm sure someone else will. See also How do I ask a good question?

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.