0

Whenever I have the service worker opened, my chrome extension seems to work perfectly but whenever I do not have it opened, seconds later the chrome extension just restarts on its own without any saved data. I have tried using Chrome.Storage API but I still have the same issue. I'm not sure if I coded it incorrectly or if I am just not implementing it correctly in the rest of the background script. Any help is appreciated. Thank you

background.js

let startingMins = 5;
let currentTime = startingMins * 60;
let counter;
let ifTimerOver = true;
let originalURLs = [];
let blockedDomains = [];

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  if (request.cmd === "STOP_TIMER") {
    stopTimer();
    sendResponse({ time: currentTime, timerOver: ifTimerOver });
    resetTime();
    console.log("background.js - stop timer");
  } else if (request.cmd === "START_TIMER") {
    currentTime = request.when;
    startingMins = request.strarting;
    storeCurrrentTime();
    storeStartingMins();
    startTimer();
    console.log("background.js - timer started");
  } else if (request.cmd === "GET_TIME") {
    sendResponse({
      time: currentTime,
      timerOver: ifTimerOver,
      startedMinutes: startingMins,
    });
    console.log("background.js - sending current time");
  } else if (request.cmd === "RESET_TIME") {
    clearInterval(counter);
    resetTime();
  } else if (request.cmd === "STORE_URL") {
    let tempURL = request.link;
    storeURL(tempURL);
  } else if (request.cmd === "GET_DATA") {
    sendResponse({ link: blockedDomains });
  } else if (request.cmd === "CLEAR_URLs") {
    clearAllURLs();
  } else if (request.cmd === "DELETE_URL") {
    let del = request.link;
    deleteURL(del);
  } else if (request.cmd === "CONTENT_SCRIPT_INIT") {
    // is timer running
    sendResponse({
      time: currentTime,
      isRunning: !ifTimerOver,
    });
  }
  return true;
});

// call this when URL of current tab is changed to see if contentscript.js needs to be injected or not
try {
  chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
    console.log(changeInfo, tab);
    if (changeInfo.status == "complete") {
      console.log("testing onUpdated");
      attemptInject(tab, tabId);
    }
  });
} catch (e) {
  console.log("Error with onUpdated");
  console.log(e);
}

// call this when the User changes tab and get the URL to see if contentscript.js needs to be injected or not
try {
  chrome.tabs.onActivated.addListener(function (activeInfo) {
    console.log("Tabs changed");
    getCurrentTab();
  });
} catch (e) {
  console.log("ERROR with onActivated");
  console.log(e);
}

///////////////   FUNCTIONS    /////////////////////////

function attemptInject(tab, tabId) {
  let testURL = new URL(tab.url);
  // remove http:// https:// and www. from start of string
  let testDomain = testURL.hostname.replace(/^(?:https?:\/\/)?(?:www\.)?/i, "");
  // if url is in the blocked domains list
  console.log("should inject block?", {
    array: blockedDomains,
    host: testDomain,
  });
  if (blockedDomains.includes(testDomain)) {
    console.log("execute content script");
    chrome.scripting.executeScript({
      files: ["contentscript.js"],
      target: { tabId: tabId },
    });
  } else {
    console.log("blocked domain");
  }
}

function displayBlockerUI() {
  chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
    chrome.tabs.sendMessage(
      tabs[0].id,
      { isTimerOver: ifTimerOver },
      function (response) {
        console.log(response);
      }
    );
  });
}

function getCurrentTab() {
  chrome.tabs.query({ active: true, lastFocusedWindow: true }, (tabs) => {
    let url = tabs[0].url;
    let tab_Id = tabs[0].id;
    try {
      attemptInject(tabs[0], tab_Id);
    } catch (e) {
      console.log("ERROR HAPPENED - " + e);
    }
  });
}

function reloadPage(userURL) {
  let givenURL = new URL(userURL);
  let givenDomain = givenURL.hostname.replace(/^(?:https?:\/\/)?(?:www\.)?/i, "");
  console.log(givenDomain);
  chrome.tabs.query({}, function(tabs) {
    for (let i = 0; i < tabs.length; i++) {
      let temp = new URL(tabs[i].url);
      let tempURL = temp.hostname.replace(/^(?:https?:\/\/)?(?:www\.)?/i, "");
      if (tabs[i].active) {
        if (givenDomain == tempURL && blockedDomains.includes(tempURL)) {
          chrome.tabs.reload(tabs[i].id);
        }
      }
    }
  });
}

function timerEndedReloadPages() {
  chrome.tabs.query({}, function(tabs){
    for (let i = 0; i < tabs.length; i++) {
      let temp = new URL(tabs[i].url);
      let tempURL = temp.hostname.replace(/^(?:https?:\/\/)?(?:www\.)?/i, "");
      if (blockedDomains.includes(tempURL)) {
        chrome.tabs.reload(tabs[i].id);
      }
    }
  });
}

function startTimer() {
  chrome.tabs.query({}, function(tabs) {
    counter = setInterval(UpdateCountDown, 1000);
    ifTimerOver = false;
    for (let i = 1; i < tabs.length; i++) {
      console.log(tabs[i]);
      if (tabs[i].active) {
        let temp = new URL(tabs[i].url);
        let tempURL = temp.hostname.replace(/^(?:https?:\/\/)?(?:www\.)?/i, "");
        if (blockedDomains.includes(tempURL)) {
          chrome.tabs.reload(tabs[i].id);
        }
      }
    }
  });
}

