From 8f992943ee1bec662ec34b8e1d5824f0080569c4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 27 Mar 2026 05:15:43 +0000 Subject: [PATCH] fix: resolve 6 bugs in background.js and popup.js Agent-Logs-Url: https://github.com/vili-pet/Rewards-Search-Automator/sessions/c0af5874-8bf1-458a-8e6d-2c7377abb25f Co-authored-by: vili-pet <199537307+vili-pet@users.noreply.github.com> --- js/background.js | 83 +++++++++++++++++++++++++++++++----------------- js/popup.js | 16 +++++----- 2 files changed, 62 insertions(+), 37 deletions(-) diff --git a/js/background.js b/js/background.js index 7143a42..434149e 100644 --- a/js/background.js +++ b/js/background.js @@ -131,8 +131,11 @@ async function loadState() { // Falls back to the local words list when the fetch fails. async function fetchTrendingWords() { // Return in-memory cache if still valid - if (trendingWordsCache) { - return trendingWordsCache; + if ( + trendingWordsCache && + Date.now() - trendingWordsCache.timestamp < TRENDS_CACHE_DURATION + ) { + return trendingWordsCache.terms; } // Check storage cache @@ -145,7 +148,7 @@ async function fetchTrendingWords() { entry.terms.length > 0 && Date.now() - entry.timestamp < TRENDS_CACHE_DURATION ) { - trendingWordsCache = entry.terms; + trendingWordsCache = { terms: entry.terms, timestamp: entry.timestamp }; return entry.terms; } @@ -169,9 +172,10 @@ async function fetchTrendingWords() { .filter((t) => t && t.length > 0); if (terms.length > 0) { - trendingWordsCache = terms; + const timestamp = Date.now(); + trendingWordsCache = { terms, timestamp }; await chrome.storage.local.set({ - trendingWordsCache: { terms, timestamp: Date.now() }, + trendingWordsCache: { terms, timestamp }, }); console.info(`Loaded ${terms.length} trending search terms from Google Trends.`); return terms; @@ -184,26 +188,24 @@ async function fetchTrendingWords() { } // Fallback: use the local Finnish word list - trendingWordsCache = words; + trendingWordsCache = { terms: words, timestamp: Date.now() }; return words; } function getRandomSearchWord() { const pool = - Array.isArray(trendingWordsCache) && trendingWordsCache.length > 0 - ? trendingWordsCache + trendingWordsCache && Array.isArray(trendingWordsCache.terms) && trendingWordsCache.terms.length > 0 + ? trendingWordsCache.terms : words; return pool[Math.floor(Math.random() * pool.length)]; } function randomDelay() { - return Math.floor( - Math.random() * - (parseInt(searchState.millisecondsMax) - - parseInt(searchState.millisecondsMin) + - 1) + - parseInt(searchState.millisecondsMin), - ); + const min = parseInt(searchState.millisecondsMin); + const max = parseInt(searchState.millisecondsMax); + const lo = Math.min(min, max); + const hi = Math.max(min, max); + return Math.floor(Math.random() * (hi - lo + 1) + lo); } // Return true if current local time is within the [startHHMM, endHHMM) window. @@ -301,11 +303,22 @@ async function scheduleAutoStartAlarm() { } async function getTabId() { - return new Promise((resolve, reject) => { + return new Promise((resolve) => { chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) { - var activeTab = tabs[0]; - var activeTabId = activeTab.id; - resolve(activeTabId); + if (tabs && tabs.length > 0 && tabs[0].id) { + resolve(tabs[0].id); + } else { + // No active tab found (e.g. auto-start triggered in background). + // Create a dedicated tab so we never hijack a user's page. + chrome.tabs.create({ url: "about:blank", active: false }, function (tab) { + if (chrome.runtime.lastError || !tab) { + console.warn("Could not create fallback tab:", chrome.runtime.lastError?.message); + resolve(null); + return; + } + resolve(tab.id); + }); + } }); }); } @@ -319,8 +332,13 @@ function notifyPopup(message) { // Enable debugger async function enableDebugger(tabId) { - return new Promise((resolve, reject) => { + return new Promise((resolve) => { chrome.debugger.attach({ tabId }, "1.2", function () { + if (chrome.runtime.lastError) { + console.warn(`Debugger attach error for tab ${tabId}:`, chrome.runtime.lastError.message); + resolve(false); + return; + } console.log(`Debugger enabled for tab: ${tabId}`); resolve(true); }); @@ -329,8 +347,13 @@ async function enableDebugger(tabId) { // Disable debugger async function disableDebugger(tabId) { - return new Promise((resolve, reject) => { + return new Promise((resolve) => { chrome.debugger.detach({ tabId }, function () { + if (chrome.runtime.lastError) { + console.warn(`Debugger detach error for tab ${tabId}:`, chrome.runtime.lastError.message); + resolve(false); + return; + } console.log(`Debugger disabled for tab: ${tabId}`); resolve(true); }); @@ -780,15 +803,17 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { }); // Close debugger in case is open when popup closes (fallback) -chrome.runtime.onConnect.addListener(async function (port) { +chrome.runtime.onConnect.addListener(function (port) { if (port.name === "popup") { - port.onDisconnect.addListener(async function () { - // Only detach debugger if searches are NOT running - // This allows searches to continue when popup closes - if (!searchState.isRunning) { - let tabId = await getTabId(); - chrome.debugger.detach({ tabId }, function () { - console.log(`Debugger disabled for tab: ${tabId}`); + port.onDisconnect.addListener(function () { + // Only detach debugger if searches are NOT running and we have a known tab. + // Use the stored tabId — not the current active tab — to avoid detaching + // a debugger from the wrong tab. + if (!searchState.isRunning && searchState.tabId) { + chrome.debugger.detach({ tabId: searchState.tabId }, function () { + if (chrome.runtime.lastError) { + // Tab was closed or debugger was already detached; nothing to do. + } }); } }); diff --git a/js/popup.js b/js/popup.js index 52886b5..8ee222c 100644 --- a/js/popup.js +++ b/js/popup.js @@ -132,10 +132,10 @@ function sendAutoStartSettingsToBackground() { time: config.searches.autoStartTime || "", // Auto-start always runs the full "desktopMobile" session searchType: "desktopMobile", - desktopSearches: parseInt(config.searches.desktop), - mobileSearches: parseInt(config.searches.mobile), - millisecondsMin: parseInt(config.searches.millisecondsMin), - millisecondsMax: parseInt(config.searches.millisecondsMax), + desktopSearches: parseInt(config.searches.desktop) || 3, + mobileSearches: parseInt(config.searches.mobile) || 3, + millisecondsMin: parseInt(config.searches.millisecondsMin) || 120000, + millisecondsMax: parseInt(config.searches.millisecondsMax) || 3600000, scheduleStartTime: config.searches.scheduleStartTime || "", scheduleEndTime: config.searches.scheduleEndTime || "", }, @@ -149,10 +149,10 @@ async function startSearches(searchType) { deactivateForms(); const settings = { - desktopSearches: parseInt(config.searches.desktop), - mobileSearches: parseInt(config.searches.mobile), - millisecondsMin: parseInt(config.searches.millisecondsMin), - millisecondsMax: parseInt(config.searches.millisecondsMax), + desktopSearches: parseInt(config.searches.desktop) || 3, + mobileSearches: parseInt(config.searches.mobile) || 3, + millisecondsMin: parseInt(config.searches.millisecondsMin) || 120000, + millisecondsMax: parseInt(config.searches.millisecondsMax) || 3600000, scheduleStartTime: config.searches.scheduleStartTime || "", scheduleEndTime: config.searches.scheduleEndTime || "", };