226 lines
6.3 KiB
JavaScript
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();
|
|
}
|
|
});
|
|
});
|