Bug 899276 - Don't collect/save private tabs. r=ttaubert

This commit is contained in:
David Rajchenbach-Teller 2013-12-18 12:39:53 -05:00
Родитель abf7280748
Коммит 1d719236e6
6 изменённых файлов: 134 добавлений и 10 удалений

Просмотреть файл

@ -308,6 +308,30 @@ let SessionStorageListener = {
Ci.nsISupportsWeakReference])
};
/**
* Listen for changes to the privacy status of the tab.
* By definition, tabs start in non-private mode.
*
* Causes a SessionStore:update message to be sent for
* field "isPrivate". This message contains
* |true| if the tab is now private
* |null| if the tab is now public - the field is therefore
* not saved.
*/
let PrivacyListener = {
init: function() {
docShell.addWeakPrivacyTransitionObserver(this);
},
// Ci.nsIPrivacyTransitionObserver
privateModeChanged: function(enabled) {
MessageQueue.push("isPrivate", () => enabled || null);
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPrivacyTransitionObserver,
Ci.nsISupportsWeakReference])
};
/**
* A message queue that takes collected data and will take care of sending it
* to the chrome process. It allows flushing using synchronous messages and
@ -466,3 +490,4 @@ ProgressListener.init();
PageStyleListener.init();
SessionStorageListener.init();
DocShellCapabilitiesListener.init();
PrivacyListener.init();

Просмотреть файл

@ -72,7 +72,7 @@ this.SessionSaver = Object.freeze({
* Immediately saves the current session to disk.
*/
run: function () {
SessionSaverInternal.run();
return SessionSaverInternal.run();
},
/**
@ -129,7 +129,7 @@ let SessionSaverInternal = {
* Immediately saves the current session to disk.
*/
run: function () {
this._saveState(true /* force-update all windows */);
return this._saveState(true /* force-update all windows */);
},
/**
@ -192,12 +192,24 @@ let SessionSaverInternal = {
stopWatchStart("COLLECT_DATA_MS", "COLLECT_DATA_LONGEST_OP_MS");
let state = SessionStore.getCurrentState(forceUpdateAllWindows);
// Forget about private windows.
// Forget about private windows and tabs.
for (let i = state.windows.length - 1; i >= 0; i--) {
if (state.windows[i].isPrivate) {
state.windows.splice(i, 1);
if (state.selectedWindow >= i) {
state.selectedWindow--;
let win = state.windows[i];
if (win.isPrivate || false) { // The whole window is private, remove it
state.windows.splice(i, 1);
if (state.selectedWindow >= i) {
state.selectedWindow--;
}
continue;
}
// The window is not private, but its tabs still might
for (let j = win.tabs.length - 1; j >= 0 ; --j) {
let tab = win.tabs[j];
if (tab.isPrivate || false) {
win.tabs.splice(j, 1);
if (win.selected >= j) {
win.selected--;
}
}
}
}
@ -209,6 +221,10 @@ let SessionSaverInternal = {
}
}
// Note that closed private tabs are never stored (see
// SessionStoreInternal.onTabClose), so we do not need to remove
// them.
// Make sure that we keep the previous session if we started with a single
// private window and no non-private windows have been opened, yet.
if (state.deferredInitialState) {
@ -235,7 +251,7 @@ let SessionSaverInternal = {
#endif
stopWatchFinish("COLLECT_DATA_MS", "COLLECT_DATA_LONGEST_OP_MS");
this._writeState(state);
return this._writeState(state);
},
/**
@ -278,7 +294,7 @@ let SessionSaverInternal = {
// Don't touch the file if an observer has deleted all state data.
if (!data) {
return;
return Promise.resolve();
}
// We update the time stamp before writing so that we don't write again
@ -290,7 +306,7 @@ let SessionSaverInternal = {
// Write (atomically) to a session file, using a tmp file. Once the session
// file is successfully updated, save the time stamp of the last save and
// notify the observers.
SessionFile.write(data).then(() => {
return SessionFile.write(data).then(() => {
this.updateLastSaveTime();
notify(null, "sessionstore-state-write-complete");
}, Cu.reportError);

Просмотреть файл

@ -1311,6 +1311,11 @@ let SessionStoreInternal = {
// Get the latest data for this tab (generally, from the cache)
let tabState = TabState.collectSync(aTab);
// Don't save private tabs
if (tabState.isPrivate || false) {
return;
}
// store closed-tab data for undo
if (this._shouldSaveTabState(tabState)) {
let tabTitle = aTab.label;

Просмотреть файл

@ -59,6 +59,7 @@ support-files =
[browser_merge_closed_tabs.js]
[browser_pageshow.js]
[browser_pageStyle.js]
[browser_privatetabs.js]
[browser_sessionStorage.js]
[browser_swapDocShells.js]
[browser_tabStateCache.js]

Просмотреть файл

@ -0,0 +1,70 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
let Imports = {};
Cu.import("resource:///modules/sessionstore/SessionSaver.jsm", Imports);
let {Promise, Task, SessionSaver} = Imports;
add_task(function cleanup() {
info("Forgetting closed tabs");
while (ss.getClosedTabCount(window)) {
ss.forgetClosedTab(window, 0);
}
});
add_task(function() {
let URL_PUBLIC = "http://example.com/public/" + Math.random();
let URL_PRIVATE = "http://example.com/private/" + Math.random();
let tab1, tab2;
try {
// Setup a public tab and a private tab
info("Setting up public tab");
tab1 = gBrowser.addTab(URL_PUBLIC);
yield promiseBrowserLoaded(tab1.linkedBrowser);
info("Setting up private tab");
tab2 = gBrowser.addTab();
yield promiseBrowserLoaded(tab2.linkedBrowser);
yield setUsePrivateBrowsing(tab2.linkedBrowser, true);
tab2.linkedBrowser.loadURI(URL_PRIVATE);
yield promiseBrowserLoaded(tab2.linkedBrowser);
info("Flush to make sure chrome received all data.");
SyncHandlers.get(tab2.linkedBrowser).flush();
info("Checking out state");
yield SessionSaver.run();
let path = OS.Path.join(OS.Constants.Path.profileDir, "sessionstore.js");
let data = yield OS.File.read(path);
let state = new TextDecoder().decode(data);
info("State: " + state);
// Ensure that sessionstore.js only knows about the public tab
ok(state.indexOf(URL_PUBLIC) != -1, "State contains public tab");
ok(state.indexOf(URL_PRIVATE) == -1, "State does not contain private tab");
// Ensure that we can close and undo close the public tab but not the private tab
gBrowser.removeTab(tab2);
tab2 = null;
gBrowser.removeTab(tab1);
tab1 = null;
tab1 = ss.undoCloseTab(window, 0);
ok(true, "Public tab supports undo close");
is(ss.getClosedTabCount(window), 0, "Private tab does not support undo close");
} finally {
if (tab1) {
gBrowser.removeTab(tab1);
}
if (tab2) {
gBrowser.removeTab(tab2);
}
}
});
function setUsePrivateBrowsing(browser, val) {
return sendMessage(browser, "ss-test:setUsePrivateBrowsing", val);
}

Просмотреть файл

@ -52,3 +52,10 @@ addMessageListener("ss-test:setAuthorStyleDisabled", function (msg) {
markupDocumentViewer.authorStyleDisabled = msg.data;
sendSyncMessage("ss-test:setAuthorStyleDisabled");
});
addMessageListener("ss-test:setUsePrivateBrowsing", function (msg) {
let loadContext =
docShell.QueryInterface(Ci.nsILoadContext);
loadContext.usePrivateBrowsing = msg.data;
sendAsyncMessage("ss-test:setUsePrivateBrowsing");
});