javascriptmanifest.jsonweb-extension

Creating a web extension tracking time on website


I am relative newbie with web extensions. My idea is that I want to create a web extension that inputs an integer through a popup when the user enters an entertaining website. When this limit runs out, I want to block the site for a given time depending on the time of day.

So far, I have created this manifest.json file:

{
  "manifest_version": 3,
  "name": "Entertainment Time Tracker",
  "version": "1.0.0",
  "description": "Tracks time spent on entertaining websites and allows the user to set time limits for each session.",
  "permissions": [
    "activeTab", "<all_urls>", "declerativeNetRequest", "tabs", "notifications", "http://*/*", "https://*/*"
  ],
  "background": {
    "service_worker": "background.js"
  },
  "action": {
    "default_popup": "popup.html"
  }
}

Then I got the following code from ChatGPT:

// The URLs of the entertaining websites to track
const ENTERTAINMENT_URLS = [
    "https://www.youtube.com",
    "https://www.netflix.com",
    "https://tv.nrk.no/",
    "https://www.discoveryplus.com/no/",
    "https://www.disneyplus.com/",
    "https://www.hbo.com/",
    "https://www.hbo.no/",   
  ];
  
  // The current session start time
let sessionStartTime = null;

// The total time spent on entertaining websites in the current session
let sessionTimeSpent = 0;

// The interval ID for the time checker
let checkIntervalID = null;

// The time limit for the current session, in minutes
let sessionTimeLimit = null;

// Check the time spent on entertaining websites and update the UI
function checkTime() {
  // Calculate the time spent in the current session
  const timeElapsed = Date.now() - sessionStartTime;
  sessionTimeSpent += timeElapsed;

  // Update the UI with the time spent in the current session
  updateUI(sessionTimeSpent);

  // Check if the time limit has been reached
  if (sessionTimeSpent >= sessionTimeLimit * 60 * 1000) {
    // Stop the time checker
    clearInterval(checkIntervalID);

    // Show an alert to the user that the time limit has been reached
    alert(`You have reached the time limit of ${sessionTimeLimit} minutes for this session.`);
    
    // Change the site to show clouds and a 404 error
    switch (window.location.hostname) {
      case "www.youtube.com":
         document.head.innerHTML = generateSTYLES();    
      document.body.innerHTML = generateHTML("YOUTUBE");
    }
    // Reset the session start time, time spent, and time limit
    sessionStartTime = null;
    sessionTimeSpent = 0;
    sessionTimeLimit = null;
  }
}

// Initialize the time tracker
function initialize() {
  // Get the current tab
  browser.tabs.query({ active: true, currentWindow: true }).then((tabs) => {
    const currentTab = tabs[0];

    // Check if the current tab is an entertaining website to track
    if (isTrackedWebsite(currentTab.url)) {
      // Show the popup
      showPopup();

      // Set the session start time
      sessionStartTime = Date.now();

      // Start the time checker
      checkIntervalID = setInterval(checkTime, 60  * 1000);

      // Show the time limit setting form
      showSettingForm();
    }
  });
}

// Check if the given URL is an entertaining website to track
function isTrackedWebsite(url) {
  return ENTERTAINMENT_URLS.some((trackedUrl) => url.startsWith(trackedUrl));
}

// Show the popup
function showPopup() {
  // Create the popup HTML
  const popupHtml = `
  <form>
      <label>Enter an integer: <input type="number" name="integer" min="1" max="100" required /></label>
      <input type="submit" value="Submit" />
  </form>
  `;
  // Show the popup
  browser.windows.create({
    type: "popup",
    url: "data:text/html;charset=utf-8," + encodeURI(popupHtml),
  });
}
// Show the time limit setting form
function showSettingForm() {
  // Get the time limit setting form
  const form = document.getElementById("setting-form");

  // Show the form
  form.style.display = "block";

  // Add an event listener for the submit event on the form
  form.addEventListener("submit", (event) => {
  // Prevent the form from submitting and reloading the page
  event.preventDefault();

  // TODO: Handle the form submission here
  });
  }

initialize();

Obviously, it is lacking some essential features. For instance the "updateUI" function is not implemented. I also have two functions ("generateSTYLES" and "generateHTML") that creates a loading screen for websites that are "blocked".

My main problems with the scripts:

  1. It does not force the user to output a time limit when an entertaining site is accessed.
  2. The "cooldown" after a block should vary depending on time of day, and this has not been added.
  3. How to handle form submissions - see last part of script

So, I would love help in general on improvements to the scripts and answers/help with the questions above. Also, should I make a separate html file or include it in the js-file?


Solution

  • You miss how web extensions work.

    Web extensions are made of 3 main contexts:

    1. Background script
    2. Popup
    3. Content script

    The popup is what you see when you click your extension icon in the browser toolbar.

    The background script works as background API for your extension.

    The content script is a kind of JS script that you inject in the target pages. This is what you actually need.

    First of all, you should create 1 separate script for the 3 contexts. Additionally, in your manifest.json you should define on which pages/entertainment websites you want to inject your content script. Here is an example:

    "content_scripts": [
        {
            "matches": [ "http://siebelgcs.invensys.com/serviceoui_enu/*" ],
            "run_at": "document_end",
            "js": [
                "lib/require.js",
                "lib/require-cs.js",
                "lib/require-cfg.js",
                "app/main.js"
            ],
            "css": [
                "css/content.css",
                "css/controls.css",
                "css/activityInStatus.css"
            ]
        }
    ],
    

    The content script should then be able to block the website. For example you can append a new div to the page that disappears when the user enters the time in your popup. The communication between your content script and your popup you should use the runtime message API: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/sendMessage

    I would read Mozilla documentation on the topic, they have such good information there.