зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1002843 - Wait until important parts have been initialized before restoring tabs into windows r=smacleod
This commit is contained in:
Родитель
d01bf252c5
Коммит
28b75bf5ec
|
@ -858,9 +858,11 @@ var gBrowserInit = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Certain kinds of automigration rely on this notification to complete their
|
// Certain kinds of automigration rely on this notification to complete
|
||||||
// tasks BEFORE the browser window is shown.
|
// their tasks BEFORE the browser window is shown. SessionStore uses it to
|
||||||
Services.obs.notifyObservers(null, "browser-window-before-show", "");
|
// restore tabs into windows AFTER important parts like gMultiProcessBrowser
|
||||||
|
// have been initialized.
|
||||||
|
Services.obs.notifyObservers(window, "browser-window-before-show", "");
|
||||||
|
|
||||||
// Set a sane starting width/height for all resolutions on new profiles.
|
// Set a sane starting width/height for all resolutions on new profiles.
|
||||||
if (!document.documentElement.hasAttribute("width")) {
|
if (!document.documentElement.hasAttribute("width")) {
|
||||||
|
|
|
@ -30,7 +30,7 @@ const MAX_CONCURRENT_TAB_RESTORES = 3;
|
||||||
|
|
||||||
// global notifications observed
|
// global notifications observed
|
||||||
const OBSERVING = [
|
const OBSERVING = [
|
||||||
"domwindowopened", "domwindowclosed",
|
"browser-window-before-show", "domwindowclosed",
|
||||||
"quit-application-requested", "quit-application-granted",
|
"quit-application-requested", "quit-application-granted",
|
||||||
"browser-lastwindow-close-granted",
|
"browser-lastwindow-close-granted",
|
||||||
"quit-application", "browser:purge-session-history",
|
"quit-application", "browser:purge-session-history",
|
||||||
|
@ -540,8 +540,8 @@ let SessionStoreInternal = {
|
||||||
*/
|
*/
|
||||||
observe: function ssi_observe(aSubject, aTopic, aData) {
|
observe: function ssi_observe(aSubject, aTopic, aData) {
|
||||||
switch (aTopic) {
|
switch (aTopic) {
|
||||||
case "domwindowopened": // catch new windows
|
case "browser-window-before-show": // catch new windows
|
||||||
this.onOpen(aSubject);
|
this.onBeforeBrowserWindowShown(aSubject);
|
||||||
break;
|
break;
|
||||||
case "domwindowclosed": // catch closed windows
|
case "domwindowclosed": // catch closed windows
|
||||||
this.onClose(aSubject);
|
this.onClose(aSubject);
|
||||||
|
@ -919,71 +919,59 @@ let SessionStoreInternal = {
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* On window open
|
* Called right before a new browser window is shown.
|
||||||
* @param aWindow
|
* @param aWindow
|
||||||
* Window reference
|
* Window reference
|
||||||
*/
|
*/
|
||||||
onOpen: function ssi_onOpen(aWindow) {
|
onBeforeBrowserWindowShown: function (aWindow) {
|
||||||
let onload = () => {
|
// Just call onLoad() directly if we're initialized already.
|
||||||
aWindow.removeEventListener("load", onload);
|
if (this._sessionInitialized) {
|
||||||
|
this.onLoad(aWindow);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let windowType = aWindow.document.documentElement.getAttribute("windowtype");
|
// The very first window that is opened creates a promise that is then
|
||||||
|
// re-used by all subsequent windows. The promise will be used to tell
|
||||||
|
// when we're ready for initialization.
|
||||||
|
if (!this._promiseReadyForInitialization) {
|
||||||
|
let deferred = Promise.defer();
|
||||||
|
|
||||||
// Ignore non-browser windows.
|
// Wait for the given window's delayed startup to be finished.
|
||||||
if (windowType != "navigator:browser") {
|
Services.obs.addObserver(function obs(subject, topic) {
|
||||||
|
if (aWindow == subject) {
|
||||||
|
Services.obs.removeObserver(obs, topic);
|
||||||
|
deferred.resolve();
|
||||||
|
}
|
||||||
|
}, "browser-delayed-startup-finished", false);
|
||||||
|
|
||||||
|
// We are ready for initialization as soon as the session file has been
|
||||||
|
// read from disk and the initial window's delayed startup has finished.
|
||||||
|
this._promiseReadyForInitialization =
|
||||||
|
Promise.all([deferred.promise, gSessionStartup.onceInitialized]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We can't call this.onLoad since initialization
|
||||||
|
// hasn't completed, so we'll wait until it is done.
|
||||||
|
// Even if additional windows are opened and wait
|
||||||
|
// for initialization as well, the first opened
|
||||||
|
// window should execute first, and this.onLoad
|
||||||
|
// will be called with the initialState.
|
||||||
|
this._promiseReadyForInitialization.then(() => {
|
||||||
|
if (aWindow.closed) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this._sessionInitialized) {
|
if (this._sessionInitialized) {
|
||||||
this.onLoad(aWindow);
|
this.onLoad(aWindow);
|
||||||
return;
|
} else {
|
||||||
|
let initialState = this.initSession();
|
||||||
|
this._sessionInitialized = true;
|
||||||
|
this.onLoad(aWindow, initialState);
|
||||||
|
|
||||||
|
// Let everyone know we're done.
|
||||||
|
this._deferredInitialized.resolve();
|
||||||
}
|
}
|
||||||
|
}, console.error);
|
||||||
// The very first window that is opened creates a promise that is then
|
|
||||||
// re-used by all subsequent windows. The promise will be used to tell
|
|
||||||
// when we're ready for initialization.
|
|
||||||
if (!this._promiseReadyForInitialization) {
|
|
||||||
let deferred = Promise.defer();
|
|
||||||
|
|
||||||
// Wait for the given window's delayed startup to be finished.
|
|
||||||
Services.obs.addObserver(function obs(subject, topic) {
|
|
||||||
if (aWindow == subject) {
|
|
||||||
Services.obs.removeObserver(obs, topic);
|
|
||||||
deferred.resolve();
|
|
||||||
}
|
|
||||||
}, "browser-delayed-startup-finished", false);
|
|
||||||
|
|
||||||
// We are ready for initialization as soon as the session file has been
|
|
||||||
// read from disk and the initial window's delayed startup has finished.
|
|
||||||
this._promiseReadyForInitialization =
|
|
||||||
Promise.all([deferred.promise, gSessionStartup.onceInitialized]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// We can't call this.onLoad since initialization
|
|
||||||
// hasn't completed, so we'll wait until it is done.
|
|
||||||
// Even if additional windows are opened and wait
|
|
||||||
// for initialization as well, the first opened
|
|
||||||
// window should execute first, and this.onLoad
|
|
||||||
// will be called with the initialState.
|
|
||||||
this._promiseReadyForInitialization.then(() => {
|
|
||||||
if (aWindow.closed) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._sessionInitialized) {
|
|
||||||
this.onLoad(aWindow);
|
|
||||||
} else {
|
|
||||||
let initialState = this.initSession();
|
|
||||||
this._sessionInitialized = true;
|
|
||||||
this.onLoad(aWindow, initialState);
|
|
||||||
|
|
||||||
// Let everyone know we're done.
|
|
||||||
this._deferredInitialized.resolve();
|
|
||||||
}
|
|
||||||
}, console.error);
|
|
||||||
};
|
|
||||||
|
|
||||||
aWindow.addEventListener("load", onload);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -31,9 +31,7 @@ function test() {
|
||||||
|
|
||||||
// open a window and add the above closed tab list
|
// open a window and add the above closed tab list
|
||||||
let newWin = openDialog(location, "", "chrome,all,dialog=no");
|
let newWin = openDialog(location, "", "chrome,all,dialog=no");
|
||||||
newWin.addEventListener("load", function(aEvent) {
|
promiseWindowLoaded(newWin).then(() => {
|
||||||
newWin.removeEventListener("load", arguments.callee, false);
|
|
||||||
|
|
||||||
gPrefService.setIntPref("browser.sessionstore.max_tabs_undo",
|
gPrefService.setIntPref("browser.sessionstore.max_tabs_undo",
|
||||||
test_state.windows[0]._closedTabs.length);
|
test_state.windows[0]._closedTabs.length);
|
||||||
ss.setWindowState(newWin, JSON.stringify(test_state), true);
|
ss.setWindowState(newWin, JSON.stringify(test_state), true);
|
||||||
|
@ -71,5 +69,5 @@ function test() {
|
||||||
newWin.close();
|
newWin.close();
|
||||||
gPrefService.clearUserPref("browser.sessionstore.max_tabs_undo");
|
gPrefService.clearUserPref("browser.sessionstore.max_tabs_undo");
|
||||||
finish();
|
finish();
|
||||||
}, false);
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,9 +52,7 @@ function test() {
|
||||||
|
|
||||||
// open a window and add the above closed tab list
|
// open a window and add the above closed tab list
|
||||||
let newWin = openDialog(location, "", "chrome,all,dialog=no");
|
let newWin = openDialog(location, "", "chrome,all,dialog=no");
|
||||||
newWin.addEventListener("load", function(aEvent) {
|
promiseWindowLoaded(newWin).then(() => {
|
||||||
newWin.removeEventListener("load", arguments.callee, false);
|
|
||||||
|
|
||||||
gPrefService.setIntPref("browser.sessionstore.max_tabs_undo",
|
gPrefService.setIntPref("browser.sessionstore.max_tabs_undo",
|
||||||
test_state.windows[0]._closedTabs.length);
|
test_state.windows[0]._closedTabs.length);
|
||||||
ss.setWindowState(newWin, JSON.stringify(test_state), true);
|
ss.setWindowState(newWin, JSON.stringify(test_state), true);
|
||||||
|
@ -83,5 +81,5 @@ function test() {
|
||||||
gPrefService.clearUserPref("browser.sessionstore.max_tabs_undo");
|
gPrefService.clearUserPref("browser.sessionstore.max_tabs_undo");
|
||||||
finish();
|
finish();
|
||||||
});
|
});
|
||||||
}, false);
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,9 +15,7 @@ function test() {
|
||||||
|
|
||||||
// open a window and set a value on it
|
// open a window and set a value on it
|
||||||
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no");
|
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no");
|
||||||
newWin.addEventListener("load", function(aEvent) {
|
promiseWindowLoaded(newWin).then(() => {
|
||||||
newWin.removeEventListener("load", arguments.callee, false);
|
|
||||||
|
|
||||||
ss.setWindowValue(newWin, uniqueKey1, uniqueValue1);
|
ss.setWindowValue(newWin, uniqueKey1, uniqueValue1);
|
||||||
|
|
||||||
let newState = { windows: [{ tabs:[{ entries: [] }], extData: {} }] };
|
let newState = { windows: [{ tabs:[{ entries: [] }], extData: {} }] };
|
||||||
|
@ -44,5 +42,5 @@ function test() {
|
||||||
// clean up
|
// clean up
|
||||||
newWin.close();
|
newWin.close();
|
||||||
finish();
|
finish();
|
||||||
}, false);
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,7 @@ function test() {
|
||||||
waitForExplicitFinish();
|
waitForExplicitFinish();
|
||||||
|
|
||||||
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no");
|
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no");
|
||||||
newWin.addEventListener("load", function(aEvent) {
|
promiseWindowLoaded(newWin).then(() => {
|
||||||
newWin.removeEventListener("load", arguments.callee, false);
|
|
||||||
|
|
||||||
let newState = { windows: [{
|
let newState = { windows: [{
|
||||||
tabs: [{ entries: [] }],
|
tabs: [{ entries: [] }],
|
||||||
_closedTabs: [{
|
_closedTabs: [{
|
||||||
|
@ -59,5 +57,5 @@ function test() {
|
||||||
}, 0);
|
}, 0);
|
||||||
}, 0);
|
}, 0);
|
||||||
}, 0);
|
}, 0);
|
||||||
}, false);
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,8 +80,7 @@ function test() {
|
||||||
|
|
||||||
// open a window and add the above closed window list
|
// open a window and add the above closed window list
|
||||||
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no");
|
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no");
|
||||||
newWin.addEventListener("load", function(aEvent) {
|
promiseWindowLoaded(newWin).then(() => {
|
||||||
this.removeEventListener("load", arguments.callee, false);
|
|
||||||
gPrefService.setIntPref("browser.sessionstore.max_windows_undo",
|
gPrefService.setIntPref("browser.sessionstore.max_windows_undo",
|
||||||
test_state._closedWindows.length);
|
test_state._closedWindows.length);
|
||||||
ss.setWindowState(newWin, JSON.stringify(test_state), true);
|
ss.setWindowState(newWin, JSON.stringify(test_state), true);
|
||||||
|
@ -117,5 +116,5 @@ function test() {
|
||||||
newWin.close();
|
newWin.close();
|
||||||
gPrefService.clearUserPref("browser.sessionstore.max_windows_undo");
|
gPrefService.clearUserPref("browser.sessionstore.max_windows_undo");
|
||||||
finish();
|
finish();
|
||||||
}, false);
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,47 +8,38 @@ function test() {
|
||||||
waitForExplicitFinish();
|
waitForExplicitFinish();
|
||||||
|
|
||||||
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no,toolbar=yes");
|
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no,toolbar=yes");
|
||||||
newWin.addEventListener("load", function() {
|
promiseWindowLoaded(newWin).then(() => {
|
||||||
newWin.removeEventListener("load", arguments.callee, false);
|
let state1 = ss.getWindowState(newWin);
|
||||||
|
newWin.close();
|
||||||
|
|
||||||
executeSoon(function() {
|
newWin = openDialog(location, "_blank",
|
||||||
let state1 = ss.getWindowState(newWin);
|
"chrome,extrachrome,menubar,resizable,scrollbars,status,toolbar=no,location,personal,directories,dialog=no");
|
||||||
|
promiseWindowLoaded(newWin).then(() => {
|
||||||
|
let state2 = ss.getWindowState(newWin);
|
||||||
newWin.close();
|
newWin.close();
|
||||||
|
|
||||||
newWin = openDialog(location, "_blank",
|
function testState(state, expected, callback) {
|
||||||
"chrome,extrachrome,menubar,resizable,scrollbars,status,toolbar=no,location,personal,directories,dialog=no");
|
let win = openDialog(location, "_blank", "chrome,all,dialog=no");
|
||||||
newWin.addEventListener("load", function() {
|
promiseWindowLoaded(win).then(() => {
|
||||||
newWin.removeEventListener("load", arguments.callee, false);
|
|
||||||
|
|
||||||
executeSoon(function() {
|
is(win.gURLBar.readOnly, false,
|
||||||
let state2 = ss.getWindowState(newWin);
|
"URL bar should not be read-only before setting the state");
|
||||||
newWin.close();
|
is(win.gURLBar.getAttribute("enablehistory"), "true",
|
||||||
|
"URL bar autocomplete should be enabled before setting the state");
|
||||||
|
ss.setWindowState(win, state, true);
|
||||||
|
is(win.gURLBar.readOnly, expected.readOnly,
|
||||||
|
"URL bar read-only state should be restored correctly");
|
||||||
|
is(win.gURLBar.getAttribute("enablehistory"), expected.enablehistory,
|
||||||
|
"URL bar autocomplete state should be restored correctly");
|
||||||
|
|
||||||
function testState(state, expected, callback) {
|
win.close();
|
||||||
let win = openDialog(location, "_blank", "chrome,all,dialog=no");
|
executeSoon(callback);
|
||||||
win.addEventListener("load", function() {
|
|
||||||
win.removeEventListener("load", arguments.callee, false);
|
|
||||||
|
|
||||||
is(win.gURLBar.readOnly, false,
|
|
||||||
"URL bar should not be read-only before setting the state");
|
|
||||||
is(win.gURLBar.getAttribute("enablehistory"), "true",
|
|
||||||
"URL bar autocomplete should be enabled before setting the state");
|
|
||||||
ss.setWindowState(win, state, true);
|
|
||||||
is(win.gURLBar.readOnly, expected.readOnly,
|
|
||||||
"URL bar read-only state should be restored correctly");
|
|
||||||
is(win.gURLBar.getAttribute("enablehistory"), expected.enablehistory,
|
|
||||||
"URL bar autocomplete state should be restored correctly");
|
|
||||||
|
|
||||||
win.close();
|
|
||||||
executeSoon(callback);
|
|
||||||
}, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
testState(state1, {readOnly: false, enablehistory: "true"}, function() {
|
|
||||||
testState(state2, {readOnly: true, enablehistory: "false"}, finish);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}, false);
|
}
|
||||||
|
|
||||||
|
testState(state1, {readOnly: false, enablehistory: "true"}, function() {
|
||||||
|
testState(state2, {readOnly: true, enablehistory: "false"}, finish);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}, false);
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,11 +17,10 @@ function test() {
|
||||||
browserWindowsCount(1);
|
browserWindowsCount(1);
|
||||||
|
|
||||||
var win = openDialog(location, "", "chrome,all,dialog=no");
|
var win = openDialog(location, "", "chrome,all,dialog=no");
|
||||||
win.addEventListener("load", function () {
|
promiseWindowLoaded(win).then(() => {
|
||||||
win.removeEventListener("load", arguments.callee, false);
|
|
||||||
browserWindowsCount(2);
|
browserWindowsCount(2);
|
||||||
win.close();
|
win.close();
|
||||||
browserWindowsCount(1);
|
browserWindowsCount(1);
|
||||||
finish();
|
finish();
|
||||||
}, false);
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,9 +10,7 @@ function test() {
|
||||||
|
|
||||||
// open a new window and setup the window state.
|
// open a new window and setup the window state.
|
||||||
newWin = openDialog(getBrowserURL(), "_blank", "chrome,all,dialog=no");
|
newWin = openDialog(getBrowserURL(), "_blank", "chrome,all,dialog=no");
|
||||||
newWin.addEventListener("load", function onLoad(event) {
|
whenWindowLoaded(newWin, function () {
|
||||||
this.removeEventListener("load", onLoad, false);
|
|
||||||
|
|
||||||
let newState = {
|
let newState = {
|
||||||
windows: [{
|
windows: [{
|
||||||
tabs: [{
|
tabs: [{
|
||||||
|
@ -69,5 +67,5 @@ function test() {
|
||||||
}
|
}
|
||||||
newWin.addEventListener("tabviewshown", onTabViewShow, false);
|
newWin.addEventListener("tabviewshown", onTabViewShow, false);
|
||||||
waitForFocus(function() { newWin.TabView.toggle(); });
|
waitForFocus(function() { newWin.TabView.toggle(); });
|
||||||
}, false);
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -142,8 +142,10 @@ function afterAllTabsLoaded(callback, win) {
|
||||||
browser.__SS_restoreState &&
|
browser.__SS_restoreState &&
|
||||||
browser.__SS_restoreState == TAB_STATE_NEEDS_RESTORE);
|
browser.__SS_restoreState == TAB_STATE_NEEDS_RESTORE);
|
||||||
|
|
||||||
if (isRestorable && browser.contentDocument.readyState != "complete" ||
|
let isLoading = browser.webProgress.isLoadingDocument ||
|
||||||
browser.webProgress.isLoadingDocument) {
|
browser.contentDocument.readyState != "complete";
|
||||||
|
|
||||||
|
if (isRestorable && isLoading) {
|
||||||
stillToLoad++;
|
stillToLoad++;
|
||||||
browser.addEventListener("load", onLoad, true);
|
browser.addEventListener("load", onLoad, true);
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче