-1

Right now, I am working on a Chrome Extension in which, after I download it to Chrome, it should automatically open a popup in the upper right of the screen and grey out the rest of the page. I have gotten it pretty much work when I just test the html file itself. Screenshot of an example website that is made with the html.

I am having trouble with two things:

  1. I am lost on how to automatically open the popup when a new page follows a few conditions (specifically, the most important one is if the domain name of the page is contained in a database I will eventually use).

  2. How to display the popup like it looked like in the screenshot (where it is not connected to the toolbar and it greys out the rest of the screen until your close).

For the first problem, I have tried researching "background pages," because that is what people from earlier posts have said you have to use in this type of situation. However, I just don't understand how to connect the background.js, for example, to my other html and javascript files. As well, to make matters worse, it seems Chrome has recently switched to something called "service workers" which I really do not know how to use. If I could do my project without these, that would be preferable.

Second, it seems that instead of applying to the current page, whenever I download my extension into Chrome and click on it in the toolbar, the popup in the upper right and the "greying out" only apply to the little page created by the extension. Screenshot of how only the little page created by clicking the extension shows up. Is there anyway I can make the popup shown in the first picture appear on the screen not connected to the toolbar with the greyed-out screen? Essentially as if it were overlaying the current page?

Thank you for your help. I have attached my javascript, html, and manifest files. I changed some unimportant text for privacy's sake (it's really just for strings that need to be displayed.) Note also that I am using an array of URL's to stand in for my database right now.

document.addEventListener('DOMContentLoaded', function () {

    chrome.tabs.getSelected(null, function (tab) {

        d = document;

        shorterUrlHttps = tab.url.substr(8);

        var hostName = shorterUrlHttps.substr(0, shorterUrlHttps.indexOf('/'));

        const hostNames = [
            "www.blah.com",
            "www.blahblah.co.uk",
            "www.blahblahblah.com"];

        var count = 0;

        for (let i = 0; i < hostNames.length; i++) {
            if (hostName == hostNames[i]) {
                count = 1;
            }
        }

        var popup = d.getElementById('extension-overlay');
        var companyName = d.getElementById('companyName');
        var company = hostName.substr(5,shorterUrlHttps.indexOf('.c',5))


        if (count == 1) {
            popup.style.display = 'block';
            companyName.innerHTML = company;
            
        }
        else {
            popup.style.display = 'none';
        }

        d.getElementById("extension-close-icon").onclick = function () {
            popup.style.display = 'none';
        }
    });
}, false);
<!doctype html>
<html>

<head>
    <title><strong>LUX Rewards</strong></title>
    <script src="popup.js"></script>
    <style>
        .header {
            color: rgba(211, 198, 14, 0.968);
            text-align: center;
            font-size: 32px;
            border: none;
            margin: 0;
        }

        .bodytext {
            color: black;
            text-align: center;
        }

        .center {
            display: block;
            margin-left: auto;
            margin-right: auto;
            width: 50%;
        }

        /* body {
            background: linear-gradient(to bottom, #ffcc00 72%, #ffff99 119%);
        } */

        html * {
            font-family: Georgia, 'Times New Roman', Times, serif;
        }
    </style>
</head>

<body>
    <p>This is the example website</p>
    <div id="extension-overlay"
        style="display:block;position: fixed; inset: 0px; padding: 60px; background-color: rgba(0, 0, 0, 0.24); z-index: 99999999;">
        <link href="https://fonts.googleapis.com/css?family=Montserrat:100,300,400,500,600,700" rel="stylesheet">
        <style>
            #popup h1,
            #popup p {
                color: #000 !important;
            }
        </style>
        <div id="popup"
            style="position:relative;overflow:hidden;float:right;width: 270px;border-radius: 6px;box-shadow: 0 9px 46px 8px rgba(0,0,0,0.12), 0 24px 38px 3px rgba(0,0,0,0.14), 0 11px 15px -7px rgba(0,0,0,0.2); text-align:center;">
            <div style="padding: 20px; background: linear-gradient(180deg, #ffcc00 38%, #ffff99 119%);"> <button
                    type="button" id="extension-close-icon"
                    style="background:url(closeicon.png);background-size:cover;position:absolute; top:13px; right: 13px; width:20px;height:20px;cursor:pointer;"></button>
                <h1 class="header"><strong>blah</strong></h1> <img src="backgroundthumbnail.png"
                    style="width:120px; margin:20px auto;">
                <h1
                    style="font-family: Montserrat;font-size: 18px;font-weight: bold;letter-spacing: 0;line-height: 25px; margin: 0;">
                    blah</h1>
                <p style="font-family: Montserrat;font-size: 15px;letter-spacing: 0;line-height: 21px;margin:0;">blah blah blah</p>
            </div> <a id="popup-benefit-link" href="https://www.luxrewards.co.uk/home"
                style="cursor:pointer;text-decoration:none;display:block;background-color: rgb(96, 93, 7);color:rgb(255, 255, 255);padding: 15px; font-family: Montserrat;font-size: 15px;font-weight: bold;letter-spacing: 0;line-height: 25px;"
                target="_blank">blah blah blah</a>
        </div>
    </div>
