1

I finished writting my first extension and it works as I programmed it, but after completing it, I realised I made a mistake in its design, currently its designed to alert me before a event occurs (webRequest.onBeforeRequest()), I want to be alerted after the event has occurred and completed (webRequest.onCompleted()).

I tried changing, webRequest.onBeforeRequest() to webRequest.onCompleted() and make the necessary adjustments elsewhere but it just keeps throwing errors. I have removed as much irrelevant code as I can to keep my example short. I would appreciate any help.

manifest file:

{
    "name": "shell",
    "manifest_version": 2,
    "version": "1.0",

    "background": {"scripts": ["background.js"]},
    "content_scripts": [
        {
          "matches": ["<all_urls>"],
          "js": ["content.js"]
        }
      ],
    "permissions": ["tabs","activeTab", "webRequest", "<all_urls>"]
}

Content.js file:

"use strict";

browser.runtime.onMessage.addListener((request) => {
  console.log("Message from the background script:");
  console.log(request.greeting);
  return Promise.resolve({ response: "Hi from content script" });
});

background.js file:

activeTab = browser.tabs.query({currentWindow: true,active: true,})  //tabs.sendMessage must always send a message to a specific tab. Use this to get a tab
function onError(error){console.log("error")}
function sendMessageToTabs(activeTab) {
      browser.tabs.sendMessage(activeTab.tabId, { greeting: "Hi from background script" })
         .then((response) => {
            console.log("Message from the content script:");
            console.log(response.response); 
         })
         .catch(onError);
    }
// Trigger the messaging event when wiki/vihicle is visited
browser.webRequest.onBeforeRequest.addListener(sendMessageToTabs, {urls:["https://en.wikipedia.org/wiki/Vehicle"]});  

The above works perfectly fine, the content script responds back to the background script, on the console when I visit wiki/vehicle:

Message from the content script:
Hi from content script

Where I am going wrong

But when I try to only rework the background.js file, so that it uses webRequest.onCompleted() rather than webRequest.onBeforeRequest, my extension stops working. I get the error:

Error: Type error for parameter tabId (Integer -1 is too small (must be at least 0)) for tabs.sendMessage.

The reworked background.js file is:

activeTab = browser.tabs.query({currentWindow: true,active: true,})  //tabs.sendMessage must always send a message to a specific tab. Use this to get a tab
function onError(error){console.log("error")}
function sendMessageToTabs(activeTab) {
      browser.tabs.sendMessage(activeTab.tabId, { greeting: "Hi from background script" })
         .then((response) => {
            console.log("Message from the content script:");
            console.log(response.response);     //response is the object passed back by the content script
         })
         .catch(onError);
    }
browser.webRequest.onCompleted.addListener(sendMessageToTabs, {urls:["https://en.wikipedia.org/wiki/Vehicle"]});   // this is used to trigger the messaging event

Edit1:

as per @wOxxOm suggestion, after reading the documentation again, I added the property types['main_frame'] the background.js file looks like:

activeTab = browser.tabs.query({currentWindow: true,active: true,})  //tabs.sendMessage must always send a message to a specific tab. Use this to get a tab
function onError(error){console.log("error")}
function sendMessageToTabs(activeTab) {
      browser.tabs.sendMessage(activeTab.tabId, { greeting: "Hi from background script" })
         .then((response) => {
            console.log("Message from the content script:");
            console.log(response.response);     //response is the object passed back by the content script
         })
         .catch(onError);
    }
browser.webRequest.onCompleted.addListener(sendMessageToTabs, {urls:["https://en.wikipedia.org/wiki/Vehicle"], types['main_frame']});   // this is used to trigger the messaging event

but I am still getting this error:Error: Type error for parameter tabId (Integer -1 is too small (must be at least 0)) for tabs.sendMessage.

7
  • 1
    Your code intercepts all requests, not just the main one. You need to specify types:['main_frame'], see the documentation. Commented Nov 8, 2023 at 20:13
  • 1
    Actually, webRequest may be the wrong API, depending on what you want to achieve webNavigation.onCompleted may be the right choice. Commented Nov 8, 2023 at 21:50
  • @wOxxOm, I tried your suggestion but I continue to get the same error. I made an edit to my question, reporting back on your suggestions. Please take a look. I dont understand why webRequest.onBeforeRequest() correctly passes the tab id but webRequest.onCompleted() passes -1 as a tab id, which the docs state is a result of the request not being associated with a tab. Commented Nov 9, 2023 at 14:09
  • @wOxxOm, I actually need webRequest.onCompleted(). The website I am targeting is one of these modern "app" sites, so the tite bar and url never changes. I am trying to target a event that automatically occurs by rellying on when the website request a resource on the background. I have tested for this event on the site manually and works as I expect it. Commented Nov 9, 2023 at 14:11
  • 1
    Apparently the site makes the request in its service worker, which is why its tabId is -1. You can just get the list of all tabs matching the URL of the site e.g. chrome.tabs.query({url: '*://site.com/*'}) and send a message to all found tabs. Note that if the resource is not the main page itself then it's not main_frame but something else e.g. xmlhttprequest depending on how that request is made. Commented Nov 9, 2023 at 16:05

1 Answer 1

0

So after re reading all of wOxxOm comments, especially his last one. I started to try random URLs such as the BBC and McDonalds etc. And they all worked. I did not even need to specify type: ["main_frame"]. I also tried it on my final site and it worked too. It seems, my failing came down to using Wikipedia as an example to test my code on, something I initially picked sole SO's "reproduceable" example convention. Lesson learned.

The final Background.js is:

function onError(error){console.log("error")}
function sendMessageToTabs(activeTab) {
      browser.tabs.sendMessage(activeTab.tabId, { greeting: "Hi from background script" })
         .then((response) => {
            console.log("Message from the content script:");
            console.log(response.response);     //response is the object passed back by the content script
         })
         .catch(onError);
    }
browser.webRequest.onCompleted.addListener(sendMessageToTabs, {urls:["https://final/web/site/here.com"]});  //This time it does not send `-1`

I just want to thank w0xx0m, I doubt I would have caught without their patient back and forth with me, cheers

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

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.