Bug 1070096 - Collect no SessionStore information for about:tabcrashed pages. r=ttaubert.

--HG--
extra : rebase_source : 589c6e50cbf17d8e84d9885d00683c62684118b7
This commit is contained in:
Mike Conley 2014-10-20 16:48:13 -04:00
parent c7f57b14ce
commit b7f1de559c
2 changed files with 80 additions and 8 deletions

View File

@ -44,7 +44,8 @@ const WINDOW_HIDEABLE_FEATURES = [
"menubar", "toolbar", "locationbar", "personalbar", "statusbar", "scrollbars"
];
const MESSAGES = [
// Messages that will be received via the Frame Message Manager.
const FMM_MESSAGES = [
// The content script gives us a reference to an object that performs
// synchronous collection of session data.
"SessionStore:setupSyncHandler",
@ -73,6 +74,16 @@ const MESSAGES = [
"SessionStore:reloadPendingTab",
];
// Messages that will be received via the Parent Process Message Manager.
const PPMM_MESSAGES = [
// A tab is being revived from the crashed state. The sender of this
// message should actually be running in the parent process, since this
// will be the crashed tab interface. We use the Child and Parent Process
// Message Managers because the message is sent during framescript unload
// when the Frame Message Manager is not available.
"SessionStore:RemoteTabRevived",
];
// These are tab events that we listen to.
const TAB_EVENTS = [
"TabOpen", "TabClose", "TabSelect", "TabShow", "TabHide", "TabPinned",
@ -97,7 +108,9 @@ XPCOMUtils.defineLazyServiceGetter(this, "gScreenManager",
"@mozilla.org/gfx/screenmanager;1", "nsIScreenManager");
XPCOMUtils.defineLazyServiceGetter(this, "Telemetry",
"@mozilla.org/base/telemetry;1", "nsITelemetry");
XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
"@mozilla.org/parentprocessmessagemanager;1",
"nsIMessageListenerManager");
XPCOMUtils.defineLazyModuleGetter(this, "console",
"resource://gre/modules/devtools/Console.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "RecentWindow",
@ -297,6 +310,11 @@ let SessionStoreInternal = {
// For each <browser> element being restored, records the current epoch.
_browserEpochs: new WeakMap(),
// Any browsers that fires the oop-browser-crashed event gets stored in
// here - that way we know which browsers to ignore messages from (until
// they get restored).
_crashedBrowsers: new WeakSet(),
// whether a setBrowserState call is in progress
_browserSetState: false,
@ -383,6 +401,8 @@ let SessionStoreInternal = {
Services.obs.addObserver(this, aTopic, true);
}, this);
PPMM_MESSAGES.forEach(msg => ppmm.addMessageListener(msg, this));
this._initPrefs();
this._initialized = true;
},
@ -509,6 +529,8 @@ let SessionStoreInternal = {
// Make sure to cancel pending saves.
SessionSaver.cancel();
PPMM_MESSAGES.forEach(msg => ppmm.removeMessageListener(msg, this));
},
/**
@ -551,9 +573,18 @@ let SessionStoreInternal = {
/**
* This method handles incoming messages sent by the session store content
* script and thus enables communication with OOP tabs.
* script via the Frame Message Manager or Parent Process Message Manager,
* and thus enables communication with OOP tabs.
*/
receiveMessage: function ssi_receiveMessage(aMessage) {
receiveMessage(aMessage) {
// We'll deal with any Parent Process Message Manager messages first...
if (aMessage.name == "SessionStore:RemoteTabRevived") {
this._crashedBrowsers.delete(aMessage.objects.browser);
return;
}
// If we got here, that means we're dealing with a frame message
// manager message, so the target will be a <xul:browser>.
var browser = aMessage.target;
var win = browser.ownerDocument.defaultView;
let tab = this._getTabForBrowser(browser);
@ -567,6 +598,11 @@ let SessionStoreInternal = {
TabState.setSyncHandler(browser, aMessage.objects.handler);
break;
case "SessionStore:update":
if (this._crashedBrowsers.has(browser.permanentKey)) {
// Ignore messages from <browser> elements that have crashed
// and not yet been revived.
return;
}
this.recordTelemetry(aMessage.data.telemetry);
TabState.update(browser, aMessage.data);
this.saveStateDelayed(win);
@ -651,7 +687,7 @@ let SessionStoreInternal = {
}
break;
default:
debug("received unknown message '" + aMessage.name + "'");
debug(`received unknown message '${aMessage.name}'`);
break;
}
},
@ -675,7 +711,6 @@ let SessionStoreInternal = {
*/
handleEvent: function ssi_handleEvent(aEvent) {
var win = aEvent.currentTarget.ownerDocument.defaultView;
let browser;
switch (aEvent.type) {
case "TabOpen":
this.onTabAdd(win, aEvent.originalTarget);
@ -700,6 +735,9 @@ let SessionStoreInternal = {
case "SwapDocShells":
this.saveStateDelayed(win);
break;
case "oop-browser-crashed":
this._crashedBrowsers.add(aEvent.originalTarget);
break;
}
this._clearRestoringWindows();
},
@ -738,7 +776,7 @@ let SessionStoreInternal = {
aWindow.__SSi = this._generateWindowID();
let mm = aWindow.getGroupMessageManager("browsers");
MESSAGES.forEach(msg => mm.addMessageListener(msg, this));
FMM_MESSAGES.forEach(msg => mm.addMessageListener(msg, this));
// Load the frame script after registering listeners.
mm.loadFrameScript("chrome://browser/content/content-sessionStore.js", true);
@ -1067,7 +1105,7 @@ let SessionStoreInternal = {
DyingWindowCache.set(aWindow, winData);
let mm = aWindow.getGroupMessageManager("browsers");
MESSAGES.forEach(msg => mm.removeMessageListener(msg, this));
FMM_MESSAGES.forEach(msg => mm.removeMessageListener(msg, this));
delete aWindow.__SSi;
},
@ -1260,6 +1298,7 @@ let SessionStoreInternal = {
onTabAdd: function ssi_onTabAdd(aWindow, aTab, aNoNotification) {
let browser = aTab.linkedBrowser;
browser.addEventListener("SwapDocShells", this);
browser.addEventListener("oop-browser-crashed", this);
if (!aNoNotification) {
this.saveStateDelayed(aWindow);
}
@ -1278,6 +1317,7 @@ let SessionStoreInternal = {
let browser = aTab.linkedBrowser;
delete browser.__SS_data;
browser.removeEventListener("SwapDocShells", this);
browser.removeEventListener("oop-browser-crashed", this);
// If this tab was in the middle of restoring or still needs to be restored,
// we need to reset that state. If the tab was restoring, we will attempt to

View File

@ -29,6 +29,10 @@ XPCOMUtils.defineLazyModuleGetter(this, "SessionHistory",
XPCOMUtils.defineLazyModuleGetter(this, "SessionStorage",
"resource:///modules/sessionstore/SessionStorage.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
"@mozilla.org/childprocessmessagemanager;1",
"nsISyncMessageSender");
Cu.import("resource:///modules/sessionstore/FrameTree.jsm", this);
let gFrameTree = new FrameTree(this);
@ -711,7 +715,35 @@ ScrollPositionListener.init();
DocShellCapabilitiesListener.init();
PrivacyListener.init();
function handleRevivedTab() {
if (content.document.documentURI.startsWith("about:tabcrashed")) {
if (Services.appinfo.processType != Services.appinfo.PROCESS_TYPE_DEFAULT) {
// Sanity check - we'd better be loading this in a non-remote browser.
throw new Error("We seem to be navigating away from about:tabcrashed in " +
"a non-remote browser. This should really never happen.");
}
// We can't send a message using the frame message manager because by
// the time we reach the unload event handler, it's "too late", and messages
// won't be sent or received. The child-process message manager works though,
// despite the fact that we're really running in the parent process.
let browser = docShell.chromeEventHandler;
cpmm.sendSyncMessage("SessionStore:RemoteTabRevived", null, {browser: browser});
}
}
// If we're browsing from the tab crashed UI to a blacklisted URI that keeps
// this browser non-remote, we'll handle that in a pagehide event.
addEventListener("pagehide", handleRevivedTab);
addEventListener("unload", () => {
// If we're browsing from the tab crashed UI to a URI that causes the tab
// to go remote again, we catch this in the unload event handler, because
// swapping out the non-remote browser for a remote one in
// tabbrowser.xml's updateBrowserRemoteness doesn't cause the pagehide
// event to be fired.
handleRevivedTab();
// Remove all registered nsIObservers.
PageStyleListener.uninit();
SessionStorageListener.uninit();