Bug 603903 - Part 4: don't restore tabs until session unlock
MozReview-Commit-ID: 2NMEdbQnXsd
--- a/browser/components/sessionstore/SessionStore.jsm
+++ b/browser/components/sessionstore/SessionStore.jsm
@@ -42,17 +42,18 @@ const MAX_CONCURRENT_TAB_RESTORES = 3;
const SCREEN_EDGE_SLOP = 8;
// global notifications observed
const OBSERVING = [
"browser-window-before-show", "domwindowclosed",
"quit-application-granted", "browser-lastwindow-close-granted",
"quit-application", "browser:purge-session-history",
"browser:purge-domain-data",
- "idle-daily", "clear-origin-attributes-data"
+ "idle-daily", "clear-origin-attributes-data",
+ "windows-session-unlocked"
];
// XUL Window properties to (re)store
// Restored in restoreDimensions()
const WINDOW_ATTRIBUTES = ["width", "height", "screenX", "screenY", "sizemode"];
// Hideable window features to (re)store
// Restored in restoreWindowFeatures()
@@ -623,16 +624,23 @@ var SessionStoreInternal = {
TelemetryTimestamps.add("sessionRestoreInitialized");
OBSERVING.forEach(function(aTopic) {
Services.obs.addObserver(this, aTopic, true);
}, this);
this._initPrefs();
this._initialized = true;
+ if (Services.appinfo.OS == "WINNT" &&
+ Services.appinfo.QueryInterface(Ci.nsIWinAppHelper).waitingForUnlock) {
+ this._restoreWhenUnlocked = [];
+ } else {
+ this._restoreWhenUnlocked = null;
+ }
+
Telemetry.getHistogramById("FX_SESSION_RESTORE_PRIVACY_LEVEL").add(
Services.prefs.getIntPref("browser.sessionstore.privacy_level"));
},
/**
* Initialize the session using the state provided by SessionStartup
*/
initSession() {
@@ -802,16 +810,32 @@ var SessionStoreInternal = {
break;
case "clear-origin-attributes-data":
let userContextId = 0;
try {
userContextId = JSON.parse(aData).userContextId;
} catch (e) {}
if (userContextId)
this._forgetTabsWithUserContextId(userContextId);
+ break;
+ case "windows-session-unlocked":
+ {
+ if (this._restoreWhenUnlocked === null) {
+ break;
+ }
+ for (let i = 0; i < this._restoreWhenUnlocked.length; i++) {
+ this._restoreWhenUnlocked[i].msg.requestTime =
+ Services.telemetry.msSystemNow();
+ this._restoreWhenUnlocked[i].browser.messageManager.sendAsyncMessage(
+ "SessionStore:restoreTabContent",
+ this._restoreWhenUnlocked[i].msg);
+ }
+ this._restoreWhenUnlocked = null;
+ break;
+ }
}
},
/**
* This method handles incoming messages sent by the session store content
* script via the Frame Message Manager or Parent Process Message Manager,
* and thus enables communication with OOP tabs.
*/
@@ -3429,33 +3453,41 @@ var SessionStoreInternal = {
for (var t = 0; t < newTabCount; t++) {
let tabData = winData.tabs[t];
let userContextId = tabData.userContextId;
let select = t == selectTab - 1;
let tab;
+ let delayRestoreContent = this._restoreWhenUnlocked !== null &&
+ Services.appinfo.QueryInterface(Ci.nsIWinAppHelper).waitingForUnlock;
+
// Re-use existing selected tab if possible to avoid the overhead of
// selecting a new tab.
- if (select &&
+ if (select && !delayRestoreContent &&
tabbrowser.selectedTab.userContextId == userContextId) {
tab = tabbrowser.selectedTab;
if (!tabData.pinned) {
tabbrowser.unpinTab(tab);
}
tabbrowser.moveTabToEnd();
if (aWindow.gMultiProcessBrowser && !tab.linkedBrowser.isRemoteBrowser) {
tabbrowser.updateBrowserRemoteness(tab.linkedBrowser, true);
}
}
// Add a new tab if needed.
if (!tab) {
let createLazyBrowser = restoreTabsLazily && !select && !tabData.pinned;
+ let noInitialRestoreContent = false;
+ if (restoreTabsLazily && !createLazyBrowser && delayRestoreContent) {
+ createLazyBrowser = true;
+ noInitialRestoreContent = true;
+ }
let url = "about:blank";
if (createLazyBrowser && tabData.entries && tabData.entries.length) {
// Let tabbrowser know the future URI because progress listeners won't
// get onLocationChange notification before the browser is inserted.
let activeIndex = (tabData.index || tabData.entries.length) - 1;
// Ensure the index is in bounds.
activeIndex = Math.min(activeIndex, tabData.entries.length - 1);
@@ -3468,16 +3500,17 @@ var SessionStoreInternal = {
// Each tab will get its initial label set in restoreTab.
tab = tabbrowser.addTab(url,
{ createLazyBrowser,
skipAnimation: true,
noInitialLabel: true,
userContextId,
skipBackgroundNotify: true,
bulkOrderedOpen: true });
+ tab.noInitialRestoreContent = noInitialRestoreContent;
if (select) {
let leftoverTab = tabbrowser.selectedTab;
tabbrowser.selectedTab = tab;
tabbrowser.removeTab(leftoverTab);
}
}
@@ -4006,21 +4039,26 @@ var SessionStoreInternal = {
}
// If the restored browser wants to show view source content, start up a
// view source browser that will load the required frame script.
if (uri && ViewSourceBrowser.isViewSource(uri)) {
new ViewSourceBrowser(browser);
}
- browser.messageManager.sendAsyncMessage("SessionStore:restoreTabContent",
- {loadArguments, isRemotenessUpdate,
+ let restoreMessage = {loadArguments, isRemotenessUpdate,
reason: aOptions.restoreContentReason ||
RESTORE_TAB_CONTENT_REASON.SET_STATE,
- requestTime: Services.telemetry.msSystemNow()});
+ requestTime: Services.telemetry.msSystemNow()};
+
+ if (aTab.noInitialRestoreContent && this._restoreWhenUnlocked !== null) {
+ this._restoreWhenUnlocked.push({browser, msg: restoreMessage});
+ } else {
+ browser.messageManager.sendAsyncMessage("SessionStore:restoreTabContent", restoreMessage);
+ }
// Focus the tab's content area.
if (aTab.selected) {
browser.focus();
}
},
/**
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -1437,16 +1437,36 @@ nsXULAppInfo::Callback(nsISupports* aDat
{
nsCOMPtr<nsIFile> file = do_QueryInterface(aData);
MOZ_ASSERT(file);
CrashReporter::SetMemoryReportFile(file);
return NS_OK;
}
+#ifdef XP_WIN
+NS_IMETHODIMP
+nsXULAppInfo::GetWaitingForUnlock(bool *aWaiting) {
+ if (!gRARRestarted) {
+ *aWaiting = false;
+ return NS_OK;
+ }
+
+ HDESK hDesk = ::OpenInputDesktop(0, false, 0);
+ if (!hDesk) {
+ *aWaiting = true;
+ return NS_OK;
+ }
+ CloseDesktop(hDesk);
+
+ *aWaiting = false;
+ return NS_OK;
+}
+#endif
+
static const nsXULAppInfo kAppInfo;
static nsresult AppInfoConstructor(nsISupports* aOuter,
REFNSIID aIID, void **aResult)
{
NS_ENSURE_NO_AGGREGATION(aOuter);
return const_cast<nsXULAppInfo*>(&kAppInfo)->
QueryInterface(aIID, aResult);
--- a/toolkit/xre/nsIWinAppHelper.idl
+++ b/toolkit/xre/nsIWinAppHelper.idl
@@ -11,9 +11,11 @@
* @status UNSTABLE - This interface is not frozen and will probably change in
* future releases.
*/
[scriptable, uuid(dc263ca8-b257-47eb-b5b7-339d9e0b90f7)]
interface nsIWinAppHelper : nsISupports
{
readonly attribute boolean userCanElevate;
+
+ readonly attribute boolean waitingForUnlock;
};
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -5292,19 +5292,25 @@ nsWindow::ProcessMessage(UINT msg, WPARA
break;
case WM_WTSSESSION_CHANGE:
{
switch (wParam) {
case WTS_CONSOLE_CONNECT:
case WTS_REMOTE_CONNECT:
case WTS_SESSION_UNLOCK:
+ {
+ nsCOMPtr<nsIObserverService> obsServ =
+ mozilla::services::GetObserverService();
+ obsServ->NotifyObservers(nullptr, "windows-session-unlocked", nullptr);
+
// When a session becomes visible, we should invalidate.
Invalidate(true, true, true);
- break;
+ }
+ break;
default:
break;
}
}
break;
case WM_FONTCHANGE:
{