Browse Source

further address #853

pull/2/head
gorhill 7 years ago
parent
commit
e278a7d4e3
No known key found for this signature in database GPG Key ID: 25E1490B761470C2
  1. 176
      src/js/cookies.js

176
src/js/cookies.js

@ -41,10 +41,10 @@
var µm = µMatrix;
var recordPageCookiesQueue = {};
var removePageCookiesQueue = {};
var removeCookieQueue = {};
var cookieDict = {};
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;
@ -54,10 +54,11 @@ var processPageRemoveQueueTimer = null;
/******************************************************************************/
var CookieEntry = function(cookie) {
this.set(cookie);
this.usedOn = new Set();
this.init(cookie);
};
CookieEntry.prototype.set = function(cookie) {
CookieEntry.prototype.init = function(cookie) {
this.secure = cookie.secure;
this.session = cookie.session;
this.anySubdomain = cookie.domain.charAt(0) === '.';
@ -67,36 +68,37 @@ CookieEntry.prototype.set = function(cookie) {
this.name = cookie.name;
this.value = cookie.value;
this.tstamp = Date.now();
this.usedOn = {};
this.usedOn.clear();
return this;
};
// Release anything which may consume too much memory
CookieEntry.prototype.unset = function() {
CookieEntry.prototype.dispose = function() {
this.hostname = '';
this.domain = '';
this.path = '';
this.name = '';
this.value = '';
this.usedOn = {};
this.usedOn.clear();
return this;
};
/******************************************************************************/
var addCookieToDict = function(cookie) {
var cookieKey = cookieKeyFromCookie(cookie);
if ( cookieDict.hasOwnProperty(cookieKey) === false ) {
var cookieEntry = cookieEntryJunkyard.pop();
var cookieKey = cookieKeyFromCookie(cookie),
cookieEntry = cookieDict.get(cookieKey);
if ( cookieEntry === undefined ) {
cookieEntry = cookieEntryJunkyard.pop();
if ( cookieEntry ) {
cookieEntry.set(cookie);
cookieEntry.init(cookie);
} else {
cookieEntry = new CookieEntry(cookie);
}
cookieDict[cookieKey] = cookieEntry;
cookieDict.set(cookieKey, cookieEntry);
}
return cookieDict[cookieKey];
return cookieEntry;
};
/******************************************************************************/
@ -111,13 +113,11 @@ var addCookiesToDict = function(cookies) {
/******************************************************************************/
var removeCookieFromDict = function(cookieKey) {
if ( cookieDict.hasOwnProperty(cookieKey) === false ) {
return false;
}
var cookieEntry = cookieDict[cookieKey];
delete cookieDict[cookieKey];
var cookieEntry = cookieDict.get(cookieKey);
if ( cookieEntry === undefined ) { return false; }
cookieDict.delete(cookieKey);
if ( cookieEntryJunkyard.length < 25 ) {
cookieEntryJunkyard.push(cookieEntry.unset());
cookieEntryJunkyard.push(cookieEntry.dispose());
}
return true;
};
@ -159,12 +159,6 @@ var cookieKeyFromCookieURL = function(url, type, name) {
/******************************************************************************/
var cookieEntryFromCookie = function(cookie) {
return cookieDict[cookieKeyFromCookie(cookie)];
};
/******************************************************************************/
var cookieURLFromCookieEntry = function(entry) {
if ( !entry ) {
return '';
@ -175,10 +169,8 @@ var cookieURLFromCookieEntry = function(entry) {
/******************************************************************************/
var cookieMatchDomains = function(cookieKey, allHostnamesString) {
var cookieEntry = cookieDict[cookieKey];
if ( !cookieEntry ) {
return false;
}
var cookieEntry = cookieDict.get(cookieKey);
if ( cookieEntry === undefined ) { return false; }
if ( allHostnamesString.indexOf(' ' + cookieEntry.hostname + ' ') < 0 ) {
if ( !cookieEntry.anySubdomain ) {
return false;
@ -202,7 +194,7 @@ var recordPageCookiesAsync = function(pageStats) {
if ( !pageStats ) {
return;
}
recordPageCookiesQueue[pageStats.pageUrl] = pageStats;
recordPageCookiesQueue.set(pageStats.pageUrl, pageStats);
if ( processPageRecordQueueTimer === null ) {
processPageRecordQueueTimer = vAPI.setTimeout(processPageRecordQueue, 1000);
}
@ -220,11 +212,9 @@ var cookieLogEntryBuilder = [
];
var recordPageCookie = function(pageStore, cookieKey) {
if ( vAPI.isBehindTheSceneTabId(pageStore.tabId) ) {
return;
}
if ( vAPI.isBehindTheSceneTabId(pageStore.tabId) ) { return; }
var cookieEntry = cookieDict[cookieKey];
var cookieEntry = cookieDict.get(cookieKey);
var pageHostname = pageStore.pageHostname;
var block = µm.mustBlock(pageHostname, cookieEntry.hostname, 'cookie');
@ -240,7 +230,7 @@ var recordPageCookie = function(pageStore, cookieKey) {
pageStore.recordRequest('cookie', cookieURL, block);
µm.logger.writeOne(pageStore.tabId, 'net', pageHostname, cookieURL, 'cookie', block);
cookieEntry.usedOn[pageHostname] = true;
cookieEntry.usedOn.add(pageHostname);
// rhill 2013-11-21:
// https://github.com/gorhill/httpswitchboard/issues/65
@ -267,7 +257,7 @@ var removePageCookiesAsync = function(pageStats) {
if ( !pageStats ) {
return;
}
removePageCookiesQueue[pageStats.pageUrl] = pageStats;
removePageCookiesQueue.set(pageStats.pageUrl, pageStats);
if ( processPageRemoveQueueTimer === null ) {
processPageRemoveQueueTimer = vAPI.setTimeout(processPageRemoveQueue, 15 * 1000);
}
@ -278,7 +268,7 @@ var removePageCookiesAsync = function(pageStats) {
// Candidate for removal
var removeCookieAsync = function(cookieKey) {
removeCookieQueue[cookieKey] = true;
removeCookieQueue.add(cookieKey);
};
/******************************************************************************/
@ -318,13 +308,10 @@ var i18nCookieDeleteFailure = vAPI.i18n('loggerEntryDeleteCookieError');
var processPageRecordQueue = function() {
processPageRecordQueueTimer = null;
for ( var pageURL in recordPageCookiesQueue ) {
if ( !recordPageCookiesQueue.hasOwnProperty(pageURL) ) {
continue;
}
findAndRecordPageCookies(recordPageCookiesQueue[pageURL]);
delete recordPageCookiesQueue[pageURL];
for ( var pageStore of recordPageCookiesQueue.values() ) {
findAndRecordPageCookies(pageStore);
}
recordPageCookiesQueue.clear();
};
/******************************************************************************/
@ -332,13 +319,10 @@ var processPageRecordQueue = function() {
var processPageRemoveQueue = function() {
processPageRemoveQueueTimer = null;
for ( var pageURL in removePageCookiesQueue ) {
if ( !removePageCookiesQueue.hasOwnProperty(pageURL) ) {
continue;
}
findAndRemovePageCookies(removePageCookiesQueue[pageURL]);
delete removePageCookiesQueue[pageURL];
for ( var pageStore of removePageCookiesQueue.values() ) {
findAndRemovePageCookies(pageStore);
}
removePageCookiesQueue.clear();
};
/******************************************************************************/
@ -359,19 +343,12 @@ var processRemoveQueue = function() {
var srcHostnames;
var cookieEntry;
for ( var cookieKey in removeCookieQueue ) {
if ( removeCookieQueue.hasOwnProperty(cookieKey) === false ) {
continue;
}
delete removeCookieQueue[cookieKey];
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[cookieKey];
if ( !cookieEntry ) {
continue;
}
cookieEntry = cookieDict.get(cookieKey);
if ( cookieEntry === undefined ) { continue; }
// Delete obsolete session cookies: enabled.
if ( tstampObsolete !== 0 && cookieEntry.session ) {
@ -399,6 +376,8 @@ var processRemoveQueue = function() {
}
}
removeCookieQueue.clear();
vAPI.setTimeout(processRemoveQueue, processRemoveQueuePeriod);
};
@ -407,16 +386,29 @@ var processRemoveQueue = function() {
// 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() {
// 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 cookieKeys = Object.keys(cookieDict);
if ( cookieKeys.length > 25 ) {
cookieKeys = cookieKeys.sort(function(){return Math.random() < 0.5;}).splice(0, 50);
}
while ( cookieKeys.length ) {
removeCookieAsync(cookieKeys.pop());
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);
@ -425,45 +417,33 @@ var processClean = function() {
/******************************************************************************/
var findAndRecordPageCookies = function(pageStore) {
for ( var cookieKey in cookieDict ) {
if ( !cookieDict.hasOwnProperty(cookieKey) ) {
continue;
}
if ( cookieMatchDomains(cookieKey, pageStore.allHostnamesString) === false ) {
continue;
for ( var cookieKey of cookieDict.keys() ) {
if ( cookieMatchDomains(cookieKey, pageStore.allHostnamesString) ) {
recordPageCookie(pageStore, cookieKey);
}
recordPageCookie(pageStore, cookieKey);
}
};
/******************************************************************************/
var findAndRemovePageCookies = function(pageStore) {
for ( var cookieKey in cookieDict ) {
if ( !cookieDict.hasOwnProperty(cookieKey) ) {
continue;
for ( var cookieKey of cookieDict.keys() ) {
if ( cookieMatchDomains(cookieKey, pageStore.allHostnamesString) ) {
removeCookieAsync(cookieKey);
}
if ( !cookieMatchDomains(cookieKey, pageStore.allHostnamesString) ) {
continue;
}
removeCookieAsync(cookieKey);
}
};
/******************************************************************************/
var canRemoveCookie = function(cookieKey, srcHostnames) {
var cookieEntry = cookieDict[cookieKey];
if ( !cookieEntry ) {
return false;
}
var cookieEntry = cookieDict.get(cookieKey);
if ( cookieEntry === undefined ) { return false; }
var cookieHostname = cookieEntry.hostname;
var srcHostname;
for ( srcHostname in cookieEntry.usedOn ) {
if ( cookieEntry.usedOn.hasOwnProperty(srcHostname) === false ) {
continue;
}
for ( srcHostname of cookieEntry.usedOn ) {
if ( µm.mustAllow(srcHostname, cookieHostname, 'cookie') ) {
return false;
}
@ -500,14 +480,12 @@ 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[cookieKey];
if ( !cookieEntry ) {
var cookieEntry = cookieDict.get(cookieKey);
if ( cookieEntry === undefined ) {
cookieEntry = addCookieToDict(cookie);
} else {
cookieEntry.tstamp = Date.now();
if ( cookie.value === cookieEntry.value ) {
return;
}
if ( cookie.value === cookieEntry.value ) { return; }
cookieEntry.value = cookie.value;
}
@ -543,8 +521,8 @@ vAPI.cookies.onRemoved = function(cookie) {
// Listen to any change in cookieland, we will update page stats accordingly.
vAPI.cookies.onAllRemoved = function() {
for ( var cookieKey in cookieDict ) {
if ( cookieDict.hasOwnProperty(cookieKey) && removeCookieFromDict(cookieKey) ) {
for ( var cookieKey of cookieDict.keys() ) {
if ( removeCookieFromDict(cookieKey) ) {
µm.logger.writeOne('', 'info', 'cookie', i18nCookieDeleteSuccess.replace('{{value}}', cookieKey));
}
}

Loading…
Cancel
Save