</body>



</html>

1 Answers1

-1

Your popup is declared via action or browser_action, which means it's a separate page with its own chrome-extension:// URL, shown in a separate window not related to the current web page.

The solution is to show your UI inside the web page as a DOM element using a content script.

To show it only on sites defined in a database, the best method is to register the content script dynamically only on the required urls, so the browser won't waste resources to run your content script on unrelated sites. In ManifestV3 you can use chrome.scripting.registerContentScripts (Firefox has a different API), which is available only in a non-content script e.g. the background script or the options/action page. If you want to avoid using a background script and allow the user to add the current site to the database, use the action popup to show the add/delete buttons.

manifest.json:

  "permissions": ["activeTab", "scripting", "storage"],
  "action": {"default_popup": "popup.html"},

popup.html (shown when the extension icon is clicked):

<button id=add disabled>Add</button>
<button id=del disabled>Delete</button>
<div id=error></div>
<script src=popup.js></script>

popup.js:

const [btnAdd, btnDel] = ['add', 'del'].map(id => document.getElementById(id));
btnAdd.onclick = btnDel.onclick = toggleCurrentSite;
getData().then(({site, sites}) => {
  (sites.includes(site) ? btnDel : btnAdd).disabled = false;
});
async function getData() {
  const [[tab], {sites}] = await Promise.all([
    chrome.tabs.query({currentWindow: true, active: true}),
    chrome.storage.local.get({sites: []}),
  ]);
  const site = new URL(tab.url).hostname;
  return {site, sites, tab};
}
async function toggleCurrentSite(e) {
  const add = e.target === btnAdd || btnAdd.contains(e.target);
  const {site, sites} = await getData();
  const i = sites.indexOf(site);
  if (add && i < 0) sites.push(site);
  else if (!add && i >= 0) sites.splice(i, 1);
  else return;
  try {
    await chrome.scripting.unregisterContentScripts({ids: ['foo']}).catch(() => {});
    await chrome.scripting.registerContentScripts([{
      id: 'foo',
      matches: sites.map(s => `*://${s}/*`),
      js: ['content.js'],
    }]);
    await chrome.storage.local.set({sites});
    btnAdd.disabled = add;
    btnDel.disabled = !add;
  } catch (e) {
    document.getElementById('error').textContent = e.message;
  }
}

Finally, content.js adds the DOM element for your UI. To isolate your UI and styles use a chrome-extension:// iframe or a div with shadowDOM as explained in this topic.

wOxxOm
  • 65,848
  • 11
  • 132
  • 136
  • Hello, thank you so much for your answer! Bear with me because I am basically brand new to html, javascript, and definitely to extensions. First, is that I all I need to change in my manifest.json or do I also need to add "content_scripts"? Second, for popup.html, is that all I need in or should I add it to my existing html file? Third, how does popup.js both add URL's to a database and how does it connect to content.js (everytime I run the plugin and click "Add", it says "Nonexistent script ID 'foo'". Finally, what should I put it content.js specifically? And does it need an html file? – Akku Kumar Apr 11 '22 at 03:09
  • 1) No need to add `content_scripts` (these are static). 2) It's an example. 3) See the fixed code which now suppresses the foo error. 4) The examples are given in the topic I've linked. – wOxxOm Apr 11 '22 at 06:11