Skip to content

Commit

Permalink
Bug 1728800 - Collect window features from chrome flags. r=Gijs
Browse files Browse the repository at this point in the history
  • Loading branch information
vyv03354 committed Feb 7, 2022
1 parent f4b6bf2 commit 4ba863e
Show file tree
Hide file tree
Showing 2 changed files with 172 additions and 32 deletions.
86 changes: 76 additions & 10 deletions browser/components/sessionstore/SessionStore.jsm
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,48 @@ const OBSERVING = [
// Restored in restoreDimensions()
const WINDOW_ATTRIBUTES = ["width", "height", "screenX", "screenY", "sizemode"];

const CHROME_FLAGS_MAP = [
[Ci.nsIWebBrowserChrome.CHROME_TITLEBAR, "titlebar"],
[Ci.nsIWebBrowserChrome.CHROME_WINDOW_CLOSE, "close"],
[Ci.nsIWebBrowserChrome.CHROME_TOOLBAR, "toolbar"],
[Ci.nsIWebBrowserChrome.CHROME_LOCATIONBAR, "location"],
[Ci.nsIWebBrowserChrome.CHROME_PERSONAL_TOOLBAR, "personalbar"],
[Ci.nsIWebBrowserChrome.CHROME_STATUSBAR, "status"],
[Ci.nsIWebBrowserChrome.CHROME_MENUBAR, "menubar"],
[Ci.nsIWebBrowserChrome.CHROME_WINDOW_RESIZE, "resizable"],
[Ci.nsIWebBrowserChrome.CHROME_WINDOW_MIN, "minimizable"],
[Ci.nsIWebBrowserChrome.CHROME_SCROLLBARS, "", "scrollbars=0"],
[Ci.nsIWebBrowserChrome.CHROME_PRIVATE_WINDOW, "private"],
[Ci.nsIWebBrowserChrome.CHROME_NON_PRIVATE_WINDOW, "non-private"],
// Do not inherit remoteness and fissionness from the previous session.
//[Ci.nsIWebBrowserChrome.CHROME_REMOTE_WINDOW, "remote", "non-remote"],
//[Ci.nsIWebBrowserChrome.CHROME_FISSION_WINDOW, "fission", "non-fission"],
[Ci.nsIWebBrowserChrome.CHROME_WINDOW_POPUP, "popup"],
[
Ci.nsIWebBrowserChrome.CHROME_WINDOW_POPUP |
Ci.nsIWebBrowserChrome.CHROME_TITLEBAR,
"",
"titlebar=0",
],
[
Ci.nsIWebBrowserChrome.CHROME_WINDOW_POPUP |
Ci.nsIWebBrowserChrome.CHROME_WINDOW_CLOSE,
"",
"close=0",
],
[Ci.nsIWebBrowserChrome.CHROME_WINDOW_LOWERED, "alwayslowered"],
[Ci.nsIWebBrowserChrome.HROME_WINDOW_RAISED, "alwaysraised"],
// "chrome" and "suppressanimation" are always set.
//[Ci.nsIWebBrowserChrome.CHROME_SUPPRESS_ANIMATION, "suppressanimation"],
[Ci.nsIWebBrowserChrome.CHROME_ALWAYS_ON_TOP, "alwaysontop"],
//[Ci.nsIWebBrowserChrome.CHROME_OPENAS_CHROME, "chrome", "chrome=0"],
[Ci.nsIWebBrowserChrome.CHROME_EXTRA, "extrachrome"],
[Ci.nsIWebBrowserChrome.CHROME_CENTER_SCREEN, "centerscreen"],
[Ci.nsIWebBrowserChrome.CHROME_DEPENDENT, "dependent"],
[Ci.nsIWebBrowserChrome.CHROME_MODAL, "modal"],
[Ci.nsIWebBrowserChrome.CHROME_OPENAS_DIALOG, "dialog", "dialog=0"],
];

// Hideable window features to (re)store
// Restored in restoreWindowFeatures()
const WINDOW_HIDEABLE_FEATURES = [
Expand Down Expand Up @@ -1481,6 +1523,9 @@ var SessionStoreInternal = {
_closedTabs: [],
_lastClosedTabGroupCount: -1,
busy: false,
chromeFlags: aWindow.docShell.treeOwner
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIAppWindow).chromeFlags,
};

if (PrivateBrowsingUtils.isWindowPrivate(aWindow)) {
Expand Down Expand Up @@ -5146,18 +5191,39 @@ var SessionStoreInternal = {
argString.data = "";

// Build feature string
let features = ["chrome", "dialog=no", "suppressanimation"];
let features;
let winState = aState.windows[0];
let hidden = winState.hidden?.split(",") || [];
if (!hidden.length) {
features.push("all");
} else {
features.push("resizable");
WINDOW_HIDEABLE_FEATURES.forEach(aFeature => {
if (!hidden.includes(aFeature)) {
features.push(WINDOW_OPEN_FEATURES_MAP[aFeature] || aFeature);
if (winState.chromeFlags) {
features = ["chrome", "suppressanimation"];
let chromeFlags = winState.chromeFlags;
const allFlags = Ci.nsIWebBrowserChrome.CHROME_ALL;
const hasAll = (chromeFlags & allFlags) == allFlags;
if (hasAll) {
features.push("all");
}
for (let [flag, onValue, offValue] of CHROME_FLAGS_MAP) {
if (hasAll && allFlags & flag) {
continue;
}
});
let value = chromeFlags & flag ? onValue : offValue;
if (value) {
features.push(value);
}
}
} else {
// |chromeFlags| is not found. Fallbacks to the old method.
features = ["chrome", "dialog=no", "suppressanimation"];
let hidden = winState.hidden?.split(",") || [];
if (!hidden.length) {
features.push("all");
} else {
features.push("resizable");
WINDOW_HIDEABLE_FEATURES.forEach(aFeature => {
if (!hidden.includes(aFeature)) {
features.push(WINDOW_OPEN_FEATURES_MAP[aFeature] || aFeature);
}
});
}
}
WINDOW_ATTRIBUTES.forEach(aFeature => {
// Use !isNaN as an easy way to ignore sizemode and check for numbers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,38 @@

"use strict";

function testFeatures(win, barprops) {
for (let [name, visible] of Object.entries(barprops)) {
const BARPROP_NAMES = [
"locationbar",
"menubar",
"personalbar",
"scrollbars",
"statusbar",
"toolbar",
];

function testFeatures(win, test) {
for (let name of BARPROP_NAMES) {
is(
win[name].visible,
visible,
name + " should be " + (visible ? "visible" : "hidden")
!!test.barprops?.[name],
name + " should be " + (test.barprops?.[name] ? "visible" : "hidden")
);
}
is(win.toolbar.visible, false, "toolbar should be hidden");
let toolbar = win.document.getElementById("TabsToolbar");
is(toolbar.collapsed, true, "tabbar should be collapsed");
is(
toolbar.collapsed,
!win.toolbar.visible,
win.toolbar.visible
? "tabbar should not be collapsed"
: "tabbar should be collapsed"
);
let chromeFlags = win.docShell.treeOwner
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIAppWindow).chromeFlags;
is(
chromeFlags & Ci.nsIWebBrowserChrome.CHROME_WINDOW_RESIZE,
Ci.nsIWebBrowserChrome.CHROME_WINDOW_RESIZE,
"window should be resizable"
);
is(chromeFlags & test.chromeFlags, test.chromeFlags, "flags should be set");
if (test.unsetFlags) {
is(chromeFlags & test.unsetFlags, 0, "flags should be unset");
}
}

add_task(async function testRestoredWindowFeatures() {
Expand All @@ -30,30 +43,80 @@ add_task(async function testRestoredWindowFeatures() {
{
url: "http://example.com/browser/" + DUMMY_PAGE,
features: "menubar=0,resizable",
barprops: { menubar: false },
barprops: { scrollbars: true },
chromeFlags: Ci.nsIWebBrowserChrome.CHROME_WINDOW_RESIZE,
unsetFlags: Ci.nsIWebBrowserChrome.CHROME_OPENAS_DIALOG,
},
{
url: "data:,", // title should be empty
checkContentTitleEmpty: true,
features: "location,resizable",
barprops: { locationbar: true },
barprops: { locationbar: true, scrollbars: true },
chromeFlags: Ci.nsIWebBrowserChrome.CHROME_WINDOW_RESIZE,
unsetFlags: Ci.nsIWebBrowserChrome.CHROME_OPENAS_DIALOG,
},
{
url: "http://example.com/browser/" + DUMMY_PAGE,
features: "dialog,resizable",
barprops: { scrollbars: true },
chromeFlags:
Ci.nsIWebBrowserChrome.CHROME_OPENAS_DIALOG |
Ci.nsIWebBrowserChrome.CHROME_WINDOW_RESIZE,
},
{
chrome: true,
url: "http://example.com/browser/" + DUMMY_PAGE,
features: "chrome,all,dialog=no",
barprops: {
locationbar: true,
menubar: true,
personalbar: true,
scrollbars: true,
statusbar: true,
toolbar: true,
},
chromeFlags: Ci.nsIWebBrowserChrome.CHROME_ALL,
unsetFlags: Ci.nsIWebBrowserChrome.CHROME_OPENAS_DIALOG,
},
];
const TEST_URL_CHROME = "chrome://mochitests/content/browser/" + DUMMY_PAGE;

for (let test of TESTS) {
BrowserTestUtils.loadURI(gBrowser.selectedBrowser, TEST_URL_CHROME);
await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
BrowserTestUtils.loadURI(gBrowser.selectedBrowser, TEST_URL_CHROME);
await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);

for (let test of TESTS) {
let newWindowPromise = BrowserTestUtils.waitForNewWindow({
url: test.url,
});
await SpecialPowers.spawn(gBrowser.selectedBrowser, [test], t => {
content.eval(`window.open("${t.url}", "_blank", "${t.features}")`);
});
let win = await newWindowPromise;
let win;
if (test.chrome) {
win = window.openDialog(
AppConstants.BROWSER_CHROME_URL,
"_blank",
test.features,
test.url
);
} else {
await SpecialPowers.spawn(gBrowser.selectedBrowser, [test], t => {
content.window.open(t.url, "_blank", t.features);
});
}
win = await newWindowPromise;

let title = win.document.title;
if (test.checkContentTitleEmpty) {
let contentTitle = await SpecialPowers.spawn(
win.gBrowser.selectedBrowser,
[],
() => content.document.title
);
is(contentTitle, "", "title should be empty");
}

testFeatures(win, test.barprops);
testFeatures(win, test);
let chromeFlags = win.docShell.treeOwner
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIAppWindow).chromeFlags;

await BrowserTestUtils.closeWindow(win);

Expand All @@ -64,7 +127,18 @@ add_task(async function testRestoredWindowFeatures() {
win = await newWindowPromise;

is(title, win.document.title, "title should be preserved");
testFeatures(win, test.barprops);
testFeatures(win, test);
is(
win.docShell.treeOwner
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIAppWindow).chromeFlags,
// Use |>>> 0| to force unsigned.
(chromeFlags |
Ci.nsIWebBrowserChrome.CHROME_OPENAS_CHROME |
Ci.nsIWebBrowserChrome.CHROME_SUPPRESS_ANIMATION) >>>
0,
"unexpected chromeFlags"
);

await BrowserTestUtils.closeWindow(win);
}
Expand Down

0 comments on commit 4ba863e

Please sign in to comment.