sleepytabs/service_worker.js
2023-02-26 01:50:25 +01:00

226 lines
6.3 KiB
JavaScript

//-----------
// FUNCTIONS
//-----------
function getInactiveTabs(callback) {
chrome.storage.local.get(['sleepyTabsInactiveTabs'], (result) => {
callback(result.sleepyTabsInactiveTabs || {});
});
}
function getOptions(callback) {
chrome.storage.local.get(['sleepyTabsOptions'], (result) => {
callback(result.sleepyTabsOptions || {
suspendAfterMins: 30,
suspendIncognito: false,
suspendAudible: false,
whitelistPages: [],
whitelistDomains: [],
});
});
}
function inWhitelist(url, options) {
let inWhiteList = false;
options.whitelistPages.every((whitelistUrl, index) => {
if(url.replace(/\?.*$/, '') == whitelistUrl) {
inWhiteList = true;
return false;
}
return true;
});
if(!inWhiteList) {
options.whitelistDomains.every((whitelistUrl, index) => {
if(url.match(whitelistUrl)) {
inWhiteList = true;
return false;
}
return true;
});
}
return inWhiteList;
}
function setInactiveTabs(inactiveTabs, callback) {
chrome.storage.local.set({
sleepyTabsInactiveTabs: inactiveTabs
}, callback);
}
function setOptions(options, callback) {
chrome.storage.local.set({
sleepyTabsOptions: options
}, callback);
}
function suspendTab(_tab) {
getInactiveTabs((inactiveTabs) => {
let _params = new URLSearchParams();
_params.append('url', _tab.url);
_params.append('title', _tab.title);
_params.append('favIconUrl', _tab.favIconUrl);
chrome.tabs.update(_tab.id, {
url: 'suspended.html?' + _params
});
delete inactiveTabs[_tab.id];
setInactiveTabs(inactiveTabs);
});
}
function unSuspendTab(_tab, _updateInactiveTabList = true) {
getInactiveTabs((inactiveTabs) => {
if(_tab.url.match('^chrome-extension://' + chrome.runtime.id + '/suspended.html')) { // check if currently suspended
chrome.tabs.sendMessage(_tab.id, {type: 'UNSUSPEND'}, () => {
if(_updateInactiveTabList) {
inactiveTabs[_tab.id] = Date.now();
setInactiveTabs(inactiveTabs);
}
});
}
});
}
function startAlarm() {
stopAlarm(); // just to make sure it's not already running
setInactiveTabs({}); // re-start timer for inactive tabs
chrome.alarms.create('sleepyTabsAlarm', {
when: Date.now(),
periodInMinutes: 1
});
}
function stopAlarm() {
chrome.alarms.clear('sleepyTabsAlarm');
}
//-----------
// LISTENERS
//-----------
// check to suspend tabs (once per minute)
chrome.alarms.onAlarm.addListener((alarm) => {
if(alarm.name == 'sleepyTabsAlarm') {
const _currentTime = Date.now();
getOptions((options) => {
if(options.suspendAfterMins > 0) {
getInactiveTabs((inactiveTabs) => {
chrome.windows.getAll({populate: true}, (_windows) => {
_windows.forEach((_window, _windowIndex) => {
_window.tabs.forEach((_tab, _tabIndex) => {
if(!_tab.active &&
!_tab.url.match(/^chrome/) &&
!inWhitelist(_tab.url, options) &&
!(options.suspendIncognito && _tab.incognito) &&
!(options.suspendAudible && _tab.audible)) {
if(!inactiveTabs[_tab.id]) {
inactiveTabs[_tab.id] = _currentTime;
setInactiveTabs(inactiveTabs);
} else if(_currentTime - inactiveTabs[_tab.id] >= options.suspendAfterMins * 60000) {
suspendTab(_tab);
}
}
});
});
});
});
}
});
}
});
// remove tab from inactive list when activated
chrome.tabs.onActivated.addListener((activeInfo) => {
getInactiveTabs((inactiveTabs) => {
delete inactiveTabs[activeInfo.tabId];
setInactiveTabs(inactiveTabs);
});
});
// remove tab from inactive list when removed
chrome.tabs.onRemoved.addListener((tabId, removeInfo) => {
getInactiveTabs((inactiveTabs) => {
delete inactiveTabs[tabId];
setInactiveTabs(inactiveTabs);
});
});
// listen for messages
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
getOptions((options) => {
switch(request.type) {
case 'GET_OPTIONS':
sendResponse(options);
break;
case 'SET_OPTIONS':
setOptions(request.options);
if(options.suspendAfterMins > 0 && request.options.suspendAfterMins == 0) {
stopAlarm();
} else if(options.suspendAfterMins == 0 && request.options.suspendAfterMins > 0) {
startAlarm();
}
sendResponse();
break;
case 'SUSPEND_TAB':
suspendTab(request.tab);
sendResponse();
break;
case 'UNSUSPEND_TAB':
unSuspendTab(request.tab);
sendResponse();
break;
case 'SUSPEND_OTHER_TABS':
chrome.tabs.query({windowId: request.tab.windowId}, (_tabs) => {
_tabs.forEach((_tab, _tabIndex) => {
if(_tab.id != request.tab.id && !_tab.url.match(/^chrome/)) {
suspendTab(_tab);
sendResponse();
}
});
});
break;
case 'UNSUSPEND_ALL_TABS':
setInactiveTabs({});
chrome.tabs.query({windowId: request.tab.windowId}, (_tabs) => {
_tabs.forEach((_tab, _tabIndex) => {
unSuspendTab(_tab, false);
sendResponse();
});
});
break;
case 'NEVER_SUSPEND_PAGE':
options.whitelistPages.push(request.tab.url.replace(/(^.*)\?.*$/, '$1'));
setOptions(options);
sendResponse();
break;
case 'REMOVE_NEVER_SUSPEND_PAGE':
options.whitelistPages.splice(options.whitelistPages.indexOf(request.tab.url.replace(/(^.*)\?.*$/, '$1')));
setOptions(options);
sendResponse();
break;
case 'NEVER_SUSPEND_DOMAIN':
options.whitelistDomains.push(request.tab.url.replace(/(^https?:\/\/[^/]+).*$/, '$1'));
setOptions(options);
sendResponse();
break;
case 'REMOVE_NEVER_SUSPEND_DOMAIN':
options.whitelistDomains.splice(options.whitelistDomains.indexOf(request.tab.url.replace(/(^https?:\/\/[^/]+).*$/, '$1')));
setOptions(options);
sendResponse();
break;
}
});
return true;
});
//------
// INIT
//------
chrome.runtime.onInstalled.addListener(() => {
getOptions((options) => {
if(options.suspendAfterMins > 0) {
startAlarm();
}
});
});