diff options
Diffstat (limited to 'js/cookies.js')
-rw-r--r-- | js/cookies.js | 837 |
1 files changed, 418 insertions, 419 deletions
diff --git a/js/cookies.js b/js/cookies.js index 4aa76c0..ee271ca 100644 --- a/js/cookies.js +++ b/js/cookies.js @@ -37,517 +37,516 @@ ηMatrix.cookieHunter = (function() { -/******************************************************************************/ + /******************************************************************************/ -var ηm = ηMatrix; + var ηm = ηMatrix; -var recordPageCookiesQueue = new Map(); -var removePageCookiesQueue = new Map(); -var removeCookieQueue = new Set(); -var cookieDict = new Map(); -var cookieEntryJunkyard = []; -var processRemoveQueuePeriod = 2 * 60 * 1000; -var processCleanPeriod = 10 * 60 * 1000; -var processPageRecordQueueTimer = null; -var processPageRemoveQueueTimer = null; + var recordPageCookiesQueue = new Map(); + var removePageCookiesQueue = new Map(); + var removeCookieQueue = new Set(); + var cookieDict = new Map(); + var cookieEntryJunkyard = []; + var processRemoveQueuePeriod = 2 * 60 * 1000; + var processCleanPeriod = 10 * 60 * 1000; + var processPageRecordQueueTimer = null; + var processPageRemoveQueueTimer = null; -/******************************************************************************/ + /******************************************************************************/ -var CookieEntry = function(cookie) { - this.usedOn = new Set(); - this.init(cookie); -}; - -CookieEntry.prototype.init = function(cookie) { - this.secure = cookie.secure; - this.session = cookie.session; - this.anySubdomain = cookie.domain.charAt(0) === '.'; - this.hostname = this.anySubdomain ? cookie.domain.slice(1) : cookie.domain; - this.domain = ηm.URI.domainFromHostname(this.hostname) || this.hostname; - this.path = cookie.path; - this.name = cookie.name; - this.value = cookie.value; - this.tstamp = Date.now(); - this.usedOn.clear(); - return this; -}; - -// Release anything which may consume too much memory - -CookieEntry.prototype.dispose = function() { - this.hostname = ''; - this.domain = ''; - this.path = ''; - this.name = ''; - this.value = ''; - this.usedOn.clear(); - return this; -}; + var CookieEntry = function(cookie) { + this.usedOn = new Set(); + this.init(cookie); + }; -/******************************************************************************/ + CookieEntry.prototype.init = function(cookie) { + this.secure = cookie.secure; + this.session = cookie.session; + this.anySubdomain = cookie.domain.charAt(0) === '.'; + this.hostname = this.anySubdomain ? cookie.domain.slice(1) : cookie.domain; + this.domain = ηm.URI.domainFromHostname(this.hostname) || this.hostname; + this.path = cookie.path; + this.name = cookie.name; + this.value = cookie.value; + this.tstamp = Date.now(); + this.usedOn.clear(); + return this; + }; -var addCookieToDict = function(cookie) { - var cookieKey = cookieKeyFromCookie(cookie), - cookieEntry = cookieDict.get(cookieKey); - if ( cookieEntry === undefined ) { - cookieEntry = cookieEntryJunkyard.pop(); - if ( cookieEntry ) { - cookieEntry.init(cookie); - } else { - cookieEntry = new CookieEntry(cookie); + // Release anything which may consume too much memory + + CookieEntry.prototype.dispose = function() { + this.hostname = ''; + this.domain = ''; + this.path = ''; + this.name = ''; + this.value = ''; + this.usedOn.clear(); + return this; + }; + + /******************************************************************************/ + + var addCookieToDict = function(cookie) { + var cookieKey = cookieKeyFromCookie(cookie), + cookieEntry = cookieDict.get(cookieKey); + if ( cookieEntry === undefined ) { + cookieEntry = cookieEntryJunkyard.pop(); + if ( cookieEntry ) { + cookieEntry.init(cookie); + } else { + cookieEntry = new CookieEntry(cookie); + } + cookieDict.set(cookieKey, cookieEntry); } - cookieDict.set(cookieKey, cookieEntry); - } - return cookieEntry; -}; + return cookieEntry; + }; -/******************************************************************************/ + /******************************************************************************/ -var addCookiesToDict = function(cookies) { - var i = cookies.length; - while ( i-- ) { - addCookieToDict(cookies[i]); - } -}; + var addCookiesToDict = function(cookies) { + var i = cookies.length; + while ( i-- ) { + addCookieToDict(cookies[i]); + } + }; -/******************************************************************************/ + /******************************************************************************/ -var removeCookieFromDict = function(cookieKey) { - var cookieEntry = cookieDict.get(cookieKey); - if ( cookieEntry === undefined ) { return false; } - cookieDict.delete(cookieKey); - if ( cookieEntryJunkyard.length < 25 ) { - cookieEntryJunkyard.push(cookieEntry.dispose()); - } - return true; -}; + var removeCookieFromDict = function(cookieKey) { + var cookieEntry = cookieDict.get(cookieKey); + if ( cookieEntry === undefined ) { return false; } + cookieDict.delete(cookieKey); + if ( cookieEntryJunkyard.length < 25 ) { + cookieEntryJunkyard.push(cookieEntry.dispose()); + } + return true; + }; -/******************************************************************************/ + /******************************************************************************/ + + var cookieKeyBuilder = [ + '', // 0 = scheme + '://', + '', // 2 = domain + '', // 3 = path + '{', + '', // 5 = persistent or session + '-cookie:', + '', // 7 = name + '}' + ]; + + var cookieKeyFromCookie = function(cookie) { + var cb = cookieKeyBuilder; + cb[0] = cookie.secure ? 'https' : 'http'; + cb[2] = cookie.domain.charAt(0) === '.' ? cookie.domain.slice(1) : cookie.domain; + cb[3] = cookie.path; + cb[5] = cookie.session ? 'session' : 'persistent'; + cb[7] = cookie.name; + return cb.join(''); + }; -var cookieKeyBuilder = [ - '', // 0 = scheme - '://', - '', // 2 = domain - '', // 3 = path - '{', - '', // 5 = persistent or session - '-cookie:', - '', // 7 = name - '}' -]; - -var cookieKeyFromCookie = function(cookie) { - var cb = cookieKeyBuilder; - cb[0] = cookie.secure ? 'https' : 'http'; - cb[2] = cookie.domain.charAt(0) === '.' ? cookie.domain.slice(1) : cookie.domain; - cb[3] = cookie.path; - cb[5] = cookie.session ? 'session' : 'persistent'; - cb[7] = cookie.name; - return cb.join(''); -}; - -var cookieKeyFromCookieURL = function(url, type, name) { - var ηmuri = ηm.URI.set(url); - var cb = cookieKeyBuilder; - cb[0] = ηmuri.scheme; - cb[2] = ηmuri.hostname; - cb[3] = ηmuri.path; - cb[5] = type; - cb[7] = name; - return cb.join(''); -}; + var cookieKeyFromCookieURL = function(url, type, name) { + var ηmuri = ηm.URI.set(url); + var cb = cookieKeyBuilder; + cb[0] = ηmuri.scheme; + cb[2] = ηmuri.hostname; + cb[3] = ηmuri.path; + cb[5] = type; + cb[7] = name; + return cb.join(''); + }; -/******************************************************************************/ + /******************************************************************************/ -var cookieURLFromCookieEntry = function(entry) { - if ( !entry ) { - return ''; - } - return (entry.secure ? 'https://' : 'http://') + entry.hostname + entry.path; -}; + var cookieURLFromCookieEntry = function(entry) { + if ( !entry ) { + return ''; + } + return (entry.secure ? 'https://' : 'http://') + entry.hostname + entry.path; + }; -/******************************************************************************/ + /******************************************************************************/ -var cookieMatchDomains = function(cookieKey, allHostnamesString) { - var cookieEntry = cookieDict.get(cookieKey); - if ( cookieEntry === undefined ) { return false; } - if ( allHostnamesString.indexOf(' ' + cookieEntry.hostname + ' ') < 0 ) { - if ( !cookieEntry.anySubdomain ) { - return false; + var cookieMatchDomains = function(cookieKey, allHostnamesString) { + var cookieEntry = cookieDict.get(cookieKey); + if ( cookieEntry === undefined ) { return false; } + if ( allHostnamesString.indexOf(' ' + cookieEntry.hostname + ' ') < 0 ) { + if ( !cookieEntry.anySubdomain ) { + return false; + } + if ( allHostnamesString.indexOf('.' + cookieEntry.hostname + ' ') < 0 ) { + return false; + } } - if ( allHostnamesString.indexOf('.' + cookieEntry.hostname + ' ') < 0 ) { - return false; + return true; + }; + + /******************************************************************************/ + + // Look for cookies to record for a specific web page + + var recordPageCookiesAsync = function(pageStats) { + // Store the page stats objects so that it doesn't go away + // before we handle the job. + // rhill 2013-10-19: pageStats could be nil, for example, this can + // happens if a file:// ... makes an xmlHttpRequest + if ( !pageStats ) { + return; } - } - return true; -}; + recordPageCookiesQueue.set(pageStats.pageUrl, pageStats); + if ( processPageRecordQueueTimer === null ) { + processPageRecordQueueTimer = vAPI.setTimeout(processPageRecordQueue, 1000); + } + }; -/******************************************************************************/ + /******************************************************************************/ -// Look for cookies to record for a specific web page - -var recordPageCookiesAsync = function(pageStats) { - // Store the page stats objects so that it doesn't go away - // before we handle the job. - // rhill 2013-10-19: pageStats could be nil, for example, this can - // happens if a file:// ... makes an xmlHttpRequest - if ( !pageStats ) { - return; - } - recordPageCookiesQueue.set(pageStats.pageUrl, pageStats); - if ( processPageRecordQueueTimer === null ) { - processPageRecordQueueTimer = vAPI.setTimeout(processPageRecordQueue, 1000); - } -}; + var cookieLogEntryBuilder = [ + '', + '{', + '', + '-cookie:', + '', + '}' + ]; -/******************************************************************************/ + var recordPageCookie = function(pageStore, cookieKey) { + if ( vAPI.isBehindTheSceneTabId(pageStore.tabId) ) { return; } -var cookieLogEntryBuilder = [ - '', - '{', - '', - '-cookie:', - '', - '}' -]; - -var recordPageCookie = function(pageStore, cookieKey) { - if ( vAPI.isBehindTheSceneTabId(pageStore.tabId) ) { return; } - - var cookieEntry = cookieDict.get(cookieKey); - var pageHostname = pageStore.pageHostname; - var block = ηm.mustBlock(pageHostname, cookieEntry.hostname, 'cookie'); - - cookieLogEntryBuilder[0] = cookieURLFromCookieEntry(cookieEntry); - cookieLogEntryBuilder[2] = cookieEntry.session ? 'session' : 'persistent'; - cookieLogEntryBuilder[4] = encodeURIComponent(cookieEntry.name); - - var cookieURL = cookieLogEntryBuilder.join(''); - - // rhill 2013-11-20: - // https://github.com/gorhill/httpswitchboard/issues/60 - // Need to URL-encode cookie name - pageStore.recordRequest('cookie', cookieURL, block); - ηm.logger.writeOne(pageStore.tabId, 'net', pageHostname, cookieURL, 'cookie', block); - - cookieEntry.usedOn.add(pageHostname); - - // rhill 2013-11-21: - // https://github.com/gorhill/httpswitchboard/issues/65 - // Leave alone cookies from behind-the-scene requests if - // behind-the-scene processing is disabled. - if ( !block ) { - return; - } - if ( !ηm.userSettings.deleteCookies ) { - return; - } - removeCookieAsync(cookieKey); -}; + var cookieEntry = cookieDict.get(cookieKey); + var pageHostname = pageStore.pageHostname; + var block = ηm.mustBlock(pageHostname, cookieEntry.hostname, 'cookie'); -/******************************************************************************/ + cookieLogEntryBuilder[0] = cookieURLFromCookieEntry(cookieEntry); + cookieLogEntryBuilder[2] = cookieEntry.session ? 'session' : 'persistent'; + cookieLogEntryBuilder[4] = encodeURIComponent(cookieEntry.name); -// Look for cookies to potentially remove for a specific web page - -var removePageCookiesAsync = function(pageStats) { - // Hold onto pageStats objects so that it doesn't go away - // before we handle the job. - // rhill 2013-10-19: pageStats could be nil, for example, this can - // happens if a file:// ... makes an xmlHttpRequest - if ( !pageStats ) { - return; - } - removePageCookiesQueue.set(pageStats.pageUrl, pageStats); - if ( processPageRemoveQueueTimer === null ) { - processPageRemoveQueueTimer = vAPI.setTimeout(processPageRemoveQueue, 15 * 1000); - } -}; + var cookieURL = cookieLogEntryBuilder.join(''); -/******************************************************************************/ + // rhill 2013-11-20: + // https://github.com/gorhill/httpswitchboard/issues/60 + // Need to URL-encode cookie name + pageStore.recordRequest('cookie', cookieURL, block); + ηm.logger.writeOne(pageStore.tabId, 'net', pageHostname, cookieURL, 'cookie', block); -// Candidate for removal + cookieEntry.usedOn.add(pageHostname); -var removeCookieAsync = function(cookieKey) { - removeCookieQueue.add(cookieKey); -}; + // rhill 2013-11-21: + // https://github.com/gorhill/httpswitchboard/issues/65 + // Leave alone cookies from behind-the-scene requests if + // behind-the-scene processing is disabled. + if ( !block ) { + return; + } + if ( !ηm.userSettings.deleteCookies ) { + return; + } + removeCookieAsync(cookieKey); + }; -/******************************************************************************/ + /******************************************************************************/ -var chromeCookieRemove = function(cookieEntry, name) { - var url = cookieURLFromCookieEntry(cookieEntry); - if ( url === '' ) { - return; - } - var sessionCookieKey = cookieKeyFromCookieURL(url, 'session', name); - var persistCookieKey = cookieKeyFromCookieURL(url, 'persistent', name); - var callback = function(details) { - var success = !!details; - var template = success ? i18nCookieDeleteSuccess : i18nCookieDeleteFailure; - if ( removeCookieFromDict(sessionCookieKey) ) { - if ( success ) { - ηm.cookieRemovedCounter += 1; - } - ηm.logger.writeOne('', 'info', 'cookie', template.replace('{{value}}', sessionCookieKey)); + // Look for cookies to potentially remove for a specific web page + + var removePageCookiesAsync = function(pageStats) { + // Hold onto pageStats objects so that it doesn't go away + // before we handle the job. + // rhill 2013-10-19: pageStats could be nil, for example, this can + // happens if a file:// ... makes an xmlHttpRequest + if ( !pageStats ) { + return; } - if ( removeCookieFromDict(persistCookieKey) ) { - if ( success ) { - ηm.cookieRemovedCounter += 1; - } - ηm.logger.writeOne('', 'info', 'cookie', template.replace('{{value}}', persistCookieKey)); + removePageCookiesQueue.set(pageStats.pageUrl, pageStats); + if ( processPageRemoveQueueTimer === null ) { + processPageRemoveQueueTimer = vAPI.setTimeout(processPageRemoveQueue, 15 * 1000); } }; - vAPI.cookies.remove({ url: url, name: name }, callback); -}; + /******************************************************************************/ -var i18nCookieDeleteSuccess = vAPI.i18n('loggerEntryCookieDeleted'); -var i18nCookieDeleteFailure = vAPI.i18n('loggerEntryDeleteCookieError'); + // Candidate for removal -/******************************************************************************/ + var removeCookieAsync = function(cookieKey) { + removeCookieQueue.add(cookieKey); + }; -var processPageRecordQueue = function() { - processPageRecordQueueTimer = null; + /******************************************************************************/ - for ( var pageStore of recordPageCookiesQueue.values() ) { - findAndRecordPageCookies(pageStore); - } - recordPageCookiesQueue.clear(); -}; + var chromeCookieRemove = function(cookieEntry, name) { + var url = cookieURLFromCookieEntry(cookieEntry); + if ( url === '' ) { + return; + } + var sessionCookieKey = cookieKeyFromCookieURL(url, 'session', name); + var persistCookieKey = cookieKeyFromCookieURL(url, 'persistent', name); + var callback = function(details) { + var success = !!details; + var template = success ? i18nCookieDeleteSuccess : i18nCookieDeleteFailure; + if ( removeCookieFromDict(sessionCookieKey) ) { + if ( success ) { + ηm.cookieRemovedCounter += 1; + } + ηm.logger.writeOne('', 'info', 'cookie', template.replace('{{value}}', sessionCookieKey)); + } + if ( removeCookieFromDict(persistCookieKey) ) { + if ( success ) { + ηm.cookieRemovedCounter += 1; + } + ηm.logger.writeOne('', 'info', 'cookie', template.replace('{{value}}', persistCookieKey)); + } + }; -/******************************************************************************/ + vAPI.cookies.remove({ url: url, name: name }, callback); + }; -var processPageRemoveQueue = function() { - processPageRemoveQueueTimer = null; + var i18nCookieDeleteSuccess = vAPI.i18n('loggerEntryCookieDeleted'); + var i18nCookieDeleteFailure = vAPI.i18n('loggerEntryDeleteCookieError'); - for ( var pageStore of removePageCookiesQueue.values() ) { - findAndRemovePageCookies(pageStore); - } - removePageCookiesQueue.clear(); -}; + /******************************************************************************/ -/******************************************************************************/ + var processPageRecordQueue = function() { + processPageRecordQueueTimer = null; -// Effectively remove cookies. + for ( var pageStore of recordPageCookiesQueue.values() ) { + findAndRecordPageCookies(pageStore); + } + recordPageCookiesQueue.clear(); + }; -var processRemoveQueue = function() { - var userSettings = ηm.userSettings; - var deleteCookies = userSettings.deleteCookies; + /******************************************************************************/ - // Session cookies which timestamp is *after* tstampObsolete will - // be left untouched - // https://github.com/gorhill/httpswitchboard/issues/257 - var tstampObsolete = userSettings.deleteUnusedSessionCookies ? - Date.now() - userSettings.deleteUnusedSessionCookiesAfter * 60 * 1000 : - 0; + var processPageRemoveQueue = function() { + processPageRemoveQueueTimer = null; - var srcHostnames; - var cookieEntry; + for ( var pageStore of removePageCookiesQueue.values() ) { + findAndRemovePageCookies(pageStore); + } + removePageCookiesQueue.clear(); + }; - for ( var cookieKey of removeCookieQueue ) { - // rhill 2014-05-12: Apparently this can happen. I have to - // investigate how (A session cookie has same name as a - // persistent cookie?) - cookieEntry = cookieDict.get(cookieKey); - if ( cookieEntry === undefined ) { continue; } + /******************************************************************************/ + + // Effectively remove cookies. + + var processRemoveQueue = function() { + var userSettings = ηm.userSettings; + var deleteCookies = userSettings.deleteCookies; + + // Session cookies which timestamp is *after* tstampObsolete will + // be left untouched + // https://github.com/gorhill/httpswitchboard/issues/257 + var tstampObsolete = userSettings.deleteUnusedSessionCookies ? + Date.now() - userSettings.deleteUnusedSessionCookiesAfter * 60 * 1000 : + 0; + + var srcHostnames; + var cookieEntry; + + for ( var cookieKey of removeCookieQueue ) { + // rhill 2014-05-12: Apparently this can happen. I have to + // investigate how (A session cookie has same name as a + // persistent cookie?) + cookieEntry = cookieDict.get(cookieKey); + if ( cookieEntry === undefined ) { continue; } + + // Delete obsolete session cookies: enabled. + if ( tstampObsolete !== 0 && cookieEntry.session ) { + if ( cookieEntry.tstamp < tstampObsolete ) { + chromeCookieRemove(cookieEntry, cookieEntry.name); + continue; + } + } - // Delete obsolete session cookies: enabled. - if ( tstampObsolete !== 0 && cookieEntry.session ) { - if ( cookieEntry.tstamp < tstampObsolete ) { - chromeCookieRemove(cookieEntry, cookieEntry.name); + // Delete all blocked cookies: disabled. + if ( deleteCookies === false ) { continue; } - } - - // Delete all blocked cookies: disabled. - if ( deleteCookies === false ) { - continue; - } - // Query scopes only if we are going to use them - if ( srcHostnames === undefined ) { - srcHostnames = ηm.tMatrix.extractAllSourceHostnames(); - } + // Query scopes only if we are going to use them + if ( srcHostnames === undefined ) { + srcHostnames = ηm.tMatrix.extractAllSourceHostnames(); + } - // Ensure cookie is not allowed on ALL current web pages: It can - // happen that a cookie is blacklisted on one web page while - // being whitelisted on another (because of per-page permissions). - if ( canRemoveCookie(cookieKey, srcHostnames) ) { - chromeCookieRemove(cookieEntry, cookieEntry.name); + // Ensure cookie is not allowed on ALL current web pages: It can + // happen that a cookie is blacklisted on one web page while + // being whitelisted on another (because of per-page permissions). + if ( canRemoveCookie(cookieKey, srcHostnames) ) { + chromeCookieRemove(cookieEntry, cookieEntry.name); + } } - } - removeCookieQueue.clear(); + removeCookieQueue.clear(); - vAPI.setTimeout(processRemoveQueue, processRemoveQueuePeriod); -}; - -/******************************************************************************/ + vAPI.setTimeout(processRemoveQueue, processRemoveQueuePeriod); + }; -// Once in a while, we go ahead and clean everything that might have been -// left behind. - -// Remove only some of the cookies which are candidate for removal: who knows, -// maybe a user has 1000s of cookies sitting in his browser... - -var processClean = function() { - var us = ηm.userSettings; - if ( us.deleteCookies || us.deleteUnusedSessionCookies ) { - var cookieKeys = Array.from(cookieDict.keys()), - len = cookieKeys.length, - step, offset, n; - if ( len > 25 ) { - step = len / 25; - offset = Math.floor(Math.random() * len); - n = 25; - } else { - step = 1; - offset = 0; - n = len; - } - var i = offset; - while ( n-- ) { - removeCookieAsync(cookieKeys[Math.floor(i % len)]); - i += step; + /******************************************************************************/ + + // Once in a while, we go ahead and clean everything that might have been + // left behind. + + // Remove only some of the cookies which are candidate for removal: who knows, + // maybe a user has 1000s of cookies sitting in his browser... + + var processClean = function() { + var us = ηm.userSettings; + if ( us.deleteCookies || us.deleteUnusedSessionCookies ) { + var cookieKeys = Array.from(cookieDict.keys()), + len = cookieKeys.length, + step, offset, n; + if ( len > 25 ) { + step = len / 25; + offset = Math.floor(Math.random() * len); + n = 25; + } else { + step = 1; + offset = 0; + n = len; + } + var i = offset; + while ( n-- ) { + removeCookieAsync(cookieKeys[Math.floor(i % len)]); + i += step; + } } - } - vAPI.setTimeout(processClean, processCleanPeriod); -}; + vAPI.setTimeout(processClean, processCleanPeriod); + }; -/******************************************************************************/ + /******************************************************************************/ -var findAndRecordPageCookies = function(pageStore) { - for ( var cookieKey of cookieDict.keys() ) { - if ( cookieMatchDomains(cookieKey, pageStore.allHostnamesString) ) { - recordPageCookie(pageStore, cookieKey); + var findAndRecordPageCookies = function(pageStore) { + for ( var cookieKey of cookieDict.keys() ) { + if ( cookieMatchDomains(cookieKey, pageStore.allHostnamesString) ) { + recordPageCookie(pageStore, cookieKey); + } } - } -}; + }; -/******************************************************************************/ + /******************************************************************************/ -var findAndRemovePageCookies = function(pageStore) { - for ( var cookieKey of cookieDict.keys() ) { - if ( cookieMatchDomains(cookieKey, pageStore.allHostnamesString) ) { - removeCookieAsync(cookieKey); + var findAndRemovePageCookies = function(pageStore) { + for ( var cookieKey of cookieDict.keys() ) { + if ( cookieMatchDomains(cookieKey, pageStore.allHostnamesString) ) { + removeCookieAsync(cookieKey); + } } - } -}; + }; -/******************************************************************************/ + /******************************************************************************/ -var canRemoveCookie = function(cookieKey, srcHostnames) { - var cookieEntry = cookieDict.get(cookieKey); - if ( cookieEntry === undefined ) { return false; } + var canRemoveCookie = function(cookieKey, srcHostnames) { + var cookieEntry = cookieDict.get(cookieKey); + if ( cookieEntry === undefined ) { return false; } - var cookieHostname = cookieEntry.hostname; - var srcHostname; + var cookieHostname = cookieEntry.hostname; + var srcHostname; - for ( srcHostname of cookieEntry.usedOn ) { - if ( ηm.mustAllow(srcHostname, cookieHostname, 'cookie') ) { - return false; - } - } - // Maybe there is a scope in which the cookie is 1st-party-allowed. - // For example, if I am logged in into `github.com`, I do not want to be - // logged out just because I did not yet open a `github.com` page after - // re-starting the browser. - srcHostname = cookieHostname; - var pos; - for (;;) { - if ( srcHostnames.has(srcHostname) ) { + for ( srcHostname of cookieEntry.usedOn ) { if ( ηm.mustAllow(srcHostname, cookieHostname, 'cookie') ) { return false; } } - if ( srcHostname === cookieEntry.domain ) { - break; - } - pos = srcHostname.indexOf('.'); - if ( pos === -1 ) { - break; + // Maybe there is a scope in which the cookie is 1st-party-allowed. + // For example, if I am logged in into `github.com`, I do not want to be + // logged out just because I did not yet open a `github.com` page after + // re-starting the browser. + srcHostname = cookieHostname; + var pos; + for (;;) { + if ( srcHostnames.has(srcHostname) ) { + if ( ηm.mustAllow(srcHostname, cookieHostname, 'cookie') ) { + return false; + } + } + if ( srcHostname === cookieEntry.domain ) { + break; + } + pos = srcHostname.indexOf('.'); + if ( pos === -1 ) { + break; + } + srcHostname = srcHostname.slice(pos + 1); } - srcHostname = srcHostname.slice(pos + 1); - } - return true; -}; + return true; + }; -/******************************************************************************/ + /******************************************************************************/ + + // Listen to any change in cookieland, we will update page stats accordingly. -// Listen to any change in cookieland, we will update page stats accordingly. - -vAPI.cookies.onChanged = function(cookie) { - // rhill 2013-12-11: If cookie value didn't change, no need to record. - // https://github.com/gorhill/httpswitchboard/issues/79 - var cookieKey = cookieKeyFromCookie(cookie); - var cookieEntry = cookieDict.get(cookieKey); - if ( cookieEntry === undefined ) { - cookieEntry = addCookieToDict(cookie); - } else { - cookieEntry.tstamp = Date.now(); - if ( cookie.value === cookieEntry.value ) { return; } - cookieEntry.value = cookie.value; - } - - // Go through all pages and update if needed, as one cookie can be used - // by many web pages, so they need to be recorded for all these pages. - var pageStores = ηm.pageStores; - var pageStore; - for ( var tabId in pageStores ) { - if ( pageStores.hasOwnProperty(tabId) === false ) { - continue; + vAPI.cookies.onChanged = function(cookie) { + // rhill 2013-12-11: If cookie value didn't change, no need to record. + // https://github.com/gorhill/httpswitchboard/issues/79 + var cookieKey = cookieKeyFromCookie(cookie); + var cookieEntry = cookieDict.get(cookieKey); + if ( cookieEntry === undefined ) { + cookieEntry = addCookieToDict(cookie); + } else { + cookieEntry.tstamp = Date.now(); + if ( cookie.value === cookieEntry.value ) { return; } + cookieEntry.value = cookie.value; } - pageStore = pageStores[tabId]; - if ( !cookieMatchDomains(cookieKey, pageStore.allHostnamesString) ) { - continue; + + // Go through all pages and update if needed, as one cookie can be used + // by many web pages, so they need to be recorded for all these pages. + var pageStores = ηm.pageStores; + var pageStore; + for ( var tabId in pageStores ) { + if ( pageStores.hasOwnProperty(tabId) === false ) { + continue; + } + pageStore = pageStores[tabId]; + if ( !cookieMatchDomains(cookieKey, pageStore.allHostnamesString) ) { + continue; + } + recordPageCookie(pageStore, cookieKey); } - recordPageCookie(pageStore, cookieKey); - } -}; + }; -/******************************************************************************/ + /******************************************************************************/ -// Listen to any change in cookieland, we will update page stats accordingly. + // Listen to any change in cookieland, we will update page stats accordingly. -vAPI.cookies.onRemoved = function(cookie) { - var cookieKey = cookieKeyFromCookie(cookie); - if ( removeCookieFromDict(cookieKey) ) { - ηm.logger.writeOne('', 'info', 'cookie', i18nCookieDeleteSuccess.replace('{{value}}', cookieKey)); - } -}; + vAPI.cookies.onRemoved = function(cookie) { + var cookieKey = cookieKeyFromCookie(cookie); + if ( removeCookieFromDict(cookieKey) ) { + ηm.logger.writeOne('', 'info', 'cookie', i18nCookieDeleteSuccess.replace('{{value}}', cookieKey)); + } + }; -/******************************************************************************/ + /******************************************************************************/ -// Listen to any change in cookieland, we will update page stats accordingly. + // Listen to any change in cookieland, we will update page stats accordingly. -vAPI.cookies.onAllRemoved = function() { - for ( var cookieKey of cookieDict.keys() ) { - if ( removeCookieFromDict(cookieKey) ) { - ηm.logger.writeOne('', 'info', 'cookie', i18nCookieDeleteSuccess.replace('{{value}}', cookieKey)); + vAPI.cookies.onAllRemoved = function() { + for ( var cookieKey of cookieDict.keys() ) { + if ( removeCookieFromDict(cookieKey) ) { + ηm.logger.writeOne('', 'info', 'cookie', i18nCookieDeleteSuccess.replace('{{value}}', cookieKey)); + } } - } -}; + }; -/******************************************************************************/ + /******************************************************************************/ -vAPI.cookies.getAll(addCookiesToDict); -vAPI.cookies.start(); + vAPI.cookies.getAll(addCookiesToDict); + vAPI.cookies.start(); -vAPI.setTimeout(processRemoveQueue, processRemoveQueuePeriod); -vAPI.setTimeout(processClean, processCleanPeriod); + vAPI.setTimeout(processRemoveQueue, processRemoveQueuePeriod); + vAPI.setTimeout(processClean, processCleanPeriod); -/******************************************************************************/ + /******************************************************************************/ -// Expose only what is necessary + // Expose only what is necessary -return { - recordPageCookies: recordPageCookiesAsync, - removePageCookies: removePageCookiesAsync -}; + return { + recordPageCookies: recordPageCookiesAsync, + removePageCookies: removePageCookiesAsync + }; -/******************************************************************************/ + /******************************************************************************/ })(); /******************************************************************************/ - |