-1

SOLVED: see my answer below

I am attempting to learn how to pass data between files in a Chrome Extension. My goal is to query data from the dom of a site when a particular url loads. Then display the queried data in a popup. I am having trouble with passing information the order of message events for the content, popup, background script.

What I believe is the right course of action:

  1. Background script determines if tab is the correct site via url comparison
  2. Background sends message to content script, via chrome.tab.message
  3. Content script receives message via chrome.runtime.onMessage.addListener(), and performs information gathering from the site's dom.
  4. Content script sends results via chrome.runtime.sendMessage to popup script to populate information in popup.html

I can see the console.log of the background.js by inspecting the popup. However, I get Uncaught (in promise) Error: Could not establish connection. Receiving end does not exist.

and no further console.logs in either the web page or popup dev tools console.

file structure

root/
├─ manifest.json
├─ background.js
├─ popup/
│  ├─ popup.html
│  ├─ popup.js
└─ scripts/
   └─ content.js

manifest.json

{
    "manifest_version": 3,
    "name": "Plex File Name Generator",
    "version": "0.0.1",
    "description": "Generate file name for Plex from IMDb",
    "permissions": ["tabs"],
    "host_permissions": ["https://*.imdb.com/tt*"],
    "background": {
        "service_worker": "background.js"
    },
    "content_scripts": [
        {
            "matches": ["https://*.imdb.com/tt*"],
            "js": ["scripts/content.js"]
        }
    ],
    "action": {
        "default_icon": {
            "16": "assets/ext-icon.png",
            "24": "assets/ext-icon.png",
            "32": "assets/ext-icon.png"
        },
        "default_title": "Plex File Name Generator",
        "default_popup": "popup/popup.html"
    }
}

popup.html

<script type="module" src="popup.js"></script>

<div class="container">
    <div class="title">Plex File Name Generator</div>
</div>

popup.js

chrome.runtime.onMessage.addListener((obj, sender, response) => {
    const { type, movieTitle, imdbId } = obj;
    if (type === "displayMovieTitle") {
        console.log("popup", movieTitle, imdbId);
    }
});

content.js

(() => {
    chrome.runtime.onMessage.addListener((request, sender, response) => {
        const { type, imdbId } = request;

        if (type === "getMovieInfo") {
            const titleSpan = document.querySelector(
                'h1[data-testid="hero__pageTitle"] > span'
            );
            const movieTitle = titleSpan?.innerText?.trim() || "";

            chrome.runtime.sendMessage({ type: "displayMovieTitle", movieTitle, imdbId });
        }
        return true;
    });
})();

background.js

chrome.tabs.onUpdated.addListener((tabId, tab) => {
    if (tab.url?.includes("imdb.com/title/tt")) {
        chrome.tabs.onUpdated.addListener((nextTabId, nextTab) => {
            if (tabId === nextTabId && nextTab.status === "complete") {
                const imdbId = tab.url.match(/tt\d+/g)?.[0] || "";

                chrome.tabs.sendMessage(tabId, {
                    type: "getMovieInfo",
                    imdbId,
                });
            }
        });
    }
});

1 Answers1

0

Solved: My matching pattern for content scripts was incorrect. wrong

"content_scripts": [
    {
        "matches": ["https://*.imdb.com/title/tt*"], //instead of "matches": ["https://*.imdb.com/tt*"],
        "js": ["scripts/content.js"]
    }
],

Realized if I put an alert in the content script, it didnt show up. And could not find the script in the site's dom. Turns out it was never injected.