diff --git a/src/js/background.js b/src/js/background.js index 1fdc6a33..a8c19ca2 100644 --- a/src/js/background.js +++ b/src/js/background.js @@ -22,7 +22,7 @@ var tgs = (function () { lastStatus = 'normal', notice = {}, unsuspendRequestList = {}, - audibleTabsList = {}, + scrollPosByTabId = {}, lastTabCloseTimestamp = new Date(), suspensionActiveIcon = '/img/icon19.png', suspensionPausedIcon = '/img/icon19b.png'; @@ -929,20 +929,28 @@ var tgs = (function () { } switch (request.action) { - case 'prefs': + case 'initTab': + var tabScrollPos = scrollPosByTabId[sender.tab.id]; + delete scrollPosByTabId[sender.tab.id]; sendResponse({ dontSuspendForms: gsUtils.getOption(gsUtils.IGNORE_FORMS), suspendTime: gsUtils.getOption(gsUtils.SUSPEND_TIME), screenCapture: gsUtils.getOption(gsUtils.SCREEN_CAPTURE), - tabId: sender.tab.id + tabId: sender.tab.id, + scrollPos: tabScrollPos }); break; case 'reportTabState': + // If tab is currently visible then update popup icon if (sender.tab && sender.tab.id === globalCurrentTabId) { var status = processActiveTabStatus(sender.tab, request.status); updateIcon(status); } + // If tab is reported being suspended, save the tab's reported scroll position + if (request.status === 'suspended' && request.scrollPos) { + scrollPosByTabId[sender.tab.id] = request.scrollPos; + } break; case 'suspendTab': @@ -1025,7 +1033,7 @@ var tgs = (function () { //wishful thinking here that a synchronus iteration through tab views will enable them //to unsuspend before the application closes - chrome.runtime.onSuspend.addListener(function () { + chrome.runtime.setUninstallURL('', function () { chrome.extension.getViews({type: 'tab'}).forEach(function (view) { view.location.reload(); }); @@ -1053,27 +1061,25 @@ var tgs = (function () { }); chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) { + if (!changeInfo) return; + //only save session if the tab url has changed - if (changeInfo && changeInfo.url) { + if (changeInfo.url) { queueSessionTimer(); } - //check for tab playing audio - if (tab.audible) { - audibleTabsList[tab.id] = true; - - //else check if tab WAS playing audio (and now isnt) - } else if (audibleTabsList[tab.id]) { - delete audibleTabsList[tab.id]; - resetTabTimer(tab.id); - if (debug) console.log('tab finished playing audio. restarting timer: ' + tab.id); + //reset tab timer if tab has just finished playing audio + if (changeInfo.hasOwnProperty('audible') && !changeInfo.audible) { + if (gsUtils.getOption(gsUtils.IGNORE_AUDIO)) { + resetTabTimer(tab.id); + } } //check for tab having an unsuspend request if (unsuspendRequestList[tab.id]) { //only permit unsuspend if tab is being reloaded - if (changeInfo && changeInfo.status === 'loading' && isSuspended(tab)) { + if (changeInfo.status === 'loading' && isSuspended(tab)) { unsuspendTab(tab); //otherwise remove unsuspend request @@ -1143,6 +1149,7 @@ var tgs = (function () { isSpecialTab: isSpecialTab, saveSuspendData: saveSuspendData, sessionId: sessionId, + scrollPosByTabId: scrollPosByTabId, runStartupChecks: runStartupChecks, resetAllTabTimers: resetAllTabTimers, requestNotice: requestNotice, diff --git a/src/js/contentscript.js b/src/js/contentscript.js index f3379e48..45510cca 100644 --- a/src/js/contentscript.js +++ b/src/js/contentscript.js @@ -49,10 +49,8 @@ tabId = response.tabId; //handle auto-scrolling - var scrollPos = getCookieValue('gsScrollPos-' + tabId); - if (scrollPos && scrollPos !== "") { - document.body.scrollTop = scrollPos; - setCookieValue('gsScrollPos-' + tabId, ''); + if (response.scrollPos && response.scrollPos !== "") { + document.body.scrollTop = response.scrollPos; } } }); @@ -63,14 +61,21 @@ return status; } - function reportState(state) { - state = state || calculateState(); - chrome.runtime.sendMessage({ action: 'reportTabState', status: state }); + function reportState(state, scrollPos) { + var message = { + action: 'reportTabState', + status: state || calculateState() + }; + if (scrollPos) { + message.scrollPos = scrollPos; + } + chrome.runtime.sendMessage(message); } - function suspendTab(suspendedUrl) { + function suspendTab(suspendedUrl, scrollPosition) { - reportState('suspended'); + scrollPosition = scrollPosition || document.body.scrollTop; + reportState('suspended', scrollPosition); if (suspendedUrl.indexOf('suspended.html') > 0) { window.location.replace(suspendedUrl); @@ -79,24 +84,6 @@ } } - function setCookieValue(key, value) { - document.cookie = key + '=' + value; - } - - function getCookieValue(key) { - - var keyStart = document.cookie.indexOf(key + '='), - keyEnd, - value = false; - - if (keyStart >= 0) { - keyEnd = document.cookie.indexOf(';', keyStart) > 0 ? document.cookie.indexOf(';', keyStart) : document.cookie.length; - value = document.cookie.substring(keyStart + key.length + 1, keyEnd); - value = value.length > 0 ? value : false; - } - return value; - } - function handlePreviewError(suspendedUrl, err) { chrome.runtime.sendMessage({ action: 'savePreviewData', @@ -112,7 +99,6 @@ timer = new Date(), height = 0; - setCookieValue('gsScrollPos-' + tabId, document.body.scrollTop); var position = document.body.scrollTop; //safety check here. don't try to use html2canvas if the page has more than 10000 elements @@ -156,7 +142,7 @@ position: position, timerMsg: timer }, function () { - suspendTab(suspendedUrl); + suspendTab(suspendedUrl, position); }); } } @@ -205,12 +191,11 @@ } function requestPreferences(callback) { - chrome.runtime.sendMessage({ action: 'prefs' }, function (response) { + chrome.runtime.sendMessage({ action: 'initTab' }, function (response) { callback(response); }); } - //listen for background events chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) { var response = {}, @@ -272,13 +257,9 @@ //listen for suspend request case 'confirmTabSuspend': if (request.suspendedUrl) { - setCookieValue('gsScrollPos-' + tabId, document.body.scrollTop); suspendTab(request.suspendedUrl); } break; - - default: - break; } }); diff --git a/src/js/gsUtils.js b/src/js/gsUtils.js index a4bf77ce..91ca1f3e 100644 --- a/src/js/gsUtils.js +++ b/src/js/gsUtils.js @@ -885,11 +885,29 @@ this.setOption(this.SCREEN_CAPTURE, '0'); } } - - // When migrating old settings, disable sync by default. - // For new installs, we want this to default to on. if (oldVersion < 6.31) { + // When migrating old settings, disable sync by default. + // For new installs, we want this to default to on. this.setOption(this.SYNC_SETTINGS, false); + + chrome.cookies.getAll({}, function (cookies) { + var scrollPosByTabId = {}; + cookies.forEach(function(cookie) { + if (cookie.name.indexOf('gsScrollPos') === 0) { + if (cookie.value && cookie.value !== '0') { + var tabId = cookie.name.substr(12); + scrollPosByTabId[tabId] = cookie.value; + } + var prefix = cookie.secure ? "https://" : "http://"; + if (cookie.domain.charAt(0) === ".") { + prefix += "www"; + } + var url = prefix + cookie.domain + cookie.path; + chrome.cookies.remove({ 'url': url, 'name': cookie.name }); + } + }); + chrome.extension.getBackgroundPage().tgs.scrollPosByTabId = scrollPosByTabId; + }); } }, diff --git a/src/manifest.json b/src/manifest.json index b2285671..6f3308aa 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -11,7 +11,8 @@ "https://*/*", "chrome://favicon/*", "https://greatsuspender.github.io/", - "contextMenus" + "contextMenus", + "cookies" ], "background": { "scripts": ["js/db.js", "js/gsUtils.js", "js/background.js"],