function stopTimer() {
  clearInterval(counter);
  ifTimerOver = true;
  counter = null;
  timerEndedReloadPages();
}

function resetTime() {
  startingMins = 5;
  currentTime = startingMins * 60;
  storeStartingMins();
  storeCurrrentTime();
  counter = null;
  clearLocalStorage();
}

function UpdateCountDown() {
  currentTime--;
  storeCurrrentTime();
  getCurrentTime();
  const mins = Math.floor(currentTime / 60);
  let secs = currentTime % 60;
  if ((mins == 0) & (secs == 0)) {
    clearInterval(counter);
    ifTimerOver = true;
    timerEndedReloadPages();
  }
}

function storeURL(userURL) {
  let url = new URL(userURL);
  let testDomain = url.hostname.replace(/^(?:https?:\/\/)?(?:www\.)?/i, "");
  let check = false;
  for (let i = 0; i < blockedDomains.length; i++) {
    if (blockedDomains[i] == testDomain) {
      check = true;
      break;
    }
  }
  if (!check) {
    originalURLs.push(userURL);
    blockedDomains.push(testDomain);
    console.log("added url");
  }
}

function clearAllURLs() {

  chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
    let temp = new URL(tabs[0].url);
    let tempURL = temp.hostname.replace(/^(?:https?:\/\/)?(?:www\.)?/i, "");
    if (blockedDomains.includes(tempURL)) {
      console.log("Current page is part of blocked domains so refresh");
      chrome.tabs.reload(tabs[0].id);
    } else {
      console.log("Current page URL is not part of blocked domains, do nothing");
    }

    blockedDomains = [];
    originalURLs = [];
  });
}

function deleteURL(deleteURL) {
  let splitData = deleteURL.split("<");

  // when URL is deleted from User, we want to make sure that when the timer starts, the current tab URL is not
  // blocked with our content script so we refresh the page to delete
  chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
    let temp = new URL(tabs[0].url);
    let tempURL = temp.hostname.replace(/^(?:https?:\/\/)?(?:www\.)?/i, "");
    if ((tempURL == splitData[0]) && (blockedDomains.includes(tempURL))) {
      console.log("Current page is part of blocked domains so refresh");
      chrome.tabs.reload(tabs[0].id);
    } else {
      console.log("Current page URL is not part of blocked domains, do nothing");
    }

    for (let i = 0; i < blockedDomains.length; i++) {
      let testDomain = blockedDomains[i];
      if (deleteURL.includes(testDomain)) {
        blockedDomains.splice(i, 1);
        break;
      }
    }
  });
}

function storeIfTimerStarted() {
  chrome.storage.sync.set({ timerStatus: ifTimerOver }, function () {
    console.log("ifTimerOver - " + ifTimerOver);
  });
}

function getIfTimerStarted() {
  chrome.storage.sync.get(["timerStatus"], function (data) {
    ifTimerOver = data.timerStatus;
    console.log(ifTimerOver);
  });
}

function storeCurrrentTime() {
  chrome.storage.sync.set({ localTime: currentTime }, function () {
    // console.log("storeCurrentTime - " + currentTime);
  });
}

function getCurrentTime() {
  chrome.storage.sync.get(["localTime"], function (data) {
    currentTime = data.localTime;
    // console.log("getCurrentTime - " + data.localTime);
  });
}

function storeStartingMins() {
  chrome.storage.sync.set({ localStartingMins: startingMins }, function () {
    // console.log("storeStartingMins - " + startingMins);
  });
}

function getStartingMins() {
  chrome.storage.sync.get(["localStartingMins"], function (data) {
    startingMins = data.localStartingMins;
    // console.log("getStartingMins - " + data.localStartingMins);
  });
}

function clearLocalStorage() {
  chrome.storage.local.clear(function () {
    let error = chrome.runtime.lastError;
    if (error) {
      console.error(error);
    }
  });
}

function ifValidURL(site) {
  try {
    const url = new URL(site);
    return true;
  } catch (error) {
    console.log("INVALID URL");
    return false;
  }
}
Vigilante
  • 57
  • 6
  • The background script in MV3 terminates after 30 seconds so you're not using the API correctly indeed. See [this example](https://stackoverflow.com/a/70745761). There may be more problems in your full code so maybe you should add it to the question... – wOxxOm Jan 20 '22 at 19:50
  • I just added updated the code. If you don't mind, I would really appreciate the help since it is one of the last major things I need to fix and I am really stuck. Here is a [demo](https://www.youtube.com/watch?v=2ZWCpzXodZM) if you want to see how the extension works. Thank you – Vigilante Jan 20 '22 at 20:36
  • You'll have to rework the code completely and use `chrome.alarms` for timers longer than 30 seconds. See also [Persistent Service Worker in Chrome Extension](https://stackoverflow.com/a/66618269) – wOxxOm Jan 20 '22 at 20:45
  • Okay I will use `chrome.alarms` . So are you saying that I create an alarm and have it run the code for the amount of time the user wants? I'm just confused on how to approach this. – Vigilante Jan 20 '22 at 21:08
  • I need to use `chrome.alarms` for my timer and `chrome.storage` for saving the time and for keeping a persistent service worker. That is what you are saying right? – Vigilante Jan 21 '22 at 03:02
  • Or what if I changed to MV2, would that be easier and not need to use `chrome.alarms`? – Vigilante Jan 21 '22 at 03:13
  • Keeping the worker persistent would indeed help you but only within the constraints mentioned in that answer. – wOxxOm Jan 21 '22 at 08:07

0 Answers0