Bug 905533 - Move SessionStore._updateCookies() to SessionCookies.update(); f=smacleod r=yoric

This commit is contained in:
Tim Taubert 2013-08-22 19:58:23 +02:00
parent b908756702
commit bf52987802
2 changed files with 146 additions and 118 deletions

View File

@ -10,17 +10,29 @@ const Cu = Components.utils;
const Ci = Components.interfaces;
Cu.import("resource://gre/modules/Services.jsm", this);
Cu.import("resource://gre/modules/XPCOMUtils.jsm", this);
XPCOMUtils.defineLazyModuleGetter(this, "SessionStore",
"resource:///modules/sessionstore/SessionStore.jsm");
// MAX_EXPIRY should be 2^63-1, but JavaScript can't handle that precision.
const MAX_EXPIRY = Math.pow(2, 62);
// Creates a new nsIURI object.
function makeURI(uri) {
return Services.io.newURI(uri, null, null);
}
/**
* The external API implemented by the SessionCookies module.
*/
this.SessionCookies = Object.freeze({
getCookiesForHost: function (host) {
return SessionCookiesInternal.getCookiesForHost(host);
update: function (windows) {
SessionCookiesInternal.update(windows);
},
getHostsForWindow: function (window, checkPrivacy = false) {
return SessionCookiesInternal.getHostsForWindow(window, checkPrivacy);
}
});
@ -34,11 +46,66 @@ let SessionCookiesInternal = {
_initialized: false,
/**
* Returns the list of active session cookies for a given host.
* Retrieve the list of all hosts contained in the given windows' session
* history entries (per window) and collect the associated cookies for those
* hosts, if any. The given state object is being modified.
*
* @param windows
* Array of window state objects.
* [{ tabs: [...], cookies: [...] }, ...]
*/
getCookiesForHost: function (host) {
update: function (windows) {
this._ensureInitialized();
return CookieStore.getCookiesForHost(host);
for (let window of windows) {
let cookies = [];
// Collect all hosts for the current window.
let hosts = this.getHostsForWindow(window, true);
for (let [host, isPinned] in Iterator(hosts)) {
for (let cookie of CookieStore.getCookiesForHost(host)) {
// _getCookiesForHost() will only return hosts with the right privacy
// rules, so there is no need to do anything special with this call
// to checkPrivacyLevel().
if (SessionStore.checkPrivacyLevel(cookie.secure, isPinned)) {
cookies.push(cookie);
}
}
}
// Don't include/keep empty cookie sections.
if (cookies.length) {
window.cookies = cookies;
} else if ("cookies" in window) {
delete window.cookies;
}
}
},
/**
* Returns a map of all hosts for a given window that we might want to
* collect cookies for.
*
* @param window
* A window state object containing tabs with history entries.
* @param checkPrivacy (bool)
* Whether to check the privacy level for each host.
* @return {object} A map of hosts for a given window state object. The keys
* will be hosts, the values are boolean and determine
* whether we will use the deferred privacy level when
* checking how much data to save on quitting.
*/
getHostsForWindow: function (window, checkPrivacy = false) {
let hosts = {};
for (let tab of window.tabs) {
for (let entry of tab.entries) {
this._extractHostsFromEntry(entry, hosts, checkPrivacy, tab.pinned);
}
}
return hosts;
},
/**
@ -81,6 +148,76 @@ let SessionCookiesInternal = {
}
},
/**
* Fill a given map with hosts found in the given entry's session history and
* any child entries.
*
* @param entry
* the history entry, serialized
* @param hosts
* the hash that will be used to store hosts eg, { hostname: true }
* @param checkPrivacy
* should we check the privacy level for https
* @param isPinned
* is the entry we're evaluating for a pinned tab; used only if
* checkPrivacy
*/
_extractHostsFromEntry: function (entry, hosts, checkPrivacy, isPinned) {
let host = entry._host;
let scheme = entry._scheme;
// If host & scheme aren't defined, then we are likely here in the startup
// process via _splitCookiesFromWindow. In that case, we'll turn entry.url
// into an nsIURI and get host/scheme from that. This will throw for about:
// urls in which case we don't need to do anything.
if (!host && !scheme) {
try {
let uri = makeURI(entry.url);
host = uri.host;
scheme = uri.scheme;
this._extractHostsFromHostScheme(host, scheme, hosts, checkPrivacy, isPinned);
}
catch (ex) { }
}
if (entry.children) {
for (let child of entry.children) {
this._extractHostsFromEntry(child, hosts, checkPrivacy, isPinned);
}
}
},
/**
* Add a given host to a given map of hosts if the privacy level allows
* saving cookie data for it.
*
* @param host
* the host of a uri (usually via nsIURI.host)
* @param scheme
* the scheme of a uri (usually via nsIURI.scheme)
* @param hosts
* the hash that will be used to store hosts eg, { hostname: true }
* @param checkPrivacy
* should we check the privacy level for https
* @param isPinned
* is the entry we're evaluating for a pinned tab; used only if
* checkPrivacy
*/
_extractHostsFromHostScheme:
function (host, scheme, hosts, checkPrivacy, isPinned) {
// host and scheme may not be set (for about: urls for example), in which
// case testing scheme will be sufficient.
if (/https?/.test(scheme) && !hosts[host] &&
(!checkPrivacy ||
SessionStore.checkPrivacyLevel(scheme == "https", isPinned))) {
// By setting this to true or false, we can determine when looking at
// the host in update() if we should check for privacy.
hosts[host] = isPinned;
} else if (scheme == "file") {
hosts[host] = true;
}
},
/**
* Updates or adds a given cookie to the store.
*/

View File

@ -929,7 +929,7 @@ let SessionStoreInternal = {
winData.title = aWindow.content.document.title || tabbrowser.selectedTab.label;
winData.title = this._replaceLoadingTitle(winData.title, tabbrowser,
tabbrowser.selectedTab);
this._updateCookies([winData]);
SessionCookies.update([winData]);
}
#ifndef XP_MACOSX
@ -2322,110 +2322,6 @@ let SessionStoreInternal = {
return "";
},
/**
* extract the base domain from a history entry and its children
* @param aEntry
* the history entry, serialized
* @param aHosts
* the hash that will be used to store hosts eg, { hostname: true }
* @param aCheckPrivacy
* should we check the privacy level for https
* @param aIsPinned
* is the entry we're evaluating for a pinned tab; used only if
* aCheckPrivacy
*/
_extractHostsForCookiesFromEntry:
function ssi_extractHostsForCookiesFromEntry(aEntry, aHosts, aCheckPrivacy, aIsPinned) {
let host = aEntry._host,
scheme = aEntry._scheme;
// If host & scheme aren't defined, then we are likely here in the startup
// process via _splitCookiesFromWindow. In that case, we'll turn aEntry.url
// into an nsIURI and get host/scheme from that. This will throw for about:
// urls in which case we don't need to do anything.
if (!host && !scheme) {
try {
let uri = this._getURIFromString(aEntry.url);
host = uri.host;
scheme = uri.scheme;
this._extractHostsForCookiesFromHostScheme(host, scheme, aHosts, aCheckPrivacy, aIsPinned);
}
catch(ex) { }
}
if (aEntry.children) {
aEntry.children.forEach(function(entry) {
this._extractHostsForCookiesFromEntry(entry, aHosts, aCheckPrivacy, aIsPinned);
}, this);
}
},
/**
* extract the base domain from a host & scheme
* @param aHost
* the host of a uri (usually via nsIURI.host)
* @param aScheme
* the scheme of a uri (usually via nsIURI.scheme)
* @param aHosts
* the hash that will be used to store hosts eg, { hostname: true }
* @param aCheckPrivacy
* should we check the privacy level for https
* @param aIsPinned
* is the entry we're evaluating for a pinned tab; used only if
* aCheckPrivacy
*/
_extractHostsForCookiesFromHostScheme:
function ssi_extractHostsForCookiesFromHostScheme(aHost, aScheme, aHosts, aCheckPrivacy, aIsPinned) {
// host and scheme may not be set (for about: urls for example), in which
// case testing scheme will be sufficient.
if (/https?/.test(aScheme) && !aHosts[aHost] &&
(!aCheckPrivacy ||
this.checkPrivacyLevel(aScheme == "https", aIsPinned))) {
// By setting this to true or false, we can determine when looking at
// the host in _updateCookies if we should check for privacy.
aHosts[aHost] = aIsPinned;
}
else if (aScheme == "file") {
aHosts[aHost] = true;
}
},
/**
* Serialize cookie data
* @param aWindows
* An array of window data objects
* { tabs: [ ... ], etc. }
*/
_updateCookies: function ssi_updateCookies(aWindows) {
for (let window of aWindows) {
window.cookies = [];
// Collect all hosts for the current window.
let hosts = {};
window.tabs.forEach(function(tab) {
tab.entries.forEach(function(entry) {
this._extractHostsForCookiesFromEntry(entry, hosts, true, tab.pinned);
}, this);
}, this);
for (var [host, isPinned] in Iterator(hosts)) {
for (let cookie of SessionCookies.getCookiesForHost(host)) {
// window._hosts will only have hosts with the right privacy rules,
// so there is no need to do anything special with this call to
// checkPrivacyLevel.
if (this.checkPrivacyLevel(cookie.secure, isPinned)) {
window.cookies.push(cookie);
}
}
}
// don't include empty cookie sections
if (!window.cookies.length)
delete window.cookies;
}
},
/**
* Store window dimensions, visibility, sidebar
* @param aWindow
@ -2496,7 +2392,7 @@ let SessionStoreInternal = {
if (!this._windows[ix].isPopup)
nonPopupCount++;
}
this._updateCookies(total);
SessionCookies.update(total);
// collect the data for all windows yet to be restored
for (ix in this._statesToRestore) {
@ -2576,7 +2472,7 @@ let SessionStoreInternal = {
}
let windows = [this._windows[aWindow.__SSi]];
this._updateCookies(windows);
SessionCookies.update(windows);
return { windows: windows };
},
@ -4093,12 +3989,7 @@ let SessionStoreInternal = {
return;
// Get the hosts for history entries in aTargetWinState
let cookieHosts = {};
aTargetWinState.tabs.forEach(function(tab) {
tab.entries.forEach(function(entry) {
this._extractHostsForCookiesFromEntry(entry, cookieHosts, false);
}, this);
}, this);
let cookieHosts = SessionCookies.getHostsForWindow(aTargetWinState);
// By creating a regex we reduce overhead and there is only one loop pass
// through either array (cookieHosts and aWinState.cookies).